深度学习(二)卷积神经网络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

图像识别任务提出问题:

  • 逻辑回归:对一个28*28像素的图像进行自动识别,要建立一个逻辑回归模型,将图像数据转换成28行*28列的数组,每个数据在0-255之间,然后进行非线性预测,使用多项式作为决策边界的逻辑回归预测,待训练参数的数量巨大
  • MLP/ANN:将28*28转换为数组后的数据作为输入,然后建立2个隐藏层的MLP结构,每个隐藏层各有392个神经元,通过summary方法可以查看结构中要训练的参数量比逻辑回归小,但当图片像素高如500*400并有RGB三个通道时,使用MLP模型要训练的参数量巨大
  • 卷积处理:为了进一步减少训练参数的数量而使用的简化模型,先提取出图像中的关键信息(如轮廓),再建立MLP模型进行训练及预测

图像卷积运算Convolution:对图像矩阵与滤波器矩阵进行对应相乘再求和运算,转化得到新的矩阵,用于快速定位图像中的某些特征,如轮廓

核心:计算机根据样本图片,自动寻找合适的轮廓过滤器,对新图片进行轮廓匹配

深度学习(二)卷积神经网络CNN_第1张图片

深度学习(二)卷积神经网络CNN_第2张图片

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

深度学习(二)卷积神经网络CNN_第3张图片


2. 池化层实现维度缩减(最大法&平均法)

池化层:为了减少训练数据的参数,按照一个固定规则对图像矩阵进行处理,将其转换为更低维度的矩阵,设置合理池化参数保留主要信息

最大法池化MaxPooling:找到窗口中最大的数,作为新数据给新矩阵

深度学习(二)卷积神经网络CNN_第4张图片

pooling size:窗口大小

stride:窗口滑动步长,每次移动2*2格

平均法池化AvgPooling:对窗口内数据求平均值

深度学习(二)卷积神经网络CNN_第5张图片


3. 卷积神经网络 CNN 介绍、特点、问题

卷积神经网络:把卷积、池化、MLP先后连接在一起,组成卷积神经网络

流程

  1. 6*6图片 --矩阵-->
  2. 3*3Filter --卷积-->
  3. 4*4新数组 --Relu-->  --池化-->
  4. 2*2新矩阵 --全连接-->
  5. MLP模型

深度学习(二)卷积神经网络CNN_第6张图片

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

深度学习(二)卷积神经网络CNN_第7张图片

Sigmoid函数:

在某个范围内导数很小,然而对MLP求解就是求导,那么当大于/小于一定范围时很难求导,因为太小会导致迭代很慢,但Relu可以解决这个问题

 CNN特点:

  1. 参数共享 Parameter Sharing:同一个特征过滤器可用于整张图片
  2. 稀疏连接 Sparsity of Coneections:生成的特征图片每个节点只与原图片中特定节点连接,与其它窗口不相关

卷积运算导致的问题:

  1. 图像被压缩,造成信息丢失
  2. 边缘信息使用少,容易被忽略,即矩阵四个角落的值只被窗口使用了一次

为了解决这个问题,使用图像填充Padding:通过在图像左右两边各增加一个像素,使其在卷积运算后维持原图大小

深度学习(二)卷积神经网络CNN_第8张图片


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

4.1 LeNet-5

流程

深度学习(二)卷积神经网络CNN_第9张图片

说明

  • 6个Filters,每个Filter的窗口大小:5*5
  • 池化滑动窗口大小:s=1
  • 卷积输出层维度=输入层维度-Filter窗口大小+stride滑动窗口大小,32-5+1=28
  • 池化输出层维度=(输入层维度-f窗口尺寸)/s池化滑动窗口大小+1,(28-2)/2+1=14
  • 最后一个池化层的输出需要建立一个全连接层,作为MLP模型的输入,使用激活函数sigmoid将输入输出进行神经关联
  • 每个FC是一个全连接层
  • 共十个输出结果

输入:32*32灰度图,1个通道Channel

训练参数:约6w个

特点

  1. 随着网络越深,图像的高度和宽度缩小,通道增加(即Filter,提取图片特征)
  2. 卷积与池化先后成对使用
  3. 使用sigmoid作为激活函数 

4.2 AlexNet

流程:

深度学习(二)卷积神经网络CNN_第10张图片

说明

  • Filter的窗口大小11*11
  • (227-11)/4+1=55
  • 多次卷积可以提取出图像中更复杂的信息
  • same:对图像做填充,保证输入和输出的行/列像素一样

输入:227*227*3 RGB图,3个通道

训练参数:约6千万个

特点

  1. 适用于识别较为复杂的彩色图,可识别1000种类别
  2. 结构比LeNet更复杂,使用Relu作为激活函数
  3. 应用于计算机视觉

4.3 VGG-16

流程:

深度学习(二)卷积神经网络CNN_第11张图片

说明:

  • 由于AlexNet模型中卷积层的Filter的窗口大小和滑动步长等参数经常变化,不够稳定,为了解决这个问题,提出VGG-16模型
  • 多次卷积操作来提取轮廓信息

输入:227*227*3 RGB图,3个通道

训练参数:约1亿多

特点

  1. 所有卷积层Filters宽和高都是3*3,步长s=1,图像填充Padding都是same convolution
  2. 所有池化层Filters宽和高都是2*2,步长s=2,都使用最大化池化方法MaxPooling
  3. 相比AlexNet,有更多的Filter用于提取轮廓信息,准确度更高
  4. Filter越多,模型越稳定

二、 代码实战

1. 建立CNN模型实现猫狗图像识别,并对新图像进行预测

1.1 CNN结构图 

卷积层采用Relu作为输出时对激活函数

深度学习(二)卷积神经网络CNN_第12张图片

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)

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()

 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)

深度学习(二)卷积神经网络CNN_第13张图片


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)

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

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()

你可能感兴趣的:(机器学习与深度学习,深度学习,cnn,机器学习)