卷积等概念
卷积的概念
一种有效提取特征的方法
1、对单通道图像:一般用一个正方形的卷积核,按指定步长,在输入特征图上滑动,遍历输入特征图中的每个像素点。每一个步长,卷积核会与输入特征图出现重合区域,重合区域对应元素相乘、求和再加上偏置项得到输出特征的一个像素点。利用大小为 3×3×1 的卷积核对 5×5×1 的单通道图像做卷积计算得到相应结果。
2、对彩色RGB图像(多通道):卷积核通道数与输入特征一致,套接后在对应位置上进行乘加和操作,如图 5-5 所示,利用三通道卷积核对三通道的彩色特征图做卷积计算。
感受野
卷积神经网络各输出层每个像素点在原始图像上的映射区域大小。
第一种:原始图像5*5,先用3*3卷积核作用(步长1)得到3*3输出图像,每个像素点感受野为3,再用3*3卷积核作用,得到1*1输出图像,感受野为5(对于原始图像)
第二种:直接对原始图像用5*5卷积核作用得到1*1输出图像,感受野为5。
当我们采用尺寸不同的卷积核时,最大的区别就是感受野的大小不同,所以经常会采用多层小卷积核来替换一层大卷积核,在保持感受野相同的情况下减少参数量和计算量,例如十分常见的用 2 层 3 * 3 卷积核来替换 1 层 5 * 5 卷积核的方法
全零填充
为了保持输出图像尺寸与输入图像一致,经常会在输入图像周围进行全零填充,如图 所示,在 5×5 的输入图像周围填 0,则输出特征尺寸同为 5×5。
在 Tensorflow 框架中,用参数 padding = ‘SAME’或 padding = ‘VALID’表示是否进行全零填充。
输出图像特征尺寸
批标准化(Batch Normalization)
对一小批数据在网络各层的输出做标准化处理(标准化:使数据符合 0 均值,1 为标准差的分布。)
目的是解决神经网络中梯度消失的问题,
池化(pooling)
池化的作用是减少特征数量(降维)。最大值池化可提取图片纹理,均值池化可保留背景特征。
舍弃(Dropout)
在神经网络的训练过程中,将一部分神经元按照一定概率从神经网络中暂时舍弃,使用时被舍弃的神经元恢复链接。
卷积神经网络的主要模块
卷积层、BN 层、激活函数、池化层、全连接层
构建卷积神经网络步骤
构建神经网络“八股”套路
导入 tensorflow 及 keras、numpy 等所需模块。
读取数据集
搭建网络模型
对搭建好的网络进行编译(model.compile)
将数据输入编译好的网络来进行训练(model.fit)
将神经网络模型的具体信息打印出来(model.summary)
以cifar10图片分类为例,展示图像分类全过程
1 """
2 ######## 【1、导入文件】
3 """
4 import tensorflow as tf
5 import os
6 import numpy as np
7 from matplotlib import pyplot as plt
8 from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense
9 from tensorflow.keras import Model
10
11 np.set_printoptions(threshold=np.inf)
12
13 """
14 ####### 【2、读取数据集】导入图片特征x、图片标签y
15 """
16 cifar10 = tf.keras.datasets.cifar10 # 下载数据集
17 (x_train, y_train), (x_test, y_test) = cifar10.load_data() # 导入训练集和测试集
18 x_train, x_test = x_train / 255.0, x_test / 255.0 # 将0-255像素转化为0-1
19
20 """
21 ######## 【3、搭建网络模型】
22 """
23 class Baseline(Model):
24 def __init__(self):
25 super(Baseline, self).__init__()
26 self.c1 = Conv2D(filters=6, kernel_size=(5, 5), padding='same') # 卷积层
27 self.b1 = BatchNormalization() # BN层
28 self.a1 = Activation('relu') # 激活层
29 self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same') # 池化层
30 self.d1 = Dropout(0.2) # dropout层
31
32 self.flatten = Flatten() # 拉直层(将二维特征拉直成一维)
33 self.f1 = Dense(128, activation='relu') # 全连接层
34 self.d2 = Dropout(0.2) # dropout层
35 self.f2 = Dense(10, activation='softmax')
36
37 def call(self, x):
38 x = self.c1(x)
39 x = self.b1(x)
40 x = self.a1(x)
41 x = self.p1(x)
42 x = self.d1(x)
43
44 x = self.flatten(x)
45 x = self.f1(x)
46 x = self.d2(x)
47 y = self.f2(x)
48 return y
49
50
51 model = Baseline()
52
53 """
54 ####### 【4、model.compile】 编译网络(指定优化器、损失函数)
55 """
56 model.compile(optimizer='adam',
57 loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
58 metrics=['sparse_categorical_accuracy'])
59
60 checkpoint_save_path = "./checkpoint/Baseline.ckpt"
61 if os.path.exists(checkpoint_save_path + '.index'):
62 print('-------------load the model-----------------')
63 model.load_weights(checkpoint_save_path)
64
65 cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
66 save_weights_only=True,
67 save_best_only=True)
68
69 """
70 ####### 【5、model.fit】 断点续训(将数据输入编译好的网络来训练)
71 """
72 history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
73 callbacks=[cp_callback])
74 """
75 ####### 【6、model.summary】 将神经网络模型的具体信息打印出来
76 """
77 model.summary()
78 # print(model.trainable_variables)
79 file = open('./weights.txt', 'w')
80 for v in model.trainable_variables:
81 file.write(str() + '\n')
82 file.write(str(v.shape) + '\n')
83 file.write(str(v.numpy()) + '\n')
84 file.close()
85
86 """
87 ####### 【acc/loss可视化】
88 """
89 acc = history.history['sparse_categorical_accuracy']
90 val_acc = history.history['val_sparse_categorical_accuracy']
91 loss = history.history['loss']
92 val_loss = history.history['val_loss']
93
94 plt.subplot(1, 2, 1)
95 plt.plot(acc, label='Training Accuracy')
96 plt.plot(val_acc, label='Validation Accuracy')
97 plt.title('Training and Validation Accuracy')
98 plt.legend()
99
100 plt.subplot(1, 2, 2)
101 plt.plot(loss, label='Training Loss')
102 plt.plot(val_loss, label='Validation Loss')
103 plt.title('Training and Validation Loss')
104 plt.legend()
105 plt.show()
cifar10图像分类
1、导入tensorflow 及 keras、numpy 等所需模块
2、读取数据集
指定输入网络的训练集和测试集,如指定训练集的输入 x_train 和标签y_train,测试集的输入 x_test 和标签 y_test
MNIST、cifar10 等数据集本来就封装在tensorflow模块中,可以直接从sklearn中引入,但是在实际应用中,大多需要从图片和标签文件中读取所需的数据集。
① 网上已有资源的数据集:
Cifar10数据集:
提供 5万张 32*32 像素点的十分类彩色图片和标签,用于训练。
提供 1万张 32*32 像素点的十分类彩色图片和标签,用于测试。
1 """
2 ####### 【2、读取数据集】导入图片特征x、图片标签y
3 """
4 cifar10 = tf.keras.datasets.cifar10 # 下载数据集
5 (x_train, y_train), (x_test, y_test) = cifar10.load_data() # 导入训练集和测试集
6 x_train, x_test = x_train / 255.0, x_test / 255.0 # 将0-255像素转化为0-1
网上数据集读取
②自制数据集
利用自己的图片和标签文件来自制数据集
未完待续……
3、搭建网络模型
当网络结构比较简单时,可以利用 keras 模块中的tf.keras.Sequential 来搭建顺序网络模型;但是当网络不再是简单的顺序结构,而是有其它特殊结构出现时(例如 ResNet 中的跳连结构),便需要利用 class 来定义自己的网络结构。前者使用起来更加方便,但实际应用中往往需要利用后者来搭建网络。
1 """
2 ######## 【3、搭建网络模型】
3 """
4 class Baseline(Model):
5 def __init__(self): # 初始化模型
6 super(Baseline, self).__init__()
7 self.c1 = Conv2D(filters=6, kernel_size=(5, 5), padding='same') # C卷积层
8 self.b1 = BatchNormalization() # B 批标准化层
9 self.a1 = Activation('relu') # A 激活层
10 self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same') # P 池化层
11 self.d1 = Dropout(0.2) # D dropout层
12
13 self.flatten = Flatten() # 拉直层(将二维特征拉直成一维)
14 self.f1 = Dense(128, activation='relu') # 全连接层
15 self.d2 = Dropout(0.2) # dropout层
16 self.f2 = Dense(10, activation='softmax') # 第2个全连接层
17
18 def call(self, x): # 调用初始化模型函数,进行前向传播,返回输出y
19 x = self.c1(x)
20 x = self.b1(x)
21 x = self.a1(x)
22 x = self.p1(x)
23 x = self.d1(x)
24
25 x = self.flatten(x)
26 x = self.f1(x)
27 x = self.d2(x)
28 y = self.f2(x)
29 return y
30
31
32 model = Baseline() # 建立神经网络模型对象
搭建神经网络
4、对搭建好的网络进行编译(model.compile)
Compile 用于配置神经网络的训练方法,告知训练时使用的优化器、损失函数和准确率评测标准。
1 """
2 ####### 【4、model.compile】 编译网络(指定优化器、损失函数)
3 """
4 model.compile(optimizer='adam',
5 loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
6 metrics=['sparse_categorical_accuracy'])
7
8 checkpoint_save_path = "./checkpoint/Baseline.ckpt"
9 if os.path.exists(checkpoint_save_path + '.index'):
10 print('-------------load the model-----------------')
11 model.load_weights(checkpoint_save_path)
12
13 cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
14 save_weights_only=True,
15 save_best_only=True)
compile
——Model.compile( optimizer = 优化器,loss = 损失函数,metrics = [“准确率”])
其中:
(1)optimizer 可以是字符串形式给出的优化器名字,也可以是函数形式,使用函数形式可以设置学习率、动量和超参数。
包括4种优化器,每种优化器都有2种表达方式(优化器名字or函数形式)
① ‘sgd’or tf.optimizers.SGD( lr=学习率,decay=学习率衰减率,momentum=动量参数)
② ‘adagrad’or tf.keras.optimizers.Adagrad(lr=学习率,decay=学习率衰减率)
③ ‘adadelta’or tf.keras.optimizers.Adadelta(lr=学习率,decay=学习率衰减率)
④ ‘adam’or tf.keras.optimizers.Adam (lr=学习率,decay=学习率衰减率)
(2)loss 可以是字符串形式给出的损失函数的名字,也可以是函数形式。
可选项包括:
① ‘mse’
② tf.keras.losses.MeanSquaredError()‘sparse_categorical_crossentropy
③ tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
损失函数常需要经过 softmax 等函数将输出转化为概率分布的形式。from_logits 则用来标注该损失函数是否需要转换为概率的形式,取 False 时表示转化为概率分布,取 True 时表示没有转化为概率分布,直接输出。
(3)Metrics 标注网络评测指标。
① ‘accuracy’:y_和 y 都是数值,如 y_=[1] y=[1]。
② ‘categorical_accuracy’:y_和 y 都是以独热码和概率分布表示。如 y_=[0, 1, 0], y=[0.256, 0.695, 0.048]。
③ ‘sparse_ categorical_accuracy’:y_是以数值形式给出,y 是以独热码形式给出。如 y_=[1],y=[0.256, 0.695, 0.048]。
5、将数据输入编译好的网络来进行训练(model.fit)
告知训练集和测试集的输入值和标签、每个 batch 的大小(batchsize)和数据集的迭代次数(epoch)。
1 """
2 ####### 【5、model.fit】 执行训练过程(将数据输入编译好的网络来训练)
3 """
4 history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
5 callbacks=[cp_callback]) # 回调函数实现断点续训
fit
——model.fit(训练集的输入特征, 训练集的标签, batch_size, epochs,validation_data = (测试集的输入特征,测试集的标签),
validataion_split = 从测试集划分多少比例给训练集,
validation_freq = 测试的 epoch 间隔次数)
6、将神经网络模型的具体信息打印出来(model.summary)
打印网络结构,统计参数数目
1 """
2 ####### 【6、model.summary】 将神经网络模型的具体信息打印出来
3 """
4 model.summary()
5 # print(model.trainable_variables)
6 file = open('./weights.txt', 'w') # 保存模型参数
7 for v in model.trainable_variables:
8 file.write(str() + '\n')
9 file.write(str(v.shape) + '\n')
10 file.write(str(v.numpy()) + '\n')
11 file.close()
summary
上图是model.summary()对鸢尾花分类网络的网络结构和参数统计,对于一个输入为4输出为3的全连接网络,共有15个参数。
acc/loss可视化
1 """
2 ####### 【acc/loss可视化】
3 """
4 acc = history.history['sparse_categorical_accuracy']
5 val_acc = history.history['val_sparse_categorical_accuracy']
6 loss = history.history['loss']
7 val_loss = history.history['val_loss']
8
9 plt.subplot(1, 2, 1)
10 plt.plot(acc, label='Training Accuracy')
11 plt.plot(val_acc, label='Validation Accuracy')
12 plt.title('Training and Validation Accuracy')
13 plt.legend()
14
15 plt.subplot(1, 2, 2)
16 plt.plot(loss, label='Training Loss')
17 plt.plot(val_loss, label='Validation Loss')
18 plt.title('Training and Validation Loss')
19 plt.legend()
20 plt.show()
acc/loss