写点什么

教你如何用 Keras 搭建分类神经网络

  • 2021 年 11 月 12 日
  • 本文字数:5482 字

    阅读完需:约 18 分钟

​​摘要:本文主要通过 Keras 实现了一个分类学习的案例,并详细介绍了 MNIST 手写体识别数据集。

 

本文分享自华为云社区《[Python人工智能] 十七.Keras搭建分类神经网络及MNIST数字图像案例分析》,作者: eastmount 。

一.什么是分类学习

1.Classification


回归问题,它预测的是一个连续分布的值,例如房屋的价格、汽车的速度、Pizza 的价格等。而当我们遇到需要判断一张图片是猫还是狗时,就不能再使用回归解决了,此时需要通过分类学习,把它分成计算机能够识别的那一类(猫或狗)。



如上图所示,通常来说,计算机处理的东西和人类有所不同,无论是声音、图片还是文字,它们都只能以数字 0 或 1 出现在计算机神经网络里。神经网络看到的图片其实都是一堆数字,对数字的加工处理最终生成另一堆数字,并且具有一定认知上的意义,通过一点点的处理能够得知计算机到底判断这张图片是猫还是狗。

 

分类(Classification) 属于有监督学习中的一类,它是数据挖掘、机器学习和数据科学中一个重要的研究领域。分类模型类似于人类学习的方式,通过对历史数据或训练集的学习得到一个目标函数,再用该目标函数预测新数据集的未知属性。分类模型主要包括两个步骤:


  • 训练。给定一个数据集,每个样本都包含一组特征和一个类别信息,然后调用分类算法训练模型。

  • 预测。利用生成的模型对新的数据集(测试集)进行分类预测,并判断其分类结果。


通常为了检验学习模型的性能会使用校验集。数据集会被分成不相交的训练集和测试集,训练集用来构造分类模型,测试集用来检验多少类标签被正确分类。



那么,回归和分类有什么区别呢?


分类和回归都属于监督学习,它们的区别在于:回归是用来预测连续的实数值,比如给定了房屋面积来预测房屋价格,返回的结果是房屋价格;而分类是用来预测有限的离散值,比如判断一个人是否患糖尿病,返回值是“是”或“否”。也就是说,明确对象属于哪个预定义的目标类,预定义的目标类是离散值时为分类,连续值时为回归。

2.MNIST


MNIST 是手写体识别数据集,它是非常经典的一个神经网络示例。MNIST 图片数据集包含了大量的数字手写体图片,如下图所示,我么可以尝试用它进行分类实验。



MNIST 数据集是含标注信息的,上图分别表示数字 5、0、4 和 1。该数据集共包含三部分:

  • 训练数据集:55,000 个样本,mnist.train

  • 测试数据集:10,000 个样本,mnist.test

  • 验证数据集:5,000 个样本,mnist.validation


通常,训练数据集用来训练模型,验证数据集用来检验所训练出来的模型的正确性和是否过拟合,测试集是不可见的(相当于一个黑盒),但我们最终的目的是使得所训练出来的模型在测试集上的效果(这里是准确性)达到最佳。


如下图所示,数据是以该形式被计算机所读取,比如 28*28=784 个像素点,白色的地方都是 0,黑色的地方表示有数字的,总共有 55000 张图片。



MNIST 数据集中的一个样本数据包含两部分内容:手写体图片和对应的 label。这里我们用 xs 和 ys 分别代表图片和对应的 label,训练数据集和测试数据集都有 xs 和 ys,使用 mnist.train.images 和 mnist.train.labels 表示训练数据集中图片数据和对应的 label 数据。


如下图所示,它表示由 2828 的像素点矩阵组成的一张图片,这里的数字 784(2828)如果放在我们的神经网络中,它就是 x 输入的大小,其对应的矩阵如下图所示,类标 label 为 1。



最终 MNIST 的训练数据集形成了一个形状为 55000*784 位的 tensor,也就是一个多维数组,第一维表示图片的索引,第二维表示图片中像素的索引(tensor 中的像素值在 0 到 1 之间)。


这里的 y 值其实是一个矩阵,这个矩阵有 10 个位置,如果它是 1 的话,它在 1 的位置(第 2 个数字)上写 1,其他地方写 0;如果它是 2 的话,它在 2 的位置(第 3 个数字)上写 1,其他位置为 0。通过这种方式对不同位置的数字进行分类,例如用[0,0,0,1,0,0,0,0,0,0]来表示数字 3,如下图所示。



