机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(二)| 干货

本文涉及的产品
图像搜索,7款服务类型 1个月
简介:

现在,我们可以开始建立我们的模型啦。实际上数值计算都是由TensorFlow来完成,它使用了一个快速并高效的C++后台程序。TensorFlow希望避免频繁地在Python和C++之间切换,因为那样会降低计算速度。一般的工作流程是,首先为了定义所有的运算,先建立一个TensorFlow图表。在这个过程中没有计算,我们只是进行设置操作。之后,我们才针对输入数据运行计算操作并记录结果。

让我们开始定义我们的图表。首先通过创建占位符来描述TensorFlow输入数据的形式。占位符不包括任何实际数据,它们只是定义了数据的类型和形状。

在我们的模型中,我们首先为图像数据定义了占位符,它们包括浮点数据(tf.float32)。shape参数定义了输入数据的大小。我们将同时输入多幅图像(稍后我们将谈到这些处理),但是我们希望可以随时改变实际输入图像的个数。所以第一项shape参数为none,这代表大小可以是任何长度。第二项参数是3072,这是每幅图像的浮点值。

分类标签的占位符包括整型数据(tf.int64),每幅图像都有0到9的一个值。因为我们没有指定输入图像的个数,所以shape参数为[none]。

# Define variables (these are the values we want to optimize)

weights = tf.Variable(tf.zeros([3072, 10]))

biases = tf.Variable(tf.zeros([10]))

weights和biases是我们希望优化的变量。但现在还是先谈谈我们的模型吧。

我们的输入包括3072个浮点数据,而希望实现的输出是10个整型数据中的一个。我们怎么把3072个值变成一个呢?让我们退后一步,如果不是输出0到9中的一个数字,而是进行打分,得到10个数字-每个种类一个分数-我们挑选出得分最高的一个种类。所以我们最初的问题就变成了:如何从将3072个值变成10个值。

我们所采取的一种简单的方法是单独查询每个像素。对每一个像素(或更准确点,每个像素的颜色通道)和每个可能的种类,我们问自己是否这个像素的颜色增加或减少了它属于某个种类的可能性。比如说像素颜色是红色。如果汽车图片的像素通常是红色,我们希望增加“汽车”这一种类的得分。我们将像素是红色通道的值乘以一个正数加到“汽车”这一类的的得分里。同样,如果在位置1的地方,马的图像从来不或很少出现红色像素,我们希望将分类为“马”的分数维持在低分或再降低一些。也就是说乘以一个较小的数或者负数后加到分类为“马”的分数里。对所有的10个分类我们都重复这样的操作,对每一个像素重复计算,3072个值进行相加得到一个总和。3072个像素的值乘以3072个加权参数值得到这一分类的得分。最后我们得到10个分类的10个分数。然后我们挑选出得分最高的,将图像打上这一类型的标签。


机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(二)| 干货

一幅图像通过一个3072个值的一维数组来表示。每个值乘以一个加权参数,将所有值相加得到一个数值-特定种类的分值。

我们可以用矩阵的方法,这样使用像素值乘以加权值再相加的过程大大简化。我们的图像通过一个3072维向量表示。如果我们将这个向量乘以一个3072x10的加权矩阵,结果就是一个10维向量。它包括了我们需要的加权和。


机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(二)| 干货

通过矩阵乘法计算一个图像在所有10个类别中的分数。

3072x10矩阵中的具体值就是我们模型的参数。如果它没有规律或毫无用处,那我们的输出也是一样。这就需要训练数据参与工作。通过查询训练数据,我们希望模型能自己计算出最后的参数。

上面这两行代码里,我们告诉TensorFlow,加权矩阵的大小是3072x10,初始值都被设置为0。另外,我们定义了第二个参数,一个包含偏差值的10维向量。这个偏差值并不直接作用于图像数据,而仅仅是与加权和相加。这个偏差值可以被看做是最后得分的一个起始点。想象一下,一副全黑的图片,所有像素的只都是0。那么不管加权矩阵的只是多少,所有分类的得分都是0。通过偏差值,我们则可以保证我们的每一分类的起始值不是0。

# Define the classifier's result

logits = tf.matmul(images_placeholder, weights) + biases

下面就要讲到预测。通过这一步,我们已经确定了多幅图像向量和矩阵的维度。这个操作的结果就是每幅输入图像都有一个10维向量。


机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(二)| 干货

通过矩阵乘法,计算多幅图像的所有10个分类的分数。

# Define the loss function

loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits,labels_placeholder))

weights和bias参数逐渐优化的过程叫做训练,它包括以下步骤:第一,我们输入训练数据让模型根据当前参数进行预测。将预测值与正确的分类标签进行比较。比较的数值结果被叫做损失。越小的损失值表示预测值与正确标签越接近,反之亦然。我们希望将模型的损失值降到最小,让预测值与真实标签更接近。但是在我们将损失最小化之前,先来看看损失是怎么计算出来的。

