第十一周周报

news2025/7/28 9:19:16

学习目标:

DDPM

学习内容:

DDPM代码

学习时间:

11.13-11.18

学习产出:

一、DDPM

1、trainer

trainer用来计算损失,即将图片加噪后计算损失,损失公式如下:
在这里插入图片描述
在这里插入图片描述
extract()函数:选取特下标的t并转换成特定维度

# 根据Loss公式计算Loss
class GaussianDiffusionTrainer(nn.Module):
    '''
    model=Unet,beta_1=β1,beta_T=βT,(β1,βT指方差的最小值和最大值,β1和βT产生linear schecule,越往后β越大,如果扩散步数T足够大,那么Xt忽悠完全丢掉了原始数据而变成了一个随机噪声),T指的是逆向计算中前向的时间步,
    '''

    def __init__(self, model, beta_1, beta_T, T):
        super().__init__()
        self.model = model
        self.T = T  # 1000
        # 得到一个线性增长的Bt
        self.register_buffer(
            'betas', torch.linspace(beta_1, beta_T, T).double())
        # 通过Bt得到论文中的α
        alphas = 1. - self.betas
        # 通过α累乘得到αt
        alphas_bar = torch.cumprod(alphas, dim=0)
        # calculations for diffusion q(x_t | x_{t-1}) and others
        self.register_buffer(
            'sqrt_alphas_bar', torch.sqrt(alphas_bar))
        self.register_buffer(
            'sqrt_one_minus_alphas_bar', torch.sqrt(1. - alphas_bar))
        print('计算loss')

    def forward(self, x_0):
        """
        Algorithm 1.
        随机生成t和噪声,通过t和噪声得到x_t(即通过t和噪声得到最终的噪声图像),计算出loss后返回
        """
        t = torch.randint(self.T, size=(x_0.shape[0],), device=x_0.device)  # torch.Size([64, 3, 32, 32]),生成的最大数为1000
        # 随机生成一个和X0一样的噪声
        noise = torch.randn_like(x_0)
        # 正向得到最终噪声图片Xt
        x_t = (
                extract(self.sqrt_alphas_bar, t, x_0.shape) * x_0 +
                extract(self.sqrt_one_minus_alphas_bar, t, x_0.shape) * noise)
        # 计算纯噪声noise和生成噪声Xt的loss
        loss = F.mse_loss(self.model(x_t, t), noise, reduction='none')
        return loss

forward()中
在这里插入图片描述
计算时间步
在这里插入图片描述
生成纯噪声noise
在这里插入图片描述
通过计算
在这里插入图片描述
得到最终得噪声图片Xt
在这里插入图片描述
然后通过
在这里插入图片描述
计算loss。计算loss伪代码为:
在这里插入图片描述

2、sampler

