⚽开发平台:jupyter lab
🎈运行环境:python3、tensorflow2.x
第4章 卷积神经网络实战 | 利用自定义的卷积层实现MNIST识别
1.利用自定义的卷积层实现MNIST识别
1.1实现思想
(1) 如何在良好的训练结果上作进一步的提高呢?
一个简单的思想就是建立short-cut,即建立数据通路,使得输入的模型和经过卷积计算后的数据连接在一起,从而解决卷积层总是会忽略掉的某些特定的小细节的问题。
(2) 残差网络:将输入的数据经过计算后又重新与未经过计算的数据通过“叠加”的方式连接在一起,从而建立一个能够保留更多细节内容的卷积结构。
1.2 程序4.6(完整代码)
## 导入相关工具包
import numpy as np
import tensorflow as tf
## 加载MNIST数据集
mnist = tf.keras.datasets.mnist
(x_train,y_train),(x_test,y_test) = mnist.load_data()
## 训练集数目为60000,测试集数目为10000
### 由于CPU训练较慢,现在取部分数据进行实验,若处理速度较快,可省去该步骤
x_train.shape,y_train.shape,x_test.shape #((60000, 28, 28), (60000,), (10000, 28, 28))
(x_train,y_train),(x_test,y_test) = (x_train[:600],y_train[:600]),(x_test[:100],y_test[:100])
x_train.shape,y_train.shape,x_test.shape ## ((600, 28, 28), (600,), (100, 28, 28))
### # 将样本从整数转换为[0,1]区间的浮点数
x_train,x_test = x_train/255.0,x_test/255.0
## 在给定一个input时,在axis轴处给input增加一个维度
x_train = tf.expand_dims(x_train,-1)
### 因为有10个不同的目标值
y_train = np.float32(tf.keras.utils.to_categorical(y_train,num_classes=10))
## 对测试集进行上述操作
x_test = tf.expand_dims(x_test,-1)
y_test = np.float32(tf.keras.utils.to_categorical(y_test,num_classes=10))
## 划分数据集
### 这里是为了shuffle数据,单独定义了每个batch的大小batch_size,这与下方的shuffle对应
batch_size = 128
train_dataset = tf.data.Dataset.from_tensor_slices((x_train,y_train)).batch(batch_size).shuffle(batch_size*10)
test_dataset = tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(batch_size) ## 测试集不用打乱
## 自定义的残卷积层
class MyLayer(tf.keras.layers.Layer):
## kernel_size:卷积核数目,filter:卷积核大小
def __init__(self,kernel_size,filter):
self.filter = filter
self.kernel_size = kernel_size
super(MyLayer,self).__init__()
def build(self,input_shape):
self.weight = tf.Variable(tf.random.normal([self.kernel_size,self.kernel_size,input_shape[-1],self.filter]))
self.bias = tf.Variable(tf.random.normal([self.filter]))
super(MyLayer,self).build(input_shape)
##该部分对于残差网络的简单表示如下:
## conv = conv(input)
## out = relu(conv) + input
def call(self,input_tensor):
conv = tf.nn.conv2d(input_tensor,self.weight,strides=[1,2,2,1],padding='SAME')
conv = tf.nn.bias_add(conv,self.bias)
out = tf.nn.relu(conv)+conv
return out
## 定义模型
input_xs = tf.keras.Input([28,28,1])
conv = tf.keras.layers.Conv2D(16,3,padding='SAME',activation=tf.nn.relu)(input_xs)
##添加自定义层
### 使用自定义的层替换TensorFlow的卷积层
conv = MyLayer(32,3)(conv) ### 增加部分
## BatchNormalization()和MaxPool2D层的目的:使输入数据正则化,最大限度地减少魔性的过拟合和增大模型的泛化能力。
conv = tf.keras.layers.BatchNormalization()(conv)
conv = tf.keras.layers.Conv2D(32,3,padding='SAME',activation=tf.nn.relu)(conv)
conv = tf.keras.layers.MaxPool2D(strides = [1,1])(conv)
conv = tf.keras.layers.Conv2D(64,3,padding='SAME',activation=tf.nn.relu)(conv)
## flat函数:将提取计算后的特征值平整化,之后的两个全连接层起到特征提取和分类的作用,最终作出分类。
flat = tf.keras.layers.Flatten()(conv)
## Dense,两个全连接层,用于对卷积层所提取的特征做最终分类
dense = tf.keras.layers.Dense(128,activation=tf.nn.relu)(flat)
logits = tf.keras.layers.Dense(10,activation=tf.nn.softmax)(dense)
model = tf.keras.Model(inputs = input_xs,outputs = logits)
## 编译模型,并进行训练模型
model.compile(optimizer=tf.optimizers.Adam(0.001),loss=tf.losses.categorical_crossentropy,metrics=['acc'])
hist = model.fit(train_dataset,epochs=10)
##
model.save('./saver/model.h5')
1.3 数据展示
import matplotlib.pyplot as plt
### 精确度变化
plt.plot(range(10),hist.history.get('acc'))
### 损失度变化
plt.plot(range(10),hist.history.get('loss'))
1.4 数据预测
### 预测测试集数据
predict_x_test = model.predict(x_test)
### 获取测试集数据的最大可能性数值
predict_answer = np.argmax(predict_x_test,axis = 1)
### 获取其中一个样本,进行预测校对
predict_answer[2]
plt.imshow(x_test[2])
1.5 模型参数
### 模型参数获取
model.summary()