keras学习-RNN
keras-RNN
参考《python深度学习》
关于RNN
questions : 每次 RNN神经元个数代表什么,输入又代表什么? 输入的是一个RNN的词数? 具体详细的描述:https://zhuanlan.zhihu.com/p/47412782 可以这么理解。
首先,RNN也不过是一个普通的全连接网络,RNN神经元的个数,代表着全连接网络的一层,这一层可以有很多神经元 如:
model.add(LSTM(hidden_featrue, input_shape=(timestamp, input_feature)))
hidden_featrue:就是全连接的一层,即units 个数。 timestamp :一句话,有多少个单词(或填充后的长度) input_feature :可以理解为词向量的长度。然后它本身这个全连接网络,会遍历timestamp中每一个维度进行迭代。 相当于它的输入其实是input_feature,然后遍历timestamp次。 然后遍历完一句话得到一个输出。
堆多层,只是堆两个全连接层里的层罢了,想要时序反过来(比如双向LSTM)就需要专门的另一个设置
以下:RNN的numpy实现
import numpy as np
timesteps = 100 # 输入序列的时间步数
input_features = 32 #输入特征空间的维度
output_features = 64 #输出特征空间的维度
inputs = np.random.random((timesteps,input_features)) # 100×32
state_t = np.zeros((output_features,))
# 以下是权重矩阵
W = np.random.random((output_features,input_features))#全连接层的权重
U = np.random.random((output_features,output_features))#输出输出的迭代
b = np.random.random((output_features,))#全连接层
successive_outputs = []
for input_t in inputs:
output_t = np.tanh(np.dot(W,input_t)+np.dot(U,state_t)+b)
successive_outputs.append(output_t) #隐状态输出
state_t = output_t
final_output_sequence = np.stack(successive_outputs, axis=0)#时间步个output
#不过keras呢?
'''
本例中,最终输出是一个形状为 (timesteps, output_features) 的二维张量,其中
每个时间步是循环在 t 时刻的输出。输出张量中的每个时间步 t 包含输入序列中时间步
0 ~ t 的信息,即关于全部过去的信息。因此,在多数情况下,你并不需要这个所有输出
组成的序列,你只需要最后一个输出(循环结束时的 output_t ),因为它已经包含了整
个序列的信息。
'''
使用keras RNN
二者有一点小小的区别: SimpleRNN 层能够像其他 Keras 层一样处理序列批量,而不是 像 Numpy 示例那样只能处理单个序列。因此,它接收形状为 (batch_size, timesteps, input_features) 的输入,而不是 (timesteps, input_features) 与 Keras 中的所有循环层一样, SimpleRNN 可以在两种不同的模式下运行:一种是返回每 个时间步连续输出的完整序列,即形状为 (batch_size, timesteps, output_features) 的三维张量;另一种是只返回每个输入序列的最终输出,即形状为 (batch_size, output_ features) 的二维张量。 这两种模式由 return_sequences 这个构造函数参数来控制。
from keras.models import Sequential
from keras.layers import Embedding, SimpleRNN
model = Sequential()
model.add(Embedding(10000,32)) # 10000个词,32维
#embedding_layer = Embedding(vocab_size, W2V_SIZE, weights=[embedding_matrix], input_length=SEQUENCE_LENGTH, trainable=False)
#↑之前写的一个代码的参考
model.add(SimpleRNN(32))
model.summary()
# 注意下面:输出了一个32维的,就是32个神经元(类比全连接层32个神经元)的结果
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, None, 32) 320000
_________________________________________________________________
simple_rnn (SimpleRNN) (None, 32) 2080
=================================================================
Total params: 322,080
Trainable params: 322,080
Non-trainable params: 0
_________________________________________________________________
#如果返回完整的呢?
model = Sequential()
model.add(Embedding(10000,32,input_length=100))
model.add(SimpleRNN(32,return_sequences=True))
model.summary()
#注意输出就是100个32个神经元。100就是时序
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, 100, 32) 320000
_________________________________________________________________
simple_rnn_1 (SimpleRNN) (None, 100, 32) 2080
=================================================================
Total params: 322,080
Trainable params: 322,080
Non-trainable params: 0
_________________________________________________________________
为了提高网络的表示能力,将多个循环层逐个堆叠有时也是很有用的。在这种情况下,你需要让所有中间层都返回完整的输出序列。 参数计算:https://zhuanlan.zhihu.com/p/52618361
model = Sequential()
model.add(Embedding(10000, 32,input_length=100))
model.add(SimpleRNN(32, return_sequences=True))
model.add(SimpleRNN(32, return_sequences=True))
model.add(SimpleRNN(32, return_sequences=True))
model.add(SimpleRNN(32))
model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_3 (Embedding) (None, 100, 32) 320000
_________________________________________________________________
simple_rnn_2 (SimpleRNN) (None, 100, 32) 2080
_________________________________________________________________
simple_rnn_3 (SimpleRNN) (None, 100, 32) 2080
_________________________________________________________________
simple_rnn_4 (SimpleRNN) (None, 100, 32) 2080
_________________________________________________________________
simple_rnn_5 (SimpleRNN) (None, 32) 2080
=================================================================
Total params: 328,320
Trainable params: 328,320
Non-trainable params: 0
双向RNN
model = Sequential()
model.add(layers.Embedding(max_features, 32))
model.add(layers.Bidirectional(layers.LSTM(32)))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
history = model.fit(x_train, y_train,epochs=10,batch_size=128,validation_split=0.2)
Tips:
- 关于评估方法的选择,对于不平衡数据问题:比如分类,90%A,10%B,都预测A就会有90%的准确率,因此一个好的模型应该>90%。
比如预测温度,这里可以考虑预测后一天温度=今天,这种情况下,得到的结果为 0.29,因为温度数据被标准化成均值为 0、标准差为 1,所以无法直接对这个值进行解释。它转化成温度的平均绝对误差为 0.29× temperature_std 摄氏度,即 2.57℃。因此好的模型得到的结果应该比这个好。
遇到新问题时,最好首先为你选择的指标建立一个基于常识的基准。如果没有需要打败的基准,那么就无法分辨是否取得了真正的进步
2.是否使用双向RNN或更深层的RNN要考虑问题内容,GRU 层通常更善于记住最近的数据,而不是久远的数据,与更早的数据点相比,更靠后的天气数据点对问题自然具有更高的预测能力(这也是基于常识的基准方法非常强大的原因)。因此,按时间正序的模型必然会优于时间逆序的模型。重要的是,对许多其他问题(包括自然语言)而言,情况并不是这样:直觉上来看,一个单词对理解句子的重要性通常并不取决于它在句子中的位置。这时,正序和逆序的效果相似。