# 采样过程
class GaussianDiffusionSampler(nn.Module):
    '''
    mean_type表示均值采用的类型,var_type表示方差β固定很小或很大的值
    '''

    def __init__(self, model, beta_1, beta_T, T, img_size=32,
                 mean_type='eps', var_type='fixedlarge'):
        # xpre通过xt预测xt-1,xstart通过xt预测x0,epsilon为预测误差
        assert mean_type in ['xprev' 'xstart', 'epsilon']
        assert var_type in ['fixedlarge', 'fixedsmall']
        super().__init__()

        self.model = model
        self.T = T
        self.img_size = img_size
        self.mean_type = mean_type
        self.var_type = var_type
        self.register_buffer(
            'betas', torch.linspace(beta_1, beta_T, T).double())
        # 得到α
        alphas = 1. - self.betas
        # 得到αt
        alphas_bar = torch.cumprod(alphas, dim=0)
        # #所有alphas_bar向后移动一位,第一位等于1
        # 得到αt-1
        alphas_bar_prev = F.pad(alphas_bar, [1, 0], value=1)[:T]
        # calculations for diffusion q(x_t | x_{t-1}) and others
        self.register_buffer(
            'sqrt_recip_alphas_bar', torch.sqrt(1. / alphas_bar))
        self.register_buffer(
            'sqrt_recipm1_alphas_bar', torch.sqrt(1. / alphas_bar - 1))

        # calculations for posterior q(x_{t-1} | x_t, x_0)、
        # 方差
        self.register_buffer(
            'posterior_var',
            self.betas * (1. - alphas_bar_prev) / (1. - alphas_bar))
        # below: log calculation clipped because the posterior variance is 0 at
        # the beginning of the diffusion chain
        self.register_buffer(
            'posterior_log_var_clipped',
            torch.log(
                torch.cat([self.posterior_var[1:2], self.posterior_var[1:]])))
        # 均值公式中X0前面的常数
        self.register_buffer(
            'posterior_mean_coef1',
            torch.sqrt(alphas_bar_prev) * self.betas / (1. - alphas_bar))
        # 均值公式中Xt前面的常数
        self.register_buffer(
            'posterior_mean_coef2',
            torch.sqrt(alphas) * (1. - alphas_bar_prev) / (1. - alphas_bar))

    # 计算逆向过程需要的均值和方差
    def q_mean_variance(self, x_0, x_t, t):
        """
        Compute the mean and variance of the diffusion posterior
        q(x_{t-1} | x_t, x_0)
        """
        assert x_0.shape == x_t.shape
        # 通过均值公式的第一步乘以X0和第二步乘以Xt得到均值
        posterior_mean = (
                extract(self.posterior_mean_coef1, t, x_t.shape) * x_0 +
                extract(self.posterior_mean_coef2, t, x_t.shape) * x_t
        )
        # 得到方差
        posterior_log_var_clipped = extract(
            self.posterior_log_var_clipped, t, x_t.shape)
        return posterior_mean, posterior_log_var_clipped

    def predict_xstart_from_eps(self, x_t, t, eps):
        assert x_t.shape == eps.shape
        return (
                extract(self.sqrt_recip_alphas_bar, t, x_t.shape) * x_t -
                extract(self.sqrt_recipm1_alphas_bar, t, x_t.shape) * eps
        )

    def predict_xstart_from_xprev(self, x_t, t, xprev):
        assert x_t.shape == xprev.shape
        return (  # (xprev - coef2*x_t) / coef1
                extract(
                    1. / self.posterior_mean_coef1, t, x_t.shape) * xprev -
                extract(
                    self.posterior_mean_coef2 / self.posterior_mean_coef1, t,
                    x_t.shape) * x_t
        )

    # 计算逆向过程
    def p_mean_variance(self, x_t, t):
        # below: only log_variance is used in the KL computations
        # 后验分布方差
        model_log_var = {
            # for fixedlarge, we set the initial (log-)variance like so to
            # get a better decoder log likelihood
            'fixedlarge': torch.log(torch.cat([self.posterior_var[1:2],
                                               self.betas[1:]])),
            'fixedsmall': self.posterior_log_var_clipped,
        }[self.var_type]
        # print('model_log_var1',model_log_var)
        # 计算方差
        model_log_var = extract(model_log_var, t, x_t.shape)
        # print('model_log_var2',model_log_var)
        # Mean parameterization
        '''
        mean_type == 'xprev'和mean_type == 'xstart'没有使用,这里只用到第三种,即mean_type == 'epsilon'
        '''
        if self.mean_type == 'xprev':  # the model predicts x_{t-1}
            # print('xprev')
            x_prev = self.model(x_t, t)
            x_0 = self.predict_xstart_from_xprev(x_t, t, xprev=x_prev)
            model_mean = x_prev
        elif self.mean_type == 'xstart':  # the model predicts x_0
            # print('xstart')
            x_0 = self.model(x_t, t)
            model_mean, _ = self.q_mean_variance(x_0, x_t, t)
        elif self.mean_type == 'epsilon':  # the model predicts epsilon
            # print('epsilon')
            eps = self.model(x_t, t)  # 模型预测的噪声
            x_0 = self.predict_xstart_from_eps(x_t, t, eps=eps)  # 得到均值计算需要的X0
            model_mean, _ = self.q_mean_variance(x_0, x_t, t)  # 计算均值
        else:
            raise NotImplementedError(self.mean_type)
        x_0 = torch.clip(x_0, -1., 1.)

        return model_mean, model_log_var

    def forward(self, x_T):
        """
        Algorithm 2.
        """
        x_t = x_T  # torch.Size([64, 3, 32, 32])
        # print('x_t', x_t.shape)
        for time_step in reversed(range(self.T)):
            t = x_t.new_ones([x_T.shape[0], ], dtype=torch.long) * time_step  # 时间步,torch.Size([64])
            # print('t.shape',t.shape)
            mean, log_var = self.p_mean_variance(x_t=x_t, t=t)
            # print('mean',mean)
            # print('log_var',log_var)
            # no noise when t == 0
            if time_step > 0:
                # print('have noise')
                noise = torch.randn_like(x_t)
            else:
                # print('not noise')
                noise = 0
            x_t = mean + torch.exp(0.5 * log_var) * noise  # 得到Xt-1,循环得到X0
            # print('x_t',x_t)
        x_0 = x_t
        return torch.clip(x_0, -1, 1)

