内容简介:【CSDN 编者按】人工智能想入门深度学习?却苦恼网上的入门教程太零碎,不知道用什么框架好?本文作者用两万字手分别从百度的PaddlePaddle深度学习框架、Google的TensorFlow深度学习框架和快速实现原型的Keras框架,手把手教你学习!
【CSDN 编者按】人工智能想入门深度学习?却苦恼网上的入门教程太零碎,不知道用什么框架好?本文作者用两万字手分别从百度的PaddlePaddle深度学习框架、Google的TensorFlow深度学习框架和快速实现原型的Keras框架,手把手教你学习!
作者 | 张强
责编 | 伍杏玲
今天要给大家分享一个人工智能之深度学习领域的MNIST手写数字识别入门级教程,等等?
这跟那些网上一搜一大把的MNIST入门级教程有什么区别吗?
我想说的是,还真有很大的区别!
首先这是一个针对初学者入门级的训练MNIST模型教程,因为一般我们在网上搜索的教程都是零散的,没有比较整套的代码和说明教程。
我们本篇就将MNIST教程的简单及完整的代码用百度的PaddlePaddle深度学习框架、Google的TensorFlow深度学习框架和快速实现原型的Keras框架编写而成。
特写的优点:
-
从MNIST原始图像数据到最后使用训练的模型进行识别
-
三种深度学习框架使用统一的编程方式和流程实现
-
不仅仅是文字型介绍它们的区别,而是直接通过代码来看
-
模型训练完,如何去保存模型以及以后的使用
-
不需要一分钱即可在国内通过打开一个URL地址,就可以训练模型,免费的CPU服务器永久时长,免费的GPU V100 16GB服务器使用
-
看完本篇,你也不必纠结是使用PaddlePaddle、TensorFlow还是Keras
目录
我们来看下具体的六个步骤,每个步骤都将用三种方式实现:
-
一.运行环境
-
二.下载/加载数据集
-
三.随机预览图像
-
四.创建模型
-
五.训练/保存模型
-
六.测试模型
官网
-
PaddlePaddle: http://paddlepaddle.org/ 是一个由百度出品的基于产业实践的开源深度学习框架平台
-
TensorFlow:https://www.tensorflow.org/ 是一个由Google出品的端到端的开源机器学习框架平台
-
Keras:https://keras.io/ 是一个对TensorFlow,CNTK,Theano的高度封装的高级神经网络的API开源框架
今天本篇的教程就是围绕着这三个开源ML/DL Framework来讲的,不管是哪一种框架都可以实现你想要的模型,MNIST就是这样的一个简单的开始。
这三种开源框架都可以创建模型、训练模型、模型推理、上线部署等等一大堆功能。以下的内容每一段都是按照PaddlePaddle代码、TensorFlow代码和Keras代码的顺序而讲。
运行环境
1、PaddlePaddle代码
import numpy as np print(np.__version__) 1.15.4 import matplotlib print(matplotlib.__version__) 2.2.3 import paddle print(paddle.__version__) 1.4.0
PaddlePaddle的安装可以通过:
pip install paddlepaddle
2、TensorFlow代码
import numpy as np print(np.__version__) 1.15.4 import matplotlib print(matplotlib.__version__) 2.2.3 import tensorflow as tf print(tf.__version__) 1.13.1
TensorFlow的安装可以通过:
pip install tensorflow
3、Keras代码
import matplotlib print(matplotlib.__version__) 2.2.3 import numpy print(numpy.__version__) 1.15.4 import tensorflow print(tensorflow.__version__) 1.13.1 import keras print(keras.__version__) 2.2.4
Keras的安装可以通过:
pip install keras
因为我们用的是TensorFlow后端,所以安装完keras后需要再安装TensorFlow。
下载/加载数据集
1、PaddlePaddle代码
import paddle train = paddle.dataset.mnist.train() test = paddle.dataset.mnist.test()
调用这个train()函数就会主动去下载MNIST的训练集图像,test()函数就是下载测试集图像。如果已经下载过了,它就会从硬盘缓存中读取图像数据
通过查看变量train,得知它返回的是一个生成器,数据类型是reader :
train() 输出 <generator object reader_creator.<locals>.reader at 0x7f4d70c77e60>
然后再看下训练集和测试集共有多少张图像:
train_imgs = [img for img in train()] test_imgs = [img for img in test()] print("train_length={}, test_length={}".format(len(train_imgs), len(test_imgs))) 输出 train_length=60000, test_length=10000
60000张训练集图像,10000张测试集图像。
2、TensorFlow代码
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("data/data65/", one_hot=True)
read_data_sets()函数表示去下载数据集或者从指定文件夹下加载数据集,也就是说,MNIST数据集不存在就下载,存在就直接加载。
然后读取训练集、验证集和测试集图像数据 :
x_train, y_train = mnist.train.images, mnist.train.labels x_valid, y_valid = mnist.validation.images, mnist.validation.labels x_test, y_test = mnist.test.images, mnist.test.labels print("训练集图像大小:{}, 标签大小:{}".format(x_train.shape, y_train.shape)) print("验证集图像大小:{},标签大小:{}".format(x_valid.shape, y_valid.shape)) print("测试集图像大小:{},标签大小:{}".format(x_test.shape, y_test.shape))
输出是:
训练集图像大小:(55000, 784), 标签大小:(55000, 10) 验证集图像大小:(5000, 784),标签大小:(5000, 10) 测试集图像大小:(10000, 784),标签大小:(10000, 10)
55000张训练集图像,5000张验证集图像,10000张测试集图像。
3、Keras代码
import keras from keras.datasets import mnist (X_train, y_train), (X_test, y_test) = mnist.load_data()
load_data()函数就是加载MNIST图像数据集,如果本地缓存不存在数据集,就主动去在线下载;存在的话,就直接加载。
然后查看训练集和测试集图像数据的个数 :
print("X_train.shape={}, y_train.shape={}".format(X_train.shape, y_train.shape)) print("X_test.shape={}, y_test.shape={}".format(X_test.shape, y_test.shape))
输出:
X_train.shape=(60000, 28, 28), y_train.shape=(60000,) X_test.shape=(10000, 28, 28), y_test.shape=(10000,)
60000张训练集图像,10000张测试集图像。
4、小结:
通过PaddlePaddle、TensorFlow和Keras加载的MNIST图像数据集基本是6万张训练集和1万张测试集,只有TensorFlow会把6万张的训练集分出去5000张给验证集。
数据集的加载方式都是通过一开始是在线下载,当第二次加载图像时就可以从本地的硬盘缓存中查找图像数据集了。
MNIST图像数据集的官网是:http://yann.lecun.com/exdb/mnist/
它的标准图像张数就是60000张用来训练,和10000张用来测试。
随机预览图像
1、PaddlePaddle代码
首先随机从训练集图像中选择5张图像:
import random # 随机从数组中选择5张图像 random_5_imgs = random.sample(train_imgs, 5) # PaddlePaddle读取出来的数据是由一个个元组作为数组元素 # 每个元组的第一位为图像的向量,第二位是该向量对应的标签 vector = random_5_imgs[0][0] label = random_5_imgs[0][1] print("vector.shape={}, label={}".format(vector.shape, label)) vectors = [] labels = [] for vector, label in random_5_imgs: # 将每张图像向量转换成图像矩阵 vectors.append(vector.reshape((28,28))) labels.append(label) print("第一张图像的.shape是{}".format(vectors[0].shape))
输出:
vector.shape=(784,), label=6 第一张图像的.shape是(28, 28)
然后使用matplotlib绘图输出:
import matplotlib.pyplot as plt %matplotlib inline import numpy as np # 创建一个10x5大小的绘图对象 fig = plt.figure(figsize=(10, 5)) # 遍历5次,因为我们只随机选择了5张图像, # 所以这里显示的图像取决于每次随机的图像而变化 # 每次的图像显示的肯定不一样 for i in range(5): ax = fig.add_subplot(1, 5, i+1, xticks=[], yticks=[]) ax.imshow(np.reshape(vectors[i:i+1], (28, 28)), cmap='gray') print("图像对应的标签是{}。".format(labels))
输出:
2、TensorFlow代码
我们就从训练集图像中选择5张图像,这里选择的图像索引位置从10到15:
import matplotlib.pyplot as plt %matplotlib inline import numpy as np # 创建一个10x5大小的绘图对象 fig = plt.figure(figsize=(10, 5)) # 遍历5次,因为我们只随机选择了5张图像, # 所以这里显示的图像取决于每次随机的图像而变化 # 每次的图像显示的肯定不一样 for i in range(5): ax = fig.add_subplot(1, 5, i+1, xticks=[], yticks=[]) ax.imshow(np.reshape(vectors[i:i+1], (28, 28)), cmap='gray') print("图像对应的标签是{}。".format(labels))
输出:
3、Keras代码
我们就从训练集图像中选择5张图像,这里选择的图像索引位置从0到4 :
import matplotlib.pyplot as plt %matplotlib inline import numpy as np fig = plt.figure(figsize=(10, 10)) for i in range(5): ax = fig.add_subplot(1, 5, i+1) ax.imshow(np.reshape(X_train[i:i+1], (28, 28)), cmap='gray')
输出:
创建模型
1、PaddlePaddle代码
import paddle.fluid as fluid import numpy as np # 表示0到9的共10个数字,就是10个类别 num_classes = 10 # 我们使用CPU来训练模型 use_cuda = False place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() # 输入的原始图像数据,大小为28*28*1 X = fluid.layers.data(name="img", shape=[1, 28, 28], dtype=np.float32) # 输入的原始图像数据的标签 y = fluid.layers.data(name="label", shape=[1], dtype=np.int64) # 创建输出层,以softmax为激活函数的全连接层,输出层的大小必须为数字的个数10 # fc表示全连接层(fully connected layer) predict = fluid.layers.fc(input=X, size=num_classes, act="softmax") # 使用类交叉熵函数计算predict和y之间的损失函数 cost = fluid.layers.cross_entropy(input=predict, label=y) # 计算平均损失 avg_loss = fluid.layers.mean(cost) # 计算分类准确率 acc = fluid.layers.accuracy(input=predict, label=y) # 告知网络传入的数据分为两部分,第一部分是img值X,第二部分是label值y feeder = fluid.DataFeeder(feed_list=[X, y], place=place) # 选择Adam优化器,使损失最小化 optimizer = fluid.optimizer.Adam(learning_rate=0.001).minimize(avg_loss)
2、TensorFlow代码
# 超参数准备 img_size = 28 * 28 num_classes = 10 learning_rate = 0.1 # 创建模型 # x表示输入,创建输入占位符,该占位符会在训练时,会对每次迭代的数据进行填充上 x = tf.placeholder(tf.float32, [None, img_size]) # W表示weight,创建权重,初始化时都是为0,它的大小是(图像的向量大小,图像的总类别) W = tf.Variable(tf.zeros([img_size, num_classes])) # b表示bias,创建偏移项 b = tf.Variable(tf.zeros([num_classes])) # y表示计算输出结果,softmax表示激活函数是多类别分类的输出 # 感知器的计算公式就是:(x * W) + b y = tf.nn.softmax(tf.matmul(x, W) + b) # 定义输出预测占位符y_ y_ = tf.placeholder(tf.float32, [None, 10]) # 通过激活函数softmax的交叉熵来定义损失函数 cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)) # 定义梯度下降优化器 optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) # 比较正确的预测结果 correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) # 计算预测准确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
3、Keras代码
因为Keras将MNIST图像数据集加载到内存时是原生的图像数据,没有经过任何预处理,而PaddlePaddle和TensorFlow在加载时就做了处理。
所以这里我们需要将Keras加载的数据做预处理。
分割测试集为一半是验证集,另一半是测试集:
valid_len = int(X_test.shape[0] / 2) X_valid = X_test[:valid_len] y_valid = y_test[:valid_len] X_test = X_test[valid_len:] y_test = y_test[valid_len:] print("X_train.shape={}, y_train.shape={}".format(X_train.shape, y_train.shape)) print("X_valid.shape={}, y_valid.shape={}".format(X_valid.shape, y_valid.shape)) print("X_test.shape={}, y_test.shape={}".format(X_test.shape, y_test.shape))
输出:
X_train.shape=(60000, 28, 28), y_train.shape=(60000,) X_valid.shape=(5000, 28, 28), y_valid.shape=(5000,) X_test.shape=(5000, 28, 28), y_test.shape=(5000,)
图像数据预处理:
import numpy as np img_size = 28 * 28 num_classes = 10 # 将训练集、验证集和测试集数据进行图像向量转换 X_train = X_train.reshape(X_train.shape[0], img_size) X_valid = X_valid.reshape(X_valid.shape[0], img_size) X_test = X_test.reshape(X_test.shape[0], img_size) # 将训练集、验证集和测试集数据都转换成float32类型 X_train = X_train.astype(np.float32) X_valid = X_valid.astype(np.float32) X_test = X_test.astype(np.float32) # 将训练集、验证集和测试集数据都转换成0到1之间的数值,就是归一化处理 X_train /= 255 X_valid /= 255 X_test /= 255 # 通过to_categorical()函数将训练集标签、验证集标签和测试集标签独热编码(one-hot encoding) y_train = keras.utils.to_categorical(y_train, num_classes) y_valid = keras.utils.to_categorical(y_valid, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes)
创建Keras的多层感知器模型:
from keras import Sequential from keras.layers import Dense, Dropout # 创建Sequential模型 model = Sequential() # 创建输入层,有512个深度,必须要传的参数是input_shape,它表示输入的图像的大小 model.add(Dense(512, activation='relu', input_shape=(img_size,))) model.add(Dropout(0.2)) # 创建一个隐藏层,也有512个深度 model.add(Dense(512, activation='relu')) model.add(Dropout(0.2)) # 添加输出层,因为有10个类别的概率输出,所以使用softmax model.add(Dense(num_classes, activation='softmax')) # 模型架构预览 model.summary()
输出:
Layer (type) Output Shape Param # ================================================================= dense_1 (Dense) (None, 512) 401920 _________________________________________________________________ dropout_1 (Dropout) (None, 512) 0 _________________________________________________________________ dense_2 (Dense) (None, 512) 262656 _________________________________________________________________ dropout_2 (Dropout) (None, 512) 0 _________________________________________________________________ dense_3 (Dense) (None, 10) 5130 ================================================================= Total params: 669,706 Trainable params: 669,706 Non-trainable params: 0 _________________________________________________________________
训练/保存模型
1、PaddlePaddle代码
首先创建执行器、主程序和测试程序:
# 创建执行器 executor = fluid.Executor(place) executor.run(fluid.default_startup_program()) # 设置 main_program 和 test_program main_program = fluid.default_main_program() test_program = fluid.default_main_program().clone(for_test=True)
然后创建一个在训练模型时定期评估模型的函数test_loss_acc():
def test_loss_acc(test_program, test_reader, test_feeder): """ 在训练模型时,计算测试集的损失值和精确度 """ loss_arr = [] accuracy_arr = [] # 开始迭代测试loss和acc for test_data in test_reader(): # 在Paddle中推理计算loss和acc _loss, _acc = executor.run(test_program, feed=test_feeder.feed(test_data), fetch_list=[avg_loss, acc]) loss_arr.append(float(_loss)) accuracy_arr.append(float(_acc)) # 获得测试数据集上的准确率和损失值的均值 loss_mean = np.array(loss_arr).mean() accuracy_mean = np.array(accuracy_arr).mean() return loss_mean, accuracy_mean
将数据集分成多个batch,根据计算得来。
通过batch返回数据集的总数量除以64的每批次数,所以:
训练集的batch的数量就是 60000 / 64 = 937.5 向上取整等于938。
测试集的batch的数量就是 10000 / 64 = 156.25 向上取整等于157
。BATCH_SIZE = 64 train_reader = paddle.batch(paddle.reader.shuffle(train, buf_size=500), batch_size=BATCH_SIZE) test_reader = paddle.batch(paddle.reader.shuffle(test, buf_size=500), batch_size=BATCH_SIZE) train_reader_length = len([1 for _ in train_reader()]) test_reader_length = len([1 for _ in test_reader()]) print("train_reader分了{}个batch,test_reader分了{}个batch。".format(train_reader_length, test_reader_length))
输出:
train_reader分了938个batch,test_reader分了157个batch。
训练模型
-
我们通过5个epoch就可以训练出一个Accuracy还不错的模型;
-
在训练模型期间,总是保存模型到指定路径,即saved_model_filename变量;
-
在每训练100个进度的时候,我们打印一次日志显示它的训练效果,训练集和测试的loss和acc;
-
最后训练完,我们也通过fluid.io.save_inference_mode()函数将模型保存了起来。
epochs = 5
saved _model_ filename = "mnist.inference.model"
result_arr = []
step = 0
# 开始迭代训练模型
for epoch_id in range(epochs):
# 遍历训练集数据
for step _i, data in enumerate(train_ reader()):
# 训练模型
metrics = executor.run(main_program,
feed=feeder.feed(data),
fetch _list=[avg_ loss, acc])
# 每训练100次打印一次日志
if step % 100 == 0:
loss _train, accuracy_ train = metrics[ 0 ][ 0 ], metrics[ 1 ][ 0 ]
print("Train Epoch {}, step _i {}, loss {}, acc {}".format(epoch_ id,
step,
metrics[ 0 ][ 0 ],
metrics[ 1 ][ 0 ]))
# 评估测试集的分类效果
loss _val, accuracy_ val = test _loss_ acc(test _program, test_ reader, feeder)
print("Valid Epoch {}, step _i {},loss {},acc {}".format(epoch_ id,
step,
loss_val,
accuracy_val))
step += 1
result _arr.append((epoch_ id, loss _val, accuracy_ val, loss _train, accuracy_ train))
# 保存训练好的模型参数用于预测
fluid.io.save _inference_ model(saved _model_ filename,
["img"],
[predict],
executor,
model_filename=None,
params_filename=None)
输出:
Train Epoch 0, step_i 0, loss 3.662783145904541, acc 0.0625 Valid Epoch 0, step_i 0,loss 0.9381991980751608,acc 0.7200437898089171 Train Epoch 0, step_i 100, loss 0.4590408504009247, acc 0.890625 ...... Train Epoch 4, step_i 4500, loss 0.350452721118927, acc 0.90625 Valid Epoch 4, step_i 4500,loss 0.19813986520051577,acc 0.9416799363057324 Train Epoch 4, step_i 4600, loss 0.1873813271522522, acc 0.9375 Valid Epoch 4, step_i 4600,loss 0.19667905686529957,acc 0.9430732484076433
最后一次训练获得了训练集精确度是93.75%,验证集精确度是94.30%,
然后我们看下整个训练过程的loss和acc的绘图。
先获取最佳的loss和acc:
best_predict = sorted(result_arr, key=lambda ele:float(ele[1]))[0] print("Valid Loss {}, Acc {:.5f}%.".format(best_predict[1], float(best_predict[2])*100)) print("Train Loss {}, Acc {:.5f}%.".format(best_predict[3], float(best_predict[4])*100))
输出:
Valid Loss 0.19667905686529957, Acc 94.30732%. Train Loss 0.1873813271522522, Acc 93.75000%.
绘图显示:
import matplotlib.pyplot as plt %matplotlib inline # 将训练时记录的loss和acc的数组的每一列都取出来 result_np = np.array(result_arr) # 索引为1的就是验证集loss loss_val = result_np[:,1] # 索引为2的就是验证集的acc accuracy_val = result_np[:,2] # 索引为3的就是训练集loss loss_train = result_np[:,3] # 索引为4的就是训练集acc accuracy_train = result_np[:,4] # 绘制训练集和验证集的损失值 plt.plot(loss_train) plt.plot(loss_val) plt.title('Model Loss') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show() # 绘制训练集和验证集的精确度 plt.plot(accuracy_val) plt.plot(accuracy_train) plt.title('Model Accuracy') plt.ylabel('Accuracy') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show()
输出:
2、TensorFlow代码
我们使用了100个epoch来训练所有的图像数据集,每个batch分成了128个大小。
跟PaddlePaddle一样,通过两次for循环,外循环是来训练在一次epoch内,所有的MNIST图像都需要训练一遍,然后共训练100次;内循环是来将一个epoch,所有的MNIST图像,根据batch_size大小分成多个批次,来一批次批次的训练。
最后将训练好的模型检查点通过saver.save()函数保存到本地硬盘:
import math epochs = 100 batch_size = 128 iteration = 0 # 定义训练时的检查点 saver = tf.train.Saver() valid_feed_dict = { x: x_valid, y_: y_valid } test_feed_dict = { x: x_test, y_: y_test } history_train = [] history_valid = [] # 创建一个TensorFlow的会话 with tf.Session() as sess: # 初始化全局变量 sess.run(tf.global_variables_initializer()) # 根据每批次训练128个样本,计算出一共需要迭代多少次 batch_count = int(math.ceil(mnist.train.labels.shape[0] / 128.0)) # 开始迭代训练样本 for e in range(epochs): # 每个样本都需要在TensorFlow的会话里进行运算,训练 for batch_i in range(batch_count): # 样本的索引,间隔是128个 batch_start = batch_i * batch_size # 取出图像样本 batch_x = mnist.train.images[batch_start:batch_start+batch_size] # 取出图像对应的标签 batch_y = mnist.train.labels[batch_start:batch_start+batch_size] # 训练模型 loss, acc, _ = sess.run([cost, accuracy, optimizer], feed_dict={x: batch_x, y_: batch_y}) # 每100个批次时输出一次训练损失等日志信息 if batch_i % 100 == 0: print("Epoch: {}/{}".format(e+1, epochs), "Iteration: {}".format(iteration), "Train loss: {:.5f}".format(loss), "Train acc: {:.5f}".format(acc)) history_train.append((iteration, loss, acc)) iteration += 1 # 每128个样本时,验证一下训练的效果如何,并输出日志信息 if iteration % batch_size == 0: valid_loss, valid_acc = sess.run([cost, accuracy], feed_dict=valid_feed_dict) print("Epoch: {}/{}".format(e, epochs), "Iteration: {}".format(iteration), "Valid Loss: {:.5f}".format(valid_loss), "Valid Acc: {:.5f}".format(valid_acc)) history_valid.append((iteration, valid_loss, valid_acc)) # 保存训练模型的检查点 saver.save(sess, "checkpoints/mnist_mlp_tf.ckpt")
输出:
Epoch: 1/100 Iteration: 0 Train loss: 2.30259 Train acc: 0.11719 Epoch: 1/100 Iteration: 100 Train loss: 2.08399 Train acc: 0.50781 Epoch: 0/100 Iteration: 128 Valid Loss: 1.97898 Valid Acc: 0.63220 ...... Epoch: 100/100 Iteration: 42870 Train loss: 1.50794 Train acc: 0.96875 Epoch: 99/100 Iteration: 42880 Valid Loss: 1.54402 Valid Acc: 0.92800 Epoch: 100/100 Iteration: 42970 Train loss: 1.57890 Train acc: 0.89062
最后一次训练获得了训练集精确度是89.06%,验证集精确度是92.80%。然后我们将训练时记录的loss和acc绘图出来 :
import matplotlib.pyplot as plt %matplotlib inline import numpy as np # 绘制训练集和验证集的损失值 plt.plot(np.array(history_train)[:,1]) plt.plot(np.array(history_valid)[:,1]) plt.title('Model Loss') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show() # 绘制训练集和验证集的精确度 plt.plot(np.array(history_train)[:,2]) plt.plot(np.array(history_valid)[:,2]) plt.title('Model Accuracy') plt.ylabel('Accuracy') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show()
输出:
3、Keras代码
先编译模型,编译模型时,指定优化器、损失函数和度量方式的参数 :
from keras.optimizers import RMSprop model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])
然后训练模型:
epochs = 20 batch_size = 128 history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, verbose=1, validation_data=(X_valid, y_valid))
输出:
Train on 60000 samples, validate on 5000 samples Epoch 1/20 60000/60000 [==============================] - 9s 150us/step - loss: 0.2438 - acc: 0.9242 - val_loss: 0.1313 - val_acc: 0.9592 Epoch 2/20 60000/60000 [==============================] - 9s 146us/step - loss: 0.1012 - acc: 0.9691 - val_loss: 0.1032 - val_acc: 0.9692 Epoch 3/20 ...... 60000/60000 [==============================] - 9s 146us/step - loss: 0.0190 - acc: 0.9948 - val_loss: 0.1506 - val_acc: 0.9756 Epoch 19/20 60000/60000 [==============================] - 9s 145us/step - loss: 0.0174 - acc: 0.9953 - val_loss: 0.1456 - val_acc: 0.9776 Epoch 20/20 60000/60000 [==============================] - 9s 152us/step - loss: 0.0182 - acc: 0.9955 - val_loss: 0.1736 - val_acc: 0.9758
最后一次训练获得了训练集精确度是99.55%,验证集精确度是97.58%。然后我们将训练时记录的loss和acc绘图出来:
import matplotlib.pyplot as plt %matplotlib inline # 绘制训练集和验证集的精确度 plt.plot(history.history['acc']) plt.plot(history.history['val_acc']) plt.title('Model Accuracy') plt.ylabel('Accuracy') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show() # 绘制训练集和验证集的损失值 plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) plt.title('Model Loss') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend(['train', 'test'], loc='upper left') plt.show()
输出:
测试模型
1、PaddlePaddle代码
比如我们选择一张图像,看看它是几?
import matplotlib.pyplot as plt import matplotlib.image as mpimg img_matrix = next(train())[0].reshape(28, 28) img_label = next(train())[1] imgplot = plt.imshow(img_matrix, cmap="gray") plt.show() print("这张图像的标签是{}。".format(img_label))
输出:
然后推理这张图像是多少。首先创建执行器,然后把上面训练的模型文件加载进来,再通过run()函数来推理计算识别到的概率。
最后推理出来的概率是标签5,跟真实的标签一致,这就完全正确!
# 创建执行器 test_executor = fluid.Executor(place) test_executor.run(fluid.default_startup_program()) inference_scope = fluid.core.Scope() with fluid.scope_guard(inference_scope): # 加载模型 [inference_program, feed_target_names, fetch_targets] = \ fluid.io.load_inference_model(saved_model_filename, test_executor, None, None) # 运行推理图像 results = test_executor.run(inference_program, feed={feed_target_names[0]: img_matrix.reshape(1,1,28,28)}, fetch_list=fetch_targets) # 预测的标签 predicted_label = np.argmax(results[0][0]) # 预测概率 predicted_prob = max(results[0][0]) print("Accuracy = {}, Label = {}".format(predicted_prob, predicted_label)) 输出 Accuracy = 0.9278314113616943, Label = 5
2、TensorFlow代码
假设我们就读取测试集中索引为21的图像,看看它是几?
import matplotlib.pyplot as plt import matplotlib.image as mpimg target_label_index = 21 index_21_img = x_test[target_label_index].reshape(28, 28) imgplot = plt.imshow(index_21_img, cmap="gray") plt.show()
输出:
它对应的标签是多少了?
target_label_arr = y_test[target_label_index] target_label = np.argmax(target_label_arr) print("索引为21的图像是数字{}。".format(target_label))
输出:索引为21的图像是数字6。
然后推理计算,将模型检查点文件加载进来,构建计算图,然后从模型架构中所有的operation中查找最后的分类器,因为我们的模型最后一层是softmax激活函数,所以我们通过graph.get_operations()函数遍历出来,找到Softmax那一层,将它读取出来,就是我们要放到run()函数的第一个参数,即classifier。
最后得到的预测是数字6,完全正确!
checkpoint_file = tf.train.latest_checkpoint("checkpoints") graph = tf.get_default_graph() with graph.as_default(): sess = tf.Session() with sess.as_default(): saver = tf.train.import_meta_graph("{}.meta".format(checkpoint_file)) saver.restore(sess,checkpoint_file) # for op in graph.get_operations(): # print(op.name) softmax_classifer = graph.get_operation_by_name("Softmax").outputs[0] index_10_img_to_predict = x_test[target_label_index].reshape((1, 784)) predicted_result = sess.run([softmax_classifer], feed_dict={x: index_10_img_to_predict}) print(predicted_result) print("预测的数字是{}。".format(np.argmax(predicted_result))) 输出 INFO:tensorflow:Restoring parameters from checkpoints/mnist_mlp_tf.ckpt [array([[1.6478752e-07, 1.8716774e-10, 1.4367420e-05, 7.6656121e-08, 7.3713923e-06, 2.4220503e-04, 9.9968493e-01, 6.0247163e-13, 5.0681083e-05, 1.7343659e-07]], dtype=float32)]
预测的数字是6。
3、Keras代码
假设我们就读取测试集中索引为10的图像,看看它是几?
import matplotlib.pyplot as plt import matplotlib.image as mpimg index_10_img = X_test[10].reshape(28, 28) imgplot = plt.imshow(index_10_img, cmap="gray") plt.show()
输出:
然后看下这张图像的真实标签是多少:
target_label_arr = y_test[10] target_label = np.argmax(target_label_arr) print("索引为10的图像是数字{}。".format(target_label))
输出:
索引为10的图像是数字6。
最后使用Keras来的模型predict()函数来计算概率,跟真实的标签是一致的,模型预测的完全正确!
index_10_img_to_predict = X_test[10].reshape((1, 784)) predictions = model.predict(index_10_img_to_predict) print("预测的结果是{}。".format(np.argmax(predictions[0])))
输出:
预测的结果是6。
总结
一开始我们通过PaddlePaddle、TensorFlow和Keras各自的API读取MNIST数据集,然后又各自预览了5张随机图像,然后就创建神经网络模型,PaddlePaddle和TensorFlow都是一层神经网络模型,而Keras是三层神经网络模型。
然后我们通过各自的API来训练模型,PaddlePaddle和TensorFlow都是能高度自定义模型的,所以代码略微多;而Keras训练模型就比较简单,通过一个fit()函数就能完成。
接着,对于三种模型,我们在训练时记录了它们的loss和acc,所以就绘图展示了各自的训练表现。
最后,我们将各自训练的模型都通过任意选择一张图片来识别它是数字几,概率是多少?
关于本篇的三个代码文件,可以去百度AI Studio上上手操作,地址是:
https://aistudio.baidu.com/aistudio/#/education/teacher/dashboard
登录后,进入这个2019年的班级,在线训练模型,显示的有效期时间是5月份,其实这个是平台的限制,我会将这个时间调整始终有效,它快到时间了我们再次增加/调整时间。
作者简介: 张强,CSDN博客专家,现任特拉字节(北京)科技有限公司创始人兼CTO,曾任职奇虎360企业安全集团蓝信团队高级研发工程师,知乎主前端高级研发工程师,多家国内一线互联网知名企业任职研发部门。
【END】
作为码一代,想教码二代却无从下手:
听说少儿编程很火,可它有哪些好处呢?
孩子多大开始学习比较好呢?又该如何学习呢?
最新的编程教育政策又有哪些呢?
下面给大家介绍CSDN新成员: 极客宝宝(ID: geek_baby)
戳他了解更多↓↓↓
热 文推 荐
☞ 移动互联网这十年
☞ 调查 10,000 名学生开发者:65% 自学成才,学 6 门编程语言!
☞ 独家! 币安被盗原因找到了! 7074枚比特币竟是这样丢掉的
☞ 补偿100万?Oracle裁900+程序员,新方案已出!
你点的每个“在看”,我都认真当成了喜欢
以上所述就是小编给大家介绍的《2 万字全面测评深度学习框架 PaddlePaddle、TensorFlow 和 Keras | 程序员硬核评测》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 全方位测评Hive、SparkSQL、Presto 等七个大数据查询引擎,最快的竟是……| 程序员硬核测评
- 中国信息安全测评中心石竑松:密码模块安全测评的思路和方法
- 2020 前端框架测评总结
- 2018阿里前端测评
- 战争迷雾开源库测评
- 麦昆小车 - 测评
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
无懈可击的Web设计
西德霍姆 / 刘建宁 / 清华大学出版社 / 2009-4 / 59.90元
一个网站,无论视觉上多么美观,内容多么丰富,如果不能面向最广泛的用户群,那它就不算是真正成功的网站。《无懈可击的Web设计:利用XHTML和CSS提高网站的灵活性与适应性》是Web标准设计领域的公认专家Dan Cederholm的倾力之作,向您描述了基于Web标准的设计策略,以适应各种各样的用户浏览方式。书中每一章的开头都给出了一个基于传统HTML技术的实例,然后对它进行重构,指出它的局限性,并利......一起来看看 《无懈可击的Web设计》 这本书的介绍吧!