【计算机视觉】深度学习框架-Keras

1. 从零开始训练网络

1.1 搭建网络基本架构

网络的最终目标是,输入一张手写数字图片后,网络输出该图片对应的数字。

我们的代码要导出三个接口,分别完成以下功能:

1,初始化initialisation,设置输入层,中间层,和输出层的节点数。

2,训练train:根据训练数据不断的更新权重值

3,查询query,把新的数据输入给神经网络,网络计算后输出答案。(推理)

完成以上代码后,神经网络的大体框架就完成了,我们留下最重要的train函数,也就是通过训练样本训练链路权重的流程到下一步实现

1.2 构建训练网络

实现网络训练功能

自我训练过程分两步:

  1. 第一步是计算输入训练数据,给出网络的计算结果,这点跟我们前面实现的query()功能很像。

  2. 第二步是将计算结果与正确结果相比对,获取误差,采用误差反向传播法更新网络里的每条链路权重。

获取训练数据及预处理

接下来我们就得拿实际数据来训练我们的神经网络了。

我们要做的是读取训练数据,以及数据的预处理(归一化)

1.3 启动训练网络并测试数据

网络的最终目标是,输入一张手写数字图片后,网络输出该图片对应的数字。

由于网络需要从0到9一共十个数字中挑选出一个,于是我们的网络最终输出层应该有十个节点,每个节点对应一个数字。

假设图片对应的是数字0,那么输出层网络中,第一个节点应该输出一个高百分比,其他节点输出低百分比,如果图片对应的数字是9,那么输出层最后一个节点应该输出高百分比,其他节点输出低百分比。

2. 用Keras实现一个简单神经网络

2.1 Keras简介

Keras是基于theano/tensorflow的深度学习框架。是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras:
a)简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
b)支持CNN和RNN,或二者的结合
c)无缝CPU和GPU切换

2.2 MNIST手写数字识别(详细解释步骤)

2.2.1 数据的加载

MINIST数据集是一个公开的数据集,由0〜9手写数字图片和数字标签所组成的,由60000个训练样本和10000个测试样本组成,每个样本都是一张28 * 28像素的灰度手写数字图片。

from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

load_data()函数就会自动从网上下载MNIST数据,加载(下载)数据时顺便做完了训练集(train set)和测试集(test set)的分割。

将训练数据和检测数据加载到内存中(第一次运行需要下载数据,会比较慢):
train_images是用于训练系统的手写数字图片;
train_labels是用于标注图片的信息;
test_images是用于检测系统训练效果的图片;
test_labelstest_images图片对应的数字标签。

2.2.2 对数据做基本确认(该步骤可有可无)

查看训练集和测试集的数据情况

print('train_images.shape = ',train_images.shape)
print('train_labels = ', train_labels)
print('test_images.shape = ', test_images.shape)
print('test_labels', test_labels)

打印结果:
train_images.shape =  (60000, 28, 28)
tran_labels =  [5 0 4 ... 5 6 8]
test_images.shape =  (10000, 28, 28)
test_labels [7 2 1 ... 4 5 6]
  1. train_images.shape打印结果表明,train_images是一个含有60000个元素的数组.数组中的元素是一个二维数组,二维数组的行和列都是28.也就是说,一个数字图片的大小是28*28.
  2. train_lables打印结果表明,第一张手写数字图片的内容是数字5,第二种图片是数字0,以此类推.
  3. test_images.shape的打印结果表示,用于检验训练效果的图片有10000张。
  4. test_labels输出结果表明,用于检测的第一张图片内容是数字7,第二张是数字2,依次类推。

查看测试集的第一张图片

digit = test_images[0]
import matplotlib.pyplot as plt
plt.imshow(digit, cmap=plt.cm.binary)
plt.show()

在这里插入图片描述

2.2.3 搭建神经网络

使用tensorflow.Keras搭建一个有效识别图案的神经网络

from tensorflow.keras import models
from tensorflow.keras import layers
#模型构建
network = models.Sequential()
#隐藏层结点个数为512,激活函数为relu,输入为一个28*28的图像	
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
#输出层 输出节点个数为10,结点映射到1到0之间
network.add(layers.Dense(10, activation='softmax'))
  1. layers:表示神经网络中的一个数据处理层。(dense:全连接层)

  2. models.Sequential():顺序模型,表示把每一个数据处理层串联起来,即通过一层层神经网络连接构建深度神经网络。通过model.add()叠加一些网络层如LSTM和Dense。

  3. layers.Dense(…):构造一个数据处理层。

  4. input_shape(28*28,):表示当前处理层接收的数据格式必须是长和宽都是28的二维数组,后面的“,“表示数组里面的每一个元素到底包含多少个数字都没有关系.

  5. softmax用于多分类过程中,它将多个神经元的输出映射到[0,1]区间内,故可以看成是某个类的概率,从而来进行多分类。假设我们有一个数组V,V_i表示V中的第i个元素,计算softmax值公式为:
    S i = e V i ∑ j e V i S_i=\frac{e^{V_i}}{\sum_je^{V_i}} Si=jeVieVi

搭建完模型后使用compile()函数进行编译

# 编译
network.compile(optimizer='rmsprop', loss='categorical_crossentropy',
               metrics=['accuracy'])

compile()函数参数介绍

  1. optimizer:优化器/优化算法
  2. loss:描述模型预测值与真实值的差距大小。两种常见的算法——均值平方差(MSE)和交叉熵。
  3. metric:在训练和测试过程中需要监控的指标/度量。正确分类的比例用"accuracy"即可。注意metrics参数的传递方法是指定一个列表,这意味着可以指定的性能度量项可以不限于一项。

