深度学习(二)卷积神经网络CNN
目录
一、 定义和公式
1. 图像卷积运算:图像矩阵*Filter
2. 池化层实现维度缩减(最大法&平均法)
3. 卷积神经网络 CNN 介绍、特点、问题
4. 经典的CNN模型:LeNet-5,AlexNet,VGG-16
4.1 LeNet-5
4.2 AlexNet
4.3 VGG-16
二、 代码实战
1. 建立CNN模型实现猫狗图像识别,并对新图像进行预测
1.1 CNN结构图
1.2 建立CNN模型实现猫狗图像识别
1.3 对新图像进行预测
2. 基于VGG-16模型,构建MLP,实现猫狗识别
2.1 使用VGG-16结构提取单个图像特征
2.2 使用VGG-16结构批量提取图像特征
2.3 根据图像特征数据,分离数据,建立MLP,计算测试数据预测准确率
2.4 下载新图片,对其进行预测
一、 定义和公式
1. 图像卷积运算:图像矩阵*Filter
图像识别任务中的一个问题:
逻辑回归:构建一个逻辑回归模型用于自动完成图像识别过程。具体而言,需将输入的28x28像素图像数据转换为二维数组,并确保每个像素值范围在0至255之间。随后通过多项式函数作为决策边界来进行非线性预测。
MLP/ANN:将上述转换后的数据作为输入层接收到该二维数组,并设计两个隐藏层结构。每个隐藏层均包含392个神经元节点,在此过程中总共有大量参数需要进行训练。值得注意的是,在处理更高分辨率(如500x400像素)且具有RGB三通道颜色信息的图片时,直接使用MLP架构会显著增加所需训练参数数量。
卷积处理:为了优化参数规模并提高效率,在此阶段引入了卷积神经网络(CNN)相关技术。该方法通过提取图像中的关键特征(如边缘轮廓),继而构建MLP模型用于完成后续的训练与预测任务。
图像的卷积操作:执行对应元素的乘法并累加的操作,在二维空间中实现图像与滤波器之间的映射关系,并计算得到新的结果矩阵。该矩阵能够迅速识别图像中的特定特征(如边缘、纹理等)。关键点:基于样本图片集合自动训练出适合的边缘检测滤波器集合,并实现新输入图片的边缘特征匹配过程。


RGB图像的卷积 :对RGB三个通道分别求卷积再相加

2. 池化层实现维度缩减(最大法&平均法)
池化层 :为了减少训练数据的参数,按照一个固定规则对图像矩阵进行处理,将其转换为更低维度的矩阵,设置合理池化参数保留主要信息
最大法池化MaxPooling :找到窗口中最大的数,作为新数据给新矩阵

pooling尺寸:指定窗口大小
stride:滑动步长设置为2*2格
平均法池化(AvgPooling):计算并输出窗口区域内数据的均值

3. 卷积神经网络 CNN 介绍、特点、问题
卷积神经网络 :把卷积、池化、MLP先后连接在一起,组成卷积神经网络
流程 :
- 6*6图片 --矩阵-->
- 3*3Filter --卷积-->
- 4*4新数组 --Relu--> --池化-->
- 2*2新矩阵 --全连接-->
- MLP模型

Relu函数: f(x)=max(x,0)

Sigmoid函数:
在特定范围内其导数值较小,在神经网络模型如MLP中需要计算梯度以进行参数更新的过程中发现,在超过/低于某一阈值时由于其极小的导数值会导致优化过程缓慢收敛。然而这一问题可以通过使用Rectified Linear Unit(ReLU)来有效缓解。
CNN特点:
- 参数共享机制:同一组滤波器在所有图像像素上均适用
- 稀疏连接特性:每个特征节点仅与原图中的特定位置产生关联
卷积运算所面临的问题如下:**
**
- 图像发生压缩会导致数据信息损失
- 边缘区域的细节特征未被充分捕捉
即在矩阵的四个角落位置的数据仅能通过一次窗口采样实现
为了解决这一问题,在图像的左右两侧各添加一个像素以实现填充Padding的效果:通过这种方式,在执行卷积运算后能够确保卷积运算后的图像尺寸与原图保持一致

4. 经典的CNN模型:LeNet-5,AlexNet,VGG-16
4.1 LeNet-5
流程 :