mnist.train.labels 是一个 55000*10 的二维数组,如下图所示。它表示 55000 个数据点,第一个数据 y 表示 5,第二个数据 y 表示 0,第三个数据 y 表示 4,第四个数据 y 表示 1。



知道了 MNIST 数据集的组成,以及 x 和 y 具体的含义,我们就开始编写 Keras 吧!

二.Keras 实现 MNIST 分类


本文通过 Keras 搭建一个分类神经网络,再训练 MNIST 数据集。其中 X 表示图片,28*28,y 对应的是图像的标签。


第一步,导入扩展包。


import numpy as npfrom keras.datasets import mnistfrom keras.utils import np_utilsfrom keras.models import Sequentialfrom keras.layers import Dense, Activationfrom keras.optimizers import RMSprop
复制代码


第二步,载入 MNIST 数据及预处理。


  • X_train.reshape(X_train.shape[0],-1) / 255

将每个像素点进行标准化处理,从 0-255 转换成 0-1 的范围。

  • np_utils.to_categorical(y_train,nb_classes=10)

调用 up_utils 将类标转换成 10 个长度的值,如果数字是 3,则会在对应的地方标记为 1,其他地方标记为 0,即{0,0,0,1,0,0,0,0,0,0}。


由于 MNIST 数据集是 Keras 或 TensorFlow 的示例数据,所以我们只需要下面一行代码,即可实现数据集的读取工作。如果数据集不存在它会在线下载,如果数据集已经被下载,它会被直接调用。


# 下载MNIST数据 # X shape(60000, 28*28) y shape(10000, )(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 数据预处理X_train = X_train.reshape(X_train.shape[0], -1) / 255 # normalizeX_test = X_test.reshape(X_test.shape[0], -1) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵y_train = np_utils.to_categorical(y_train, num_classes=10)y_test = np_utils.to_categorical(y_test, num_classes=10)
复制代码


第三步,创建神经网络层。


前面介绍创建神经网络层的方法是定义之后,利用 add()添加神经层。

  • model = Sequential()

  • model.add(Dense(output_dim=1,input_dim=1))


而这里采用另一种方法,在 Sequential()定义的时候通过列表添加神经层。同时需要注意,这里增加了神经网络激励函数并调用 RMSprop 加速神经网络。

  • from keras.layers importDense, Activation

  • from keras.optimizersimport RMSprop


该神经网络层为:

  • 第一层为 Dense(32, input_dim=784),它将传入的 784 转换成 32 个输出

  • 该数据加载一个激励函数 Activation(‘relu’),并转换成非线性化数据

  • 第二层为 Dense(10),它输出为 10 个单位。同时 Keras 定义神经层会默认其输入为上一层的输出,即 32(省略)

  • 接着加载一个激励函数 Activation(‘softmax’),用于分类


# Another way to build your neural netmodel = Sequential([        Dense(32, input_dim=784),  # 输入值784(28*28) => 输出值32        Activation('relu'),        # 激励函数 转换成非线性数据        Dense(10),                 # 输出为10个单位的结果        Activation('softmax')      # 激励函数 调用softmax进行分类        ])
# Another way to define your optimizerrmsprop = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0) #学习率lr
# We add metrics to get more results you want to see# 激活神经网络model.compile( optimizer = rmsprop, # 加速神经网络 loss = 'categorical_crossentropy', # 损失函数 metrics = ['accuracy'], # 计算误差或准确率 )
复制代码


第四步,神经网络训练及预测。


print("Training")model.fit(X_train, y_train, nb_epoch=2, batch_size=32)    # 训练次数及每批训练大小
print("Testing")loss, accuracy = model.evaluate(X_test, y_test)
print("loss:", loss)print("accuracy:", accuracy)
复制代码


完整代码:


