keras入门系列(一)——实现全连接神经网络手写数字的分类识别

【参考视频网址:】https://space.bilibili.com/45151802/video
(老师讲的特别好,良心推荐)
【mnist数据集下载:】https://download.csdn.net/download/weixin_41874898/11434107
【github代码下载:】https://github.com/Seasea77/keras_small_project_19_07_26

文章目录

      • 1. 实现功能:使用keras实现全连接神经网络手写数字的识别
      • 2. 准备工作
        • 2.1文章目录
        • 2.2 BatchNormalization
      • 3. keras_mnist_fc.py
        • 3.1 代码如下
        • 3.2 思路总结
        • 3.3 问题解决
      • 4. test.png(灰度图)文件生成
      • 5. 测试结果

1. 实现功能:使用keras实现全连接神经网络手写数字的识别

2. 准备工作

2.1文章目录

在这里插入图片描述

2.2 BatchNormalization

BN的基本思想其实相当直观:因为深层神经网络在做非线性变换前的激活输入值(就是那个x=WU+B,U是输入)随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近(对于Sigmoid函数来说,意味着激活输入值WU+B是大的负值或正值),所以这导致反向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因,而BN就是通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0方差为1的标准正态分布,其实就是把越来越偏的分布强制拉回比较标准的分布,这样使得激活输入值落在非线性函数对输入比较敏感的区域,这样输入的小变化就会导致损失函数较大的变化,意思是这样让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。

THAT’S
IT。其实一句话就是:对于每个隐层神经元,把逐渐向非线性函数映射后,向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。因为梯度一直都能保持比较大的状态,所以很明显对神经网络的参数调整效率比较高,就是变动大,就是说向损失函数最优值迈动的步子大,也就是说收敛地快。BN说到底就是这么个机制,方法很简单,道理很深刻。

3. keras_mnist_fc.py

3.1 代码如下

# coding:utf-8
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential, Model
from keras.layers.core import Dense, Activation, Dropout
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimage
from PIL import Image


"""1设置基本参数"""
batch_size = 1024  # 一次训练需要给神经网络注入多少个数据,即神经网络跑一次,能跑1024个数据。这个值取的太大效果不好
num_class = 10  # 训练分类的个数
num_epochs = 2  # 训练的次数(所有60000个数据用一次叫做1个epoch)


"""2加载原始数据"""
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()  # 加载进来的二值图就是矩阵
# (1)mnist数据集的加载
# ——问题:
# # 使用(X_train, Y_train), (X_test, Y_test) = mnist.load_data()下载失败,所以无法加载成功。
# ——解决:
# # 加载失败会提示下载地址,通过下载,通过,下载速度很快。
# # 在执行上述指令时,mnist.load_data(),会在home(C:/Users/61052)目下的.keras目录下生成datasets文件夹,
# 因为下载失败,所以文件夹为空。
# # cmd打开终端,在home目录下,cd .keras、cd datasets、start .(打开当前文件夹),执行将下载好的mnist
# 数据集放入到文件夹再运行就不会报错。
# 
# # X_train.shape=(60000, 28, 28)
# Y_train.shape=(60000,)
# X_test.shape=(10000, 28, 28)
# Y_test.shape=(10000,)
# # 加载进来的二值图就是矩阵


"""3处理数据集,归一化"""
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)

# 转换成小数,进行归一化(相当于是BN)
# X_train = X_train.astype("float32")
X_train = X_train / 255.  # 255加小数点;print(X_train[9999]) #打印其中任意一行,看一下

# 将整型标签转为onehot
Y_train = np_utils.to_categorical(Y_train, num_class)  # Y_train必须为数组
Y_test = np_utils.to_categorical(Y_test, num_class)  # 可以print(Y_test[99])看其中一个标签的形式


"""4设置网络结构"""
model = Sequential()  # 开始keras的序列模型

# 第一层
model.add(Dense(512, input_shape=(784,))) 
# 只用写一张图片的形状就行,784既可以表示行又可以表示列,此处表示一行
# 第一层必须告诉系统你的输入是多少,默认1行784列,输入是(*,784),输出是(*,512)
# (784, )逗号不能少,(784,1)或者写成这样
model.add(Activation("relu"))
model.add(Dropout(0.2))  # 随机失活一部分

# 第二层
model.add(Dense(256))
model.add(Activation("relu"))
model.add(Dropout(0.2))

# 第三层
model.add(Dense(10))
model.add(Activation("softmax"))  # softmax针对10个进行分类


"""5编译"""
# 用什么函数来处理
model.compile(
    loss="categorical_crossentropy",  # 损失函数
    optimizer="rmsprop",  # 优化函数,SGD、adam不同优化函数不同的路径向最优点推进,adam最新
    metrics=["accuracy"]  # 达到的目标
)
# model.save("./mine.h5")  # 模型的保存


