PixelSNAIL论文代码学习(1)——总体框架和平移实现因果卷积

news2024/11/26 14:35:42

文章目录

    • 引言
    • 正文
      • 目录解析
      • README.md阅读
        • Setup配置
        • Training the model训练模型
        • Pretrained Model Check Point预训练的模型
        • 训练方法
      • train.py文件的阅读
      • model.py文件阅读
        • h12_noup_smallkey_spec模型定义
        • _base_noup_smallkey_spec模型实现
        • 一、定义因果卷积过程
          • 通过平移实现因果卷积的原理讲解
            • 一维向量实现因果卷积
            • 二维矩阵实现因果卷积
          • 平移实现因果卷积
          • nn.down_shifted_conv2d下卷积
            • 填充实现
          • 权重归一化二维卷积实现
            • 自定义实现权重归一化卷积层
            • 使用pytorch自带的权重归一化修饰器
          • nn.down_right_shifted_conv2d:右下移卷积
          • nn.down_shift:下移
          • nn.right_shift:右移
        • 二、门控残差网络
        • 三、因果自注意力机制实现
        • 四、使用pytorch实现
    • 总结

引言

  • 阅读了PixelSNAIL的相关论文,具体链接如下,论文学习链接
  • 这篇文章是一个自回归神经网络,将自注意力机制和因果卷积进行结合,我们在PixelCNN中学习过因果卷积的具体实现,并且结合了相关代码进行阅读,这里给出链接:
    • PixelCNN的论文和代码学习连接
  • PixelSNAIL的效果是远比PixelCNN的效果好的,而且,这里并不知道如何实现自注意力机制,所以需要好学习一下他的代码。
  • 很烦,之前弄得深度学习环境因为系统快照的问题,需要重新安装,所以在做这个代码分析之前,还是得重新安装对应的tensorflow深度学习环境。
  • 对应github项目的连接

正文

目录解析

  • data
    • cifar10_data.py 下载并加载相关的数据集
    • cifar10_plotdata.py 绘制对应的图片
    • imagenet_data.py 下载并加载相关的数据集
  • pixel_cnn_pp
    • linearize.py 优化tensorflow计算图的执行顺序
    • model.py 模型定义函数
    • nn.py 实现pixelCNN ++模型的实用函数和层,包括了自定义的损失函数
    • plotting.py 绘制训练图
  • train.py 训练以及测试文件

README.md阅读

Setup配置

  • 需要运行这个代码,需要具有如下的内容
    • 具有多个GPU的机器
    • python3以上的编译器
    • Numpy,TensorFlow

Training the model训练模型

  • 使用train.py脚本去训练模型

Pretrained Model Check Point预训练的模型

  • 直接在对应的连接上进行下载
    • CIFAR10 model
    • ImageNet model

训练方法

  • CIFAR-10的训练脚本
python train.py \
       --data_set=cifar \
       --model=h12_noup_smallkey \
       --nr_logistic_mix=10 \
       --nr_filters=256 \
       --batch_size=8 \
       --init_batch_size=8 \
       --dropout_p=0.5 \
       --polyak_decay=0.9995 \
       --save_interval=10
  • ImageNet的训练脚本
python train.py \
       --data_set=imagenet \
       --model=h12_noup_smallkey \
       --nr_logistic_mix=32 \
       --nr_filters=256 \
       --batch_size=8 \
       --init_batch_size=8 \
       --learning_rate=0.001 \
       --dropout_p=0.0 \
       --polyak_decay=0.9997 \
       --save_interval=1

train.py文件的阅读

  • 这个代码写的真的不敢苟同,所有的处理逻辑都放在一个train.p中,看起来很混乱。他的代码是tensorflow的,而且是1.0系列的代码,可读性并不是那么好,所以这里就不 投入太多关注了,仅仅阅读模型的生成部分。

  • 调用并生成模型的代码

    • 这里是调用了一个模型模板,传入了model文件,然后具体的模型名称是在训练脚本中指名的,是参数"model=h12_noup_smallkey"这个键值对
# 创建模型
model_opt = {'nr_resnet': args.nr_resnet, 'nr_filters': args.nr_filters,
             'nr_logistic_mix': args.nr_logistic_mix, 'resnet_nonlinearity': args.resnet_nonlinearity}