前一步计算出来的分数被存储在logits变量里,包含任意实数。我们可以调用softmax函数将这些值转化成概率值(0到1之间的实数,总和为1),这样将输入转变成能表示其特征的输出。相对应的输入排列保持不变,原本得分最好的分类拥有最大的概率。softmax函数输出的概率分布与真实的概率分布相比较。在真实的概率分布中正确的类别概率为1,其他类别的概率为0。我们使用交叉熵来比较两种概率分布(更多技术性的解释可以在这里找到)。交叉熵越小,预测值的概率分布与正确值的概率分布的差别就越小。这个值代表了我们模型的损失。

幸运的是TensorFlow提供了一个函数帮我们完成了这一系列的操作。我们比较模型预测值logits和正确分类值labels_placeholder。sparse_softmax_cross_entropy_with_logits()函数的输出就是每幅输入图像的损失值。然后我们只需计算输入图像的平均损失值。

# Define the training operation

train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

但是我们如何调整参数来将损失最小化呢?TensorFlow这时就大发神威了。通过被称作自动分化(auto-differentiation)的技术,它可以计算出相对于参数值,损失值的梯度。这就是说它可以知道每个参数对总的损失的影响,小幅度的加或减参数是否可以降低损失。然后依此调整所有参数值,增加模型的准确性。在完成参数调整之后,整个过程重新开始,新的一组图片被输入到模型中。

TensorFlow知道不同的优化技术可以将梯度信息用于更新参数值。这里我们使用梯度下降算法。在决定参数是,它只关心模型当前的状态,而不去考虑以前的参数值。参数下降算法只需要一个单一的参数,学习率,它是参数更新的一个比例因子。学习率越大,表示每一步参数值的调整越大。如果学习率过大,参数值可能超过正确值导致模型不能收敛。如果学习率过小,模型的学习速度会非常缓慢,需要花很长时间才能找到一个好的参数值。

输入图像分类,比较预测结果和真实值,计算损失和调整参数的过程需要重复多次。对于更大,更复杂的模型,这个计算量将迅速上升。但是对于我们的简单模型,我们既不需要考验耐心也不需要专门的硬件设备就可以得到结果。

# Operation comparing prediction with true label

correct_prediction = tf.equal(tf.argmax(logits, 1), labels_placeholder)

 

# Operation calculating the accuracy of our predictions

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

这两行代码用于检验模型的精确度。logits的argmax返回分数最高的分类。这就是预测的分类标签。tf.equal()将这个标签与正确的分类标签相比较,然后返回布尔向量。布尔数转换为浮点数(每个值不是0就是1),这些数求平均得到的分数就是正确预测图像的比例。

# -----------------------------------------------------------------------------

# Run the TensorFlow graph

# -----------------------------------------------------------------------------

 

with tf.Session() as sess:

  # Initialize variables

  sess.run(tf.initialize_all_variables())

 

  # Repeat max_steps times

  for i in range(max_steps):

最后,我们定义了TensorFlow图表并准备好运行它。在一个会话控制中运行这个图表,可以通过sess变量对它进行访问。运行这个会话控制的第一步就是初始化我们早先创建的变量。在变量定义中我们指定了初始值,这时就需要把这些初始值赋给变量。

然后我们开始迭代训练过程。它会重复进行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]

这几行代码随机抽取了训练数据的几幅图像。从训练数据中抽取的几幅图像和标签被称作批。批的大小(单个批中图像的数量)告诉我们参数更新的频率。我们首先对批中所有图像的损失值求平均。然后根据梯度下降算法更新参数。

如果我们先就对训练集中的所有图像进行分类,而不是在批处理完之后这样做,我们能够计算出初始平均损失和初始梯度,用它们来取代批运行时使用的估计值。但是这样的话,对每个迭代参数的更新都需要进行更多的计算。在另一种极端情况下,我们可以设置批的大小为1,然后更新单幅图像的参数。这会造成更高频率的参数更新,但是更有可能出现错误。从而向错误的方向频繁修正。

通常在这两种极端情况的中间位置我们能得到最快的改进结果。对于更大的模型,对内存的考虑也至关重要。批的大小最好尽可能大,同时又能使所有变量和中间结果能写入内存。

这里第一行代码batch_size在从0到整个训练集的大小之间随机指定一个值。然后根据这个值,批处理选取相应个数的图像和标签。

# Periodically print out the model's current accuracy

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))

每100次迭代,我们对模型训练数据批的当前精确率进行检查。我们只需要调用我们之前定义的精确率操作来完成。