"""6启动网络--训练网络"""
Trainning = model.fit(
    X_train, Y_train,
    batch_size=batch_size,
    epochs=num_epochs,
    validation_data=(X_test, Y_test),  # 可加可不加,输出多一条数据
    # - 3s - loss: 0.5421 - acc: 0.8313 - val_loss: 1.2277 - val_acc: 0.9230
    verbose=2
    # 默认为1,输出显示进度条,显示每个Epoch
    # 2,输出不显示进度条,显示每个Epoch
    # 0,输出什么都不显示
)


"""7把Training实例化"""
print("_________________________________________________________________")
print(Trainning.history)  #
print(Trainning.params)  # 网络的设置


"""8测试test数据"""
testpic = X_test[9998].reshape(1, 784)
testlabel = np.argmax(Y_test[9998])
testpic = testpic.reshape(28, 28)
print("标签结果:", testlabel)
plt.imshow(testpic)
plt.show()

# 模型预测结果
testpic = testpic.reshape(1, 784)
pred = model.predict(testpic)
print("预测结果:", np.argmax(pred))


"""9测试自己的照片"""

# # 方法1:变成灰度图
# def rgb2gray(rgb):
#     return np.dot(rgb[..., :3], [0.299, 0.587, 0.144])
# mine_img = mpimage.imread("./test.jpg")
# mine_img_L = rgb2gray(mine_img)
# print(mine_img_L.shape)

# 方法2:变成灰度图
mine_img = Image.open("./test.png")  # open和imread的区别
mine_img_L = mine_img.convert("L")
mine_img_L = mine_img_L.resize((28, 28), Image.ANTIALIAS)   # 调整图片大小为(28, 28)
mine_img_L = np.array(mine_img_L)  # mine_img_L的shape为(28, 28)
# np.savetxt('4.csv', mine_img_L, delimiter=',')  # 把矩阵存放到csv文件里面
plt.imshow(mine_img_L)  # mine_img_L.show(),使用电脑自带的照片显示软件。plt.imshow(mine_img_L),使用plt来显示图片。
plt.show()
print(mine_img_L.shape)

# 模型预测结果
mine_img_L = mine_img_L.reshape(1, 784)
mine_img_L = mine_img_L / 255.
pred = model.predict(mine_img_L)
print(np.argmax(pred))  # 预测不准和背景色有关,与训练模板背景色相同

3.2 思路总结

  1. 数据集加载及处理
  • 此处用的是mnist数据集,使用mnist.load_data()获取数据集,(X_train, Y_train), (X_test, Y_test) = mnist.load_data() ,加载进来的二值图就是矩阵
  • 数据集最后为两类:X_train,Y_train(X_test,Y_test),其中X_train为(-1, 784)且除以255.归一化矩阵,Y_train(-1,10)为one-hot类型矩阵
  1. 网络结构设置

    model = Sequential()

    model.add()

  2. 网络编译

    model.compile(loss, optimizer, metrics=[“accuracy”])

  3. 网络训练

    Trainning = model.fit()

  4. 测试自己的照片

3.3 问题解决

mnist.load_data()下载失败**

(1)在执行该指令时,mnist.load_data(),会在home(C:/Users/61052)目下的.keras目录下生成datasets文件夹,因为下载失败,所以文件夹为空。

(2)加载失败会提示下载地址,通过下载,通过,下载速度很快。

(3)cmd打开终端,在home目录下,cd .keras、cd datasets、start .(打开当前文件夹),执行将下载好的mnist;数据集放入到文件夹再运行就不会报错。

4. test.png(灰度图)文件生成

(1)打开ps,操作三步骤如下:

(测试图片大小不用28*28也可以,代码中会统一)

keras入门系列(一)——实现全连接神经网络手写数字的分类识别_第1张图片

(2)ALT+鼠标滚轮调整新建图片大小;选中画笔,切换成英文输入法,中括号调节画笔大小; Ctrl+Alt+z撤销操作(此步可能需要退出下qq,要不老是跳出qq);使用快捷键Ctrl+Shift+Alt+w保存图片,保存格式为png,test.png

keras入门系列(一)——实现全连接神经网络手写数字的分类识别_第2张图片

5. 测试结果

(1)test.png测试图

keras入门系列(一)——实现全连接神经网络手写数字的分类识别_第3张图片
(2)测试结果为:
keras入门系列(一)——实现全连接神经网络手写数字的分类识别_第4张图片

你可能感兴趣的:(keras系列,keras,mnist,手写数字识别,全连接神经网络)