# 生成一个模型模板,模型可以多次重复使用,不需要重复创建变量
model = tf.make_template('model', getattr(pxpp_models, args.model + "_spec"))

# 用于依赖于数据的参数初始化
with tf.device('/gpu:0'):
  gen_par = model(x_init, h_init, init=True,
                  dropout_p=args.dropout_p, **model_opt)
  • 综上所述,所以具体使用的模型是"h12_noup_smallkey_spec"

model.py文件阅读

  • 鉴于上一个文件,这里直接从h12_noup_smallkey_spec这个函数开始看。

h12_noup_smallkey_spec模型定义

  • 定义h12_noup_smallkey_spec的代码:
    • functools.partial:用于固定某个函数的一些参数,然后生成一个新的函数
    • 实现:创建了一个h12_noup_smalleky_spec的函数,这个函数的逻辑和_base_noup_smallkey_spc的逻辑一样,但是参数attn_rep是固定的12
h12_noup_smallkey_spec = functools.partial(_base_noup_smallkey_spec, attn_rep=12)
h12_pool2_smallkey_spec = functools.partial(_base_noup_smallkey_spec, attn_rep=12, att_downsample=2)
h8_noup_smallkey_spec = functools.partial(_base_noup_smallkey_spec, attn_rep=8)
  • 所以,下一步,是仔细看_base_noup_smallkey_spec的具体实现逻辑。

_base_noup_smallkey_spec模型实现

  • 参照论文,我们看一下整个模型基本的定义图,具体如下,主要是两个模块,分别是

    • 门控残差网络的实现(左下角蓝色的模块)
    • 自注意力机制的实现(右下角蓝色的模块)
  • 具体执行逻辑如下图

    • 将图片进行2*2的因果卷积得到A
    • 重复执行一下模块M次
      • 将A重复执行4次门控残差模块得到B,两步执行
        • 步骤一:对B执行1*卷积,得到C
        • 步骤二:对B执行因果注意力模块,得到D
      • 将C和D进行拼接,程序例又执行了一次因果卷积,得到E,将E保存起来
      • 然后最终进行输出
        在这里插入图片描述
  • 下述为原程序代码

