2.全连接以及简单CNN实例
本节用到的素材:Fashion MNIST是一个包含服装项目的数据集,有衣服,裤子,鞋子...还有另一个类似的数据集叫MNIST,它包含很多手写数字(0到9)的图片和标签。
全连接解决手写数字识别
编写一个MNIST分类器,让它可以训练到99%以上的准确率,并且在达到这个准确率时,就通过回调函数停止训练。
一些注意事项。
- 它应该在小于10个epochs的情况下成功,所以把epochs改成10个也可以,但不能大过10个。
- 当它达到99%以上时,应该打印出 "达到99%准确率,所以取消训练!"的字符串。
- 如果你添加了任何额外的变量,请确保你使用与类中使用的变量相同的名称。
代码:
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
Comments NOTHING