Python-深度学习-学习笔记(13):keras搭建卷积神经网络(对二维数据进行一维卷积)

卷积神经网络进行图像分类是深度学习关于图像处理的一个应用,卷积神经网络的优点是能够直接与图像像素进行卷积,从图像像素中提取图像特征,这种处理方式更加接近人类大脑视觉系统的处理方式。另外,卷积神经网络的权值共享属性和pooling层使网络需要训练的参数大大减小,简化了网络模型,提高了训练的效率。

一、搭建卷积网络步骤
1、建立模型
1.1、建立Sequential模型

Sequential模型是多个神经网络的线性堆叠。类似于一个框架结构,之后将设计好的层及层的参数填到到这个模型中,实现一个整体网络的效果。

from keras.layers import Dense,Dropout,Flatten,Conv2D,MaxPooling2D
"""
	建立Sequential模型
"""
from keras.models import Sequential #在使用前需要先提前导入这个函数
model = Sequential()
1.2、建立卷积层

卷积神经网络的卷积层,也叫做特征提取层,包括二个部分。第一部分是真正的卷积层,主要作用是提取输入数据特征。每一个不同的卷积核提取输入数据的特征都不相同,卷积层的卷积核数量越多,就能提取越多输入数据的特征。

"""
    建立卷积层1
    
    参数:
        filters - 建立的滤镜个数
        kernel_size - 滤镜大小
        padding - 填充:当为'same'时,使得图像卷积后的大小保持不变
        input_shape - 输入图形大小
        activation - 设置激活函数
"""
model.add(Conv2D(filters=16,
                 kernel_size=(5,5),
                 padding = 'same',
                 input_shape = (28,28,1),
                 activation = 'relu'))

1.3、建立池化层

pooling层,也叫下采样层,主要目的是在保留有用信息的基础上减少数据处理量,加快训练网络的速度。通常情况下,卷积神经网络至少包含二层卷积层(这里把真正的卷积层和下采样层统称为卷积层),即卷积层,pooling层,卷积层,pooling层。卷积层数越多,在前一层卷积层基础上能够提取更加抽象的特征。

"""
    建立池化层1
    
    参数:
        pool_size - 池化层大小
        
"""
model.add(MaxPooling2D(pool_size = (2,2)))

在这之后也可以继续添加卷积层2 -> 池化层2 ……依据你的神经网络需求而定,这里不再做过多赘述。

1.4、建立平坦层

由于通过了过滤器,使得数据维度发生改变,而这一步的作用是在输入到神经网络之前,将待处理的数据转换为一维向量,对应到输入层的神经单元上。

#建立平坦层
model.add(Flatten())
1.5、建立隐蔽层和输出层

这一步同建立多层神经网络方法相同,这里不再做过多的解释。
如何搭建单层或多层神经网络请见上一篇博客。

https://blog.csdn.net/qq_42826337/article/details/89341800

#建立隐蔽层
model.add(Dense(128,activation='relu'))
model.add(Dropout(0.5))

#建立输出层
model.add(Dense(10,activation='softmax'))

可以包含多个全连接层,实际上就是多层感知机的隐含层部分。通常情况下后面层的神经节点都和前一层的每一个神经节点连接,同一层的神经元节点之间是没有连接的。每一层的神经元节点分别通过连接线上的权值进行前向传播,加权组合得到下一层神经元节点的输入。

1.6、查看模型摘要
print(model.summary())

在这里插入图片描述

2、开始训练
2.1、定义训练方式
"""
    定义训练方式

    参数:
        loss - 损失函数: 这里采用交叉熵的方式
        optimizer - 优化器: 使用adam优化器可以让训练收敛更快
        metrics - 评估模型:设置为准确率

"""
model.compile(loss='categorical_crossentropy',
              optimizer='adam',metrics=['accuracy'])
2.2、开始训练
"""
    开始训练

    参数:
        x_train4D_normalize - feature数字图像的特征值
        y_trainOneHot - 数字图像的真实标签
        validation_spli - 训练与验证数据比例:80%用作训练数据,20%用作验证数据
        epochs - 训练周期
        batch_size - 每批次的数据项数
        verbose - 显示训练过程
"""
train_history=model.fit(x=x_train4D_normalize,
                        y=y_trainOneHot,validation_split=0.2,
                        epochs=10,batch_size=300,verbose=2)

在这里插入图片描述

