本文中的RNN泛指LSTM,GRU等等
CNN和RNN中batch_size的默认位置是不同的。
position 0
.position 1
.对于最简单的RNN,我们可以使用两种方式来调用 torch.nn.RNNCell()。
它只接受序列中的单步输入,必须显式的传入隐藏状态。torch.nn.RNN()
可以接受一个序列的输入,默认会传入一个全0的隐藏状态,也可以自己申明隐藏状态传入。
[seq_len,batch_size,input_dim]
input_dim
是输入的维度,比如是128。
batch_size
是一次往RNN
输入句子的数目,比如是5
。seq_len
是一个句子的最大长度,比如15。
所以千万注意,RNN
输入的是序列,一次把批次的所有句子都输入了,得到的ouptut
和hidden
都是这个批次的所有的输出和隐藏状态,维度也是三维。
可以理解为现在一共有batch_size
个独立的RNN
组件,RNN
的输入维度是input_dim
,总共输入seq_len
个时间步,则每个时间步输入到这个整个RNN
模块的维度是[batch_size,input_dim]
# 构造RNN网络,x的维度5 (embedding_size or input_dim),
# 隐层的维度10 (hidden_size or output_dim), 网络的层数2
rnn_seq = nn.RNN(5, 10, 2)
# 构造一个输入序列,句长为 6,batch 是 3, 每个单词使用长度是 5的向量表示
x = torch.randn(6, 3, 5)
# out, ht = rnn_seq(x, h0)
out, ht = rnn_seq(x) #h0可以指定或者不指定
问题1:这里out
、ht
的size是多少呢?
回答:out
:6 * 3 * 10, ht
: 2 * 3 * 10,out
的输出维度[seq_len,batch_size,output_dim]
,ht的维度[num_layers * num_directions, batch_size, hidden_size]
,如果是单向单层的RNN那么一个句子只有一个hidden,即,ht的维度为[batch_size, hidden_size]
。
问题2:out[-1]
和ht[-1]
是否相等?
回答:相等,每个时间步的输出其实就是那个时间步在网络最后一层的隐藏单元。
RNN
的其他参数RNN(input_dim ,hidden_dim ,num_layers ,…)
– input_dim 表示输入的特征维度
– hidden_dim 表示输出的特征维度,如果没有特殊变化,相当于out
– num_layers 表示网络的层数
– nonlinearity 表示选用的非线性激活函数,默认是 ‘tanh’
– bias 表示是否使用偏置,默认使用
– batch_first 表示输入数据的形式,默认是 False,就是这样形式,(seq, batch, feature),也就是将序列长度放在第一位,batch 放在第二位
– dropout 表示是否在输出层应用 dropout
– bidirectional 表示是否使用双向的 rnn,默认是 False
# 输入维度 50,隐层100维,两层
lstm_seq = nn.LSTM(50, 100, num_layers=2)
# 输入序列seq= 10,batch =3,输入维度=50
lstm_input = torch.randn(10, 3, 50)
out, (h, c) = lstm_seq(lstm_input) # 使用默认的全 0 隐藏状态
问题1:out
和(h,c)
的size各是多少?
回答:out
:(10 * 3 * 100),(h,c)
:都是(2 * 3 * 100)
问题2:out[-1,:,:]
和h[-1,:,:]
相等吗?
回答: 相等
gru_seq = nn.GRU(10, 20, 2) # x_dim,h_dim,layer_num
gru_input = torch.randn(3, 32, 10) # seq,batch,x_dim
out, h = gru_seq(gru_input)
同样,out
的输出维度[seq_len,batch_size,output_dim]
,h的维度[num_layers * num_directions, batch_size, hidden_size]。