导语:WolfgangBeyer的一篇优秀的博文,详细介绍了如何使TensorFlow搭建一个简单的图像识别系统。
本篇主要对该教程实践过程做了简单的整理。
首先,定义一个通用的数学模型,将输入图像转换为输出标签。
这个模型的实际输出不仅仅依赖于图像本身,还依赖模型内建的参数。这些参数并不是由我们提供,而是由计算机通过学习获得。
这个过程可以被理解为一个参数的优化问题,主要步骤如下:
上述学习过程即监督学习—输入包括数据以及标签。
注意:cifar-10-batches-py需要解压到python源代码的目录下,其余工具及环境自行配置
https://github.com/wolfib/image-classification-CIFAR10-tf
代码分析过程中主要通过代码+注释的形式,请不要忽略注释。
在这个过程中不执行任何操作
1. 导入需要的包
# 为了python2和python3的兼容性
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import time
import data_helpers #包内函数主要用于加载和处理数据集的函数
读取数据部分的函数单独放在data_helper.py文件中,负责读取包含数据集的文件,并把数据放入一个方便我们操作的数据结构中。
2. 准备数据集
data_sets = data_helpers.load_data()
load_data()将数据集进行处理,返回一个dictionary类型数据,便于训练时喂养模型使用:
值得注意的是,load_data()函数将60000幅图像分为训练集和测试集。训练集包含50000幅图像,用于训练我们的模型。测试集包含1000幅图像,用于训练完成后检验模型的性能。
3. 定义训练恒参
# Parameter definitions
batch_size = 100 #将数据集随机分批喂给模型,每批100个数据
learning_rate = 0.005 #梯度优化时的学习速率
max_steps = 1000 #训练次数
4.定义模型内建参数
# Define variables (these are the values we want to optimize)
weights = tf.Variable(tf.zeros([3072, 10])) #3072*10的零矩阵
biases = tf.Variable(tf.zeros([10])) #大小为10的列表
内建参数就是我们在训练过程中想要优化的参数。我们将每幅图像以3072个浮点数(size=3027的列表)表示,作为输入;最终结果以10个浮点数(size=10的列表)表示每个种类的得分。
5.定义placeholder用于接收数据集
images_placeholder = tf.placeholder(tf.float32, shape=[None, 3072])
labels_placeholder = tf.placeholder(tf.int64, shape=[None])
placeholder主要在需要运行时给节点输入数据时使用。在这里相当于提供了一个接收训练数据输入的接口,每次训练需要输入数据时只需要使用feed_dict={images_placeholder: , labels_placeholder: }即可。
6.定义用于描述模型预测结果的表达式
logits = tf.matmul(images_placeholder, weights) + biases
7.定义预测结果与真实值之间的损失量表达式
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,
labels=labels_placeholder)) #tf.reduce_mean求损失值均值,softmax函数将logits转化为概率值,能表示特征的输出。
将预测值与正确的分类标签进行比较,损失越小表示预测值越接近正确标签。
8.定义对损失值做梯度下降优化的动作
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
9.定义计算准确率的表达式
#tf.argmax(x,1)按行找,找到每一行中最大数值的下标,返回结果是一个列表
#correct_prediction是一个布尔型
correct_prediction = tf.equal(tf.argmax(logits, 1), labels_placeholder)
#tf.cast(x,dtype)将x转换为dtype数据格式
#计算平均准确度/平均分
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
将操作的执行放在Session会话中进行。
1.对所有变量完成初始化
sess.run(tf.global_variables_initializer())
2.循环迭代,每次随机抽取一批数据喂养模型
for i in range(max_steps):
# Generate input data batch
indices = np.random.choice(data_sets['images_train'].shape[0], batch_size)
images_batch = data_sets['images_train'][indices]
labels_batch = data_sets['labels_train'][indices]
# 每100次迭代,对模型训练数据批的当前精确率进行检查。直接调用先前定义的精确率操作来完成。
if i % 100 == 0:
train_accuracy = sess.run(accuracy, feed_dict={
images_placeholder: images_batch, labels_placeholder: labels_batch})
print('Step {:5d}: training accuracy {:g}'.format(i, train_accuracy))
# Perform a single training step
sess.run(train_step, feed_dict={images_placeholder: images_batch,
labels_placeholder: labels_batch})
每次训练随机抽取训练数据中的一批图像。每训练一批数据都会更新一遍模型的参数,因此批的大小代表了参数更新的频率。
批的大小需要选择相对合适的值,如果太大,每次迭代参数的更新都需要大量的计算;如果太小,会造成高频率的参数更新,但更有可能向错误的方向频繁修正。
在这个模型中,每次训练的数据大小为0-batch_size之间随机指定的一个值。
3.训练完成后,使用测试数据集测试模型效果
test_accuracy = sess.run(accuracy, feed_dict={
images_placeholder: data_sets['images_test'],
labels_placeholder: data_sets['labels_test']})
print('Test accuracy {:g}'.format(test_accuracy))
在命令行模式中,python softmax.py
运行softmax.py脚本,通过打印的training accuracy,我们可以看到两点: