当前位置: 首页 > news >正文

深度学习pytorch笔记:TCN

1 TCN

1.1 主要架构

  • 因果卷积
    • TCN使用因果卷积来确保在预测未来值时,只会使用当前和过去的信息,而不会出现信息泄露
  • 扩张卷积
    • 通过扩张卷积,TCN可以在不丢失时间分辨率的情况下增加感受野
    • 此时kernel size=2,dilation=[1,2,4,8]
    • 一般膨胀系数是kernel size的指数次方,即1,2,4,8,16,32…
  • 无偏移填充
    • 为了保持输出的时间长度与输入相同,TCN在卷积操作前使用了一种特殊的填充方式
      • 不仅如此,每一个隐层的输入输出的时间长度都相同

2 pytorch 实现

2.1 导入库

import torch
import torch.nn as nn
from torch.nn.utils import weight_norm

2.2 裁剪模块

如上图,把输出后的x5'和x6'裁剪掉

class Chomp1d(nn.Module):
    def __init__(self, chomp_size):
        super(Chomp1d, self).__init__()
        self.chomp_size = chomp_size

    def forward(self, x):
        return x[:, :, :-self.chomp_size].contiguous()

2.3 TemporalBlock

每一个TemporalBlock是由两个因果扩张卷积组成的

2.3.1 __init__

class TemporalBlock(nn.Module):
    def __init__(self, 
                n_inputs, 
                n_outputs, 
                kernel_size, 
                stride, 
                dilation, 
                padding, 
                dropout=0.2):

        super(TemporalBlock, self).__init__()
        

        #######################一个扩张因果卷积#####################
        self.conv1 = weight_norm(nn.Conv1d(n_inputs, 
                                            n_outputs, 
                                            kernel_size,
                                            stride=stride, 
                                            padding=padding, 
                                            dilation=dilation))
        #(Batch, output_channel, seq_len + padding)
        
        self.chomp1 = Chomp1d(padding)  # 裁剪掉多出来的padding部分,维持输出时间步为seq_len
        #(Batch, output_channel, seq_len)
        
        
        self.relu1 = nn.ReLU()
        self.dropout1 = nn.Dropout(dropout)

        #############################################################


        

        ####################这个Temporal Block中的另一个扩张因果卷积#################
        #和同一个Temporal Block的第一个扩张因果卷积唯一的区别是,他是n_outputs到n_outputs
        self.conv2 = weight_norm(nn.Conv1d(n_outputs, 
                                            n_outputs, 
                                            kernel_size,
                                            stride=stride, 
                                            padding=padding, 
                                            dilation=dilation))

        self.chomp2 = Chomp1d(padding)  

        self.relu2 = nn.ReLU()

        self.dropout2 = nn.Dropout(dropout)

        #############################################################

        self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,
                                 self.conv2, self.chomp2, self.relu2, self.dropout2)


        self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
        #一般TCN都需要输入和输出的通道数一样,如果不一样,需要downsampling以下

        self.relu = nn.ReLU()
        self.init_weights()

2.3.2  参数初始化

def init_weights(self):
        """
        参数初始化

        :return:
        """
        self.conv1.weight.data.normal_(0, 0.01)
        self.conv2.weight.data.normal_(0, 0.01)
        if self.downsample is not None:
            self.downsample.weight.data.normal_(0, 0.01)

2.3.3 forward

 def forward(self, x):
        #x: (Batch, input_channel, seq_len)
        out = self.net(x)


        res = x if self.downsample is None else self.downsample(x)


        return self.relu(out + res)
        #残差连接,防止层数过深之后的梯度消失

2.4  TCN整体

2.4.1 __init__

class TemporalConvNet(nn.Module):
    def __init__(self, 
                num_inputs, 
                num_channels, 
                kernel_size=2, 
                dropout=0.2):
        """
        num_channels: list,每层的hidden_channel数,例如[25,25,25,25]表示有4个隐层,每层hidden_channel数为25
        """

        super(TemporalConvNet, self).__init__()
        layers = []

        num_levels = len(num_channels)
        #需要多长层卷积单元(2.3的内容)

        for i in range(num_levels):
            dilation_size = 2 ** i   
            # 膨胀系数:1,2,4,8……
            #这可以保证没有历史时刻没被考虑到

            in_channels = num_inputs if i == 0 else num_channels[i-1]  
            # 确定每一层的输入通道数


            out_channels = num_channels[i]  
            # 确定每一层的输出通道数

            layers += [TemporalBlock(in_channels, 
                                    out_channels, 
                                    kernel_size, 
                                    stride=1, 
                                    dilation=dilation_size,
                                    padding=(kernel_size-1) * dilation_size,
                                    dropout=dropout)]

        self.network = nn.Sequential(*layers)

注:以下是个人观点:这边kernel_size=2(TCN的标准做法),所以此时dilation = 2**i还是dilation = kernel_size**i是无所谓的,但如果 kernel_size > 2,则可以改用 kernel_size**i 以进一步扩大感受野

2.4.2 forward

 def forward(self, x):
        """
        x: (Batch, input_channel, seq_len)
        :return: (Batch, output_channel, seq_len)
        """
        return self.network(x)

相关文章:

  • 从零开始使用 **Taki + Node.js** 实现动态网页转静态网站的完整代码方案
  • 谈谈 TypeScript 中的联合类型(union types)和交叉类型(intersection types),它们的应用场景是什么?
  • 代码随想录算法训练营第34天 | 62.不同路径 63. 不同路径 II 整数拆分 不同的二叉搜索树 (跳过)
  • linux(centos8)下编译ffmpeg
  • HCIA-PPP
  • 每天五分钟深度学习PyTorch:循环神经网络RNN的计算以及维度信息
  • 大数据 Spark 技术简介
  • TLSR8355F128芯片特色解析
  • Linux中的epoll简单使用案例
  • 视频转音频, 音频转文字
  • 通过socket实现文件上传和下载功能
  • 信息系统运行管理员教程5--信息系统数据资源维护
  • PAT甲级(Advanced Level) Practice 1023 Have Fun with Numbers
  • LeetCode 1005. K 次取反后最大化的数组和 java题解
  • C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷二)
  • SpringBoot3+Druid+MybatisPlus多数据源支持,通过@DS注解配置Service/Mapper/Entity使用什么数据源
  • Windows11 新机开荒(二)电脑优化设置
  • C++ 类和对象 友元 内部类 this指针 默认成员函数 初始化列表……
  • Pandas DataFrame:数据分析的利器
  • 14 结构体
  • 科技部等七部门:优先支持取得关键核心技术突破的科技型企业上市融资
  • 黄仕忠丨戏曲文献研究之回顾与展望
  • 人大新闻教育70年丨16759门课程里的时代密码
  • 贵州省总工会党组成员、副主席梁伟接受审查调查
  • 优秀“博主”在上海杨浦购房最高补贴200万元,有何条件?
  • 保利42.41亿元竞得上海杨浦东外滩一地块,成交楼面单价超8万元