import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
from tfcv import *
(x_train,y_train),(x_test,y_test) = keras.datasets.mnist.load_data()
x_train = x_train.astype(np.float32) / 255.0
x_test = x_test.astype(np.float32) / 255.0
plot_convolution(x_train[:5],[[-1.,0.,1.],[-1.,0.,1.],[-1.,0.,1.]],'Vertical edge filter')
plot_convolution(x_train[:5],[[-1.,-1.,-1.],[0.,0.,0.],[1.,1.,1.]],'Horizontal edge filter')
im2col转换:图像块转成矩阵,矩阵乘法用GPU加速(比直接卷积快) + 反向传播(梯度用矩阵求导->简化训练过程)
设图像5x5,卷积核3x3,步长1
提取所有3x3局部区域,每个区域展开成列==矩阵;原图(5-3+1)(5-3+1)=9局部区域,展成9x1列向量(按序)--> 9阶矩阵
卷积核权重矩阵化:
卷积核:两个3x3滤波器;权重矩阵(滤波器权重展平1x9行向量,两个滤波器=2x9权重矩阵W)
卷积用矩阵乘法:C(x) = W x im2col(x),2x9W阵重塑为3x3特征图 -> 重塑完就是卷积完成
用简单CNN架构算MNIST:
输入层28x28灰阶,卷积层9个5x5滤波器(步长1,输入尺寸28-5+1=24生成24x24x9特征图),激活函数ReLU(支持非线性),展平层24x24x9=5184维向量,全连接层5184->10维(10个数字类别)
Conv2d参数:filters(滤波器,9个),kernel_size
参数数量计算:参数层(每个滤波器参数5x5权重+1偏置=26;9个滤波器总参数9x26=234)+ 全输出层(5184->10 => 5184x10+10=51850)
代码:
model = keras.models.Sequential([
keras.layers.Conv2D(filters=9, kernel_size=(5,5), input_shape=(28,28,1),activation='relu'),
keras.layers.Flatten(),
keras.layers.Dense(10)])
model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['acc'])
model.summary()
结果:1个网络有50k个训练参数,同PyTorch
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 24, 24, 9) 234
flatten (Flatten) (None, 5184) 0
dense (Dense) (None, 10) 51850
=================================================================
Total params: 52,084
Trainable params: 52,084
Non-trainable params: 0
先将训练数据重塑,再训练:
x_train_c = np.expand_dims(x_train,3)x_test_c = np.expand_dims(x_test,3)hist = model.fit(x_train_c,y_train,validation_data=(x_test_c,y_test),epochs=5)
结果:
Epoch 1/5
1875/1875 [==============================] - 15s 7ms/step - loss: 0.2099 - acc: 0.9410 - val_loss: 0.0879 - val_acc: 0.9735
Epoch 2/5
1875/1875 [==============================] - 13s 7ms/step - loss: 0.0858 - acc: 0.9753 - val_loss: 0.0682 - val_acc: 0.9791
Epoch 3/5
1875/1875 [==============================] - 13s 7ms/step - loss: 0.0665 - acc: 0.9808 - val_loss: 0.0553 - val_acc: 0.9829
Epoch 4/5
1875/1875 [==============================] - 15s 8ms/step - loss: 0.0582 - acc: 0.9835 - val_loss: 0.0513 - val_acc: 0.9835
Epoch 5/5
1875/1875 [==============================] - 14s 8ms/step - loss: 0.0527 - acc: 0.9847 - val_loss: 0.0503 - val_acc: 0.9833
绘图:
plot_results(hist)
可视化卷积层:
fig,ax = plt.subplots(1,9)
l = model.layers[0].weights[0]
for i in range(9):
ax[i].imshow(l[...,0,i])
ax[i].axis('off')
金三角架构:
model = keras.models.Sequential([
keras.layers.Conv2D(filters=10, kernel_size=(5,5), input_shape=(28,28,1),activation='relu'),
keras.layers.MaxPooling2D(),
keras.layers.Conv2D(filters=20, kernel_size=(5,5), activation='relu'),
keras.layers.MaxPooling2D(),
keras.layers.Flatten(),
keras.layers.Dense(10)])
model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['acc'])
model.summary()
hist = model.fit(x_train_c,y_train,validation_data=(x_test_c,y_test),epochs=5)
结果:
Epoch 1/5 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0723 - acc: 0.9780 - val_loss: 0.0423 - val_acc: 0.9861 Epoch 2/5 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0523 - acc: 0.9842 - val_loss: 0.0425 - val_acc: 0.9866 Epoch 3/5 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0448 - acc: 0.9868 - val_loss: 0.0403 - val_acc: 0.9865 Epoch 4/5 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0383 - acc: 0.9886 - val_loss: 0.0323 - val_acc: 0.9888 Epoch 5/5 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0338 - acc: 0.9895 - val_loss: 0.0331 - val_acc: 0.9896
用CIFAR-10数据集:
(x_train,y_train),(x_test,y_test) = keras.datasets.cifar10.load_data()
x_train = x_train.astype(np.float32) / 255.0
x_test = x_test.astype(np.float32) / 255.0
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
model = keras.models.Sequential([
keras.layers.Conv2D(filters = 6, kernel_size = 5, strides = 1, activation = 'relu', input_shape = (32,32,3)),
keras.layers.MaxPooling2D(pool_size = 2, strides = 2),
keras.layers.Conv2D(filters = 16, kernel_size = 5, strides = 1, activation = 'relu'),
keras.layers.MaxPooling2D(pool_size = 2, strides = 2),
keras.layers.Flatten(),
keras.layers.Dense(120, activation = 'relu'),
keras.layers.Dense(84, activation = 'relu'),
keras.layers.Dense(10, activation = 'softmax')])
model.summary()
model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = ['acc'])
hist = model.fit(x_train,y_train,validation_data=(x_test,y_test),epochs=10)
plot_results(hist)
扩展阅读:
-
识别宠物脸部实验
-
卷积神经网络PyTorch试水
-
OpenCV实验
-
用光流实现手掌运动检测