2.全连接以及简单CNN实例

本节用到的素材:Fashion MNIST是一个包含服装项目的数据集,有衣服,裤子,鞋子...还有另一个类似的数据集叫MNIST,它包含很多手写数字(0到9)的图片和标签。

全连接解决手写数字识别

编写一个MNIST分类器,让它可以训练到99%以上的准确率,并且在达到这个准确率时,就通过回调函数停止训练。

一些注意事项。

  1. 它应该在小于10个epochs的情况下成功,所以把epochs改成10个也可以,但不能大过10个。
  2. 当它达到99%以上时,应该打印出 "达到99%准确率,所以取消训练!"的字符串。
  3. 如果你添加了任何额外的变量,请确保你使用与类中使用的变量相同的名称。

代码:

import tensorflow as tf

# 设置自动结束
class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.99):
      print("\nReached 99% accuracy so cancelling training!")
      self.model.stop_training = True

mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
# 归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 创造实例
callbacks = myCallback()

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=10, callbacks=[callbacks])

输出:

Epoch 1/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.2001 - accuracy: 0.9412
Epoch 2/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0804 - accuracy: 0.9750
Epoch 3/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0510 - accuracy: 0.9843
Epoch 4/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0365 - accuracy: 0.9883
Epoch 5/10
1871/1875 [============================>.] - ETA: 0s - loss: 0.0284 - accuracy: 0.9907
Reached 99% accuracy so cancelling training!
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0284 - accuracy: 0.9907

补充知识:

Sequential。这定义了神经网络中的层数序列。一开始学习神经元网络总是使用序列模型。

Flatten。把二维数组变成一维数组。

Dense:增加一层神经元。

每一层神经元都需要一个激活函数 activation来告诉它们输出什么。有很多选项,但目前只用这些(relu和softmax)。

Relu的意思是 "如果X>0返回X,否则返回0"--所以它的作用是它只把大于0的值传递给网络中的下一层,小于0的也当作0。

Softmax激活函数接收到一组值后,选择其中最大的一个输出。

全连接解决服饰分类

代码:

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
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)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)

test_loss = model.evaluate(test_images, test_labels)

输出:

Epoch 1/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.4996 - accuracy: 0.8236
Epoch 2/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3763 - accuracy: 0.8639
Epoch 3/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3349 - accuracy: 0.8791
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3125 - accuracy: 0.8847
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.2953 - accuracy: 0.8911
313/313 [==============================] - 0s 2ms/step - loss: 0.3495 - accuracy: 0.8741

CNN解决服饰分类

可以看出三层DNN在解决手写数字辨识上有很好的的准确率,但是倘若图片稍微复杂就像上述的服装识别,其效果就会急剧下降,训练5次的准确率仅为0.87。为此CNN在处理这种分类问题是必须的,它主要做的就是卷积和池化,这里不多做阐述。

代码:

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
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([
  tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
  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.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)

输出:

2.2.0
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_3 (Dense)              (None, 10)                1290      
=================================================================
Total params: 243,786
Trainable params: 243,786
Non-trainable params: 0
_________________________________________________________________
Epoch 1/5
1875/1875 [==============================] - 49s 26ms/step - loss: 0.4418 - accuracy: 0.8409
Epoch 2/5
1875/1875 [==============================] - 49s 26ms/step - loss: 0.2931 - accuracy: 0.8941
Epoch 3/5
1875/1875 [==============================] - 49s 26ms/step - loss: 0.2491 - accuracy: 0.9076
Epoch 4/5
1875/1875 [==============================] - 48s 26ms/step - loss: 0.2151 - accuracy: 0.9198
Epoch 5/5
1875/1875 [==============================] - 49s 26ms/step - loss: 0.1908 - accuracy: 0.9280
313/313 [==============================] - 3s 10ms/step - loss: 0.2817 - accuracy: 0.9019

综上,可以很明显的看出CNN在分类中的强势。

CNN解决手写数字识别(高准确率)

可想而知,在这种简单分类上CNN也很行!

通过这个练习,看看可否只使用单个卷积层和单个MaxPooling 2D将MNIST(手写数字)识别率提高到99.8%或更高的准确率。一旦准确率超过这个数值,应该停止训练。Epochs不应超过20个。如果epochs达到20但精度未达到要求,那么就需要重新设计层结构。

当达到99.8%的准确率时,你应该打印出 "达到99.8%准确率,所以取消训练!"的字符串。

代码:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.998):
      print("\nReached 99.8% accuracy so cancelling training!")
      self.model.stop_training = True

callbacks = myCallback()
mnist = tf.keras.datasets.mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
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([
  tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(28, 28, 1)),
  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.fit(training_images, training_labels, epochs=10, callbacks=[callbacks])

输出:

Epoch 1/10
1875/1875 [==============================] - 18s 10ms/step - loss: 0.1534 - accuracy: 0.9549
Epoch 2/10
1875/1875 [==============================] - 20s 11ms/step - loss: 0.0538 - accuracy: 0.9837
Epoch 3/10
1875/1875 [==============================] - 17s 9ms/step - loss: 0.0350 - accuracy: 0.9893
Epoch 4/10
1875/1875 [==============================] - 18s 9ms/step - loss: 0.0229 - accuracy: 0.9929
Epoch 5/10
1875/1875 [==============================] - 17s 9ms/step - loss: 0.0152 - accuracy: 0.9953
Epoch 6/10
1875/1875 [==============================] - 18s 10ms/step - loss: 0.0111 - accuracy: 0.9965
Epoch 7/10
1875/1875 [==============================] - 18s 10ms/step - loss: 0.0089 - accuracy: 0.9971
Epoch 8/10
1875/1875 [==============================] - 18s 9ms/step - loss: 0.0066 - accuracy: 0.9977
Epoch 9/10
1874/1875 [============================>.] - ETA: 0s - loss: 0.0055 - accuracy: 0.9983
Reached 99.8% accuracy so cancelling training!
1875/1875 [==============================] - 17s 9ms/step - loss: 0.0055 - accuracy: 0.9983