这一节我们主要学习
- 根据上节课学习的深度神经网络训练技巧,改善表现不好的手写数字识别网络。
# 导入相应的工具包
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers import Conv2D, MaxPooling2D, Flatten
from keras.optimizers import SGD, Adam
from keras.utils import np_utils
from keras.datasets import mnist
#categorical_crossentropy
# 这是我们上节课训练坏掉的模型
def load_data():
(x_train, y_train) , (x_test, y_test) = mnist.load_data()
number = 10000
x_train = x_train[0:number]
y_train = y_train[0:number]
x_train = x_train.reshape(number, 28*28)
x_test = x_test.reshape(x_test.shape[0], 28*28)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# convert class vectors to binary class matrices
y_train = np_utils.to_categorical(y_train,10)
y_test = np_utils.to_categorical(y_test,10)
x_train = x_train
x_test = x_test
# x_test = np.random.normal(x_test)
x_train = x_train / 255
x_test = x_test / 255
return (x_train, y_train), (x_test, y_test)
(x_train,y_train), (x_test,y_test) = load_data()
model = Sequential()
model.add(Dense(units=689,activation='sigmoid'))
model.add(Dense(units=689,activation='sigmoid'))
#for i in range(10):
# model.add(Dense(units=689,activation='sigmoid'))
model.add(Dense(units=10,activation='softmax'))
model.compile(loss='mse',optimizer=SGD(lr=0.1),metrics=['accuracy'])
model.fit(x_train,y_train,batch_size=100,epochs=20)
result = model.evaluate(x_test,y_test,batch_size=10000)
print("\nTest Acc:"+"{:.4f}".format(result[1]))
# 第二步,换合适的损失函数:
# 代码中的问题是损失函数设的不对,之前已经讲过在分类问题中用均方误差(mse)是不能得到好的结果的,这里不再解释。
# 所以,把损失函数换成交叉熵(categorical_crossentropy)运行一遍。会发现模型在训练集上的表现明显提升。
model.compile(loss='categorical_crossentropy',optimizer=SGD(lr=0.1),metrics=['accuracy'])
# 第三步,改变 batch_size 的影响:
# batch_size 设大(10000),运行速度会加快,但是表现会变差。
# batch_size 设小(1),运行速度会变慢。
# 所以想要利用 GPU 加速,要把 batch_size 设大一点。
# 第四步,改变网络深度的影响:
# 发现网络加深,训练效果不好。
for i in range(10):
model.add(Dense(units=689,activation='sigmoid'))
# 第五步,换激活函数:
# 把 sigmoid 换成 relu. 发现训练集上正确率有很大提升,测试集上正确率也很不错。
model.add(Dense(units=689,activation='relu'))
model.add(Dense(units=689,activation='relu'))
for i in range(10):
model.add(Dense(units=689,activation='relu'))
# 第六步,数据规范化(normalization)的重要性:
# 把 x_train = x_train / 255 和 x_test = x_test / 255 注释掉,发现模型训练失败。
# 然后把规范化重新加上。
# 第七步,改变梯度下降策略:
# 1.先把网络深度变小(把 10 层注释掉),跑一次。
#for i in range(10):
# model.add(Dense(units=689,activation='relu'))
# 2.再改一下梯度下降的策略,从 SGD 改成 ‘adam’ 跑一遍。会发现训练时正确率上升的速度变快。
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
# 第八步,添加噪声,使用 Dropout:
# 1.对测试集加噪声,发现测试集正确率下降。
x_test = np.random.normal(x_test)
# 2. Dropout 的效果。
# 加上 Dropout 之后,会发现每一个 epoch 训练时训练集上的效果变差。
# 但计算训练集的正确率和测试的时候是用整个网络测试,所以效果变好。
model.add(Dense(input_dim=28*28,units=689,activation='relu'))
model.add(Dropout(0.7))
model.add(Dense(units=689,activation='relu'))
model.add(Dropout(0.7))
model.add(Dense(units=689,activation='relu'))
model.add(Dropout(0.7))