一维卷积
torch.nn.Conv1d
(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=’zeros’)
这个函数用来对输入张量做一维卷积
- in_channel和out_channel是卷积核个数
- kernel_size是卷积核的大小
- stride是卷积核移动步长, padding是否对输入张量补0
现在我有一个音频的梅尔频谱数据输入,一个batch为十张频谱, 一张频谱大小为129帧, 频率幅度为128,这个张量表示为(10, 128, 129),
1 | import torch.nn as nn |
可以看出来上面这个函数只在频谱的时域上进行一维卷积,卷积核大小为4帧,在频域上没有卷积.为什么输出是130,反而多了一帧呢?
这是因为这个一维卷积函数
- Input(batch_size, Channel_input, length_input)
- Output(batch_size, Channel_output, length_output)
$L_{out}=\lfloor\frac{L_{in}+2\times padding-dilation\times(kernel_size-1)-1}{stride}+1\rfloor=\frac{129+2\times2-1\times(4-1)-1}1+1=130$
RNN
结构
函数
torch.nn.RNN
(args, kwargs*)
这个函数对输入的的sequence施加一个带tanh或者Relu的RNN.对输入的sequence每一个元素,每一层都施加如下计算:
- $h_t=tanh(W_{hi}xt+b_{hi}+W_{hh}h_{t-1}+b_{hh})$
$h_t$是t时刻的隐层状态,$x_t$是t时刻的输入,$h_{t-1}$是t-1时刻的隐层状态或者是0时刻的隐层状态.
参数:
- input_size:输入x的维度
- hidden_size:隐层状态h的维度
- numpy_layers:循环层的数目
- nonlinearity: 非线性变换,可以使tanh或者relu, 默认是tanh
- bias:如果是False,不使用$b_{hi}$和$b_{hh}$,默认为True
- batch_first: 如果是True,输入和输出张量的形状是{batch,seq,feature}
- bidirectional: 如果是True,那么是一个双向RNN
输入:input和h_0
- input的形状是{seq_len,batch,input_size},我看大家一般喜欢用{batch,seq_len,input_size}一些
- h_0的形状是(num_layers*num_birections,batch,hidden_size),对batch中每一个元素的初始隐层状态
输出:output,h_n
- output的形状是(seq_len,batch,num_directions*hidden_size),最后一个RNN层的输出特征(h_t)
- h_n的形状是(num_layers*num_birections,batch,hidden_size),t=seq_len时刻的隐层状态
Note:h_n和output的关系:output包括了seq_len中每一个时间点的隐层状态,而h_n是第seq_len时刻的隐层状态,所以output中最后一个元素就是h_n,即output[-1] ==h_n.
范例代码
下面是一个pytorch中使用RNN通过Sin来预测Cos
1 | import torch |
训练到460epoch, loss0.000313,可以看到已经完全拟合了
LSTM
结构
函数
torch.nn.LSTM
(args, kwargs*)
这个函数对输入的sequence施加一个多层的长短周期记忆RNN.对输入的sequence的每一个元素,每一层都施加如下计算.
- $f_t=\sigma(W_{fi}\;x_t+b_{fi}+W_{fh}h_{t-1}+b_{fh})$
- $i_t=\sigma(W_{ii}\;x_t+b_{ii}+W_{ih}h_{t-1}+b_{if})$
- $g_t=\tan h(W_{gi}\;x_t+b_{gi}+W_{gh}h_{t-1}+b_{gh})$
- $o_t=\sigma(W_{oi}\;x_t+b_{oi}+W_{oh}h_{t-1}+b_{oh})$
- $c_t=f_t\ast c_{t-1}+i_t\ast g_t$
- $h_t=\tan h(c_t)\ast o_t$
$h_t$是t时刻的隐层状态,$c_t$是t时刻的细胞状态,$x_t$是t时刻的输入,$h_{t-1}$是t-1时刻的隐层状态或者是0时刻的隐层状态.$i_t$,$f_t$,$g_t$,$o_t$是输入门,忘记门,细胞门,输出门.$\sigma$是sigmoid函数,*是元素乘积
LSTM函数的参数和RNN都是一致的,区别在于输入输出不同,从上面的简图可以看出,LSTM多了一个细胞的状态,所以每一个循环层都增加了一个细胞状态的输出.
输入:input,(h_0,c_0)
input的形状和RNN的一样,都是(seq_len,betch,input_size)
h_0:(num_layers*numpy_directions,batch,hidden_size),对batch中每一个元素的初始隐层状态
c_0:(num_layers*numpy_directions,batch,hidden_size),对batch中的每一个元素的初始细胞状态
输出:output,(h_n,c_n)
output的形状和RNN一样,都是(seq_len,batch,num_directions*hidden_size),最后一个LSTM层的输出特征(h_t)
h_n:(num_layers*numpy_directions,batch,hidden_size),t=seq_len时刻的隐层状态
c_n:(num_layers*numpy_directions,batch,hidden_size),t=seq_len时刻的细胞状态
范例代码
还是使用LSTM通过Sin来预测Cos
1 | import torch |
训练到1980epoch, loss0.000004,可以看到已经完全拟合了.