forward()中
通过
在这里插入图片描述
生成时间步。
通过
在这里插入图片描述
计算均值和方差。具体为:
在这里插入图片描述
均值类型有‘xprev’、‘xstart’和‘epsilon’三种,这里只使用了‘epsilon’。
即通过
在这里插入图片描述
计算方差,由于方差是常数,因此可以直接得出。使用公式为:
在这里插入图片描述

通过
在这里插入图片描述
计算均值。其中eps为trainer中训练好后预测输出的噪声。然后使用
在这里插入图片描述
得出原图片X0.使用公式为
在这里插入图片描述
得出X0后,使用
在这里插入图片描述
计算均值,具体为:
在这里插入图片描述
使用到的公式为
在这里插入图片描述
通过q_mean_variance()函数和p_mean_variance()计算得出均值和方差后,使用
在这里插入图片描述
计算Xt-1,使用的公式为
在这里插入图片描述

在这里插入图片描述
通过for循环将time_step从1000到0的过程就是从Xt到X0的过程。
生成图像伪代码为:
在这里插入图片描述

二、Unet网络

Unet网络中分为DownBlocksMiddleUpBlockstail
DownBlocks中一个Block包括两个ResBlock和一个DownSample,将Blocks重复三次再加上两个ResBlock后就构成了DonwBlocks。(特征提取作用)
MIddle由一个具有Attntion的ResBlock和一个普通的ResBlock组成。
UpBlocks中一个Block包括三个ResBlock和一个UpSample,将Blocks重复三次后再加上三个ResBlock就构成了UpBlocks。(特征融合作用)
tail由一个线性层+卷积层构成。
在这里插入图片描述

class UNet(nn.Module):
    def __init__(self, T, ch, ch_mult, attn, num_res_blocks, dropout):
        super().__init__()
        assert all([i < len(ch_mult) for i in attn]), 'attn index out of bound'
        tdim = ch * 4   #
        self.time_embedding = TimeEmbedding(T, ch, tdim)  # (1000,128,512)

        self.head = nn.Conv2d(3, ch, kernel_size=3, stride=1,
                              padding=1)  # (3,128,kernel_size(3,3),stride(1,1),padding(1,1))
        self.downblocks = nn.ModuleList()
        chs = [ch]  # record output channel when dowmsample for upsample
        now_ch = ch
        for i, mult in enumerate(ch_mult):
            out_ch = ch * mult
            for _ in range(num_res_blocks):
                self.downblocks.append(ResBlock(
                    in_ch=now_ch, out_ch=out_ch, tdim=tdim,
                    dropout=dropout, attn=(i in attn)))
                now_ch = out_ch
                chs.append(now_ch)
            if i != len(ch_mult) - 1:
                self.downblocks.append(DownSample(now_ch))
                chs.append(now_ch)

        self.middleblocks = nn.ModuleList([
            ResBlock(now_ch, now_ch, tdim, dropout, attn=True),
            ResBlock(now_ch, now_ch, tdim, dropout, attn=False),
        ])

        self.upblocks = nn.ModuleList()
        for i, mult in reversed(list(enumerate(ch_mult))):
            print('upblocks_i',i)
            print('upblocks_mult',mult)
            out_ch = ch * mult  # mult:2 2 2 1;out_ch = ch * mult =
            print('out_ch:',out_ch)
            for _ in range(num_res_blocks + 1):
                self.upblocks.append(ResBlock(
                    in_ch=chs.pop() + now_ch, out_ch=out_ch, tdim=tdim,
                    dropout=dropout, attn=(i in attn)))
                now_ch = out_ch
            if i != 0:
                self.upblocks.append(UpSample(now_ch))
        assert len(chs) == 0

        self.tail = nn.Sequential(
            nn.GroupNorm(32, now_ch),
            Swish(),
            nn.Conv2d(now_ch, 3, 3, stride=1, padding=1)
        )
        self.initialize()

    def initialize(self):
        init.xavier_uniform_(self.head.weight)
        init.zeros_(self.head.bias)
        init.xavier_uniform_(self.tail[-1].weight, gain=1e-5)
        init.zeros_(self.tail[-1].bias)

    def forward(self, x, t):
        # Timestep embedding
        # print('t.shape',t.shape)    # torch.Size([64])
        # print('x.shape', x.shape)   # torch.Size([64, 3, 32, 32])
        temb = self.time_embedding(t)  # (64,512)
        # print('temb',temb)
        # Downsampling
        h = self.head(x)  # (64,128,32,32)
        hs = [h]
        for layer in self.downblocks:
            h = layer(h, temb)
            hs.append(h)
        # Middle
        # print('h.shape',h.shape)    # torch.Size([64, 256, 4, 4]),尺寸从32x32变为4x4
        for layer in self.middleblocks:
            h = layer(h, temb)
        # print('h.shape', h.shape)  # torch.Size([64, 256, 4, 4])
        # Upsampling
        for layer in self.upblocks:
            if isinstance(layer, ResBlock):  # isinstance() 函数来判断一个对象是否是一个已知的类型
                h = torch.cat([h, hs.pop()], dim=1)
            h = layer(h, temb)
        # print('h.shape',h.shape)    # torch.Size([64, 128, 32, 32])
        h = self.tail(h)
        # print('h.shape', h.shape)   # torch.Size([64, 3, 32, 32])
        assert len(hs) == 0
        return h  # torch.Size([64, 3, 32, 32])