2.2.4 数据标准化

将数据从二维数组变为一位数组,然后数据归一化处理(在把数据输入到网络模型之前)

train_images = train_images.reshape((60000, 28*28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28*28))
test_images = test_images.astype('float32') / 255
  1. reshape(60000, 28*28):train_images数组原来含有60000个元素,每个元素是一个28行,28列的二维数组,现在把每个二维数组转变为一个含有28*28个元素的一维数组.
  2. astype(“float32”)/255: 由于数字图案是一个灰度图,图片中每个像素点值的大小范围在0到255之间。/255就是把每个像素点的值从范围0-255转变为范围在0-1之间的浮点值。

把图片对应的标记也做一个更改(该步骤可有可无)

如果没有对标签进行处理,在预测推理时,只需使用argmax函数将概率最大的位置输出即可

from tensorflow.keras.utils import to_categorical
print("before change:" ,test_labels[0])
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
print("after change: ", test_labels[0])
运行结果:
before change: 7
after change:  [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]

to_categoricall(数据的类别标签, 总类别数):将类别标签向量转换为二进制(只有0和1)的矩阵类型表示。每一个标签用矩阵的对应的行向量来表示。

目前所有图片的数字图案对应的是0到9。例如test_images[0]对应的是数字7的手写图案,那么其对应的标记test_labels[0]的值就是7。我们需要把数值7变成一个含有10个元素的数组,然后在第8个元素设置为1,其他元素设置为0。test_lables[0] 的值由7转变为数组[0,0,0,0,0,0,0,1,0,0]

2.2.5 训练模型

把数据输入模型进行训练

#指定了训练5轮,小批量训练数据块大小为128个数据样本
network.fit(train_images, train_labels, epochs=5, batch_size = 128)

训练过程:
Epoch 1/5

  128/60000 [..............................] - ETA: 1:49 - loss: 2.3711 - acc: 0.0625
  384/60000 [..............................] - ETA: 44s - loss: 1.9454 - acc: 0.3516 
    ······
    ······
59520/60000 [============================>.] - ETA: 0s - loss: 0.0380 - acc: 0.9884
60000/60000 [==============================] - 5s 79us/sample - loss: 0.0379 - acc: 0.9885
  1. train_images:用于训练的手写数字图片;
  2. train_labels:对应的是图片的标记;
  3. epochs:每次计算的循环是五次
  4. batch_size:每次网络从输入的图片数组中随机选取128个作为一组进行计算。把batch_size传递给模型,它自动计算需要分为多少个mini-batch。如果除不尽的话,是向下取整,最后不足部分舍弃。
    • batch mode(批量模式):将整个数据集作为一个数据块训练。若batch_size等于训练集大小就是batch mode。
    • minibatch mode(小批量模式):分为多个数据块(通常是相同大小的)逐个处理。
    • stochastic mode:逐个数据进行训练处理。batch_size=1时的minibatch mode的特例。

2.2.6 性能评估

上一步骤已经训练好模型了,将测试数据输入,检验网络学习后的图片识别效果

test_loss, test_acc = network.evaluate(test_images, test_labels, verbose=1)
print(test_loss) 
print('test_acc', test_acc)
运行结果
0.07136689759036526
test_acc 0.9796

evaluate()函数用于进行模型性能评估,将test_images, test_labels一起传递给evaluate()函数即可。

识别效果与硬件有关(CPU/GPU).

2.2.7 预测推理

输入一张手写数字图片到网络中,看看它的识别效果

先来看看手写图片

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
digit = test_images[1]
plt.imshow(digit, cmap=plt.cm.binary)
plt.show()

在这里插入图片描述

将图片数据输入模型进行训练

test_images = test_images.reshape((10000, 28*28))
res = network.predict(test_images)#预测函数
#前面数据处理时,将训练集的数字变成了只含有0和1的数组,故此时模型输出的是一个10维向量,当哪个的概率最大时将对应位置的赋值为1
print(res[1])
print("the number for the picture is : ", res[1].argmax())
#for i in range(res[1].shape[0]):
#    if (res[1][i] == 1):
#        print("the number for the picture is : ", i)
#        break
        
运行结果:
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
the number for the picture is : 2
#the number for the picture is :  2

【代码实现】直接调用接口

from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print('train_images.shape = ',train_images.shape)
print('train_labels = ', train_labels)
print('test_images.shape = ', test_images.shape)
print('test_labels', test_labels)

digit = test_images[0]
import matplotlib.pyplot as plt
plt.imshow(digit, cmap=plt.cm.binary)
plt.show()


from tensorflow.keras import models
from tensorflow.keras import layers

network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
network.add(layers.Dense(10, activation='softmax'))

network.compile(optimizer='rmsprop', loss='categorical_crossentropy',
               metrics=['accuracy'])
      

train_images = train_images.reshape((60000, 28*28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28*28))
test_images = test_images.astype('float32') / 255


from tensorflow.keras.utils import to_categorical
print("before change:" ,test_labels[0])
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
print("after change: ", test_labels[0])


network.fit(train_images, train_labels, epochs=5, batch_size = 128)


test_loss, test_acc = network.evaluate(test_images, test_labels, verbose=1)
print(test_loss) 
print('test_acc', test_acc)


(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
digit = test_images[1]
plt.imshow(digit, cmap=plt.cm.binary)
plt.show()
test_images = test_images.reshape((10000, 28*28))
res = network.predict(test_images)
print(res[1])
#print("the number for the picture is : ", res[1].argmax())
for i in range(res[1].shape[0]):
    if (res[1][i] == 1):
        print("the number for the picture is : ", i)
        break
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃_早餐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值