本公众号由哥大,清华,复旦,中科大多名研究生共同创建,主要更新最新AI顶会快速解读和Pytorch编程,金融大数据与量化投资。如果你喜欢的话,请关注我们公众号,有学习资源放送,谢谢
本公众号由哥大,清华,复旦,中科大多名研究生共同创建,主要更新最新AI顶会快速解读和Pytorch编程,金融大数据与量化投资。如果你喜欢的话,请关注我们公众号,有学习资源放送,谢谢!
http://weixin.qq.com/r/Bik6IiTElnnprWBB93wU (二维码自动识别)
欢迎加微信号:uft-uft进群交流,记得备注知乎+所在学校或企业。
https://u.wechat.com/MK2C3qQoAkXkuiSqn2DomBc (二维码自动识别)
TCN是指时间卷积网络,一种新型的可以用来解决时间序列预测的算法。在上三次更新中已经做了初步介绍以及数据预处理部分的代码实现。
每天三分钟之Pytorch编程-5:RNN的新对手TCN(1)
每天三分钟之Pytorch编程-5:RNN的新对手TCN(2)
每天三分钟之Pytorch编程-5:RNN的新对手TCN(3)
论文名称:
An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling
作者:Shaojie Bai 1 J. Zico Kolter 2 Vladlen Koltun 3
1
模型展示
为了方便解读代码,先将模型的图片展示如下:
2
代码详解
下面是代码详解部分
实现因果卷积的类
残差模块
时间卷积网络的架构
TCN
具体代码
# 定义实现因果卷积的类(继承自类nn.Module)
class Chomp1d(nn.Module):
#继承自类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()
# tensor.contiguous()会返回有连续内存的相同张量
#有些tensor并不是占用一整块内存,而是由不同的数据块组成
#而tensor的view()操作依赖于内存是整块的,这时只需要执行
#contiguous()这个函数,就能把tensor变成在内存中连续分布的形式。
# 通过增加Padding方式对卷积后的张量做切片而实现因果卷积
# 残差模块,其中有两个一维卷积与恒等映射,具体结构可看图片
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))
#定义第一个扩散卷积层,扩散是指dilation=dilation
self.chomp1 = Chomp1d()
# 根据第一个卷积层的输出与padding大小实现因果卷积
self.relu1 = nn.ReLU()
self.dropout1 = nn.Dropout2d(dropout)
# 在先前的输出结果上添加激活函数与dropout完成第一个卷积
self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs,
kernel_size,
stride=stride,
padding=padding,
dilation=dilation))
self.chomp2 = Chomp1d(padding)
# padding保证了输入序列与输出序列的长度相等,
#但卷积前的通道数与卷积后的通道数不一定一样。
self.relu2 = nn.ReLU()
self.dropout2 = nn.Dropout2d(dropout)
#以上四行是与第一个卷积层堆叠了同样结构的第二个卷积层
http://self.net = nn.Sequential(self.conv1, self.chomp1,
self.relu1, self.dropout1,
self.conv2, self.chomp2,
self.relu2, self.dropout2)
# 将卷积模块的所有组建通过Sequential方法依次堆叠在一起
#具体来说的话网络结构是一层一层的叠加起来的,nn库里有一个类型:
#叫做Sequential序列,它是一个容器类,可以在里面添加一些基本的模块。
self.downsample=nn.Conv1d(n_inputs,n_outputs,1)if n_inputs!=n_outputs else None
self.relu = nn.ReLU()
self.init_weights()
#正如先前提到的卷积前与卷积后的通道数不一定相同
#所以如果通道数不一样,那么需要对输入x做一个逐元素的一维卷积
#以使得它的维度与前面两个卷积相等。
def init_weights(self):
self.conv1.weight.data.normal_(0, 0.01)
self.conv2.weight.data.normal_(0, 0.01)
#初始化方法是从均值为0,标准差为0.01的正态分布采样
if self.downsample is not None:
self.downsample.weight.data.normal_(0, 0.01)
def forward(self, x):
out = http://self.net(x)#输入的逐元素卷积与relu激活函数
res = x if self.downsample is None else self.downsample(x)
#残差模块
return self.relu(out + res)
# 定义时间卷积网络的架构
class TemporalConvNet(nn.Module):
def __init__(self, num_inputs, num_channels,
kernel_size=2, dropout=0.2):
super(TemporalConvNet, self).__init__()
layers = []
#num_channels为各层卷积运算的输出通道数或卷积核数量
#num_channels的长度即需要执行的卷积层数量
num_levels = len(num_channels)
# 扩张系数若能随着网络层级的增加而成指数增加,
#则可以增大感受野并不丢弃任何输入序列的元素
for i in range(num_levels):
dilation_size = 2 ** i
#dilation_size根据层级数指数增加
in_channels = num_inputs if i == 0 else num_channels[i – 1]
out_channels = num_channels[i]
#从num_channels中抽取每一个残差模块的输入通道数与输出通道数
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)
def forward(self, x):
return self.network(x)
class TCN(nn.Module):
def __init__(self, input_size, output_size, num_channels,
kernel_size=2, dropout=0.3, emb_dropout=0.1,
tied_weights=False):
super(TCN, self).__init__()
self.encoder = nn.Embedding(output_size, input_size)
#将one-hot encoding 部分送入编码器作为一个批量的词嵌入向量
#output_size为词汇量,input_size是词向量的长度
self.tcn = TemporalConvNet(input_size, num_channels,
kernel_size, dropout=dropout)
#时间卷积网络的架构
self.decoder = nn.Linear(num_channels[-1], output_size)
# 定义最后线性变换的维度,即最后一个卷积层的通道数到所有词汇的映射
if tied_weights:
if num_channels[-1] != input_size:
raise ValueError(‘When using the tied flag, nhid must be equal to emsize’)
self.decoder.weight = self.encoder.weight
print(“Weight tied”)
#是否共享编码器与解码器的权重,默认值为共享
#共享时需要保持隐藏单元数等于词嵌入的长度
#此时将预测的向量认为是词嵌入向量
self.drop = nn.Dropout(emb_dropout)
self.emb_dropout = emb_dropout
#对输入词嵌入进行dropout
self.init_weights()
def init_weights(self):
self.encoder.weight.data.normal_(0, 0.01)
self.decoder.bias.data.fill_(0)
self.decoder.weight.data.normal_(0, 0.01)
#进行初始化
def forward(self, input):
“””Input ought to have dimension (N, C_in, L_in),
where L_in is the seq_len; here the input is (N, L, C)”””
emb = self.drop(self.encoder(input))#编码并进行dropout
y = self.tcn(emb.transpose(1, 2)).transpose(1, 2)
#输入到网络进行推断
y = self.decoder(y)
#将推断结果解码为词
return y.contiguous()
往期文章精选
AI顶会论文快速解读|将金融领域中的CVaR作为目标策略来定制对话模型
AI顶会论文快速解读|上下文对比特征与门控多尺度聚合用于场景分割
AI顶会论文详细解读|对抗训练解决开放式生成式对话
AI顶会论文详细解读|深度强化学习之基于对话交互的学习对话
AI顶会论文快速解读|控制具体化程度的闲聊对话系统
精美PPT快速熟悉RNN与LSTM,附tensorflow教程代码(回复PPT有资源放送)
每天三分钟之Pytorch编程-1:为何选择你?
每天三分钟之Pytorch编程-2:一起来搭积木吧
每天三分钟之Pytorch编程-3:没事就来炼丹吧
每天三分钟之Pytorch编程-4:来搭建个翻译系统吧(1)
每天三分钟之Pytorch编程-4:来搭建个翻译系统吧(2)
每天三分钟之Pytorch编程-4:来搭建个翻译系统吧(3)
关注本公众号
http://weixin.qq.com/r/Bik6IiTElnnprWBB93wU (二维码自动识别)