# -*- coding: utf-8 -*-"""Created on Fri Feb 14 16:43:21 2020 @author: Eastmount CSDN YXZO(∩_∩)O Wuhan Fighting!!!"""import numpy as npfrom keras.datasets import mnistfrom keras.utils import np_utilsfrom keras.models import Sequentialfrom keras.layers import Dense, Activationfrom keras.optimizers import RMSprop
#---------------------------载入数据及预处理---------------------------# 下载MNIST数据 # X shape(60000, 28*28) y shape(10000, )(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 数据预处理X_train = X_train.reshape(X_train.shape[0], -1) / 255 # normalizeX_test = X_test.reshape(X_test.shape[0], -1) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵y_train = np_utils.to_categorical(y_train, num_classes=10)y_test = np_utils.to_categorical(y_test, num_classes=10)
#---------------------------创建神经网络层---------------------------# Another way to build your neural netmodel = Sequential([ Dense(32, input_dim=784), # 输入值784(28*28) => 输出值32 Activation('relu'), # 激励函数 转换成非线性数据 Dense(10), # 输出为10个单位的结果 Activation('softmax') # 激励函数 调用softmax进行分类 ])
# Another way to define your optimizerrmsprop = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0) #学习率lr
# We add metrics to get more results you want to see# 激活神经网络model.compile( optimizer = rmsprop, # 加速神经网络 loss = 'categorical_crossentropy', # 损失函数 metrics = ['accuracy'], # 计算误差或准确率 )
#------------------------------训练及预测------------------------------print("Training")model.fit(X_train, y_train, nb_epoch=2, batch_size=32) # 训练次数及每批训练大小print("Testing")loss, accuracy = model.evaluate(X_test, y_test)
print("loss:", loss)print("accuracy:", accuracy)
复制代码


​运行代码,首先会下载 MNIT 数据集。


Using TensorFlow backend.Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz11493376/11490434 [==============================] - 18s 2us/step
复制代码


​接着输出两次训练的结果,可以看到误差不断减小、正确率不断增大。最终测试输出的误差 loss 为“0.185575”,正确率为“0.94690”。



如果读者想更直观地查看我们数字分类的图形,可以定义函数并显示。



此时的完整代码如下所示:


# -*- coding: utf-8 -*-"""Created on Fri Feb 14 16:43:21 2020 @author: Eastmount CSDN YXZO(∩_∩)O Wuhan Fighting!!!"""import numpy as npfrom keras.datasets import mnistfrom keras.utils import np_utilsfrom keras.models import Sequentialfrom keras.layers import Dense, Activationfrom keras.optimizers import RMSpropimport matplotlib.pyplot as pltfrom PIL import Image
#---------------------------载入数据及预处理---------------------------# 下载MNIST数据 # X shape(60000, 28*28) y shape(10000, )(X_train, y_train), (X_test, y_test) = mnist.load_data()
#------------------------------显示图片------------------------------def show_mnist(train_image, train_labels): n = 6 m = 6 fig = plt.figure() for i in range(n): for j in range(m): plt.subplot(n,m,i*n+j+1) index = i * n + j #当前图片的标号 img_array = train_image[index] img = Image.fromarray(img_array) plt.title(train_labels[index]) plt.imshow(img, cmap='Greys') plt.show()
show_mnist(X_train, y_train)
# 数据预处理X_train = X_train.reshape(X_train.shape[0], -1) / 255 # normalizeX_test = X_test.reshape(X_test.shape[0], -1) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵y_train = np_utils.to_categorical(y_train, num_classes=10)y_test = np_utils.to_categorical(y_test, num_classes=10)
#---------------------------创建神经网络层---------------------------# Another way to build your neural netmodel = Sequential([ Dense(32, input_dim=784), # 输入值784(28*28) => 输出值32 Activation('relu'), # 激励函数 转换成非线性数据 Dense(10), # 输出为10个单位的结果 Activation('softmax') # 激励函数 调用softmax进行分类 ])
# Another way to define your optimizerrmsprop = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0) #学习率lr
# We add metrics to get more results you want to see# 激活神经网络model.compile( optimizer = rmsprop, # 加速神经网络 loss = 'categorical_crossentropy', # 损失函数 metrics = ['accuracy'], # 计算误差或准确率 )
#------------------------------训练及预测------------------------------print("Training")model.fit(X_train, y_train, nb_epoch=2, batch_size=32) # 训练次数及每批训练大小print("Testing")loss, accuracy = model.evaluate(X_test, y_test)
print("loss:", loss)print("accuracy:", accuracy)
复制代码


点击关注,第一时间了解华为云新鲜技术~

发布于: 4 小时前阅读数: 6
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
教你如何用Keras搭建分类神经网络