介绍

时尚的中途

传递文本,它将生成与之匹配的图像。

下图是美味的巧克力

テキストからの画像生成をローカルで動かしてみる

有一条推文我想在本地运行它,

@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

相关文章:

  • 2021-11-07
  • 2021-06-12
  • 2022-12-23
  • 2022-01-22
  • 2021-11-01
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-08-20
  • 2021-07-23
  • 2021-07-05
  • 2022-12-23
  • 2021-05-27
  • 2021-04-21
  • 2021-12-11
相关资源
相似解决方案