TensorFlow Specialization Course 1学习笔记 Week 3

TensorFlow Specialization Course 1学习笔记 Week 3

卷积神经网络实现服饰分类器

在上一个课程中,我们使用深度神经网络实现了一个服饰分类器。深度神经网络包含输入层、输出层和隐藏层。如何让我们的分类器准确率更高呢?这一次,我们使用卷积神经网络来实现我们的分类器,来看看效果如何。

我们在全连接层之前添加几个卷积层和池化层。卷积层用来提取图像中的特征,将提取到的特征信息传入全连接层相比直接将图像像素值传入全连接层,可以显著提高分类器的准确率。池化层用来压缩图像,同时保留图像的特征内容。

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

# 因为卷积层的输入需为一个张量,所以这样训练集和测试卷都需要reshape为一个四维的张量
# reshape前training_images为60000个28x28x1的元素在一个列表中,reshape后training_images为一个四维列表60000x28x28x1。
training_images=training_images.reshape(60000, 28, 28, 1)

training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  
  # 定义卷积层。64为需要生成的卷积数(卷积核的数量),(3,3)为卷积核的大小,激活函数使用relu
  # 每一个卷积核都会与输入卷积计算得到一个结果。输入为28x28x1,这里64个卷积核,则输出为26x26x64。
  tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
  
  # MaxPooling层用来压缩图像,同时保留图像的特征内容
  # 尺度为(2,2)的池化层将图像大小压缩为原来的一半,上一层卷积层的输出为26x26x64
  # 经过这个池化层后,输出为13x13x64
  tf.keras.layers.MaxPooling2D(2, 2),
    
  tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 调用model.summary()方法,得到整个网络的基本信息,具体看下面输出
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)

model.summary()的输出如下

Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_3 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_6 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_7 (Dense)              (None, 10)                1290      
=================================================================
Total params: 243,786
Trainable params: 243,786
Non-trainable params: 0

使用了卷积神经网络的服饰分类器在训练11次迭代后,就可以在训练集上得到99.8%的准确率,在测试集上得到的99.1%准确率。

可视化卷积层和池化层的输出结果

输入测试集中前100个图像的标签。

print(test_labels[:100])

在上面的输出中,我们找到第0、23和28个的标签都是9,9代表鞋子。在下面的代码中,我们选择这三个都是鞋子的图像。

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 63
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

activation_model.predict()得到的结果是一个列表,包含神经网络的每一层输出结果。这里的for循环取得是第一个卷积层、第一个池化层、第二个卷积层和第二个池化层的结果,当x=0时,取第一个卷积层的输出结果。卷积或池化的结果都是有64个深度的,因为我们使用了64个卷积核。CONVOLUTION_NUMBER代表我们想要哪一个深度的结果。

举个例子,看for循环中这两行代码

f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')

当x=0,CONVOLUTION_NUMBER=63,我们取第一个卷积层的输出结果:1x26x26x64,从中取出最后一个卷积核计算的结果1x26x26x1,并将它展示出来。

自己运行上面的代码,并不断修改参数来观察有趣的输出吧。

为什么使用卷积?

和只使用全连接层相比,卷积层的两个主要优势在于参数共享和稀疏连接。

直接使用全连接层的话,需要的参数会非常多。

参数共享:观察发现,特征检测入垂直边缘检测如果适用于图片的某个区域,那么它也可能适用于图片的其他区域。整张图片共享特征检测器。

稀疏连接:第二个方法是使用稀疏连接,我来解释下。这个 0 是通过 3×3 的卷积计算得到的,它只 依赖于这个 3×3 的输入的单元格,右边这个输出单元(元素 0)仅与 36 个输入特征中 9 个 相连接。而且其它像素值都不会对输出产生任影响,这就是稀疏连接的概念。
WhyConv
神经网络可以通过这两种机制减少参数,以便我们用更小的训练集来训练它,从而预防过度拟合。你们也可能听过,卷积神经网络善于捕捉平移不变。通过观察可以发现,向右移动两个像素,图片中的猫依然清晰可见,因为神经网络的卷积结构使得即使移动几个像素,这张图片依然具有非常相似的特征,应该属于同样的输出标记。实际上,我们用同一个过滤器生成各层中,图片的所有像素值,希望网络通过自动学习变得更加健壮,以便更好地取得所期望的平移不变属性。


关于卷积神经网络的详细内容请看:https://blog.csdn.net/JSerenity/article/details/89330545

本笔记详细内容请看:https://github.com/lmoroney/dlaicourse/blob/master/Course 1 - Part 6 - Lesson 2 - Notebook.ipynb

课程地址:https://www.coursera.org/learn/introduction-tensorflow/

猜你喜欢

转载自blog.csdn.net/JSerenity/article/details/89418780
今日推荐