2.3、画出准确的执行过程
import matplotlib.pyplot as plt
def show_train_history(train_history,train,validation):
    """
    显示训练过程

    参数:
        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 left')
    plt.show()
show_train_history(train_history,'acc','val_acc') #绘制准确率执行曲线
show_train_history(train_history,'loss','val_loss') #绘制损失函数执行曲线

在这里插入图片描述
由于这里的训练集准确率始终大于验证集准确率,所以我们需要通过增加训练周期或是增加隐蔽层数从而提高准确率,使其在不发生过拟合的前提下实现准确率曲线尽可能的接近。同时我们可以发现卷积网络使得代价函数的值降得非常低,这说明卷积可以增加训练的准确性,训练出更接近准确值的参数。

3、评估模型准确率

根据训练来分析此模型的准确率。

scores = model.evaluate(x_test4D_normalize,y_testOneHot)
scores[1]
4、显示混淆矩阵

混淆矩阵也称误差矩阵,是一种特定的表格显示方式,可以让我们以可视化的方式了解有监督的学习算法的结果,看出算法模型是否混淆了两个类。

import pandas as pd
pd.crosstab(y_test,prediction,
            rownames=['label'],colnames=['predict'])

在这里插入图片描述
对角线为预测正确的数字,其他非对角线的数字代表将某一个标签预测错误,成为另一个标签。

二、对二维数据进行一维卷积

通常情况下我们会遇到一些一维数据,例如经过FFT卷积后得到的信号,或者是一些音频信号等自然语言处理领域,要想卷积这种数据,我们就会用到一维卷积的方法。
在这里插入图片描述
如图所示,左侧为我们需要卷积的信号,右侧是过滤器,卷积的方法与二维卷积相似,也是通过相乘 -> 相加 ->平移 ……,从而在提取特征值后压缩原有数据,从而简化网络。

1、如何搭建一维卷积网络

上述是对1维数据进行1维卷积的方法,比较简单,这里重点说如何对2维及以上数据进行1维卷积。

1.1、导入1维卷积函数

首先我们要倒入1维卷积网络的各种函数包。

from keras.models import Sequential
from keras.layers import Dense,Dropout,Flatten,Conv1D,MaxPooling1D
1.2、降维(针对2维数据做1维卷积情况)

这里要说一点,我们在对数据预处理的时候,如果不是一维数据而是二维的话,一定要先将数据进行降维,例如我之前有个28*28的数据,我们要将其变为28 * 28=784。

为了表示清楚,这里做个对比。

(1)二维卷积(不需要对数据进行降维)

x_train4D = x_train.reshape(x_train.shape[0],28,28,1).astype('float32')
x_test4D = x_test.reshape(x_test.shape[0],28,28,1).astype('float32')
x_train4D_normalize = x_train4D / 255
x_test4D_normalize = x_test4D / 255

(2)一维卷积(需要对数据进行降维)

x_train3D = x_train.reshape(x_train.shape[0],784,1).astype('float32')
x_test3D = x_test.reshape(x_test.shape[0],784,1).astype('float32')
x_train3D_normalize = x_train3D / 255
x_test3D_normalize = x_test3D / 255

强调一点,(60000,28,28,1)最后的“1”是需要与过滤器进行卷积的通道维度数,也就是说,数据的最后一位是通道数,而不是数据的维数。你不可以将降维后的数据维度写成(60000,1,784),这样就变成了60000个数据,数据大小为1,通道数为784了;你必须写成(60000,784,1),表示60000个数据,大小为784,通道数为1。

1.3、建立模型

之后所有的卷积层和池化层都要调用1维卷积的函数,也就是将之前的Conv2D都变为Conv1D。

这里需要说一点,即使是1维卷积,我们依然需要平坦层,因为在卷积后,通道数也占了一个维度,而整体看来,数据还是一个多维数据,无法作为1维数据传入神经网络的输入层,我这里想了很久,如图:
在这里插入图片描述
这是一维卷积网络的模型摘要,我们的输入为784大小的一维数据,下一层的过滤器个数为10等等……
最后在平坦层上之前,也就是我圈出来的部分,是一个2维数据,所以需要通过平坦层将49*10变为一个490的一维数据,才能传入神经网络的输入层。

之后的所有模型建立方法都与2维建立相同。


下面附上对2维数据进行1维卷积的代码事例:

from keras.datasets import mnist
from keras.utils import np_utils
import numpy as np
from keras.models import Sequential
from keras.layers import Dense,Dropout,Flatten,Conv1D,MaxPooling1D
np.random.seed(10)


(x_train,y_train),(x_test,y_test) = mnist.load_data()
#将features转换为三维矩阵
x_train3D = x_train.reshape(x_train.shape[0],784,1).astype('float32')
x_test3D = x_test.reshape(x_test.shape[0],784,1).astype('float32')
#将feature标准化
x_train3D_normalize = x_train3D / 255
x_test3D_normalize = x_test3D / 255
#将label进行one hot转换
y_trainOneHot = np_utils.to_categorical(y_train)
y_testOneHot = np_utils.to_categorical(y_test)


#建立一个Sequential线性堆叠模型
model = Sequential()
model.add(Conv1D(filters=16,
                 kernel_size=25,
                 padding = 'same',
                 input_shape = (784,1),
                 activation = 'relu'))
model.add(MaxPooling1D(pool_size = 4))
#建立卷积层2
model.add(Conv1D(filters=10,
                 kernel_size=25,
                 padding = 'same',
                 activation = 'relu'))
#建立池化层2
model.add(MaxPooling1D(pool_size = 4))
model.add(Dropout(0.25))
#建立平坦层
model.add(Flatten())
#建立隐蔽层
model.add(Dense(128,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10,activation='softmax'))
print(model.summary())

model.compile(loss='categorical_crossentropy',
              optimizer='adam',metrics=['accuracy'])
train_history=model.fit(x=x_train3D_normalize,
                        y=y_trainOneHot,validation_split=0.2,
                        epochs=30,batch_size=300,verbose=2)
import matplotlib.pyplot as plt
def show_train_history(train_history,train,validation):
    """
    显示训练过程

    参数:
        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 left')
    plt.show()
    
show_train_history(train_history,'acc','val_acc')
show_train_history(train_history,'loss','val_loss')
scores = model.evaluate(x_test3D_normalize,y_testOneHot)
scores[1]
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