Keras_rnn的搭建
2017-10-17 本文已影响0人
苟且偷生小屁屁
本文借鉴了莫凡的视频,代码,莫凡的博客:http://morvanzhou.github.io/tutorials/
第一部分,从无到有搭建rnn(复制粘贴是学不会DL的)
- 一些基本库的导入
import numpy as np
from keras.data import mnist
from keras.utils import np_utils # 这个将会在y的标签向量化中用到
from keras.utils import plot_model
from keras.models import Sequential
from keras.layers import SimpleRNN, LSTM,GRU #三种典型的rnn
from keras.layers import Dense, Activation #不够用了边写边加
- 基本参数
time_steps = 28 #将28*28的图像分拆为28段,28维的序列,这是28段
imput_size = 28 #每一段序列都有28维
batch_size = 50 #每次训练的图像个数
output_size = 10 #10个数字手写体的识别,所以结果是10
cell_size = 60 #RNN跨越的时间维度,相当于隐藏的神经元数量
batch_index = 0
- 输入的归一化处理(更好的利用激活函数的激活区间)
(x_train,y_train), (x_test,y_test) = mnist.load_data()
x_train = x_train.reshape(-1,28,28)/255.
# 或者写成, x_train = np.reshape(x_train,(-1,28,28))
x_test = x_test.reshape(-1,28,28)/255.
# 将y_train的标签变成one-hot类型的标签
y_train = np_utils.to_categorical(y_train,num_classes=output_size)
y_test = np_utils.to_categorical(y_test,num_classes = output_size)
这里一直有一点不大明白
np_utils.to_categoricall
对应的是one-hot
, 所以后面的损失函数选的是loss = categorical_crossentropy
那如果不做one-hot这样的变化, loss可以选别的吗,或者loss究竟应该怎么选择
- 搭建模型
model = Sequential()
# 第一层SimpleRNN, 第一层必须给出输入的维度,以后就不用给了
# 为了能够叠加, return_sequences必须设置为True
model.add(
SimpleRNN(
return_sequences = True,
units = cell_size # 这是你想让层有多少个时间节点,也就是多少个隐藏层神经元
input_dim= 28(input_size)
input_length = 28(time_steps)))
# 然后添加第二层SimpleRNN,这时不用再指定input的维度
model.add(
SimpleRNN(
return_sequences = True,
units = celll_size))
# 然后添加第三层SimpleRNN,因为是最后一层RNN,所以我们将return_sequences设置为False
model.add(
SimpleRNN(
units = cell_size))
# 然后添加输出层,也就是全连接层Dense
model.add(
Dense(output_size))
model.add(
Activation('softmax'))
模型搭建完毕,如果想要给模型画出来,可以写:
plot_model(model, to_file = 'rnn.png', shoe_shapes = 'True')
图里是GRU, 因为在我自己的程序里用的GRU

- 然后编译模型
model.compile(
optimizer = 'adam',
loss = 'categorical_crossentropy',
metrics=['accuracy']
- 训练模型
for step in range(1000):
x_batch = x_train(batch_index : batch_index+batch_size, : , :)
y_batch = y_train(batch_index: batch_index+batch_size, :, :)
cost = model.train_on_batch (x_batch,y_batch)
batch_index += batch_index
if step%500==0:
# 这种写法是对所有10000个测试样本进行了测试
cost,accuracy = model.evaluate(x_test, y_test, batch_size = y_train.shape[0],verbose = 0)
print('test_cost', cost,'test accuracy',accuracy)
这实际上有个问题, 因为数据没有shuffle, 所以这样的batch取法,每次取到的都是相同的元素,而且这种写法,x_train和y_train写开的,没有办法用np.random.shuffle()实现, 要么可以x_train和y_train合并,要么换一种写法:
model.fit(X_train,y_train,batch_size=BATCH_SIZE,epochs =10,shuffle=1,verbose=1)
cost,accracy = model.evaluate(X_test,y_test,verbose=0)
print('test cost: ', cost, 'test accuracy: ', accracy)
这种是传统的写法,每一个epoch会对所有60000张图像进行训练, 但是实验过程中感觉没有train_on_batch的测试结果高,原因分析: train_on_batch在每个step都会利用一个batch单元内的图像进行训练,也就是说有多少个step就有多少次训练,而epoch=1指的是一次对所有的图像进行训练,就有点sgd和bgd的感觉,所以加大epoch,比如epoch=20,就会得到较好的结果,总之就是训练的次数不够(是不是train_on_batch更容易得到较好的模型?)