记录一下昨天半夜学的东西,以下代码均通过tensorflow2自带的keras实现。
卷积神经网络(CNN)
- 为什么要使用卷积神经网络?
卷积神经网络常用于图像处理。它可以提取关键信息,如图片轮廓、主色调等信息,在减少喂入数据量的同时,又能增加模型深度,提高准确率。其具体实现笔者将在下文中介绍。
## 概念 ### 卷积 卷积是通过两个函数f 和g
生成第三个函数的一种数学算子,可以理解为,在原函数f上,通过函数g进行处理,得到结果函数。这个处理卷积过程的g,就是卷积核。
为了便于理解,举一种简单情况(选用离散数列进行演示,连续数列会更加麻烦):
接下来,卷积核从左向右移动,每三个元素通过卷积核得到结果,如:
最终得到的数列就是卷积后的结果。
上面的例子是一维矩阵(数列)的卷积,对于二维、三维甚至更高维的矩阵,都可以这样类比。
举一个例子:
同样,卷积核需要逐个移动,例如先从左往右,再从上往下,遍历每一块元素:
第一个元素:第二个元素:
最终结果:
动图演示:
更高维的卷积都可以用这种方法推广。 ####
卷积核
上面的例子已经介绍了卷积核,卷积核非常神奇,图像像素排列成的矩阵在通过卷积核可以实现锐化、模糊、边缘、浮雕等效果,因此,我们可以使用卷积核提取关键信息。
下面是一些图像处理常用卷积核: 均值模糊:锐化:边缘检测:
这里笔者使用OpenCV2演示效果,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
import cv2 import numpy as np
if __name__ == '__main__': img = cv2.imread('data/img/lena.jpg') cv2.imshow('Lena', img)
blur = np.array([[1 / 9, 1 / 9, 1 / 9], [1 / 9, 1 / 9, 1 / 9], [1 / 9, 1 / 9, 1 / 9]], np.float32) sharp = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]], np.float32) soble = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], np.float32)
blur_dst = cv2.filter2D(img, -1, kernel=blur) sharp_dst = cv2.filter2D(img, -1, kernel=sharp) soble_dst = cv2.filter2D(img, -1, kernel=soble)
cv2.imshow('blur', blur_dst) cv2.imshow('sharp', sharp_dst) cv2.imshow('soble', soble_dst)
cv2.waitKey(0)
|
运行结果:
通过修改卷积核的数值和尺寸,还可以得到不同效果的图片。
全零填充
之前卷积的例子,在卷积之后都会丢失宽度(高度),原来7个元素的数列变成了5个元素,原来4x3的矩阵变成了3x2,这与原函数和卷积核的维度和尺寸有关。
要解决宽度(高度)的丢失问题,有一个解决思路,就是使用全零填充,即在边缘加上0.
如: 原函数:卷积核:
卷积的结果是:.
但如果使用全零填充,就变成: 原函数:卷积核:
卷积的结果是:.
通过全零填充,梳理(矩阵)的尺寸得以保留,这可以有效缓解网络层数加深后数据量减少的问题。
批标准化
批标准化(Batch
Normalization)是一种用于改善人工神经网络的性能和稳定性的技术,简称BN算法。
批标准化和标准化类似,用于将数据规范到一定的范围内,以便计算。
笔者非该专业,无法深入讲解,仅在此简单介绍其作用。 ### 池化
池化是一种采样方法,它可以提取数据特征,减少数据量并缓解过拟合。下面介绍一下两种池化方法:
均值池化
顾名思义,即取平均值。 首先将源数据分块,然后取每块的平均值,如:
#### 最大值池化 最大值池化也很好理解,即取最大值: ### 失活
随机失活(Dropout)是对具有深度结构的人工神经网络进行优化的方法,在学习过程中通过将隐含层的部分权重或输出随机归零,降低节点间的相互依赖性从而实现神经网络的正则化,降低其结构风险。
如何实现呢?每次,我们可以选用神经层中的部分神经元,下次训练时再选用其他部分,通过这样的选取,可以有效缓解过拟合等问题。
图例:
Dense
Dropout
c1
c2
b1
b2
a1
a2
接下来,Dropout层会随机失活,例如,使b1失活,构成的神经网络:
Dense
Dropout
c1
c2
b1失活
b2
a1
a2
通过每次随机选择神经元失活,就可以保持神经网络的稳定性和活性。 ##
CNN结构 有了上面的介绍,概括CNN卷积神经网络的结构: 卷积(Convolutional)
→ 批标准化(BN) → 激活(Activation) → 池化(Pooling) → 失活(Dropout)* →
全连接(FC)
概括为CBAPD.
简单演示tensorflow2的keras搭建CNN神经网络,以下是一个典型的解决多分类问题(如图片内容分类)的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
import tensorflow as tf import numpy as np
if __name__ == '__main__': model = tf.keras.Sequential( tf.keras.layers.Conv2D(filters=6, kernal_size=(5, 5), padding='same'), tf.keras.layers.BatchNormalization(), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation='softmax') ) model.compile(optimize='adam', loss='mse') model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
|