forward()中先使用TimeEmbedding()函数生成时间步。然后将输出的图(64,3,32,32)经过一个head(),即经过卷积改变通道数送入DownBlocks中,DownBlocks经过下采样将尺寸从32x32变为4x4,然后送入Middle,经过Middle处理后送入UpBlocks,UpBlock将尺寸从4x4上采样为32x32,通道数由256变为128,然后经过tail处理使图片通道数从128回到3,即最后返回的尺寸为(64,3,32,32)。

二、结果

Truth:
在这里插入图片描述
训练结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/16429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于HASM模型的土壤高精度建模matlab仿真

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 土壤有机碳库是陆地生态系统中最丰富的碳库&#xff0c;其动态变化和存储分布在土壤质量评估、农田生态管理和气候变化适应与减缓等领域起着至关…

Java实现图书管理系统

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaSE基础 格言&#xff1a;目之所及皆为回忆&#xff0c;心之所想皆为过往 今天给大家带来的是用Java实现的图书管理系统。 目录 需求 图书类 创建图书类 创建书架 Operation IOperation接口 添加图书AddOperation…

easyrecovery15最新版数据恢复类软件测评

当下如今&#xff0c;利用笔记本进行学习和办公已经是毋庸置疑的了&#xff0c;所以会需要在电脑上保存大量的数据信息&#xff0c;但是电脑在带来方便的同时&#xff0c;也存在很多的隐患。万一数据丢失了&#xff0c;该怎么办呢&#xff1f;要解决数据丢失问题&#xff0c;就…

VUE3 中实现拖拽和缩放自定义看板 vue-grid-layout

Vue Grid Layout官方文档 Vue Grid Layout中文文档 1. npm下载拖拽缩放库 npm install vue-grid-layout3.0.0-beta1 --save 2. vue3 使用 vue-grid-layout报错&#xff1a;external_commonjs_vue_commonjs2_vue_root_Vue_default.a is not a constructor 解决方案: vue3版本…

力扣刷题(代码回忆录)——数组部分

数组 数组过于简单&#xff0c;但你该了解这些&#xff01;数组&#xff1a;二分查找数组&#xff1a;移除元素数组&#xff1a;序数组的平方数组&#xff1a;长度最小的子数组数组&#xff1a;螺旋矩阵II数组&#xff1a;总结篇704. 二分查找 给定一个 n 个元素有序的&#…

什么是MQ

MQ概述 MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进 行通信。 分布式系统之间进行通信&#xff1a; 远程调用&#xff1a;各系统间直接通过远程调用的方式&#xff1b; 借助第三方完成系统…

【GlobalMapper精品教程】019:基于DSM提取离散随机点的高程信息

本文讲解在globalmapper中,基于DSM提取离散随机点的高程信息,配套数据为data019.rar。 文章目录 1. 离散点创建2. 提取离散点高程信息3. 高程标注1. 离散点创建 本文在ArcGIS中,根据给定的范围,随机生成离散点,如下图: 拓展阅读: ArcGIS根据范围创建随机点教程:【ArcG…

关于Kdo N3,1380099-68-2,3-脱氧-D-甘露-辛酸(Kdo)相关物理化学知识了解下

基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a; CAS号&#xff1a;1380099-68-2 中文名&#xff1a;2-酮基-3-脱氧辛酸叠氮糖 英文名&#xff1a;Kdo Azide&#xff0c;Kdo N3 结构式&#xff08;Structural&#xff09;&#xff1a; 试剂基团反应特点&a…

