上期文章
【每日算法】理论:生成模型基础; 刷题:力扣单调栈
文章目录
- 上期文章
- 一、上期问题
- 二、理论问题
- 1、stable diffusion模型的网络架构
- 2、T5的网络架构(Text-To-Text Transfer Transformer模型)
- 3、SDXL模型
- 4、DALLE
- 5、BPE编码
- 6、为什么DDPM加噪声的幅度是不一致的?
- 三、力扣刷题回顾-单调栈部分
一、上期问题
【每日算法】理论:生成模型基础; 刷题:力扣单调栈
- 怎么理解重参数化技术
- KL散度是什么
- DDPM
- 什么是马尔可夫过程
- GAN模型
- VAE模型
二、理论问题
1、stable diffusion模型的网络架构
Stable Diffusion模型整体上是一个End-to-End模型,主要由VAE,U-Net以及CLIP Text Encoder三个核心组件构成。一般来讲,模型会有两个输入,即文本和图像输入。图像编码器VAE Encoder会将输入的图像转换为低维的Latent特征,而文本信息则会通过CLIP Text Encoder模型进行编码,处理过后的文本信息和图像信息会输入到图像优化模块中,图像优化模块进行优化迭代后,将其输出的低维Latent特征输入回图像解码器(VAE Decoder)中,重建成像素级图。
Stable Diffusion(SD)核心基础知识——(文生图、图生图)
2、T5的网络架构(Text-To-Text Transfer Transformer模型)
T5是谷歌在19年发布一个的一个模型,最主要的贡献是给整个 NLP 预训练模型领域提供了一个通用框架,将所有 NLP 任务都转化成 Text-to-Text任务。T5使用的就是Transformer标准的基本结构,包括Encoder 和 Decoder 两部分。T5在Transformer模型的基础上进行了一系列的改进和创新,包括统一的输入输出表示、任务描述符、训练目标和超参数的调整等,从而使得模型在处理文本生成任务时表现更加优异和通用。
3、SDXL模型
Stable Diffusion XL是一个二阶段的级联扩散模型,包括Base模型和Refiner模型。其中Base模型的主要工作和Stable Diffusion一致,具备文生图,图生图,图像inpainting等能力。在Base模型之后,级联了Refiner模型,对Base模型生成的图像Latent特征进行精细化,其本质上是在做图生图的工作。与Stable Diffusion模型相比,SDXL不论是模型架构上还是训练策略上都做了优化。在模型架构上,SDXL对原先sd的U-Net,VAE,CLIP Text Encoder三个部分都做了改进,在训练策略上,SDXL设计了很多训练策略,包括图像尺寸条件化策略,图像裁剪参数条件化以及多尺度训练等。
Stable Diffusion XL(SDXL)核心基础知识
4、DALLE
DALL·E 是 OpenAI 的多模态预训练模型,它的目标是将文本token和图像token当成一个数据序列,通过Transformer进行自回归。DALL-E 是一个两阶段的模型:它的第一个阶段是离散变分自编码器(Discrete Variance Auto-Encoder,dVAE),用于生成图像的token。它的第二个阶段是混合了图像和文本特征的,以Transformer为基础的生成模型。在训练阶段,模型会将文本编码和图像编码的结果进行拼接,用拼接的数据训练一个自回归transformer来建模文本和图片token的联合分布;在推理阶段,模型将输入文本编码成特征向量之后送入到自回归的Transformer中可以生成图像的token,将图像的token送入到dVAE的解码器中得到多组生成图像,此时再通过CLIP对生成样本进行评估,得到最终的生成结果。
【论文精读】DALLE: Zero-Shot Text-to-Image Generation零样本文本到图像生成
5、BPE编码
BPE(Byte Pair Encoding)编码是一种常用的无损数据压缩算法,也常被用于自然语言处理中的词汇表示和分词任务。它基于统计的方法,通过不断合并数据中出现频率最高的字节对来构建编码表。
6、为什么DDPM加噪声的幅度是不一致的?
DDPM前期的加噪幅度会小些,后期会加噪多。前期加噪少是为了保持数据结构的完整性,后期加噪多是为了加速扩散过程,从而使得模型能够更快地从噪声中恢复出清晰的数据。
三、力扣刷题回顾-单调栈部分
上期涉及题目:
- 739. 每日温度
- 496. 下一个更大元素 I
- 503. 下一个更大元素 II
本期题目:
- 42. 接雨水
- 84.柱状图中最大的矩形
42. 接雨水:
- 给定条件:包含n个非负整数的数组,每个非负整数都表示一个宽度为1的柱子的高度
- 要求输出:按照上述数组排列出的柱子,在下雨后能够接住多少雨水
84.柱状图中最大的矩形:
- 给定条件:包含n个非负整数的数组,每个非负整数都表示一个宽度为1的柱子的高度
- 要求输出:求在这个柱状图中可以勾勒出的矩形的最大面积
对比分析:
42. 接雨水这道题需要分别寻找元素右边和左边的最大元素来计算雨水面积,由于单调栈的作用是寻找一个元素右边或者左边第一个比自己大或者小的元素的位置,所以单调栈保存的标号主要是用来求雨水面积中的行。对于列的计算需要考虑两侧柱子的高度,适用到单调栈场景主要是考虑以下三种情况:
- ①当前遍历的元素(柱子)高度小于栈顶元素的高度:(把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序)
- ②当前遍历的元素(柱子)高度等于栈顶元素的高度:(更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度)
- ③当前遍历的元素(柱子)高度大于栈顶元素的高度:(出现凹槽,用栈顶和栈顶的下一个元素以及要入栈的元素三个元素来接水)
84.柱状图中最大的矩形和42. 接雨水是遥相呼应的两道题,接雨水是求外,柱状图中最大的矩形是求内。42. 接雨水是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。
42. 接雨水:
- 情况一时将当前遍历的元素加入栈;情况二时当前柱子高度和栈顶一致,左边的一个是不可能存放雨水的,所以去除左侧柱子,保留右侧新柱子;情况三时将接到的雨水进行计算。
class Solution:
def trap(self, height: List[int]) -> int:
# stack储存index,用于计算对应的柱子高度
stack=[0]
result=0
for i in range (1,len(height)):
# 情况一
if height[i]<height[stack[-1]]:
stack.append(i)
# 情况二
# 当前柱子高度和栈顶一致时,左边的一个是不可能存放雨水的,所以保留右侧新柱子
elif height[i]==height[stack[-1]]:
stack.pop()
stack.append(i)
# 情况三
else:
while len(stack)!=0 and height[i]>height[stack[-1]]:
# 栈顶是中间的柱子,也就是储水的凹槽的底部
mid_height=height[stack[-1]]
stack.pop()
if stack:
right_height=height[i]
left_height=height[stack[-1]]
# 两侧的较矮一方的高度 - 凹槽底部高度
h = min(right_height, left_height) - mid_height
# 凹槽右侧下标-凹槽左侧下标-1
w = i-stack[-1]-1
result+=h*w
stack.append(i)
return result
84.柱状图中最大的矩形:
- 和接雨水一样分为三种情况,区别在于需要提前将输入数组首尾补上0,在情况三进行计算时高度的计算方式存在不同,并且接雨水试求面积之和,而本题是求面积的最大值。
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
#输入数组首尾补上0
heights.insert(0,0)
heights.append(0)
result=0
stack=[0]
for i in range(1,len(heights)):
# 情况一
if heights[i]>heights[stack[-1]]:
stack.append(i)
# 情况二
elif heights[i] == heights[stack[-1]]:
stack.pop()
stack.append(i)
# 情况三
else:
while stack and heights[i]<heights[stack[-1]]:
# 栈顶是中间的柱子
mid_index=stack[-1]
stack.pop()
if stack:
w=i-stack[-1]-1
h=heights[mid_index]
result=max(result,w*h)
stack.append(i)
return result
参考:
代码随想录算法训练营第五十一天|503.下一个更大元素II,42. 接雨水
代码随想录算法训练营第五十二天|84.柱状图中最大的矩形,完结撒花✿✿ヽ(°▽°)ノ✿