基于keras的CNN网络搭建(数字识别为例)

基于keras的CNN网络搭建(数字识别为例)

本文章可能仅对于有一点机器学习底子的同学有帮助,很多知识点都没有详细的去说明,当然这只是keras搭建一个简单的cnn网络,如果有错误,欢迎大佬指正。一起交流一起进步

  1. 导包

    • from keras.models import Sequential

      网络模型实例化,用来存放cnn网络结构

    • from keras.layers import Deconv2D,MaxPool2D,Dense,Flatten

      分别为卷积层,最大值池化层,全连接层,压缩层

    • from keras.optimizers import Adam

      亚当算法,用来做优化方法,也可以不导入,通过keras的反向映射机制来确定优化方法

    • from keras.metrics import mse

      均方误差,用来做损失函数

    • from keras.losses import categorical_crossentropy

      评价函数,交叉熵,也可用来做损失函数

    • from keras.activations import relu,softmax

      激活函数,用于神经元的激活,relu比sigmoid更好,不会梯度消散

    • import numpy as np

      用来做数据类型的转换,转换成float32类型

    本次例子为sklearn的自带数据集-load_digits

    由于是多分类问题,结果评价用cohen_kappa作为参考

  2. 数据预处理阶段

    • 第一步数据类型转化和数据维度变换

      ld.images.reshape(1797,8,8,1).astype(np.float32)

      将数据维度转换成四维(神经网络的需求),转成np.float32类型,当然用tf也行

    • 第二步数据结果做独热编码

      可以自己写几行代码来实现,也可以通过keras.utils中的to_categorical来实现

  3. 网络搭建

    • 首先实例一个model,来存放网络结构

      model = Sequential()

    • 添加第一层卷积层和池化层

      • model.add(Deconv2D(8, (3, 3), input_shape=(8, 8, 1), strides=(1, 1), padding='SAME', activation=relu))
        model.add(MaxPool2D((2,2)))
        

        添加8个3x3的卷积核作为第一层,输入层为8x8单通道,每次卷积核移动一个像素单位,padding表示零填充,当卷积核到图像边缘不够时以0补充,最后激活函数为relu

      • model.add(MaxPool2D((2,2)))
        
    • 添加第二层卷积层和池化层

      • model.add(Deconv2D(5, (3, 3), padding='SAME', activation=relu))
        

        内容同上,和第一层差不多,不过减少了卷积核的数量

      • model.add(MaxPool2D((2,2)))
        

        添加一个2x2的最大值池化滤波窗口

    • 添加压缩层,将多维的数据压缩至一维

      • model.add(Flatten())
        
    • 添加全连接层,输出结果

      • model.add(Dense(96, activation=relu))
        model.add(Dense(10, activation=softmax))
        

        添加两个全连接层,防止下降特征太迅速,中间多一层,先用relu激活,最后结果输出时用softmax激活,将结果转换成概率的形式,最大概率值的下标,即为识别的数字结果

      • 可以添加一层model.summary() 可以查看各层的详细信息

  4. 网络模型的完成与训练

    • 实例一个亚当算法模型,op_t = Adam(lr=0.01) 也可以不用实例,不果需要修改模型参数的话,就必须要实例,默认的lr为0.001

    • model.compile(optimizer=op_t,loss=mse,metrics=[categorical_crossentropy])
      

      优化方法为adam,损失函数为均方误差法,评估方法为交叉熵损失函数,一般模型编译时,设置这三个参数就够了,我们这个例子本来就比较简单,所以值给定这三个就行

    • model.fit(train_data, target,batch_size=40,epochs=50)
      

      模型训练,和skleearn的写法差不多,先传训练数据,再给训练数据集的结果,然后确定训练的次数,理论上来说,训练的次数越多,结果会越好,但是次数越多,多电脑的消耗就会越大,因此这里自己可以更具情况来决定,最后时批量梯度下降时采取的样本数量,默认为1,可以修改,我们给定的是50

  5. 最后预测,评估模型的优劣性

    • 由于最后的输出结果是概率的形式,并不是我们想要的数字形式,所以这里需要转换。利用argmax()方法来获取条array的最大值下标,这就是我们想要的结果。存放在同一组的list中即可
    • 评估方法cohen_kappa和f1差不多,不过一个是可以用于多分类问题,一个是用于二分类问题。cohen_kappa_score的得分越接近-1,模型识别的结果就和正式结果相差越大;越接近0,模型几乎是随机识别;越接近1,则模型识别越准确。当然,也可以用正确率来当模型的评估结果。

代码

from keras.models import Sequential
from keras.layers import Deconv2D,MaxPool2D,Dense,Flatten
from keras.optimizers import Adam
from keras.metrics import mse
from keras.losses import categorical_crossentropy
from keras.utils import to_categorical
from keras.activations import relu,softmax

import numpy as np

from sklearn.datasets import load_digits
from sklearn.metrics import cohen_kappa_score

ld = load_digits()
# print(ld.images.shape)

train_data = ld.images.reshape(1797, 8, 8, 1).astype(np.float32)
target = to_categorical(ld.target)

# 搭建网络
model = Sequential()
model.add(Deconv2D(10, (3, 3), input_shape=(8, 8, 1), strides=(1, 1), padding='SAME', activation=relu))
model.add(MaxPool2D((2,2)))

model.add(Deconv2D(8, (3, 3), padding='SAME', activation=relu))
model.add(MaxPool2D((2,2)))

model.add(Flatten())

model.add(Dense(96, activation=relu))
model.add(Dense(10, activation=softmax))
# model.summary()

op_t = Adam(lr=0.01)

model.compile(optimizer=op_t,loss=mse,metrics=[categorical_crossentropy])

model.fit(train_data[:len(train_data)-500], target[:len(target)-500],batch_size=40,epochs=50)

pre = model.predict(train_data[len(train_data)-500:])

result_list = []
for value in pre:
    index = value.argmax()
    result_list.append(index)

print('正确结果', ld.target[len(ld.target)-500:])
print('预测结果', np.array(result_list))

print('kappa::',cohen_kappa_score(ld.target[len(ld.target)-500:], result_list))

代码是将数据集分为训练集和测试集,手动分割,取数据集的后500个作为测试集,当然也可以用train_test_split来分割,最有kappa得分有0.94左右,准确率接近96%。整体来说还行。
当然如果有需要,例如验证码识别或者数字的图片规格更大,可以修改网络参数,增加网络的深度。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值