4. 使用Keras-神经网络来进行MNIST手写数字分类

程序

  • 导入库
import numpy as np
import keras

from keras.datasets import mnist # mnist数据集
from keras.utils import np_utils # kerass提供的工具包
from keras.models import Sequential
from keras.layers import Dense,Activation
from keras.optimizers import SGD
  • 加载数据集
    程序会去指定目录下(默认是: .\keras\examples) 查看是否有mnist.npz数据集。如果没有,则去 https://s3.amazonaws.com/img-datasets/mnist.npz 进行下载的。不过目前好像要用梯子。所以可以参考以下博客,他们提供了百度网盘链接供下载参考1参考2
# 导入数据集
# dataset_path = 'C:\Users\Administrator\.keras\datasets\mnist.npz'
# (x_train, y_train), (x_test, y_test) = mnist.load_data(path=dataset) # 不指定路径,则默认联网下载到userhome\.keras\datasets\mnist.npz
(x_train, y_train), (x_test, y_test) = mnist.load_data()

print('x_train:',x_train.shape) # (60000, 28, 28)
print('y_train:',y_train.shape) # (60000,)
print('x_test:',x_test.shape) # (10000, 28, 28)
print('y_test:',y_test.shape) # (10000,)
  • 数据预处理
# 数据集预处理(不要多次运行)

# 将x_train(6000, 28, 28)->(6000, 784)->归一化
x_train = x_train.reshape(x_train.shape[0], -1)/255.0
x_test = x_test.reshape(x_test.shape[0], -1)/255.0
print('x_train:',x_train.shape)  # (60000, 784)

# 将label转成 one-hot 格式(代码不能多次执行,否则维数为增加)
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
print('y_shape:',y_train.shape)  # (60000, 10)
  • 建立模型+训练模型
    在compile时加入metrics = ['accuracy'] 来计算训练过程中的准确率。
    使用model.fit来训练模型。
# 建立模型
model = Sequential([
        Dense(units=10, input_dim=784, activation='softmax')  # softmax将输出转成概率
    ])

# 定义优化器
sgd = SGD(lr=0.2)

# 定义优化器,loss function,训练过程中计算准确率
model.compile(
    optimizer = sgd,
    loss = 'mse',
    metrics = ['accuracy'],
)

# 训练模型(与以前的for语句写的循环训练模型代码等价)
model.fit(x_train, y_train, batch_size=32, epochs=10) # 一次训练32张图片,一个周期要训练60000/32次,共训练10个周期

# 评估模型(用测试集测试)
loss, accuracy = model.evaluate(x_test, y_test)

print("loss: ", loss)
print("accuracy: ", accuracy)

在这里插入图片描述
由于模型的约束,识别率只能达到91%左右。

优化一:损失函数:使用交叉熵替代均方差

loss = 'mse', 替换成 loss='categorical_crossentropy',

model = Sequential([
        Dense(units=10, input_dim=784,bias_initializer='one', activation='softmax')
    ])

sgd = SGD(lr=0.2)
model.compile(optimizer=sgd, 
              loss='categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=10)

loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('accuracy',accuracy)

在这里插入图片描述
优点:
迭代速度快
精确度提高

优化二:添加隐藏层(提高模型的复杂性,但容易过拟合),Dropout(预防过拟合)

只添加隐藏层:

# 创建模型(添加隐藏层,增加网络模型的复杂度)
model = Sequential([
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh'),
        Dense(units=100,bias_initializer='one',activation='tanh'), #加入中间隐藏层
        Dense(units=10,bias_initializer='one',activation='softmax') # 最后输出层
    ])

# 定义优化器
sgd = SGD(lr=0.2)

# 定义优化器,loss function,训练过程中计算准确率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 训练模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 评估模型(测试集)
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

# 评估模型(训练集)
loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在这里插入图片描述
可以看到模型在训练集上表现极好,测试集上略差。表示模型存在过拟合现象(所以需要使用dropout)

添加隐藏层+Dropout层(需要导入库:from keras.layers import Dense,Dropout)

# 创建模型(添加隐藏层,增加网络模型的复杂度)
model = Sequential([
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh'),
        Dropout(0.4),
        Dense(units=100,bias_initializer='one',activation='tanh'),
        Dropout(0.4),
        Dense(units=10,bias_initializer='one',activation='softmax')
    ])

# 定义优化器
sgd = SGD(lr=0.2)

# 定义优化器,loss function,训练过程中计算准确率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 训练模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 评估模型(测试集)
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

# 评估模型(训练集)
loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在这里插入图片描述
精确度下降是因为网络节点不再全连接的了,而是会忽略一半的特征检测器(让一半的隐层节点值为0),具体可以参考:神经网络之dropout层
还有一点就是,可以看到模型在训练集上的预测结果和测试集上的结果相差不大了,即一定程度上避免了过拟合现象

优化三:添加正则化项

导入库:from keras.regularizers import l2 # 引入 L2 正则项
正则化器允许在优化过程中对层的参数或层的激活情况进行惩罚。 网络优化的损失函数也包括这些惩罚项。

# 创建模型
model = Sequential([
        # 添加了正则化项的模型
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh',kernel_regularizer=l2(0.0003)),
        Dense(units=100,bias_initializer='one',activation='tanh',kernel_regularizer=l2(0.0003)),
        Dense(units=10,bias_initializer='one',activation='softmax',kernel_regularizer=l2(0.0003))
    ])

# 定义优化器
sgd = SGD(lr=0.2)

# 定义优化器,loss function,训练过程中计算准确率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 训练模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 评估模型
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在这里插入图片描述
可以看到过拟合现象也不是特别严重,正则化项的应用要看具体情况而定

优化四:优化器的应用

引入库:from keras.optimizers import SGD,Adam
大多数情况下:adam比sgd效果要比较好,且优化速度比较快
下面程序在使用交叉熵后的代码上进行修改(使用adam替换sgd)的:

# 创建模型,输入784个神经元,输出10个神经元
model = Sequential([
        Dense(units=10,input_dim=784,bias_initializer='one',activation='softmax')
    ])

# 定义优化器
sgd = SGD(lr=0.2)
adam = Adam(lr=0.001)  # 定义adam优化器

# 定义优化器,loss function,训练过程中计算准确率
model.compile(
    optimizer = adam, # 使用Adam优化器
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 训练模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 评估模型
loss,accuracy = model.evaluate(x_test,y_test)

print('\ntest loss',loss)
print('accuracy',accuracy)

在这里插入图片描述

其他优化。。。。。。

参考:

视频: 覃秉丰老师的“Keras入门”:http://www.ai-xlab.com/course/32
博客参考:https://www.cnblogs.com/XUEYEYU/tag/keras%E5%AD%A6%E4%B9%A0/

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值