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


rnn_1.png
  • 然后编译模型
    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更容易得到较好的模型?)

上一篇 下一篇

猜你喜欢

热点阅读