2

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

 2 years ago
source link: https://my.oschina.net/u/4526289/blog/5308505
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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

一.什么是分类学习

1.Classification

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

v2-79df214243265b6e091ea1bf1e14d5b9_720w.jpg

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

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

  • 训练。给定一个数据集,每个样本都包含一组特征和一个类别信息,然后调用分类算法训练模型。
  • 预测。利用生成的模型对新的数据集(测试集)进行分类预测,并判断其分类结果。

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

v2-0ced25b6252f0295e3a1725a4dd4fa7d_720w.jpg

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

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

2.MNIST

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

v2-1ea12c2285a0fea4b4cc08963da2ea95_720w.jpg

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

  • 训练数据集:55,000个样本,mnist.train
  • 测试数据集:10,000个样本,mnist.test
  • 验证数据集:5,000个样本,mnist.validation

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

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

v2-679aba3b193b22b8b062138121c034d3_720w.jpg

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

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

v2-7485281e1bfe2878c55cae875923af5d_720w.jpg

最终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,如下图所示。

v2-ab1726d49bff0c55bb0c0121ab88ecef_720w.jpg

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

v2-6b66dc9f4ae27cb55403600f605f27d5_720w.jpg

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

二.Keras实现MNIST分类

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

第一步,导入扩展包。

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Activation
from 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  # normalize
X_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 import Dense, Activation
  • from keras.optimizers import RMSprop

该神经网络层为:

  • 第一层为Dense(32, input_dim=784),它将传入的784转换成32个输出
  • 该数据加载一个激励函数Activation(‘relu’),并转换成非线性化数据
  • 第二层为Dense(10),它输出为10个单位。同时Keras定义神经层会默认其输入为上一层的输出,即32(省略)
  • 接着加载一个激励函数Activation(‘softmax’),用于分类
# Another way to build your neural net
model = Sequential([
        Dense(32, input_dim=784),  # 输入值784(28*28) => 输出值32
        Activation('relu'),        # 激励函数 转换成非线性数据
        Dense(10),                 # 输出为10个单位的结果
        Activation('softmax')      # 激励函数 调用softmax进行分类
        ])

# Another way to define your optimizer
rmsprop = 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 YXZ
O(∩_∩)O Wuhan Fighting!!!
"""
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Activation
from 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  # normalize
X_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 net
model = Sequential([
        Dense(32, input_dim=784),  # 输入值784(28*28) => 输出值32
        Activation('relu'),        # 激励函数 转换成非线性数据
        Dense(10),                 # 输出为10个单位的结果
        Activation('softmax')      # 激励函数 调用softmax进行分类
        ])

# Another way to define your optimizer
rmsprop = 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.npz
11493376/11490434 [==============================] - 18s 2us/step

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

v2-d5c20cb775fcec03b0a922e498f4af7f_720w.jpg

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

v2-3f3f816ce2cf8f0c5061444ca609afc5_720w.jpg

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

# -*- coding: utf-8 -*-
"""
Created on Fri Feb 14 16:43:21 2020 
@author: Eastmount CSDN YXZ
O(∩_∩)O Wuhan Fighting!!!
"""
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import RMSprop
import matplotlib.pyplot as plt
from 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  # normalize
X_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 net
model = Sequential([
        Dense(32, input_dim=784),  # 输入值784(28*28) => 输出值32
        Activation('relu'),        # 激励函数 转换成非线性数据
        Dense(10),                 # 输出为10个单位的结果
        Activation('softmax')      # 激励函数 调用softmax进行分类
        ])

# Another way to define your optimizer
rmsprop = 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)

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK