Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作


Posted in Python onMay 25, 2021

使用keras实现CNN,直接上代码:

from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
 
class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = {'batch':[], 'epoch':[]}
        self.accuracy = {'batch':[], 'epoch':[]}
        self.val_loss = {'batch':[], 'epoch':[]}
        self.val_acc = {'batch':[], 'epoch':[]}
 
    def on_batch_end(self, batch, logs={}):
        self.losses['batch'].append(logs.get('loss'))
        self.accuracy['batch'].append(logs.get('acc'))
        self.val_loss['batch'].append(logs.get('val_loss'))
        self.val_acc['batch'].append(logs.get('val_acc'))
 
    def on_epoch_end(self, batch, logs={}):
        self.losses['epoch'].append(logs.get('loss'))
        self.accuracy['epoch'].append(logs.get('acc'))
        self.val_loss['epoch'].append(logs.get('val_loss'))
        self.val_acc['epoch'].append(logs.get('val_acc'))
 
    def loss_plot(self, loss_type):
        iters = range(len(self.losses[loss_type]))
        plt.figure()
        # acc
        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
        # loss
        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
        if loss_type == 'epoch':
            # val_acc
            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
            # val_loss
            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
        plt.grid(True)
        plt.xlabel(loss_type)
        plt.ylabel('acc-loss')
        plt.legend(loc="upper right")
        plt.show()
 
history = LossHistory()
 
batch_size = 128
nb_classes = 10
nb_epoch = 20
img_rows, img_cols = 28, 28
nb_filters = 32
pool_size = (2,2)
kernel_size = (3,3)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
 
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
 
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
 
model3 = Sequential()
 
model3.add(Convolution2D(nb_filters, kernel_size[0] ,kernel_size[1],
                        border_mode='valid',
                        input_shape=input_shape))
model3.add(Activation('relu'))
 
model3.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model3.add(Activation('relu'))
 
model3.add(MaxPooling2D(pool_size=pool_size))
model3.add(Dropout(0.25))
 
model3.add(Flatten())
 
model3.add(Dense(128))
model3.add(Activation('relu'))
model3.add(Dropout(0.5))
 
model3.add(Dense(nb_classes))
model3.add(Activation('softmax'))
 
model3.summary()
 
model3.compile(loss='categorical_crossentropy',
              optimizer='adadelta',
              metrics=['accuracy'])
 
model3.fit(X_train, Y_train, batch_size=batch_size, epochs=nb_epoch,
          verbose=1, validation_data=(X_test, Y_test),callbacks=[history])
 
score = model3.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
 
#acc-loss
history.loss_plot('epoch')

补充:使用keras全连接网络训练mnist手写数字识别并输出可视化训练过程以及预测结果

前言

mnist 数字识别问题的可以直接使用全连接实现但是效果并不像CNN卷积神经网络好。Keras是目前最为广泛的深度学习工具之一,底层可以支持Tensorflow、MXNet、CNTK、Theano

准备工作

TensorFlow版本:1.13.1

Keras版本:2.1.6

Numpy版本:1.18.0

matplotlib版本:2.2.2

导入所需的库

from keras.layers import Dense,Flatten,Dropout
from keras.datasets import mnist
from keras import Sequential
import matplotlib.pyplot as plt
import numpy as np

Dense输入层作为全连接,Flatten用于全连接扁平化操作(也就是将二维打成一维),Dropout避免过拟合。使用datasets中的mnist的数据集,Sequential用于构建模型,plt为可视化,np用于处理数据。

划分数据集

# 训练集       训练集标签       测试集      测试集标签
(train_image,train_label),(test_image,test_label) = mnist.load_data()
print('shape:',train_image.shape)   #查看训练集的shape
plt.imshow(train_image[0])    #查看第一张图片
print('label:',train_label[0])      #查看第一张图片对应的标签
plt.show()

输出shape以及标签label结果:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

查看mnist数据集中第一张图片:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

数据归一化

train_image = train_image.astype('float32')
test_image = test_image.astype('float32')
train_image /= 255.0
test_image /= 255.0

将数据归一化,以便于训练的时候更快的收敛。

模型构建

#初始化模型(模型的优化 ---> 增大网络容量,直到过拟合)
model = Sequential()
model.add(Flatten(input_shape=(28,28)))    #将二维扁平化为一维(60000,28,28)---> (60000,28*28)输入28*28个神经元
model.add(Dropout(0.1))
model.add(Dense(1024,activation='relu'))   #全连接层 输出64个神经元 ,kernel_regularizer=l2(0.0003)
model.add(Dropout(0.1))
model.add(Dense(512,activation='relu'))    #全连接层
model.add(Dropout(0.1))
model.add(Dense(256,activation='relu'))    #全连接层
model.add(Dropout(0.1))
model.add(Dense(10,activation='softmax'))  #输出层,10个类别,用softmax分类

