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 相关文章推荐
在Python编程过程中用单元测试法调试代码的介绍
Apr 02 Python
老生常谈Python startswith()函数与endswith函数
Sep 08 Python
Numpy中stack(),hstack(),vstack()函数用法介绍及实例
Jan 09 Python
浅谈numpy数组中冒号和负号的含义
Apr 18 Python
python 获取当天每个准点时间戳的实例
May 22 Python
python使用插值法画出平滑曲线
Dec 15 Python
浅谈python的输入输出,注释,基本数据类型
Apr 02 Python
python实现windows倒计时锁屏功能
Jul 30 Python
Python中正反斜杠(‘/’和‘\’)的意义与用法
Aug 12 Python
在pytorch中查看可训练参数的例子
Aug 18 Python
pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)
Mar 25 Python
快速一键生成Python爬虫请求头
Mar 04 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
CentOS安装php v8js教程
2015/02/26 PHP
laravel 5.4中实现无限级分类的方法示例
2017/07/27 PHP
Laravel学习笔记之Artisan命令生成自定义模板的方法
2018/11/22 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
2019/03/14 PHP
jQuery ajax 路由和过滤器使用说明
2011/08/02 Javascript
JQuery实现表格动态增加行并对新行添加事件
2014/07/30 Javascript
js实现表单检测及表单提示的方法
2015/08/14 Javascript
js实现正则匹配中文标点符号的方法
2015/12/23 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
纯JS单页面赛车游戏制作代码分享
2017/03/03 Javascript
详解Vue路由钩子及应用场景(小结)
2017/11/07 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
2017/12/20 jQuery
微信小程序排坑指南详解
2018/05/23 Javascript
js计算最大公约数和最小公倍数代码实例
2019/09/11 Javascript
详解如何在Javascript和Sass之间共享变量
2019/11/13 Javascript
JavaScript数值类型知识汇总
2019/11/17 Javascript
[00:43]FTP典藏礼包 DOTA2三大英雄霸气新套装
2014/03/21 DOTA
python 查找文件夹下所有文件 实现代码
2009/07/01 Python
python自动化测试之连接几组测试包实例
2014/09/28 Python
Python的Tornado框架实现异步非阻塞访问数据库的示例
2016/06/30 Python
Python 常用模块 re 使用方法详解
2019/06/06 Python
pygame实现成语填空游戏
2019/10/29 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
Python如何操作docker redis过程解析
2020/08/10 Python
python 解决pycharm运行py文件只有unittest选项的问题
2020/09/01 Python
python 如何使用find和find_all爬虫、找文本的实现
2020/10/16 Python
简洁自适应404页面HTML好看的404源码
2020/12/16 HTML / CSS
曼联官方网上商店:Manchester United Direct
2017/07/28 全球购物
尤妮佳moony海外旗舰店:日本殿堂级纸尿裤品牌
2018/02/23 全球购物
前台接待岗位职责
2013/12/03 职场文书
求职简历中自我评价
2014/01/28 职场文书
我的未来不是梦演讲稿
2014/09/02 职场文书
社区党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
机关干部正风肃纪心得体会
2016/01/15 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
解决Golang中ResponseWriter的一个坑
2021/04/27 Golang