# Perform a single training step

sess.run(train_step, feed_dict={images_placeholder: images_batch,labels_placeholder: labels_batch})

这是整个训练循环中最重要的一行代码。我们告诉模型执行一个单独的训练步骤。我们没有必要为了参数更新再次声明模型需要做什么。所有的信息都是由TensorFlow图表中的定义提供的。TensorFlow知道根据损失使用梯度下降算法更新参数。而损失依赖logits。Logits又依靠weights,biases和具体的输入批。

因此我们只需要向模型输入训练数据批。这些通过提供查找表来完成。训练数据批已经在我们早先定义的占位符中完成了赋值。

# After finishing the training, evaluate on the test set

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))

训练结束后,我们用测试集对模型进行评估。这是模型第一次见到测试集。所以测试集中的图像对模型来时是全新的。我们会评估训练后的模型在处理从未见过的数据时表现如何。

endTime = time.time()

print('Total time: {:5.2f}s'.format(endTime - beginTime))

最后一行代码打印出训练和运行模型用了多长时间。

结果

让我们用“python softmax.py”命令运行这个模型。这里是我得到的输出:

Step     0: training accuracy 0.14

Step   100: training accuracy 0.32

Step   200: training accuracy 0.3

Step   300: training accuracy 0.23

Step   400: training accuracy 0.26

Step   500: training accuracy 0.31

Step   600: training accuracy 0.44

Step   700: training accuracy 0.33

Step   800: training accuracy 0.23

Step   900: training accuracy 0.31

Test accuracy 0.3066

Total time: 12.42s

这意味着什么?在这个测试集中训练模型的估计精度为31%左右。如果你运行自己的代码,你的结果可能在25-30%。所以我们的模型能够对从未见过的图像正确标签的比率为25%-30%。还不算坏!这里有10个不同的标签,如果随机猜测,结果的准确率只有10%。我们这个非常简单的方法已经优于随机猜测。如果你觉得25%仍然有点低,别忘了这个模型其实还比较原始。它对具体图像的比如线和形状等特征毫无概念。它只是单独检测每个像素的颜色,完全不考虑与其他像素的关联。对一幅图像某一个像素的修改对模型来说意味着完全不同的输入。考虑到这些,25%的准确率看起来也不是那么差劲了。

如果我们多进行几次迭代,结果又会如何呢?这可能并不会改善模型的准确率。如果看看结果,你就会发现,训练的准确率并不是稳定上升的,而是在0.23至0.44之间波动。看起来我们已经到达了模型的极限,再进行更多的训练于事无补。这个模型无法再提供更好的结果。事实上,比起进行1000次迭代的训练,我们进行少得多的迭代次数也能得到相似的准确率。

你可能注意到的最后一件事就是:测试的精确度大大低于训练的精确度。如果这个差距非常巨大,这也意味着过度拟合。模型针对已经见过的训练数据进行了精细的调整,而对于以前从未见过的数据则无法做到这点。

这篇文章已经写了很长时间了。很感谢你看完了全文(或直接跳到了文末)!无论是对机器学习分类器如何工作或是如何使用TensorFlow建立和运行简单的图表,我希望你找到了一些你感兴趣的东西。当然,我还有很多材料希望添加进来。目前为止,我们只是用到了softmax分类器,它甚至都没应用任何一种神经网络。我的下一篇博文进行完善:一个小型神经网络模型能够怎样最大程度地改进结果。雷锋网将继续对下一篇文章进行编译,敬请期待。

 via wolfib

相关文章:

机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(一)| 干货

本文作者:晟炜

本文转自雷锋网禁止二次转载,原文链接

相关文章
|
11天前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
143 55
|
2天前
|
机器学习/深度学习 监控 算法
机器学习在图像识别中的应用:解锁视觉世界的钥匙
机器学习在图像识别中的应用:解锁视觉世界的钥匙
154 95
|
1月前
|
机器学习/深度学习 传感器 自动驾驶
探索机器学习在图像识别中的创新应用
本文深入分析了机器学习技术在图像识别领域的最新进展,探讨了深度学习算法如何推动图像处理技术的突破。通过具体案例分析,揭示了机器学习模型在提高图像识别准确率、效率及应用场景拓展方面的潜力。文章旨在为读者提供一个全面的视角,了解当前机器学习在图像识别领域的创新应用和未来发展趋势。
|
21天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
112 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
22天前
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
55 4
|
26天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
43 1
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
84 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
1月前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
93 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
1月前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
95 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
27天前
|
机器学习/深度学习 人工智能 TensorFlow
探索深度学习与计算机视觉的融合:构建高效图像识别系统
探索深度学习与计算机视觉的融合:构建高效图像识别系统
40 0

热门文章

最新文章