每层使用一次Dropout防止过拟合,激活函数使用relu,最后一层Dense神经元设置为10,使用softmax作为激活函数,因为只有0-9个数字。如果是二分类问题就使用sigmod函数来处理。

编译模型

#编译模型
model.compile(
    optimizer='adam',      #优化器使用默认adam
    loss='sparse_categorical_crossentropy', #损失函数使用sparse_categorical_crossentropy
    metrics=['acc']       #评价指标
)

sparse_categorical_crossentropy与categorical_crossentropy的区别:

sparse_categorical_crossentropy要求target为非One-hot编码,函数内部进行One-hot编码实现。

categorical_crossentropy要求target为One-hot编码。

One-hot格式如: [0,0,0,0,0,1,0,0,0,0] = 5

训练模型

#训练模型
history = model.fit(
    x=train_image,                          #训练的图片
    y=train_label,                          #训练的标签
    epochs=10,                              #迭代10次
    batch_size=512,                         #划分批次
    validation_data=(test_image,test_label) #验证集
)

迭代10次后的结果:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

绘制loss、acc图

#绘制loss acc图
plt.figure()
plt.plot(history.history['acc'],label='training acc')
plt.plot(history.history['val_acc'],label='val acc')
plt.title('model acc')
plt.ylabel('acc')
plt.xlabel('epoch')
plt.legend(loc='lower right')
plt.figure()
plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'],label='val loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(loc='upper right')
plt.show()

绘制出的loss变化图:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

绘制出的acc变化图:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

预测结果

print("前十个图片对应的标签: ",test_label[:10]) #前十个图片对应的标签
print("取前十张图片测试集预测:",np.argmax(model.predict(test_image[:10]),axis=1)) #取前十张图片测试集预测

打印的结果:

Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作

可看到在第9个数字预测错了,标签为5的,预测成了6,为了避免这种问题可以适当的加深网络结构,或使用CNN模型。

保存模型

model.save('./mnist_model.h5')

完整代码

from keras.layers import Dense,Flatten,Dropout
from keras.datasets import mnist
from keras import Sequential
import matplotlib.pyplot as plt
import numpy as np
# 训练集       训练集标签       测试集      测试集标签
(train_image,train_label),(test_image,test_label) = mnist.load_data()
# print('shape:',train_image.shape)   #查看训练集的shape
# plt.imshow(train_image[0]) #查看第一张图片
# print('label:',train_label[0])      #查看第一张图片对应的标签
# plt.show()
#归一化(收敛)
train_image = train_image.astype('float32')
test_image = test_image.astype('float32')
train_image /= 255.0
test_image /= 255.0
#初始化模型(模型的优化 ---> 增大网络容量,直到过拟合)
model = Sequential()
model.add(Flatten(input_shape=(28,28)))   #将二维扁平化为一维(60000,28,28)---> (60000,28*28)输入28*28个神经元
model.add(Dropout(0.1))
model.add(Dense(1024,activation='relu'))    #全连接层 输出64个神经元 ,kernel_regularizer=l2(0.0003)
model.add(Dropout(0.1))
model.add(Dense(512,activation='relu'))    #全连接层
model.add(Dropout(0.1))
model.add(Dense(256,activation='relu'))    #全连接层
model.add(Dropout(0.1))
model.add(Dense(10,activation='softmax')) #输出层,10个类别,用softmax分类
#编译模型
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['acc']
)
#训练模型
history = model.fit(
    x=train_image,                          #训练的图片
    y=train_label,                          #训练的标签
    epochs=10,                              #迭代10次
    batch_size=512,                         #划分批次
    validation_data=(test_image,test_label) #验证集
)
#绘制loss acc 图
plt.figure()
plt.plot(history.history['acc'],label='training acc')
plt.plot(history.history['val_acc'],label='val acc')
plt.title('model acc')
plt.ylabel('acc')
plt.xlabel('epoch')
plt.legend(loc='lower right')
plt.figure()
plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'],label='val loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(loc='upper right')
plt.show()
print("前十个图片对应的标签: ",test_label[:10]) #前十个图片对应的标签
print("取前十张图片测试集预测:",np.argmax(model.predict(test_image[:10]),axis=1)) #取前十张图片测试集预测
#优化前(一个全连接层(隐藏层))
#- 1s 12us/step - loss: 1.8765 - acc: 0.8825
# [7 2 1 0 4 1 4 3 5 4]
# [7 2 1 0 4 1 4 9 5 9]
#优化后(三个全连接层(隐藏层))
#- 1s 14us/step - loss: 0.0320 - acc: 0.9926 - val_loss: 0.2530 - val_acc: 0.9655
# [7 2 1 0 4 1 4 9 5 9]
# [7 2 1 0 4 1 4 9 5 9]
model.save('./model_nameALL.h5')