基于51单片机的波形发生器proteus仿真数码管LCD12864显示

仿真图1简介&#xff1a; 本系统采用51单片机作为系统的MCU&#xff08;具体型号见下图&#xff09;&#xff0c;该系统显示器为四位数码管&#xff0c;可实时显示波形的参数情况 可显示四种波形&#xff0c;分别是方波、正弦波、三角波、锯齿波。 该设计具有电压表功能&#…

C语言MFC导出dll回调函数方法详解

如何将回调函数导出来 这一章节主要讲述在导出函数的基础上如何将回调函数导出来。 C程序设计语言&#xff08;第1-3部分&#xff09;&#xff08;原书第4版&#xff09; 京东自营优惠价&#xff1a;&#xffe5;119.1立即抢购 回调函数的应用相信很多C程序猿儿们都不陌生吧…

弘玑Cyclone2022年产品发布会:人人可用的数字化工作平台——弘玑工作易

近日&#xff0c;在弘玑Cyclone“智无边界&#xff0c;数字未来”发布会上&#xff0c;弘玑Cyclone2022年超级自动化系列产品全新亮相&#xff0c;首席产品官贾岿博士带领产品团队以创新技术对新时代语境下的数字生产力进行了全新解读。 本文将为大家分享本次发布会重磅推出的…

为什么要让员工入职流程实现自动化

人和人之间的第一印象非常重要&#xff0c;一段缘分能不能开始&#xff0c;就看第一印象够不够给力了。其实&#xff0c;公司和新员工之间也存在着这样的关系&#xff0c;但也有些许差别。公司对新员工的第一印象&#xff0c;更多是从第一次见面的时候就产生了&#xff0c;而新…

NodeJs实战-待办列表(4)-解决待办事项中文乱码问题

NodeJs实战-待办列表4-解决待办事项中文乱码问题乱码问题在哪里产生的定位乱码问题VSCode 启动 NodeJs 调试模式浏览器中调试JS效果图执行添加执行完成乱码问题在哪里产生的 运行第3节的server.js, 当添加中文待办事项时候&#xff0c;会产生中文乱码问题。乱码可能在以下地方…

一款超好用的开源密码管理器?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store DevWeekly收集整理每周优质开发者内容&#xff0c;包括开源项目、资源工具、技术文章等方面。 每周五定期发布&#xff0c;同步更新到 知乎&#xff1a;Jackpop 。 欢迎大家投稿&#xff0c;提交iss…

最新消息:2022高被引科学家名单已公布,都想成为高被引,到底应该怎么做?(附名单)

11月15日&#xff0c;科睿唯安发布了2022年“高被引科学家”名单。该名单旨在遴选全球自然科学和社会科学领域最具影响力的研究人员。入选“高被引科学家”名单&#xff0c;意味着该学者在其所研究领域具有世界级影响力&#xff0c;其科研成果为该领域发展作出了较大贡献。 全球…

百度全景数据采集与分析

1、百度街景是什么 全景是通过将平面数字图像转换为三维空间&#xff0c;从而带来拟真交互体验的地图浏览方式。 全景技术通过专业相机将现实世界的空间场景捕捉下来&#xff0c;利用软件将多幅平面照片拼接合成&#xff0c;并模拟成三维空间的360度全景景观。全景具有真实感强…

127. 单词接龙

127. 单词接龙 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk&#xff1a; 每一对相邻的单词只差一个字母。对于 1 < i < k 时&#xff0c;每个 si 都在 wordList 中。注意&…

linux线程互斥锁

互斥量mutex 大部分情况&#xff0c;线程使用的数据都是局部变量&#xff0c;变量的地址空间在线程栈空间内&#xff0c;这种情况&#xff0c;变量归属单个线程&#xff0c;其他线程无法获得这种变量。 但有时候&#xff0c;很多变量都需要在线程间共享&#xff0c;这样的变量…

基于粒子群优化算法的冷热电联供型综合能源系统运行优化附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

JAVA图书管理练习

目录0.前言1.书类(BOOK)1.1 Book1.2 BookList2. User类2.1 user类2.2 AdminUser类2.3 NormalUser类3.Operation类3.1 添加图书3.2 删除图书3.3 查找图书3.4 展示图书3.5 退出系统3.6 借阅图书3.7 归还图书0.前言 1.在学习了面向对象,接口继承等语法后,综合使用这些语法完成一个…