在上个例子中,我们学会了如何创建神经网络,解决了预测房屋价格的问题。但是那个问题十分明确,房屋价格和房间房间数量之间的规则一目了然,并不能体现出机器学习的价值。
接下来,让我们来看一个很难定义出来明确规则的例子,如图像识别。
在这个例子中,我们利用机器学习,识别图像的类别。
fashion-minist
这里使用的数据集是fashion-minist,数据集包含60000条训练数据和10000条测试数据,每条数据都是28*28的灰度图像,及对应的10种类别。
数据大概是长这个样子的。
可以从这里查看详细的资料。
编码实现
在开始时,还是先引入tensorflow。
import tensorflow as tf
复制代码
fashion minist 数据可以使用tensorflow的API来读取。
mnist = tf.keras.datasets.fashion_mnist
复制代码
调用minist.load_data函数,得到两个数据集合,分别是训练数据和测试数据,每个数据集合由图像数据和标签组成。
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
复制代码
这个数据长的是什么样子呢?我们可以随便找一个元素打印出来图像数据和标签看下,这里打印下第一个元素。
print("lable: ", training_labels[0])
print("image: ")
for line in training_images[0]:
s = ""
for v in line:
s = s + "%3d"%v + " "
print(s)
复制代码
我们注意到打印出来的值都是在0-255之间。如果我们要训练神经网络,需要把这些值变为0-1之间,这个操作叫归一化,把数据做归一化会带来很多好处。
利用python,我们很容易做归一化操作
training_images = training_images / 255.0
test_images = test_images / 255.0
复制代码
看到这里可能会疑惑,为什么会有训练和测试两份数据集?原因是一份数据用来做训练,另一份数据是模型未见过的,用来测试模型在之前从未见过的数据中的表现。
现在让我们设计下我们的模型,这里有几个新概念,接下来会做解释。
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
复制代码
Sequential: 定义了神经网络的层序列。
Flatten:之前我们打印数据的时候,图像数据是二维的,Flatten只是将其变为一维数据。
Dense:向神经网络中添加一个层。
每一个层都需要activation function设置激活函数,我们有很多种激活函数可以选择,这里用的是Relu和Softmax。
Relu:作用相当于if (X>0) return X; else return 0;
,所以做的事情就是把0(X<=0时)或X(X>0时)传到下一层。
Softmax:获取一组值,然后选取最大的那个。举个例子,假如上一层传来的数据是[0.1, 0.1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05],那么我们得到的结果是[0, 0, 0, 0, 1, 0, 0, 0, 0]。它帮我们实现来选取最大值的编码工作,能节省大量的代码。
现在我们已经定义好来模型,接下来就是要训练模型了。我们先编译模型,编译时需指定优化函数和损失函数。然后调用model.fit
训练模型,使训练数据能够匹配到对应的标签,也就是找到训练数据和对应标签之间的关系,这样若有新的和训练数据相像的数据,模型就能预测这种数据的标签了。
model.compile(optimizer = tf.train.AdamOptimizer(),
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
复制代码
当训练完成后,我们可以看到模型的acc,就是0.8914这个数字。这个数字的含义是,我们的模型预测训练数据时,有89%的数据是准确的。这个指标不算好,但是考虑到我们只训练了5个epoch,且很快完成了训练,这个结果也是不错的了。
但是我们的模型在未见过的数据中表现如何呢?这就是上面的测试数据的用处了。我们可以调用model.evalute
,把测试数据和标签传过去,就能看到其在测试数据上的表现了。
model.evaluate(test_images, test_labels)
复制代码
可以看到acc是0.8745,意味着有87%的准确率,没有在训练数据中的表现好,这也是符合预期的。
后面可以再尝试用一些别的方法,来提高准确率。