def h6_shift_spec(x, h=None, init=False, ema=None, dropout_p=0.5, nr_resnet=5, nr_filters=160, nr_logistic_mix=10, resnet_nonlinearity='concat_elu'):
    """
    We receive a Tensor x of shape (N,H,W,D1) (e.g. (12,32,32,3)) and produce
    a Tensor x_out of shape (N,H,W,D2) (e.g. (12,32,32,100)), where each fiber
    of the x_out tensor describes the predictive distribution for the RGB at
    that position.
    'h' is an optional N x K matrix of values to condition our generative model on
    """

    counters = {}
    with arg_scope([nn.conv2d, nn.deconv2d, nn.gated_resnet, nn.dense, nn.nin, nn.mem_saving_causal_shift_nin], counters=counters, init=init, ema=ema, dropout_p=dropout_p):

        # parse resnet nonlinearity argument
        if resnet_nonlinearity == 'concat_elu':
            resnet_nonlinearity = nn.concat_elu
        elif resnet_nonlinearity == 'elu':
            resnet_nonlinearity = tf.nn.elu
        elif resnet_nonlinearity == 'relu':
            resnet_nonlinearity = tf.nn.relu
        else:
            raise('resnet nonlinearity ' +
                  resnet_nonlinearity + ' is not supported')

        with arg_scope([nn.gated_resnet], nonlinearity=resnet_nonlinearity, h=h):

            # // up pass through pixelCNN 
            xs = nn.int_shape(x)
            background = tf.concat(
                    [
                        ((tf.range(xs[1], dtype=tf.float32) - xs[1] / 2) / xs[1])[None, :, None, None] + 0. * x,
                        ((tf.range(xs[2], dtype=tf.float32) - xs[2] / 2) / xs[2])[None, None, :, None] + 0. * x,
                    ],
                    axis=3
                    )
            # add channel of ones to distinguish image from padding later on
            x_pad = tf.concat([x, tf.ones(xs[:-1] + [1])], 3)
            ul_list = [nn.causal_shift_nin(x_pad, nr_filters)]  # stream for up and to the left

            for attn_rep in range(6):
                for rep in range(nr_resnet):
                    ul_list.append(nn.gated_resnet(
                        ul_list[-1], conv=nn.mem_saving_causal_shift_nin))

                ul = ul_list[-1]

                hiers = [1, ]
                hier = hiers[attn_rep % len(hiers)]
                raw_content = tf.concat([x, ul, background], axis=3)
                key, mixin = tf.split(nn.nin(nn.gated_resnet(raw_content, conv=nn.nin), nr_filters * 2 // 2), 2, axis=3)
                raw_q = tf.concat([ul, background], axis=3)
                if hier != 1:
                    raw_q = raw_q[:, ::hier, ::hier, :]
                query = nn.nin(nn.gated_resnet(raw_q, conv=nn.nin), nr_filters // 2)
                if hier != 1:
                    key = tf.nn.pool(key, [hier, hier], "AVG", "SAME", strides=[hier, hier])
                    mixin = tf.nn.pool(mixin, [hier, hier], "AVG", "SAME", strides=[hier, hier])
                mixed = nn.causal_attention(key, mixin, query, causal_unit=1 if hier == 1 else xs[2] // hier)

                if hier != 1:
                    mixed = tf.depth_to_space(tf.tile(mixed, [1, 1, 1, hier * hier]), hier)

                ul_list.append(nn.gated_resnet(ul, mixed, conv=nn.nin))


            x_out = nn.nin(tf.nn.elu(ul_list[-1]), 10 * nr_logistic_mix)

            return x_out
  • 函数参数说明

    • x:输入张量,形状为(N,H,W,D1),N为batch_size,H,W为图像的高和宽,D1为图像的通道数
    • h:可选的N x K矩阵,用于在生成模型上进行条件,默认是不使用的。
    • init:是否初始化,默认不进行初始化
    • ema:是否使用指数移动平均,默认不进行指数平均
    • dropout_p:dropout概率,默认为0.5
    • nr_resnet:残差网络的数量,默认为5
    • nr_filters:卷积核的数量,默认为256
    • attn_rep:注意力机制的重复次数,默认重复12次
    • nr_logistic_mix:logistic混合的数量,默认混合采样10次
    • att_downsample:注意力机制的下采样,默认下采样一次
    • resnet_nonlinearity:残差网络的非线性激活函数,默认使用“concat_elu”
  • 下述将根据代码和流程图,列出因果卷积、门控残差网络和因果注意力模块的具体实现

一、定义因果卷积过程

  • 这里因果卷积的定义方式和PixelCNN不一样,他是定义掩码,这里是定义了四种不同的卷积方式来实现因果卷积的,分别是,这个过程复杂的很。

    • nn.down_shifted_conv2d:下移卷积:
    • nn.down_right_shifted_conv2d:右下移卷积
    • nn.down_shift:下移
    • nn.right_shift:右移
  • 在二维因果卷积过程中,要确保每一个输出像素仅受其左侧和上方元素的影响,通常经过一下几种方式实现

    • 零填充:卷积之前,将输入矩阵的周围填充零,卷积操作从图像边缘开始,不会看到未来消息。
    • 平移:在卷积之后,输出矩阵通常会沿着某个方向进行平移,确保因果性。这个平移是需要将原来移空的位置设置为0.
  • 在作者的代码通过了两个方法来确保每一个像素点只能获得上面和左边的信息。

    • 对矩阵的上面进行padding,然后再将,矩阵下移,来确保每一个元素只能获得上边的元素信息
    • 对矩阵的左面进行padding,然后再将矩阵右移,来确保每一个元素只能获得左边的元素信息
  • 通过上述两个方法的结合,确保元素只能获得左上部的未来信息。

通过平移实现因果卷积的原理讲解
一维向量实现因果卷积
  • 一维输入序列 x = [ x 0 , x 1 , . . . , x n − 1 ] x = [x_0,x_1,...,x_{n-1}] x=[x0,x1,...,xn1]

  • 一维卷积核 h = [ h 0 , h 1 , . . . . , h m − 1 ] h = [h _0,h_1,....,h_{m-1}] h=[h0,h1,....,hm1]

  • 因果卷积的输出 y y y定义如下, y t = ∑ i = 0 m − 1 h i x t − i               t > = i y_t = \sum_{i = 0}^{m-1} h_i x_{t-i} \ \ \ \ \ \ \ \ \ \ \ \ \ t >= i yt=i=0m1hixti             t>=i

  • 具体样例如下

    • 一维输入序列 x = [ x 0 , x 1 , x 2 , x 3 , x 4 ] x = [x_0,x_1,x_2,x_3,x_4] x=[x0,x1,x2,x3,x4]
    • 一维卷积核 h = [ h 2 , h 1 , h 1 ] h = [h _2,h_1,h_1] h=[h2,h1,h1]
    • 这个在卷积过程中,完全是按他的公式进行卷积的

在这里插入图片描述

二维矩阵实现因果卷积
  • 二维卷积:因果性意味着输出矩阵中每一个元素只能依赖于其上方和左方的输入元素,通过pading和平移实现。

*

  • 就是通过填充和平移来实现。
平移实现因果卷积
nn.down_shifted_conv2d下卷积
  • 这里使用了自定义的Conv2d卷积,还有填充模式,这里逐个进行分析
填充实现
def down_shifted_conv2d(x, num_filters, filter_size=[2, 3], stride=[1, 1], **kwargs):
    # 这里是对数据进行填充,总共有四个维度,分别是N,H,W,C
    # 第一个维度不进行填充,他是batch_size
    # 第二个维度H进行填充,开始的地方填充的大小是filter_size[0] - 1,结束的地方填充的大小是0,也就是仅仅扩充上部分
    # 第三个宽度是W进行填充,开始的地方填充的大小是int((filter_size[1] - 1) / 2),结束的地方填充的大小是int((filter_size[1] - 1) / 2),也就是仅仅扩充左右两边
    # 第四个维度不进行填充,他是channel
    x = tf.pad(x, [[0, 0], [filter_size[0] - 1, 0], [int((filter_size[1] - 1) / 2), int((filter_size[1] - 1) / 2)], [0, 0]])
    # 
    return conv2d(x, num_filters, filter_size=filter_size, pad='VALID', stride=stride, **kwargs)
  • 假设原始输入的矩阵是68的,卷积核的大小是34,原矩阵、填充之后的矩阵和卷积之后的单个矩阵,效果如下
    • 原矩阵,6*8
      在这里插入图片描述
    • 填充之后的矩阵8*10在这里插入图片描述
    • 卷积之后的矩阵6*7
      在这里插入图片描述
  • 这里对于生成的序列在于需要将生成之后的矩阵和原来的矩阵进行对齐,然后按照位置进行比对的,这里有个样例将很好。具体截图如下。
    • 上面一行是卷积之后的输出,下面一行是原始的数据集
    • 左图是正确的,timeB的时间序列仅仅获取timeA和timeB的序列,但是右图就获取了timeC未来序列的数据,所以左图是符合因果卷积的效果的。

在这里插入图片描述

权重归一化二维卷积实现
  • 这里作者自己定义了一个带有权重归一化的二维卷积层,因为正常卷积并不包含权重归一化的效果。

  • 带权重归一化的二维卷积层的优势:

    • 训练稳定:权重归一化之后,模型的训练更加稳定
    • 快速收敛:权重归一化能够加速模型收敛
    • 改进泛化:在特定的任务中,权重归一化有注意模型泛化
  • 正常二维卷积的优势:

    • 效率更高操作简单广泛应用
  • 缩放因子 g g g和偏置权重 b b b的作用:

    • 缩放因子 g g g:
      • 使用广播机制,将放缩因子与权重矩阵中的每一个数字按位相乘 S c a l e d   W e i g h t = g × N o r m a l i z e d   W e i g h t Scaled \ Weight = g \times Normalized \ Weight Scaled Weight=g×Normalized Weight

      • 主要是权重归一化之后,所有权重的范围 都是单位范围内,加上缩放因子能够适应更多范数。

      • 注意,权重归一化,是在输出通道上进行操作的

    • 偏置权重 b b b
      • 是在卷积结果之后,加上偏置,让模型输出一个非零的值
      • 具体公式如下 O u t p u t = C o n v 2 D ( x , S c a l e d   W e i g h t ) + b Output = Conv2D(x,Scaled \ Weight) + b Output=Conv2D(x,Scaled Weight)+b
  • 这里我进行了两种实现方法,一种是通过pytorch自定义权重归一化卷积层,还有一种是通过pytorch内置的权重归一化装饰器实现类似的功能。

自定义实现权重归一化卷积层
  • 这里需要继承nn.Moudle模块,自己定义forward模块实现相关功能
  • 需要实现的基本步骤:
    • 基本的init初始化函数
    • forward前向传播函数自定义
    • 计算缩放因子和偏置初值的函数,具体计算公式如下
      在这里插入图片描述
# 权重归一化卷积层
class WeightNormConv2d(nn.Module):
    def __init__(self, in_channels, out_channels,
                 kernel_size, stride=1, padding=0, 
                 nonlinearity=None, init_scale=1.):
        super(WeightNormConv2d, self).__init__()
        
        # 指定非线性激活函数
        self.nonlinearity = nonlinearity
        self.init_scale = init_scale
        
        # 定义卷积层
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)
        
        # 定义缩放因子g和偏置b
        # 将g和b声明为需要优化的参数,卷积层默认的权重是(C-out,C-in,H,W)这四个维度
        self.g = nn.Parameter(torch.ones(out_channels, 1, 1, 1))
        self.b = nn.Parameter(torch.zeros(out_channels))
 
        # 声明初始化参数
        self.reset_parameters()

    
    # 数据依赖的参数初始化
    def reset_parameters(self):
        # 初始化权重为正太分布
        init.normal_(self.conv.weight, mean=0, std=0.05)
        
        # 初始化偏置为0
        init.zeros_(self.conv.bias)
        
        # 使用一次随机输入,进行一次前向传播,以计算初始的g和b
        with torch.no_grad():
            x_init = F.conv2d(torch.randn(1, *self.conv.weight.shape[1:]), 
                              self.conv.weight)
            m_init, v_init = x_init.mean(), x_init.var()
            
            # 计算缩放因子
            scale_init = self.init_scale / torch.sqrt(v_init + 1e-8)
            self.g.data.fill_(scale_init)
            
            # 计算偏置
            # 将张量所有的元素都设定为特定的元素
            # data属性仅仅是修改对应的值,但是不会计入梯度的改变
            self.b.data.fill_(-m_init * scale_init)


    def forward(self, x):
        
        # 应用权重归一化
        W = self.conv.weight * (self.g / torch.sqrt((self.conv.weight ** 2).sum([1, 2, 3], keepdim=True)))
     
        # 执行卷积操作
        x = F.conv2d(x, W, self.b, self.conv.stride, self.conv.padding)
        
        # 应用非线性激活
        if self.nonlinearity is not None:
            x = self.nonlinearity(x)
            
        return x
    

# 测试函数
conv_layer = WeightNormConv2d(3, 16, [3, 3], stride=1, nonlinearity=F.relu)
x = torch.randn(8, 3, 64, 64)  # NCHW格式
out = conv_layer(x)
print(out.shape)
使用pytorch自带的权重归一化修饰器
  • 直接调用nn.utils中的weight.norm组件,包括原来的卷积层即可,具体如下
# 使用pytorch自定义的权重归一化层
import torch
from torch import nn
from torch.nn.utils import weight_norm

# 创建一个标准的 Conv2d 层
conv_layer = nn.Conv2d(3, 16, 3, 1)

# 应用权重归一化
conv_layer = weight_norm(conv_layer)

# 测试该层
x = torch.randn(8, 3, 64, 64)  # 输入张量,形状为 [batch_size, channels, height, width]
out = conv_layer(x)

print(out.shape)  # 输出张量的形状应为 [8, 16, 62, 62]
nn.down_right_shifted_conv2d:右下移卷积
  • 这个和上一个方式基本上都是相同的,只不过对于W和这个维度而言,仅仅是填充了左边,并没有填充右边。就是在原来的代码上进行修改,同时填充的数量也不一样。具体不再讲解
@add_arg_scope
def down_right_shifted_conv2d(x, num_filters, filter_size=[2, 2], stride=[1, 1], **kwargs):
    x = tf.pad(x, [[0, 0], [filter_size[0] - 1, 0],
                   [filter_size[1] - 1, 0], [0, 0]])
    return conv2d(x, num_filters, filter_size=filter_size, pad='VALID', stride=stride, **kwargs)
nn.down_shift:下移
  • 使用原始数据的一部分用零来替代,确保最终生成的数据是。将原始的张量往下移动n行,然后前n行全部替换成0

在这里插入图片描述

nn.right_shift:右移
  • 具体实现和上面相同,仅仅是在矩阵的作伴部分进行添加,然后返回最终的矩阵
def right_shift(x, step=1):
    xs = int_shape(x)
    return tf.cobncat([tf.zeros([xs[0], xs[1], step, xs[3]]), x[:, :, :xs[2] - step, :]], 2)

二、门控残差网络

  • 由于篇幅有限,这里具体看这篇文章和博客
    • 门控残差网络的具体实现

三、因果自注意力机制实现

  • 看对应文章的链接
    • 因果自注意力机制实现

四、使用pytorch实现

  • 之前每一个章节都有pytorch实现的版本,这里将对所有的内容进行汇总,使用pytorch对pixelSNAIL模型进行重构,具体代码如下
# 实现最终的模型
class PixelSNAIL(nn.Module):
    '''
    pixelSNAIL模型
    '''
    
    def __init__(self,nr_resnet=5, nr_filters=32, attn_rep=12, nr_logistic_mix=10, att_downsample=1):
        super(PixelSNAIL,self).__init__()
        
        # 声明类成员
        self.nr_resnet = nr_resnet
        self.nr_filters = nr_filters
        self.attn_rep = attn_rep
        self.nr_logistic_mix = nr_logistic_mix
        self.att_downsample = att_downsample
        
        # 声明定义模型对象
        # 声明因果卷积的网络
        self.down_shifted_conv2d = weight_norm(nn.Conv2d(3, self.nr_filters, kernel_size=(1, 3)))
        self.down_right_shifted_conv2d = weight_norm(nn.Conv2d(3, self.nr_filters, kernel_size=(2, 1)))
        
        # 声明包含若干门控残差网络的modulelist
        self.gated_resnets = nn.ModuleList([GatedResNet(self.nr_filters) for _ in range(self.nr_resnet)])
        
        # 声明线性模型
        self.nin1 = nn.Linear(self.nr_filters, self.nr_filters // 2 + 16)  # 假设q_size = 16
        self.nin2 = nn.Linear(self.nr_filters, 16)  # 假设q_size = 16
        
        # 声明因果注意力模块
        self.causal_attentions = nn.ModuleList([CausalAttention() for _ in range(self.attn_rep)])
        
        # 最终的卷积网络
        self.final_conv = nn.Conv2d(self.nr_filters, 10 * self.nr_logistic_mix, kernel_size=1)
    
    
    def forward(self, x):
        ul_list = []
        
        # 加上一个是四个
        
        # 按照左右上下的方式进行填充
        down_shifted = F.pad(x, (1, 1, 0, 0))  # 自定义下移和右移操作
        right_shifted = F.pad(x, (0, 0, 1, 0))
        
        
        # 因果卷积
        ds_conv = self.down_shifted_conv2d(down_shifted)
        drs_conv = self.down_right_shifted_conv2d(right_shifted)
        
        ul = ds_conv + drs_conv
        ul_list.append(ul)
        
        # 下采样,从右下角开始
        for causal_attention in self.causal_attentions:
            for gated_resnet in self.gated_resnets:
                ul = gated_resnet(ul)
                ul_list.append(ul)
            
            print('attention module')
            # 注意力机制
            last_ul = ul_list[-1]
            
            # 准备原始内容
            raw_content = torch.cat([x, last_ul], dim=1)  # 假设背景信息已经添加到x中
            
            # 生成key和value
            print(raw_content.shape)
            raw = self.nin1(raw_content)
            print('raw data shape',raw.shape)
            key, mixin = raw.split(18, dim=1)  # 假设q_size = 16
            
            # 生成query查询键
            raw_q = last_ul
            query = self.nin2(raw_q)
            
            # 计算注意力
            print(mixin.shape)
            print(query.shape)
            mixed = causal_attention(key, mixin, query)
            
            ul_list.append(mixed)
        
        x_out = F.elu(ul_list[-1])
        x_out = self.final_conv(x_out)
        
        return x_out
        
x = torch.randn(64,3,32,32)
model = PixelSNAIL()
x_out = model(x)
print(x_out.shape)
  • 这个代码多多少少有一点问题, 但是我并不想在投入时间了,因为我感觉我已经滞后了很多,有点慌张,这个模型完整的都已经知道了,具体的实现细节。pytorch的大概实现逻辑也给了,后续有空了,可以继续调整。

总结

  • 激活函数,可以试一下concat_elu,能够识别更加复杂的特征。
  • 这个PixelSNAIL用了差不多一周看完,虽然没有跑起来,没有调试,但是大部分代码自己都进行了重构,学到了很多。
  • 以后在处理序列数据,可以使用因果注意力机制,而不仅仅是使用因果卷积。除此之外,对于query、key和value的生成理解还有一些问题,总是觉得怪怪的,门控残差进行卷积一定次数之后,设定特定的filter_num,直接输出,直接进行拆分,就可以获得key和value,然后在点乘,我想知道这个操作是怎么想出来的。
  • 我想将我所有的代码都放到我的github上,现在还缺数据加载和最终生成模型的评价指标,下一步还是回归我们的那个基础的模型,然后将之模块化,主要是为了适应以后的模块替换。

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

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

相关文章

PCIe DL_Feature详解

DL_Feature的引入 Data Link Control and Management State Machine在PCIe Gen4引入了DL_Feature这个状态,该状态主要用来协商PCIe link 两端是否支持新的DL Feature,目前为止DL Feature只引入了Scaled Flow Control 来提高Gen4及以上的效率。   DL_Fe…

Qt 简单闹钟

//wiget.h#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime> //时间类 #include <QTimer> //定时器类 #include <QTextToSpeech> #include <QDebug> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPA…

YoloV8改进策略:轻量级Slim Neck打造极致的YoloV8

文章目录 摘要Yolov8官方结果源码改进方法测试结果总结摘要 论文链接:https://arxiv.org/ftp/arxiv/papers/2206/2206.02424.pdf 作者研究了增强 CNN 学习能力的通用方法,例如 DensNet、VoVNet 和 CSPNet,然后根据这些方法的理论设计了 Slim-Neck 结构。 使用轻量级卷积…

机械制图(CAD)

目录 第一课&#xff08;80分钟&#xff09; 第二课&#xff08;80分钟&#xff09; 力啥学机械制图&#xff1f;我们的工厂要加工机械&#xff0c;而加工机械零件前&#xff0c;我们要先给工人图纸来看,工人才知道该怎样加工&#xff0c;所以我们今天就来学习下怎样画出符何…

任意文件读取和漏洞复现

任意文件读取 1. 概述 一些网站的需求&#xff0c;可能会提供文件查看与下载的功能。如果对用户查看或下载的文件没有限制或者限制绕过&#xff0c;就可以查看或下载任意文件。这些文件可以是漂代码文件&#xff0c;配置文件&#xff0c;敏感文件等等。 任意文件读取会造成&…

电脑开机操作系统引导过程

电脑开机时操作系统引导&#xff1a; CPU首先执行主存中ROM中的引导程序。 将磁盘的第一块——主引导记录(MBR)读入到内存中&#xff0c;执行磁盘引导程序&#xff0c;扫描分区表。 在主分区(C盘)执行分区引导程序。 在C盘根目录下找到完整的操作系统初始化程序并执行。

系统虚拟机(VM)

系统虚拟机&#xff1a;将一台物理机器虚拟化为多台虚拟机&#xff0c;每个虚拟机上都可以运行一个独立的操作系统&#xff0c;由虚拟机管理程序(VMM)来管理。 第一种直接运行在硬件上&#xff0c;可以直接分配物理资源&#xff0c;性能更好&#xff0c;可支持更多的虚拟机&am…

ModaHub魔搭社区专访百度智能云李莅:企业需要的是一款企业级向量数据库还是向量引擎?

ModaHub魔搭社区&#xff1a;虽然您认为它是刚需&#xff0c;但也有人认为我可能不是需要一款企业级的向量数据库&#xff0c;而是需要一个向量引擎。我可以在传统的数据库上加一个向量引擎&#xff0c;然后它就变成了一款向量数据库&#xff0c;您觉得他们这样的想法是可行的吗…

布隆过滤器Moudule安装

Redis帮我们实现了布隆过滤器算法&#xff0c;可以通过module方式安装&#xff0c;直接使用&#xff0c;其实可以自己实现这样的算法。 安装遇到的问题&#xff0c;通过官网下载的zip或者git下载的源码&#xff0c;都是master版本&#xff0c;make会出问题&#xff0c;报错文件…

springboot初试elasticsearch

引入依赖 elasticsearch的依赖版本与你elasticsearch要一致 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency> 索引库的操作 创建索引库 impo…

stack和queue容器

1 stack 基本概念 概念&#xff1a;stack是一种先进后出(First In Last Out,FILO)的数据结构&#xff0c;它只有一个出口 栈中只有顶端的元素才可以被外界使用&#xff0c;因此栈不允许有遍历行为 栈中进入数据称为 — 入栈 push 栈中弹出数据称为 — 出栈 pop 2 stack 常用…

Linux——进程间信号(超级详解!!)

索引 一.初始信号1.什么是信号2.前后台进程3.信号的种类4.信号的管理 二.信号产生前1.验证键盘是可以产生信号的2.通过系统调用接口发送信号3.由软件条件产生信号4.硬件异常产生信号5.总结6.core dump 信号产生中1.信号在内核中的表示2.信号集操作函数 信号产生后1.了解内核态和…

Java Web3J :使用web3j监听、查询、订阅智能合约的事件

前面有文章写如何使用Docker-compose方式部署blockscout浏览器+charts图表,区块链浏览器已经部署成功了,同时我们在链上增加了治理投票流程,如何实时的把治理事件快速同步到浏览器呢?这时就想到了Web3J来监听智能合约的事件,来达到同步事件的效果 目录 Web3J简介功能简介m…

lv3 嵌入式开发-4 linux shell命令(进程管理、用户管理)

目录 1 进程处理相关命令 1.1 进程的概念 1.2 查看进程的命令 1.3 发送信号命令 2 用户管理相关命令 2.1 用户管理相关文件介绍 2.2 用户管理相关命令介绍 1 进程处理相关命令 1.1 进程的概念 进程的概念主要有两点&#xff1a; 进程是一个实体。每一个进程都有它自己…

【计算机组成原理】第一章 计算机概述

1.冯诺依曼结构&#xff1a; 计算机由运算器、控制器、存储器、输入设备、输出设备五大部件组成 运算器和控制器称为CPU&#xff1b;CPU和存储器称为计算机主机&#xff1b;其余输入、输出设备、外存储器称为计算机外部设备采用二进制表示数据和指令 指令由操作码&#xff08;…

20230831-完成登录框的按钮操作,并在登录成功后进行界面跳转

登录框的按钮操作&#xff0c;并在登录成功后进行界面跳转 app.cpp #include "app.h" #include <cstdio> #include <QDebug> #include <QLineEdit> #include <QLabel> #include <QPainter> #include <QString> #include <Q…

golang 通用的 grpc http 基础开发框架

go-moda golang 通用的 grpc http 基础开发框架仓库地址: https://github.com/webws/go-moda仓库一直在更新,欢迎大家吐槽和指点 特性 transport: 集成 http&#xff08;echo、gin&#xff09;和 grpc。tracing: openTelemetry 实现微务链路追踪pprof: 分析性能config: 通用…

CDN+GitHub搭建图床

前期搭建博客的时候&#xff0c;老是遇到图片无法加载、加载出错等等问题&#xff0c;很是烦恼。于是想搭建一个图床&#xff0c;进行个人博客图片的存储、显示使用。 ​ 利用GitHubjsDelivrPicGo搭建免费图床&#xff0c;CDN图床就是这么朴实无华&#xff0c;是基于免费CDN与免…

l8-d4 IP地址与端口号

一、分类IP 1.IP 地址及其表示方法 例&#xff1a; 2.IP 地址采用 2 级结构 3.分类的 IP 地址 任意一个IP地址我们都可以迅速的得出类别&#xff0c;并计算得出网络号 当一个主机通过两个网卡同时连接到两网络时&#xff0c;也就是该主机同时拥有两个IP地址&#xff0c;该主机…

【Java】网络通信基础

网络通信基础 IP地址概念格式特殊IP 端口号概念格式注意事项 认识协议概念作用知名协议的默认端口五元组协议分层OSI七层模型TCP/IP五层(或四层)模型网络设备所在分层网络分层对应封装和分用 IP地址 概念 IP地址主要用于标识网络主机、其他网络设备&#xff08;如路由器&…