该网络采用了六个卷积滤波器(Filters),每个滤波器的卷积核尺寸为5×5。
所有池化操作均使用步长为1(stride=1)。
通过计算公式得到卷积输出层的空间维度为输入层减去滤波器尺寸加上步长后的值。
经过池化后空间维度计算为(输入空间尺寸减去滤波器尺寸除以步长)加一。
将该全连接层作为多标签分类任务的神经网络输入。
十个输出结果分别对应十个类别特征进行预测。
输入 :32 \times 32灰度图具有1个通道Channel
训练参数 :约60,000个
特点 :
- 当网络越深时,图像尺寸逐渐减小,并伴随通道数量的增加(此处Filter用于提取图像特征)
- 卷积操作后紧跟池化操作
- 激活函数选用sigmoid函数。
4.2 AlexNet
流程:

说明 :
- 滤波器窗口尺寸为十一乘十一。
- (227-11)/4+1=55。
- 通过反复应用卷积操作,能够捕获图像中更为复杂的特征。
- 为了保持输入输出的尺寸一致,在执行卷积操作前需对图像进行填充处理。
输入:RGB图像的尺寸为227\times 227\times 3颜色通道数量为3
训练参数:约为6,000万个参数
特点:
- 适用于处理高复杂度的彩色图像,并支持1,000种分类类别
- 网络结构比LeNet更为复杂,并采用ReLU作为激活函数单元
- 主要应用于计算机视觉领域
4.3 VGG-16
流程:

针对AlexNet卷积层中的Filter参数(如窗口大小、滑动步长等)存在波动的问题,
为了解决这一问题,
提出了VGG-16模型。
通过反复进行卷积操作以提取图像轮廓特征,
从而提升了模型的整体性能。
输入 :2272273 RGB图,3个通道
训练参数 :约1亿多
特点 :
- 所有卷积层Filters宽和高都是3*3,步长s=1,图像填充Padding都是same convolution
- 所有池化层Filters宽和高都是2*2,步长s=2,都使用最大化池化方法MaxPooling
- 相比AlexNet,有更多的Filter用于提取轮廓信息,准确度更高
- Filter越多,模型越稳定
二、 代码实战
1. 建立CNN模型实现猫狗图像识别,并对新图像进行预测
1.1 CNN结构图
卷积层采用Relu作为输出时对激活函数