总结

使用全连接层训练得到的最后结果train_loss: 0.0242 - train_acc: 0.9918 - val_loss: 0.0560 - val_acc: 0.9826,由loss acc可视化图可以看出训练有着明显的效果。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
基于numpy.random.randn()与rand()的区别详解
Apr 17 Python
对python中dict和json的区别详解
Dec 18 Python
学生信息管理系统Python面向对象版
Jan 30 Python
查看python安装路径及pip安装的包列表及路径
Apr 03 Python
用Python从0开始实现一个中文拼音输入法的思路详解
Jul 20 Python
python自定义时钟类、定时任务类
Feb 22 Python
使用python将excel数据导入数据库过程详解
Aug 27 Python
python3 mmh3安装及使用方法
Oct 09 Python
在echarts中图例legend和坐标系grid实现左右布局实例
May 16 Python
python MD5加密的示例
Oct 19 Python
Python爬取酷狗MP3音频的步骤
Feb 26 Python
Python异常类型以及处理方法汇总
Jun 05 Python
python编写五子棋游戏
浅谈python数据类型及其操作
对Keras自带Loss Function的深入研究
May 25 #Python
pytorch中的model=model.to(device)使用说明
May 24 #Python
解决pytorch-gpu 安装失败的记录
May 24 #Python
如何解决.cuda()加载用时很长的问题
一劳永逸彻底解决pip install慢的办法
May 24 #Python
You might like
使用迭代器 遍历文件信息的详解
2013/06/08 PHP
php查找任何页面上的所有链接的方法
2013/12/03 PHP
ThinkPHP自动填充实现无限级分类的方法
2014/08/22 PHP
JSON字符串传到后台PHP处理问题的解决方法
2016/06/05 PHP
laravel如何开启跨域功能示例详解
2017/08/31 PHP
添加到收藏夹代码(兼容几乎所有的浏览器)
2007/01/09 Javascript
JavaScript中获取鼠标位置相关属性总结
2014/10/11 Javascript
JavaScript中的数值范围介绍
2014/12/29 Javascript
jQuery实现列表内容的动态载入特效
2015/08/08 Javascript
js实现对ajax请求面向对象的封装
2016/01/08 Javascript
彻底学会Angular.js中的transclusion
2017/03/12 Javascript
基于node.js制作简单爬虫教程
2017/06/29 Javascript
angular4实现tab栏切换的方法示例
2017/10/21 Javascript
使用webpack打包koa2 框架app
2018/02/02 Javascript
浅谈angular表单提交中ng-submit的默认使用方法
2018/09/30 Javascript
详解Vue路由自动注入实践
2019/04/17 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
react使用antd表单赋值,用于修改弹框的操作
2020/10/29 Javascript
[41:05]Serenity vs Pain 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python标准库内置函数complex介绍
2014/11/25 Python
python实现查询苹果手机维修进度
2015/03/16 Python
Python中字符串的常见操作技巧总结
2016/07/28 Python
Python使用装饰器进行django开发实例代码
2018/02/06 Python
Python中xml和json格式相互转换操作示例
2018/12/05 Python
使用python获取(宜宾市地震信息)地震信息
2019/06/20 Python
Python3 A*寻路算法实现方式
2019/12/24 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
Meli Melo官网:名媛们钟爱的英国奢侈手包品牌
2017/04/17 全球购物
Paul Smith英国官网:英国国宝级时装品牌
2019/03/21 全球购物
台湾全方位线上课程与职能学习平台:TibaMe
2019/12/04 全球购物
实习教师自我鉴定
2013/12/09 职场文书
无偿献血倡议书
2014/04/14 职场文书
大二学习计划书范文
2014/04/27 职场文书
工伤事故赔偿协议书范文
2014/09/24 职场文书
2014年高中生自我评价范文
2014/09/26 职场文书
2015年三八妇女节活动总结
2015/02/06 职场文书