Python 演算法 Day 19 - 卷积神经网路 (CNN) 简介

Chap.III 深度学习与模型优化

Part 4: 卷积神经网路 (CNN)

Day18提到了数字与文字辨识的机器学习。
然而实际上,我们应该进一步考虑图片的每个像素权重与各个像素间彼此的关联性。
举例来说,一张带有数字的图片,在中心区块的权重(红圈处)理当明显比角落的权重要高。
http://img2.58codes.com/2024/20138527HqlibhoODZ.png

为此,科学家提出了新方法:Convolutional Neural Network

也就是常看到的 CNN 卷积神经网路

卷积神经网路 (CNN) 是一种前馈神经网路 (Feedforward Neural Network)。
藉影像处理,从图片中萃取特徵,使特徵抽象化 (Abstraction),从而更準确辨识影像。
http://img2.58codes.com/2024/20138527qLcmmGWzeX.png

常由多个卷积层与池化层 Convolution & Pooling;和全连接层 Fully Connected 组成。
此结构使 CNN 与其他深度学习相比,在图像和语音辨识表现得更好。
http://img2.58codes.com/2024/20138527TTby2h51MV.png
原图网址

4-1. Assumption 假设

CNN 有两大假设

Local Connectivity 局部连接

即是每个神经元仅接收上一层部分神经元的传导,又称 Receptive Field 感知域。

Share Weight 共享权重

每个感知域对下一隐藏层均使用相同的权重,即 Feature Detector 也称 Filter。

4-2. Function of Layers 各层功能

A. Convolution Layer 卷积层

甚么是卷积运算?

即是将 "Input" 与 "Filter" 以 numpy nd array 的方式相乘后加总

假设今天我们有一个 7*7 的 input image
http://img2.58codes.com/2024/20138527fZJeZsRSOf.png
我们使用一个 3*3 的 Feature Detector(又称 Filter)stride=1, 1 来转换:
http://img2.58codes.com/2024/201385277HyhAViTAX.png

这样一来我们就把原图的 7*7 个特徵,萃取成 5*5 个特徵了!

实例上,我们常用卷积运算萃取物体边界
http://img2.58codes.com/2024/20138527zd9CVR2Get.png

甚至搭配 Relu 函数,进一步淬炼物体形状(因负值都变成 0,轮廓更显着)
http://img2.58codes.com/2024/20138527KQYU0ktBQJ.png

不同的 Filter

除上述自订的 Filter,也很常使用以下几种滤波器:

Denosing 去噪:滤波器内讯号平均,使噪讯被模糊化。
http://img2.58codes.com/2024/20138527cZoqrrdX41.png
http://img2.58codes.com/2024/20138527HMqTcwMI7z.pngSharpening 锐利化:中间讯号特别强,拉大每个像素与周遭的差距。
http://img2.58codes.com/2024/20138527JxSfJZmAln.png
http://img2.58codes.com/2024/20138527WCuaQM8gtB.png

重要参数

tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), strides=(2, 2), padding='same', activation='relu')
filters:就是你该卷积层想要使用多少个 filters。常设 4 的倍数。kernel_size:你使用的 filter 的 shape。常设奇数边长的正方形(3*3, 5*5 等)。strides:滑动步长,计算滑动视窗时移动的格数。默认 (1, 1)。padding:补 0 策略,卷积层取 kernel_size 滑动视窗时,若超越边界,是选择
放弃这个 output 点(valid)、一律补零(same)、或是不计算超越边界的 Input 值(causal)。
因为卷积后图形会变小,为了不让图片与原本大小有差异,会在周围补上 0 维持原本图片大小
http://img2.58codes.com/2024/20138527rECmrHvOTV.pngactivation:选择你想使用的激励函数。默认 None。

B. Pooling Layer 池化层

若说卷积层是用来萃取「精华」,那么池化层就是用来「压缩并保留」重要资讯的方法。
以上例延伸,使用较常见的 Max Pooling(另一种为 Avg),对 2*2 的範围 stride=2, 2 取最大值:
http://img2.58codes.com/2024/20138527spWd2xulU6.png

重要参数

tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')
pool_size:池化视窗的大小。常设 2*2。strides:滑动步长,计算滑动视窗时移动的格数。默认 (1, 1)。padding:补 0 策略,卷积层取 kernel_size 滑动视窗时,若超越边界,是选择
放弃这个 output 点(valid)、一律补零(same)。

C. Fully Connected Layer 全连接层

即是将结果平坦化后连接,概念就像是把 2D 的图片拍扁变成 1D 的数列。
http://img2.58codes.com/2024/20138527vAv9eoTAa5.png

4-3. 实作

讲完了概念,接着我们用 Tensorflow 官网的範例来演练一下。

官网的程式码如下:

import tensorflow as tfmnist = 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.0model = tf.keras.models.Sequential([    tf.keras.layers.Flatten(input_shape=(28, 28)),    tf.keras.layers.Dense(128, activation='relu'),    tf.keras.layers.Dropout(0.2),    tf.keras.layers.Dense(10, activation='softmax')])model.compile(optimizer='adam',              loss='sparse_categorical_crossentropy',              metrics=['accuracy'])model.fit(x_train, y_train, epochs=5)model.evaluate(x_test, y_test)

http://img2.58codes.com/2024/20138527ta79gEBVkk.png

原本的 mnist 的资料已经很乾净,因此实作的準确度本身就已相当高。
接着我们试着用 CNN 的方式来撰写:

import tensorflow as tfmnist = tf.keras.datasets.mnist(x_train, y_train),(x_test, y_test) = mnist.load_data()x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0

不同的是,这次我们在建模的时候加入 CNN:

首先,要把 x 增加一维在最后面,因为 CNN 要多一个表示颜色的维度

x_train = x_train.reshape(*x_train.shape, 1)x_test = x_test.reshape(*x_test.shape, 1)x_train.shape, x_test.shape>>  ((60000, 28, 28, 1), (10000, 28, 28, 1))

建模

model_cnn = tf.keras.Sequential([    tf.keras.Input(shape=(28, 28, 1)),    tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),    tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),    tf.keras.layers.Flatten(),    tf.keras.layers.Dropout(0.2),    tf.keras.layers.Dense(10, activation="softmax"),])

优化器设定:与前面同样使用 Adam、交叉熵做损失函数,关键指标则看準确率。

model_cnn.compile(optimizer='adam',              loss='sparse_categorical_crossentropy',              metrics=['accuracy'])history = model_cnn.fit(x_train, y_train, epochs=5, validation_split=0.2)

http://img2.58codes.com/2024/201385276OwKvs1v5I.png

如此一来,即用 CNN 的方式做出一个更準确的模型了!


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章