1.2 建立CNN模型实现猫狗图像识别
'''
基于dataset\training_set数据,根据提供的结构,建立CNN模型,识别图片中的猫/狗,计算预测准确率
'''
# 1. load the data
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255)# 1./255:归一化,图像的灰度值都除以255
training_set = train_datagen.flow_from_directory('./dataset/training_set',target_size=(50,50),batch_size=32,class_mode='binary') # flow_from_directory 文件路径
# batch_size:每次选32张图片进行反向梯度搜索来求解cnn,size越小,损失函数越不稳定
# class_mode:模式为二分类
# 2. 确认输入数据标签
training_set.class_indices
#3. 建立CNN模型 set up the cnn model
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense
#创建顺序模型的实例
model = Sequential()
#卷积层
model.add(Conv2D(32,(3,3),input_shape=(50,50,3),activation='relu')) # 32个filters,每个3*3,输入像素为50*50*3通道
#池化层
model.add(MaxPool2D(pool_size=(2,2))) # 默认s=1
#卷积层
model.add(Conv2D(32,(3,3),activation='relu'))
#池化层
model.add(MaxPool2D(pool_size=(2,2)))
#flattening layer
model.add(Flatten()) # 将(m行*n列)转换成(m*n行1列)
#FC layer
model.add(Dense(units=128,activation='relu'))
#输出层
model.add(Dense(units=1,activation='sigmoid'))
# 4. 配置模型参数 configure the model
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy']) # 每次训练完后用accuracy进行评估
# 5. 查看模型每层的结构,及多少参数
model.summary()
# 6. 训练模型 train the model
model.fit_generator(training_set,epochs=20) # 因为是通过keras中的ImageGenerator生成图像的,所以训练时要用fit_generator
# 7. 计算训练数据集的准确率,用evaluate_generator方法 accuracy on the training data
accuracy_train = model.evaluate_generator(training_set)
print(accuracy_train)
# 8. 计算测试数据集的准确率 accuracy on the test data
test_set = train_datagen.flow_from_directory('./dataset/test_set',target_size=(50,50),batch_size=32,class_mode='binary')
accuracy_test = model.evaluate_generator(test_set)
print(accuracy_test)
AI助手
1.3 对新图像进行预测
'''
从网站下载猫/狗图片,对其进行预测
'''
# 9. 加载单个狗图片,对其进行归一化,维度转换,及预测
from keras.preprocessing.image import load_img, img_to_array
pic_dog = 'dog.jpg'
pic_dog = load_img(pic_dog,target_size=(50,50))
pic_dog = img_to_array(pic_dog)
pic_dog = pic_dog/255
pic_dog = pic_dog.reshape(1,50,50,3)
result = model.predict_classes(pic_dog)
print(result) # 结果为[[1]]
# 10. 加载单个猫图片,对其进行归一化,维度转换,及预测
pic_cat = 'cat1.jpg'
pic_cat = load_img(pic_cat,target_size=(50,50))
pic_cat = img_to_array(pic_cat)
pic_cat = pic_cat/255
pic_cat = pic_cat.reshape(1,50,50,3)
result = model.predict_classes(pic_cat)
print(result) # 结果为[[0]]
# 11. 获取类别序列
training_set.class_indices # {'cats': 0, 'dogs': 1}
# 12. 在多张图中预测其类别 make prediction on multiple images
import matplotlib as mlp
font2 = {'family' : 'SimHei',
'weight' : 'normal',
'size' : 20,
}
mlp.rcParams['font.family'] = 'SimHei'
mlp.rcParams['axes.unicode_minus'] = False
from matplotlib import pyplot as plt
from matplotlib.image import imread
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import load_model
a = [i for i in range(1,10)]
fig = plt.figure(figsize=(10,10))
for i in a:
img_name = str(i)+'.jpg'
img_ori = load_img(img_name, target_size=(50, 50))
img = img_to_array(img_ori)
img = img.astype('float32')/255
img = img.reshape(1,50,50,3)
result = model.predict_classes(img)
img_ori = load_img(img_name, target_size=(250, 250))
plt.subplot(3,3,i)
plt.imshow(img_ori)
plt.title('预测为:狗狗' if result[0][0] == 1 else '预测为:猫咪')
plt.show()
AI助手

2. 基于VGG-16模型,构建MLP,实现猫狗识别
使用VGG16的结构提取图像特征,再根据特征建立mlp模型,实现猫狗图像识别。训练/测试数据:dataset\data_vgg:
1.对数据进行分离、计算测试数据预测准确率
2.从网站下载猫/狗图片,对其进行预测
mlp模型一个隐藏层,10个神经元
2.1 使用VGG-16结构提取单个图像特征
'''
单个图像预处理,使用VGG16结构提取图像特征
'''
# 1. load the data
from keras.preprocessing.image import load_img,img_to_array
img_path = '1.jpg'
img = load_img(img_path,target_size=(224,224))
img = img_to_array(img)
type(img)
# 2. 加载VGG-16模型结构
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
import numpy as np
model_vgg = VGG16(weights='imagenet',include_top=False)
x = np.expand_dims(img,axis=0)
x = preprocess_input(x)
print(x.shape)
# 3. 使用vgg模型提取图像特征
features = model_vgg.predict(x)
print(features.shape)
#4. 建立全连接层flatten
features = features.reshape(1,7*7*512)
print(features.shape)
# 5. 可视化数据 visualize the data
%matplotlib inline
from matplotlib import pyplot as plt
fig = plt.figure(figsize=(5,5))
img = load_img(img_path,target_size=(224,224))
plt.imshow(img)
AI助手

