深度学习技术
- 卷积神经网络
- 1. 导入需要的库
- 2. 加载并显示两张图像
- 2.1 加载图像
- 2.2 创建子图
- 2.3 打印图像形状
- 2.4 打印合并后的图像数组的形状
- 3. 卷积层
- 3.1 定义变量
- 3.1.1 卷积核的大小(u)
- 3.1.2 滑动步长(s)
- 3.1.3 输出特征图的数量(p)
- 3.2 卷积层形式
- 3.3 打印张量
- 4. 池化层
- 4.1 最大池化层
- 4.2 全局平均池化层
- 4.3 平均池化层
- 5. 搭建卷积神经网络进行手写数字识别
- 5.1 导入并对数据进行预处理
- 5.1.1 读取数据并存储
- 5.1.2 归一化
- 5.1.3 分割验证集和训练集
- 5.1.4 归一化
- 5.1.5 打印形状
- 5.2 搭建卷积神经网络
- 5.2.1 定义一个卷积神经网络(CNN)
- 5.2.2 重塑(reshape)
- 5.2.3 编译和训练模型
- 5.2.4 评估性能
- 6. 利用函数式API与子类API搭建复杂神经网络
- 6.1 残差层
- 6.1.1 残差连接
- 6.2 搭建完整的ResNet-34神经网络
- 6.2.1 创建一个顺序模型
- 6.2.2 向模型中添加层
- 6.2.3 构建一个深度残差网络
- 6.2.3 添加几层用于分类任务
- 6.2.4 编译和训练模型
- 6.2.5 评估性能
卷积神经网络
1. 导入需要的库
导入numpy、pandas,tensorflow、sklearn等库,以及导入matplotlib的pyplot模块。从sklearn库的datasets模块中导入load_iris函数,以及从sklearn库的model_selection模块中导入train_test_split函数。从TensorFlow库中导入Keras模块。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
import tensorflow as tf
from tensorflow import keras
2. 加载并显示两张图像
2.1 加载图像
使用了sklearn.datasets.load_sample_image函数来加载两个预先定义的样本图像,并将图像的像素值从0-255的范围缩放到0-1的范围。
china = load_sample_image("china.jpg") / 255
flower = load_sample_image("flower.jpg") / 255
2.2 创建子图
在Matplotlib中创建了两个新的子图,三个数值分别代表行数、列数以及子图的位置。(从左到右,从上到下)。
plt.subplot(1,2,1)
plt.imshow(china)
plt.subplot(1,2,2)
plt.imshow(flower)
运行结果:
2.3 打印图像形状
打印出“china.jpg”图像的形状,即图像的高度、宽度和颜色通道数。
print("china.jpg的维度: ",china.shape)
print("flower.jpg的维度: ",flower.shape)
运行结果:
2.4 打印合并后的图像数组的形状
将两个图像合并为一个NumPy数组,其中第一个元素是“china.jpg”图像,第二个元素是“flower.jpg”图像,计算并存储了合并后的图像数组的形状,并打印出合并后的图像数组的形状,即数据集中图像的数量和每个图像的高度、宽度和颜色通道数。
images = np.array([china,flower])
images_shape = images.shape
print("数据集的维度: ",images_shape)
运行结果:
3. 卷积层
3.1 定义变量
3.1.1 卷积核的大小(u)
u通常表示卷积核(也称为过滤器)的边长。在这里,u被设置为7,意味着卷积核是一个7x7的矩阵。
在图像处理中,卷积核用于检测图像中的特定模式或特征。卷积核的大小(u)决定了它可以检测的特征的大小。
u = 7 # 卷积核边长
3.1.2 滑动步长(s)
s通常表示卷积核的滑动步长(stride)。在这里,s被设置为1,这意味着在每一步,卷积核都会在输入图像上滑动一个像素。
滑动步长(s)决定了卷积核在图像上移动的步长。较小的滑动步长可以提高特征的分辨率,但会增加计算成本。
s = 1 # 滑动步长
3.1.3 输出特征图的数量(p)
p通常表示输出特征图的数量。在这里,p被设置为5,意味着卷积操作将生成5个不同的特征图。
输出特征图的数量(p)决定了卷积操作将生成多少个特征图。每个特征图都捕获了图像的不同方面或特征。
p = 5 # 输出特征图数目
3.2 卷积层形式
input_shape: 输入数据的形状,它是一个元组,代表输入特征图的尺寸加上通道数。
activation: 激活函数,这里使用的是 ReLU(修正线性单元)激活函数。
padding: padding 策略,“SAME” 表示使用边缘填充,使得输出特征图的尺寸与输入相同。
conv = keras.layers.Conv2D(filters = p, kernel_size = u, strides = s, padding="SAME", activation="relu", input_shape=images_shape)
3.3 打印张量
image_after_conv = conv(images)
print("卷积后的张量大小: ", image_after_conv.shape)
运行结果:
4. 池化层
4.1 最大池化层
最大池化(Max Pooling)是一种池化操作,它通过在局部区域中取最大值来减少数据的维度。
pool_max = keras.layers.MaxPool2D(pool_size=2)
image_after_pool_max = pool_max(image_after_conv)
print("最大汇聚后的张量大小: ",image_after_pool_max.shape)
运行结果:
4.2 全局平均池化层
全局平均池化(Global Average Pooling)是一种池化操作,它计算整个特征图的平均值,这通常用于卷积神经网络的末端,以减少特征图的空间维度到1x1,即每个特征图只保留一个平均值。这种方法可以用来减少参数数量并防止过拟合。
pool_global_avg = keras.layers.GlobalAvgPool2D()
image_after_pool_global_avg = pool_global_avg(image_after_conv)
print("全局平均汇聚后的张量大小: ",image_after_pool_global_avg.shape)
运行结果:
4.3 平均池化层
平均池化(Average Pooling)是一种池化操作,它计算每个局部区域内的平均值,并使用这些平均值来减少数据的维度。
pool_avg = keras.layers.AvgPool2D(pool_size=2)
image_after_pool_avg = pool_avg(image_after_conv)
print("平均汇聚后的张量大小: ",image_after_pool_avg.shape)
运行结果:
5. 搭建卷积神经网络进行手写数字识别
5.1 导入并对数据进行预处理
5.1.1 读取数据并存储
从指定路径读取训练数据和测试数据,并将它们存储在 train_Data 和 test_Data 变量中。这些数据是以 CSV 格式存储的,并且指定了 header=None,这意味着 CSV 文件中没有标题行。
path = "E:/工坊/深度学习/"
train_Data = pd.read_csv(path+'train.csv', header = None) # 训练数据
test_Data = pd.read_csv(path+'test.csv', header = None) # 测试数据
5.1.2 归一化
对训练数据进行处理,将像素值归一化到 [0, 1] 范围内,并将图像数据与标签分离。
X, y = train_Data.iloc[:,1:].values/255, train_Data.iloc[:,0].values #数据归一化
5.1.3 分割验证集和训练集
X_valid 和 y_valid 分别存储验证集的图像数据和标签,而 X_train 和 y_train 存储训练集的图像数据和标签。reshape 函数用于将数据从一维数组转换为三维数组,其中每个图像是一个 28x28 的矩阵。打印出的形状信息可以帮助确认数据的维度是否正确。
X_valid, X_train = X[:5000].reshape(5000,28,28) , X[5000:].reshape(55000,28,28) #验证集与训练集
y_valid, y_train = y[:5000], y[5000:]
5.1.4 归一化
test_Data.iloc[:,1:] 表示您想要获取所有行的第二列到最后一列的数据,这些列包含图像的像素值。test_Data.iloc[:,0] 则表示您想要获取所有行的第一列数据,这列包含图像的标签。
X_test,y_test = test_Data.iloc[:,1:].values.reshape(10000,28,28)/255, test_Data.iloc[:,0].values #测试集
5.1.5 打印形状
打印 X_train、X_valid 和 X_test 变量的形状。这些变量分别代表训练数据、验证数据和测试数据。
print(X_train.shape)
print(X_valid.shape)
print(X_test.shape)
运行结果:
5.2 搭建卷积神经网络
5.2.1 定义一个卷积神经网络(CNN)
Flatten():这个层将3D输出张量(特征图)展平为1D特征向量,这是后续的全连接层所必需的。
Dropout(0.25):这个层在每次训练更新时随机地将输入单元的25%设置为0,这有助于防止过拟合。
Dense(128, activation=“relu”):这是一个有128个单元的全连接层,并使用ReLU激活函数。
Dropout(0.5):另一个具有更高丢弃率(0.5)的全连接层。
model_cnn_mnist = keras.models.Sequential([
keras.layers.Conv2D(32, kernel_size=3, padding="same", activation="relu"), # 第一个卷积层
keras.layers.Conv2D(64, kernel_size=3, padding="same", activation="relu"), # 第二个卷积层
keras.layers.MaxPool2D(pool_size=2), # 最大池化层
keras.layers.Flatten(),
keras.layers.Dropout(0.25),
keras.layers.Dense(128, activation="relu"),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation="softmax")
])
5.2.2 重塑(reshape)
reshape 方法被用于改变数组的形状,而不改变其数据。
# 假设 X_train, X_valid, X_test 是您当前的图像数据
X_train = X_train.reshape(-1, 28, 28, 1)
X_valid = X_valid.reshape(-1, 28, 28, 1)
X_test = X_test.reshape(-1, 28, 28, 1)
5.2.3 编译和训练模型
compile 方法用于配置模型的学习过程。
fit 方法用于训练模型。
evaluate 方法用于评估模型的性能。
执行这些代码后,模型将经历编译、训练和评估的过程,将能够看到每个周期在验证集上的准确率,以及最终在测试集上的损失和准确率。
model_cnn_mnist.compile(loss="sparse_categorical_crossentropy", optimizer="nadam", metrics=["accuracy"])
model_cnn_mnist.fit(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
model_cnn_mnist.evaluate(X_test, y_test, batch_size=1)
运行结果:
5.2.4 评估性能
evaluate:这是模型实例的方法,用于评估模型的性能。它计算模型在编译时指定的损失函数和指标(在这个案例中是准确率)。
model_cnn_mnist.evaluate(X_test, y_test, batch_size=1)
运行结果:
6. 利用函数式API与子类API搭建复杂神经网络
6.1 残差层
6.1.1 残差连接
残差连接(Residual Connection)是深度学习中的一种常见网络架构,它允许在网络层之间直接添加输入到输出,这种连接可以帮助梯度在网络中顺畅传播,从而缓解了深层网络训练中的梯度消失和梯度爆炸问题。
ResidualUnit 类实现了一个残差单元,其中包含了主要的前向传播路径(main_layers)和一个跳跃连接(skip_layers)。
filters: 卷积层中的过滤器(卷积核)数量。
strides: 卷积层的步长,默认为1。当步长大于1时,会应用下采样。
class ResidualUnit(keras.layers.Layer):
def __init__(self, filters, strides=1, activation="relu"):
super().__init__()
self.activation = keras.activations.get(activation)
self.main_layers = [
keras.layers.Conv2D(filters, 3, strides=strides, padding = "SAME", use_bias = False),
keras.layers.BatchNormalization(),
self.activation,
keras.layers.Conv2D(filters, 3, strides=1, padding = "SAME", use_bias = False),
keras.layers.BatchNormalization()]
# 当滑动步长s = 1时,残差连接直接将输入与卷积结果相加,skip_layers为空,即实线连接
self.skip_layers = []
# 当滑动步长s = 2时,残差连接无法直接将输入与卷积结果相加,需要对输入进行卷积处理,即虚线连接
if strides > 1:
self.skip_layers = [
keras.layers.Conv2D(filters, 1, strides=strides, padding = "SAME", use_bias = False),
keras.layers.BatchNormalization()]
def call(self, inputs):
Z = inputs
for layer in self.main_layers:
Z = layer(Z)
skip_Z = inputs
for layer in self.skip_layers:
skip_Z = layer(skip_Z)
return self.activation(Z + skip_Z)
6.2 搭建完整的ResNet-34神经网络
6.2.1 创建一个顺序模型
模型中的层会依次堆叠。
model = keras.models.Sequential()
6.2.2 向模型中添加层
批量归一化层:有助于加速训练过程和稳定网络。
model.add(keras.layers.Conv2D(64, 7, strides=2, padding = "SAME", use_bias = False)) # 添加第一个卷积层
model.add(keras.layers.BatchNormalization()) # 添加批量归一化层
model.add(keras.layers.Activation("relu")) # 添加ReLU激活函数
model.add(keras.layers.MaxPool2D(pool_size=3, strides=2, padding="SAME")) # 添加最大池化层
6.2.3 构建一个深度残差网络
构建一个深度残差网络,其中的残差单元允许模型在增加深度时仍然能够有效地训练。通过逐渐增加过滤器的数量,模型能够捕捉到更复杂的特征,同时通过步长的变化来调整特征图的尺寸。这种设计使得模型能够在不牺牲性能的情况下增加深度,这是残差网络的一个重要特性。
prev_filters = 64 # 初始化前一个块的过滤器数量为64
for filters in [64] * 3 + [128] * 4 + [256] * 6 + [512] * 3: # 遍历一系列的过滤器数量
strides = 1 if filters == prev_filters else 2 #在每次特征图数目扩展时,设置滑动步长为2
model.add(ResidualUnit(filters, strides=strides))
prev_filters = filters
6.2.3 添加几层用于分类任务
model.add(keras.layers.GlobalAvgPool2D()): 这层会在每个特征图上计算全局平均池化,即将每个特征图的的所有值平均成一个单一的值。
model.add(keras.layers.Flatten()): 这层将上一个层的输出展平成一个一维向量。
model.add(keras.layers.Dense(10, activation=“softmax”)): 这是最后一个全连接层,它将一维的输入向量映射到一个长度为10的输出向量,每个元素对应一个类别。
activation="softmax"表示使用softmax激活函数,它会将输出向量转换为概率分布,每个元素都是相应类别的预测概率。
model.add(keras.layers.GlobalAvgPool2D())
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(10, activation="softmax"))
6.2.4 编译和训练模型
compile 方法用于配置模型的学习过程。
fit 方法用于训练模型。
model.compile(loss="sparse_categorical_crossentropy", optimizer="nadam", metrics=["accuracy"])
model.fit(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
运行结果:
6.2.5 评估性能
evaluate:这是模型实例的方法,用于评估模型的性能。它计算模型在编译时指定的损失函数和指标(在这个案例中是准确率)。
model.evaluate(X_test,y_test, batch_size=1)
运行结果: