一、CNN基本原理
CNN是包含卷积计算且具有深度结构的前馈神经网络,适合处理具有二维或三维结构的数据,常用于图像和音频识别。基本结构大致包括输入层,卷积层(Convolutional Layer)、激活层(Activation Layer)、池化层(Pooling Layer)、全连接层(Fully Connected Layer)、输出层等。Python中可用Keras,TensorFlow,PyTorch库来构建CNN模型。
二、卷积计算基础知识
卷积计算就是在滤波器和输入数据的局部区域间做点积。
Padding:卷积计算后特征图比原始图像减小了很多,在原始图像的周围进行补零操作来保证在卷积过程中特征图大小不变。目的是让输入的特征保留更多的信息,特征图变小的速度稍微慢一些,提取更加丰富的信息。
例如:padding 等于 1 就是补一圈的零,等于 2 就是补两圈的零
stride: 移动卷积核的步长
多通道卷积:当输入有多个通道(channel)时(例如图片可以有 RGB 三个通道),卷积核需要拥有相同的通道数(channel),每个卷积核 channel 与输入层的对应 channel 进行卷积,将每个 channel 的卷积结果按位相加得到最终的特征图。
多卷积核卷积:当有多个卷积核时,每个卷积核学习到不同的特征,对应产生包含多个特征图,也就是说最终产生的特征图有多个通道即通过多个卷积核来识别多个特征。
注:某个卷积层,无论输入图像有多少个通道,输出图像通道数总是等于卷积核数量
三、Python中keras库构建CNN
1、keras库构建一维卷积神经网络函数参数
Conv1D(filters=4, kernel_size=3, strides=1, padding='valid', dilation_rate=1, activation=relu)
- filters:卷积核个数(通道数)
- kernel_size:卷积核尺寸(长度或宽度),一般选择为奇数(因为尺寸为奇数的卷积核可以找到中心点)
- strides:卷积步长,即卷积核向右(或向下)移动步长
- padding:右边缘(或下边缘)不够一个窗口大小时,是否补零。valid 表示无填充,same 表示边缘填充
- dilation_rate:用于控制卷积核之间的间隔的整数,即每次卷积运算时,相邻元素之间的水平距离
- activation: 激活函数,如
relu
、sigmoid
、tanh
等 - 当该层作为第一层时,需提供
input_shape
参数。例如input_shape=(10,3)
表示10个时间步长的时间序列,每步中有3个特征
MaxPooling1D(pool_size=2, strides=None, padding='valid')
- pool_size:池化窗口尺寸(长度或宽度)
- strides:窗口向右(或向下)移动步长
- padding:右边缘(或下边缘)不够一个窗口大小时,是否补零。valid 表示不补,same 表示补零
Dense(units=50,activation='relu')
- units: 代表该层的节点数,即输出的维度
- activation: 代表激活函数,如'relu', 'sigmoid', 'tanh', 'softmax'
- use_bias: 布尔值,表示是否使用偏置项
- kernel_initializer: 权重矩阵的初始化方式
- bias_initializer: 偏置向量的初始化方式
- kernel_regularizer: 权重矩阵的正则化项
- bias_regularizer: 偏置向量的正则化项
- activity_regularizer: 输出的正则化项
- kernel_constraint: 权重矩阵的约束条件
- bias_constraint: 偏置向量的约束条件
2、keras库构建一维卷积神经网络代码示例
# 导入必要的库:
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense, MaxPooling1D,Conv1D, Flatten
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import pandas as pd
import joblib
# 读取数据,此处修改数据路径
feature = pd.read_csv(r'D:\1_soil_texture\ADJUST_417\dy_ALL_NEW_417.csv',
usecols=[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25])
X = feature
target = pd.read_csv(r'D:\1_soil_texture\ADJUST_417\dy_ALL_NEW_417.csv', usecols=[4])
y =np.ravel(target)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=14)
# print(X_train.shape)
# 构建CNN模型:
model = Sequential()
# 添加一维卷积层
model.add(Conv1D(filters=10, kernel_size=3, activation='relu', strides=1,input_shape=(X_train.shape[1], 1)))
# 添加最大池化层
model.add(MaxPooling1D(pool_size=2))
model.add(Conv1D(filters=10, kernel_size=3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
# 展平操作,将多维输入展平为一维
model.add(Flatten())
# 添加全连接层/隐藏层
model.add(Dense(50, activation='relu'))
# 添加输出层
model.add(Dense(1)) # 输出层,一个神经元用于回归任务
# 查看模型摘要
print(model.summary())
"""
定义训练方式
参数:
loss - 损失函数: 这里采用交叉熵的方式
optimizer - 优化器: 使用adam优化器可以让训练收敛更快
metrics - 评估模型:设置为准确率
"""
# 编译模型
model.compile(optimizer='adam', loss='mse')
"""
开始训练
参数:
x_train- feature数字图像的特征值
y_train- 数字图像的真实标签
validation_split - 训练与验证数据比例:80%用作训练数据,20%用作验证数据
epochs - 训练周期
batch_size - 每批次的数据项数
verbose - 显示训练过程
"""
# 训练模型:
train_history = model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.2,verbose=1)
# 模型评估
def show_train_history(train_history,train,validation):
plt.plot(train_history.history[train])
plt.plot(train_history.history[validation])
plt.title('Train History')
plt.ylabel(train)
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()
show_train_history(train_history,'loss','val_loss') #绘制损失函数执行曲线
# 预测并评估模型
y_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, y_pred)
print(f'Train RMSE: {rmse}')
# 绘制实际值和预测值的比较图
plt.figure(figsize=(10, 5))
plt.plot(y_test, label='Actual')
plt.plot(y_pred.flatten(), label='Predicted')
plt.title('Comparison of Actual and Predicted Values')
plt.xlabel('Sample Index')
plt.ylabel('Value')
plt.legend()
plt.show()