2.2 使用VGG-16结构批量提取图像特征
'''
任务1:批量图片预处理,用VGG16的结构提取批量图像特征
'''
# 1. 导入库
from keras.preprocessing.image import img_to_array,load_img
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
import numpy as np
# 2. 创建vgg16模型实例
model_vgg = VGG16(weights='imagenet', include_top=False)
# 3. 定义一个图片加载方法 define a method to load and preprocess the image
def modelProcess(img_path,model):
img = load_img(img_path, target_size=(224, 224))
img = img_to_array(img)
x = np.expand_dims(img,axis=0)
x = preprocess_input(x)
x_vgg = model.predict(x)
x_vgg = x_vgg.reshape(1,25088)
return x_vgg
# 4. 查看指定文件夹包含的文件名列表 list file names of the training datasets
import os
folder = "dataset/data_vgg/cats"
dirs = os.listdir(folder)
# 5. 生成各个图片路径 generate path for the images
img_path = []
for i in dirs:
if os.path.splitext(i)[1] == ".jpg":
img_path.append(i)
img_path = [folder+"//"+i for i in img_path]
# 6. 多图像预处理 preprocess multiple images
features1 = np.zeros([len(img_path),25088])
for i in range(len(img_path)):
feature_i = modelProcess(img_path[i],model_vgg)
print('preprocessed:',img_path[i])
features1[i] = feature_i
folder = "dataset/data_vgg/dogs"
dirs = os.listdir(folder)
img_path = []
for i in dirs:
if os.path.splitext(i)[1] == ".jpg":
img_path.append(i)
img_path = [folder+"//"+i for i in img_path]
features2 = np.zeros([len(img_path),25088])
for i in range(len(img_path)):
feature_i = modelProcess(img_path[i],model_vgg)
print('preprocessed:',img_path[i])
features2[i] = feature_i
# 7. 结果标签 label the results
print(features1.shape,features2.shape)
y1 = np.zeros(300)
y2 = np.ones(300)
# 8. 生成训练数据集 generate the training data
X = np.concatenate((features1,features2),axis=0)
y = np.concatenate((y1,y2),axis=0)
y = y.reshape(-1,1)
print(X.shape,y.shape)
AI助手
2.3 根据图像特征数据,分离数据,建立MLP,计算测试数据预测准确率
'''
任务2:根据任务1提取的图像特征建立MLP模型,对数据进行分离、计算测试数据预测准确率(mlp模型一个隐藏层,10个神经元)
'''
# 1. split the training and test data
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=50)
print(X_train.shape,X_test.shape,X.shape)
# 2. 建立MLP模型set up the mlp model
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(units=10,activation='relu',input_dim=25088))
model.add(Dense(units=1,activation='sigmoid'))
model.summary()
# 3. configure the model
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
# 4. train the model
model.fit(X_train,y_train,epochs=50)
# 5. 计算训练数据集的预测准确率
from sklearn.metrics import accuracy_score
y_train_predict = model.predict_classes(X_train)
accuracy_train = accuracy_score(y_train,y_train_predict)
print(accuracy_train) # 0.98
# 6. 计算测试数据集的准确率
y_test_predict = model.predict_classes(X_test)
accuracy_test = accuracy_score(y_test,y_test_predict)
print(accuracy_test) # 0.97
AI助手
2.4 下载新图片,对其进行预测
'''
任务3:从网站下载猫/狗图片,对其进行预测
'''
# 加载新图片
img_path = 'cat1.jpg'
img = load_img(img_path,target_size=(224,224))
img = img_to_array(img)
x = np.expand_dims(img,axis=0)
x = preprocess_input(x)
features = model_vgg.predict(x)
features = features.reshape(1,7*7*512)
result = model.predict_classes(features)
print(result)
# coding:utf-8
import matplotlib as mlp
font2 = {'family' : 'SimHei',
'weight' : 'normal',
'size' : 20,
}
mlp.rcParams['font.family'] = 'SimHei'
mlp.rcParams['axes.unicode_minus'] = False
from matplotlib import pyplot as plt
from matplotlib.image import imread
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import load_model
#from cv2 import load_img
a = [i for i in range(1,10)]
fig = plt.figure(figsize=(10,10))
for i in a:
img_name = str(i)+'.jpg'
img_path = img_name
img = load_img(img_path, target_size=(224, 224))
img = img_to_array(img)
x = np.expand_dims(img,axis=0)
x = preprocess_input(x)
x_vgg = model_vgg.predict(x)
x_vgg = x_vgg.reshape(1,25088)
result = model.predict_classes(x_vgg)
img_ori = load_img(img_name, target_size=(250, 250))
plt.subplot(3,3,i)
plt.imshow(img_ori)
plt.title('预测为:狗狗' if result[0][0] == 1 else '预测为:猫咪')
plt.show()
AI助手

