赞
踩
这是我关于StableDiffusion
学习系列的第二篇文章,如果第一篇你还没有阅读,强烈推荐大家翻看前篇内容。在本文中,我们将学习构成StableDiffusion
的各个基础组件,并针对每个组件的功能进行阐述。
闲话少说,我们直接开始吧!
正如前文所述,扩散模型主要用来生成高质量的图像。稳定扩散模型(StableDiffusion)
可以视为一种特殊的扩散模型,学术上叫做潜在扩散模型(Latent Diffusion model)
,相关概念来自于论文《 High-Resolution Image Synthesis with Latent Diffusion Models》
。简单来说,原始的扩散模型通常会消耗更多的内存,因此创建了潜在扩散模型,可以在被称为潜在低维度特征空间进行扩散过程。更进一步,扩散模型是机器学习模型,它被训练来在带有高斯噪声的图像上逐步进行去噪,以获得高质量图像。而潜在扩散模型被训练成在低纬度的特征空间上进行同样的过程。
一般来说,潜在扩散模型含有三个组件:
CLIP
的文本编码器Variational Auto Encoder
,也被简称为VAE
本文先从最基础的text encoder
讲起,主要介绍其在扩散过程中的用途。
CLIP text Encoder
以文本作为输入,并在潜在特征空间中生成文本嵌入(text embeddings)
;我们也可以通过CLIP模型对图像进行特征编码一样。
任何机器学习模型都无法直接理解原始文本输入数据。在机器学习领域,我们通常都需要将文本转换为包含文本含义的数字表示,称为嵌入(embedding)
。将文本转换为数字表示的过程可以分为两部分:
Tokenizer
- 将文本输入拆分为各个子单词,然后使用查找表将每个子单词转换为数字Token_To_Embedding Encoder
- 将每个子单词的数字表示转换为包含该文本语义信息的特征表示只看文字讲解还是不够直观,让我们不妨通过代码来进一步了解它。我们将从导入相关库开始:
import torch,logging
from transformers import CLIPTextModel,CLIPTokenizer
clip_path = "/media/stable_diffusion/clip-vit-large-patch14"
tokenizer = CLIPTokenizer.from_pretrained(clip_path,
local_files_only=True,
torch_dtype=torch.float16)
让我们初始化一个文本提示,并将其token
化,代码如下:
prompt = [ 'a dog wearing hat' ]
tok = tokenizer(prompt,padding="max_length",
max_length=tokenizer.model_max_length,
truncation=True,
return_tensors="pt")
print(tok.input_ids.shape)
print(tok)
输出结果如下:
观察上述输出,tokenizer
返回包含以下两个对象的字典:
●input_ids
- 表示一个文本提示被转化为一个1X77的tensor
,其中49406表示start token
, 而320表示对应单词“a”的token
,1929对应单词“dog”,3309对应单词“wearing”,3801对应单词“hat”,49407表示end token,后面重复的多个49407为了padding至固定长度77
● attention_mask
- 这里的1表示对应有效的embeded
值,0表示对应的为padding
进一步,我们可以使用一下代码来将input_ids
表示的单词依次打印出来:
for token in list(tok.input_ids[0,:7]):
print(f"{token}:{tokenizer.convert_ids_to_tokens(int(token))}")
得到结果如下:
这一节我们来介绍基于CLIP
的Text Encoder
,首先我们利用以下代码来进行初始化操作:
text_encoder = CLIPTextModel.from_pretrained(clip_path,
local_files_only=True,
torch_dtype=torch.float16).to('cuda')
接着我们利用text_encoder
来将由tokenizer
生成的input_ids
转化为对应的文本嵌入表示,代码如下:
emb = text_encoder(tok.input_ids.to("cuda"))[0].half()
print(f"shape of embedding: {emb.shape}")
print(emb)
得到结果如下:
如上所述,大小为1x77
的每个token化后的输入现在已被转换为1x77x768
嵌入(embedding)
。因此,每个单词都被表示在768维的潜在特征空间中。
事实上,Stable Diffusion
仅仅使用训练好的CLIP模型来实现将文本转化为嵌入表示,这种嵌入表示作为扩散模型UNet
的输入之一。
一般来说,CLIP使用文本编码器和图像编码器来在潜在空间进行特征嵌入,通过对比学习来将文本和图像语义接近的在特征空间进行距离拉近。关于CLIP更多的信息,大家可以访问OpenAI的关于CLIP介绍的文章,链接见附录;也可以翻看我之前的博客。
本文重点介绍了SD模型中的文本编码器text encoder
的相关功能和具体实现原理,并详细介绍了其两个具体操作步骤,并给出了相应的代码示例。
您学废了嘛!
本文涉及的相关参考链接如下:
LDM论文: 戳我
CLIP介绍: 戳我
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。