介绍
时尚的中途
传递文本,它将生成与之匹配的图像。
下图是美味的巧克力
有一条推文我想在本地运行它,
@zacky1972 看到这个并说:“有人想试试吗?”
原始存储库在这里
分叉并使其在 Docker 和 CPU 环境中工作在这里
执行环境
- macOS 蒙特雷 12.4
- Rancher 桌面版 1.5.1
Dockerfile
首先克隆原始存储库
git clone https://github.com/CompVis/latent-diffusion.git && \
cd latent-diffusion
这次想搬的是scripts/txt2img.py
下载所需的模型文件
由于是6.15GB,所以下载需要很长时间,
如果您的磁盘空间不足,请小心(我总是)
mkdir -p models/ldm/text2img-large/ && \
wget -O models/ldm/text2img-large/model.ckpt \
https://ommer-lab.com/files/latent-diffusion/nitro/txt2img-f8-large/model.ckpt
如果您的本地计算机没有启用 CUDA 的 CPU,请删除代码中的 cuda 或将其替换为 cpu
ldm/models/diffusion/ddim.py
...
def register_buffer(self, name, attr):
- if type(attr) == torch.Tensor:
- if attr.device != torch.device("cuda"):
- attr = attr.to(torch.device("cuda"))
setattr(self, name, attr)
...
ldm/modules/encoders/modules.py
...
class TransformerEmbedder(AbstractEncoder):
"""Some transformer encoder layers"""
- def __init__(self, n_embed, n_layer, vocab_size, max_seq_len=77, device="cuda"):
+ def __init__(self, n_embed, n_layer, vocab_size, max_seq_len=77, device="cpu"):
super().__init__()
self.device = device
self.transformer = TransformerWrapper(num_tokens=vocab_size, max_seq_len=max_seq_len,
...
class BERTTokenizer(AbstractEncoder):
""" Uses a pretrained BERT tokenizer by huggingface. Vocab size: 30522 (?)"""
- def __init__(self, device="cuda", vq_interface=True, max_length=77):
+ def __init__(self, device="cpu", vq_interface=True, max_length=77):
super().__init__()
from transformers import BertTokenizerFast # TODO: add to reuquirements
self.tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
self.device = device
self.vq_interface = vq_interface
self.max_length = max_length
...
class BERTEmbedder(AbstractEncoder):
"""Uses the BERT tokenizr model and add some transformer encoder layers"""
def __init__(self, n_embed, n_layer, vocab_size=30522, max_seq_len=77,
- device="cuda",use_tokenizer=True, embedding_dropout=0.0):
+ device="cpu",use_tokenizer=True, embedding_dropout=0.0):
super().__init__()
self.use_tknz_fn = use_tokenizer
if self.use_tknz_fn:
self.tknz_fn = BERTTokenizer(vq_interface=False, max_length=max_seq_len)
self.device = device
self.transformer = TransformerWrapper(num_tokens=vocab_size, max_seq_len=max_seq_len,
attn_layers=Encoder(dim=n_embed, depth=n_layer),
emb_dropout=embedding_dropout)
...
class FrozenCLIPTextEmbedder(nn.Module):
"""
Uses the CLIP transformer encoder for text.
"""
- def __init__(self, version='ViT-L/14', device="cuda", max_length=77, n_repeat=1, normalize=True):
+ def __init__(self, version='ViT-L/14', device="cpu", max_length=77, n_repeat=1, normalize=True):
super().__init__()
self.model, _ = clip.load(version, jit=False, device="cpu")
self.device = device
self.max_length = max_length
self.n_repeat = n_repeat
self.normalize = normalize
脚本/txt2img.py
...
def load_model_from_config(config, ckpt, verbose=False):
print(f"Loading model from {ckpt}")
pl_sd = torch.load(ckpt, map_location="cpu")
sd = pl_sd["state_dict"]
model = instantiate_from_config(config.model)
m, u = model.load_state_dict(sd, strict=False)
if len(m) > 0 and verbose:
print("missing keys:")
print(m)
if len(u) > 0 and verbose:
print("unexpected keys:")
print(u)
- model.cuda()
model.eval()
return model
...
最初的 README 说要使用 Anaconda 构建环境,
我想将它保存在一个容器中(我想将它移动到各个地方),所以我将创建一个 Dockerfile
我使用这篇文章作为使用 Docker 构建 Anaconda 环境的参考
Dockerfile
FROM python:3.8
RUN apt-get update && apt-get install -y \
sudo \
wget \
vim
WORKDIR /opt
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
sh Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3 && \
rm -r Miniconda3-latest-Linux-x86_64.sh
ENV PATH /opt/miniconda3/bin:$PATH
RUN pip install --upgrade pip && \
conda update -n base -c defaults conda
# 必要そうなファイルをコピー
# models は大きいのでマウントする
# scripts はいじることが多そうなのでマウントする
COPY ./configs /app/configs
COPY ./ldm /app/ldm
COPY ./setup.py /app/setup.py
COPY ./main.py /app/main.py
WORKDIR /app
# 実行環境を設定
COPY ./environment.yaml /app/environment.yaml
RUN conda env create -f environment.yaml
RUN conda init bash
RUN echo "conda activate ldm" >> ~/.bashrc
ENV CONDA_DEFAULT_ENV ldm && \
PATH /opt/conda/envs/ldm/bin:$PATH
CMD ["/bin/bash"]
创建图像输出目录
mkdir outputs
创建 docker-compose.yml 以便于启动
---
version: "2.3"
services:
ldm:
container_name: ldm
build:
context: .
volumes:
- ./models:/app/models
- ./scripts:/app/scripts
- ./outputs:/app/outputs # 出力先ディレクトリー
tty: true # 起動したままにする
模型文件为 6.15 GB,因此占用大量内存
在我的机器上,除非我在 Rancher Desktop 设置中为 VM 分配 14 GB,否则它不起作用
以此状态启动容器
构建将运行,一段时间后容器将启动
$ docker-compose up --build
...
Attaching to ldm
进入容器
docker exec -it ldm /bin/bash
根据 REDMI 安装附加包
*在Dockerfile中输入conda activate ldm时出错,请在进入容器后执行。
pip install transformers==4.19.2 scann kornia==0.6.4 torchmetrics==0.6.0
pip install git+https://github.com/arogozhnikov/einops.git
在容器内运行
以下示例将文本 a virus monster is playing guitar, oil on canvas 显示为图像
$ python scripts/txt2img.py --prompt "a virus monster is playing guitar, oil on canvas" --ddim_eta 0.0 --n_samples 4 --n_iter 4 --scale 5.0 --ddim_steps 50
Loading model from models/ldm/text2img-large/model.ckpt
...
Sampling: 0%| | 0/4 [00:00<?, ?it/s]Data shape for DDIM sampling is (4, 4, 32, 32), eta 0.0
Running DDIM Sampling with 50 timesteps
DDIM Sampler: 100%|████████████████████████████████████████████████████████████████████████████████████| 50/50 [08:11<00:00, 9.83s/it]
Sampling: 25%|██████████████████████▎ | 1/4 [08:41<26:04, 521.48s/it]Data shape for DDIM sampling is (4, 4, 32, 32), eta 0.0
Running DDIM Sampling with 50 timesteps
DDIM Sampler: 100%|████████████████████████████████████████████████████████████████████████████████████| 50/50 [08:27<00:00, 10.15s/it]
Sampling: 50%|████████████████████████████████████████████▌ | 2/4 [17:46<17:50, 535.48s/it]Data shape for DDIM sampling is (4, 4, 32, 32), eta 0.0
Running DDIM Sampling with 50 timesteps
DDIM Sampler: 100%|████████████████████████████████████████████████████████████████████████████████████| 50/50 [07:45<00:00, 9.31s/it]
Sampling: 75%|██████████████████████████████████████████████████████████████████▊ | 3/4 [25:50<08:31, 511.72s/it]Data shape for DDIM sampling is (4, 4, 32, 32), eta 0.0
Running DDIM Sampling with 50 timesteps
DDIM Sampler: 100%|████████████████████████████████████████████████████████████████████████████████████| 50/50 [07:02<00:00, 8.46s/it]
Sampling: 100%|█████████████████████████████████████████████████████████████████████████████████████████| 4/4 [33:06<00:00, 496.54s/it]
Your samples are ready and waiting four you here:
outputs/txt2img-samples
Enjoy.
由于 n_samples 指定为 4,因此每次生成 4 张图像,
由于为n_iter指定了4,所以会执行4次
outputs/txt2img-samples 生成了 16 张图片,
它们以 4 * 4 组合的图像生成为outputs/a-virus-monster-is-playing-guitar,-oil-on-canvas.png
这是完成的图像
当然,这是一幅病毒怪物弹吉他的油画。
顺便说一句,执行一次需要几十分钟
毕竟没有GPU很难,,,
使用Elixir's space adventures cartoon 运行看起来像这样
图案和标题都不错,卡通化的表现也很精彩。
概括
毕竟重模型很难没有GPU
现在它已经被容器化了,如果你正确地组织它并将它放在 AWS GPU 实例上,它应该可以正常工作
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308624169.html