使用CNN卷积神经网络(2)

使用Tensorflow搭建简单的CNN卷积神经网络对fashion_mnist数据集进行分类

不了解是那么是CNN卷积神经网络的小伙伴可以参考上一篇博客(Tensorflow学习笔记No.4.1)

2.Tensorflow卷积神经网络相关API简介

2.1.keras.layers.Conv2D()二维卷积层

例如:

  1. model.add(keras.layers.Conv2D(128, (3, 3), activation = 'relu', padding = 'same')

  向model中添加一个二维卷积层,第一个参数是filter,也就是卷积核的个数,决定了这层卷积层输出的数据有多少个通道。第二个参数是卷积核的大小,这里使用的是3×3的卷积核。activation是激活函数,不再赘述。

  padding则是卷积层的填充模式。简单来说,设卷积核的尺寸为k×k,输入数据的尺寸为size×size,若填充模式为‘same’,则卷积层输出的尺寸与输入时相同,为size×size,若为默认模式‘valid’,则输出的尺寸为(size-(k-1))×(size-(k-1))。  

  strides参数(示例中没有出现),它是卷积核每次移动的跨度,默认为(1, 1),分别是在x和y轴上移动的跨度,若调整为(2, 2)则卷积层的输出尺寸会将变为原来的1/2,即(size/2)×(size/2),同理,若为(k, k)则输出尺寸变为(size/k)×(size/k),使用这个参数会严重减少输出信息,虽然能明显减少网络容量,但是容易造成关键特征的丢失,慎重使用!

2.2.keras.layers.MaxPool2D()二维卷积的池化层

例如:

  1. 1 model.add(keras.layers.MaxPool2D())
  2. 2 model.add(keras.layers.AveragePooling2D())
  3. 3 model.add(keras.layers.GlobalAveragePooling2D())

  向model中添加二维池化层。

  池化层默认尺寸pool_size参数为2×2,会把数据的尺寸缩小至原来的1/2,并且不改变深度。

  示例中的三种池化层分别为最大值池化,均值池化与全局均值池化。

  最大值池化,选择pool_size×pool_size范围内的最大值作为当前位置的值,每次移动pool_size个单位,若size无法被整除则自动填充。均值池化同理,计算范围内的均值作为当前位置的值。全局池化有所不同,它是将全部数据进行池化压缩,将数据的尺寸size×size缩小为1×1,不改变深度,通常放在全连接层之前。

3.使用Tensorflow搭建简单的卷积神经网络模型

使用tensorflow建立一个简单的CNN网络模型,对fashion_mnist数据集进行分类,是一个较为简单的10分类问题。

首先导入需要用到的模块

  1. 1 from tensorflow import keras
  2. 2 import matplotlib.pyplot as plt
  3. 3 import numpy as np
  4. 4 import pandas as pd

3.1加载并处理数据

  加载fashion_mnist数据集,并分为训练集和测试集。

  1. fashion_mnist = keras.datasets.fashion_mnist
  2. (train_image, train_label), (test_image, test_label) = fashion_mnist.load_data()

  此时的train_image与test_image的尺寸分别为(6000, 28, 28), (1000, 28, 28),分别对应图片数,图片的长和宽。

  但是卷积神经网络的输入时图片,图片应该有三个维度,长宽以及通道数(channel),fashion_mnist数据集中均为灰度图像,所以只有一个通道,我们给测试集和训练集分别加上这一维度以便作为神经网络的输入。

  1. 1 train_image = np.expand_dims(train_image, -1)
  2. 2 test_image = np.expand_dims(test_image, -1)

  这里使用了numpy的.expand_dims()方法扩展了数据集的通道,数据尺寸的最后方加入了一个维度。

  现在数据的尺寸变为(num, 28, 28, 1),即num个28×28的单通道灰度图像。

3.2建立网络模型

  使用keras.Sequential()方法建立一个Sequential模型。

  1. 1 model = keras.Sequential()

  首先向其中添加输入层,我们要尽量保留数据的特征,所以第一层就直接选用处理图像效果较好的Conv2D卷积层,尽可能的获取图像特征。

  1. 1 model.add(keras.layers.Conv2D(32, (3, 3),
  2. 2 input_shape = (28, 28, 1),
  3. 3 activation = 'relu',
  4. 4 padding = 'same'
  5. 5 ))

  Conv2D()中的主要参数在2.1中均有提及,这里不再赘述。

  input_shape参数与之前建立的Sequential模型类似,表示输入数据的尺寸,这里为28×28的单通道灰度图像,所以input_shape应该为(28, 28, 1)。

  随后向网络中添加池化层,提取主要特征并缩小数据规模。

  规模缩小到过程也是扩大感受野的过程,随着特征规模的缩小,单个卷积核单次所能覆盖的图像特征范围逐渐扩大,这是一个逐渐从提取局部特征转变为提取全局特征的过程。

  1. 1 model.add(keras.layers.MaxPool2D())

  继续添加卷积层与池化层,最后添加全连接层输出分类结果,最终的模型为:

  1. 1 model = keras.Sequential()
  2. 2 model.add(keras.layers.Conv2D(32, (3, 3),
  3. 3 input_shape = (28, 28, 1),
  4. 4 activation = 'relu',
  5. 5 padding = 'same'
  6. 6 ))
  7. 7 #32个卷积核,每个卷积核大小为3*3,输入规格,激活函数,填充为使输出与原尺寸相同,默认(valid)为不填充
  8. 8 model.add(keras.layers.MaxPool2D())
  9. 9 #默认为2*2池化层
  10. 10 model.add(keras.layers.Conv2D(64, (3, 3), activation = 'relu'))
  11. 11 model.add(keras.layers.GlobalAveragePooling2D())
  12. 12 #全局平均池化
  13. 13 model.add(keras.layers.Dense(10, activation = 'softmax'))
  14. 14 #输出层,10分类

  这样就搭建好了一个简单的卷积神经网络。

3.3使用.compile()方法与.fit()方法训练模型

  这里与之前的训练方式相同,不熟悉的小伙伴可以翻翻之前的博客(Tensorflow学习笔记No.1)进行查看,代码如下:

  1. 1 model.compile(optimizer = 'adam',
  2. 2 loss = 'sparse_categorical_crossentropy',
  3. 3 metrics = ['acc']
  4. 4 )
  5. 5
  6. 6 history = model.fit(train_image, train_label, epochs = 30, validation_data = (test_image, test_label))

  训练过程:

  如果你使用的是notebook类的环境,训练完成后插入以下代码(Tensorflow学习笔记No.0中有相关介绍)即可查看训练的正确率图像:

  1. 1 %matplotlib inline
  2. 2 plt.plot(history.epoch, history.history.get('acc'), label = 'acc')
  3. 3 plt.plot(history.epoch, history.history.get('val_acc'), label = 'val_acc')
  4. 4 plt.legend()

  图像如下图所示:

  

4.优化已有网络模型

   以下内容是由本人经过多次试验和验证得到的:

  从刚刚训练的网络模型的训练图像中可以看出:

  训练集的正确率仅有92.5%,说明模型的拟合性不够;测试集与训练集正确率相差较大,说明在后续训练中可能出现过拟合问题。

  (注:过拟合是指在训练集达到非常好的正确率而在测试集上的正确率并不理想,这里出现的情况是训练集和测试集上的正确率均不理想,所以不能称之为过拟合,但通过图像不难看出,我们的模型继续训练下去极有可能出现过拟合现象。)

  所以我们的优化方式从这两个角度出发,首先,增加隐藏单元(卷积核)数量,加深模型深度,以增加模型的拟合度。然后,为了抑制可能出现的过拟合现象,在适当位置加入Dropout层抑制过拟合。

  改进后的模型如下:

  1. 1 model_ = keras.Sequential()
  2. 2 model_.add(keras.layers.Conv2D(64, (3, 3),
  3. 3 input_shape = (28, 28, 1),
  4. 4 activation = 'relu',
  5. 5 padding = 'same'
  6. 6 ))
  7. 7 model_.add(keras.layers.Conv2D(64, (3, 3), activation = 'relu', padding = 'same'))
  8. 8 #添加两层Conv2D以提高拟合能力
  9. 9 model_.add(keras.layers.MaxPool2D())
  10. 10 model_.add(keras.layers.Dropout(0.25))
  11. 11 #添加Dropout抑制过拟合
  12. 12 model_.add(keras.layers.Conv2D(128, (3, 3), activation = 'relu', padding = 'same'))
  13. 13 model_.add(keras.layers.Conv2D(128, (3, 3), activation = 'relu', padding = 'same'))
  14. 14 model_.add(keras.layers.MaxPool2D())
  15. 15 model_.add(keras.layers.Dropout(0.25))
  16. 16 model_.add(keras.layers.Conv2D(256, (3, 3), activation = 'relu', padding = 'same'))
  17. 17 model_.add(keras.layers.Conv2D(256, (3, 3), activation = 'relu', padding = 'same'))
  18. 18 model_.add(keras.layers.Dropout(0.25))
  19. 19 model_.add(keras.layers.GlobalAveragePooling2D())
  20. 20 model_.add(keras.layers.Dense(256, activation = 'relu'))
  21. 21 #添加Dense层进行过渡
  22. 22 model_.add(keras.layers.Dense(10, activation = 'softmax'))

  经过调整后的模型得到如下结果:

  模型的正确率图像如下:

  经过调整后的模型,拟合度有了较为明显的提高,在测试集上可以达到接近95%的正确率,在测试集上也能达到较为满意的效果,正确率约92.5%。

后续将会对模型进行改进,争取达到更高的准确率!

Tensorflow学习笔记No.4.2的更多相关文章

  1. Tensorflow学习笔记2:About Session, Graph, Operation and Tensor

    简介 上一篇笔记:Tensorflow学习笔记1:Get Started 我们谈到Tensorflow是基于图(Graph)的计算系统.而图的节点则是由操作(Operation)来构成的,而图的各个节 ...

  2. Tensorflow学习笔记2019.01.22

    tensorflow学习笔记2 edit by Strangewx 2019.01.04 4.1 机器学习基础 4.1.1 一般结构: 初始化模型参数:通常随机赋值,简单模型赋值0 训练数据:一般打乱 ...

  3. Tensorflow学习笔记2019.01.03

    tensorflow学习笔记: 3.2 Tensorflow中定义数据流图 张量知识矩阵的一个超集. 超集:如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S ...

  4. TensorFlow学习笔记之--[compute_gradients和apply_gradients原理浅析]

    I optimizer.minimize(loss, var_list) 我们都知道,TensorFlow为我们提供了丰富的优化函数,例如GradientDescentOptimizer.这个方法会自 ...

  5. 深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识

    深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识 在tf第一个例子的时候需要很多预备知识. tf基本知识 香农熵 交叉熵代价函数cross-entropy 卷积神经网络 s ...

  6. 深度学习-tensorflow学习笔记(2)-MNIST手写字体识别

    深度学习-tensorflow学习笔记(2)-MNIST手写字体识别超级详细版 这是tf入门的第一个例子.minst应该是内置的数据集. 前置知识在学习笔记(1)里面讲过了 这里直接上代码 # -*- ...

  7. tensorflow学习笔记(4)-学习率

    tensorflow学习笔记(4)-学习率 首先学习率如下图 所以在实际运用中我们会使用指数衰减的学习率 在tf中有这样一个函数 tf.train.exponential_decay(learning ...

  8. tensorflow学习笔记(3)前置数学知识

    tensorflow学习笔记(3)前置数学知识 首先是神经元的模型 接下来是激励函数 神经网络的复杂度计算 层数:隐藏层+输出层 总参数=总的w+b 下图为2层 如下图 w为3*4+4个   b为4* ...

  9. tensorflow学习笔记(2)-反向传播

    tensorflow学习笔记(2)-反向传播 反向传播是为了训练模型参数,在所有参数上使用梯度下降,让NN模型在的损失函数最小 损失函数:学过机器学习logistic回归都知道损失函数-就是预测值和真 ...

  10. tensorflow学习笔记(1)-基本语法和前向传播

    tensorflow学习笔记(1) (1)tf中的图 图中就是一个计算图,一个计算过程.                                       图中的constant是个常量 计 ...

随机推荐

  1. unity 4种实现动态障碍方法

    此文将介绍4种实现动态障碍的方法,2种基于navmesh,2种基于astar算法. 1.基于navmesh. 1.制作场景障碍: a.有几个独立的障碍物,就定义几个user area,即,一个场景仅仅 ...

  2. Vulkan相关资源

    https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/vulkan/resources.md Intel API without ...

  3. tcpdump 命令格式

    tcpdump 命令格式 tcpdump [选项] [表达式 1. 选项 常用选项: -i : 网卡名: 指定网卡,默认抓取系统第一个网卡 -n : 对地址以数字方式显示 -nn :对地址端口以数字方 ...

  4. Mac Item2自动远程连接服务器

    Mac Item2自动远程连接服务器 1.编写脚本 vi test #!/usr/bin/expect set PORT 端口 set HOST ip set USER root set PASSWO ...

  5. Mysql业务设计(逻辑设计)

    逻辑设计 数据库设计三大范式 数据库设计第一大范式 数据库表中所有的字段都只具有单一属性 单一属性的列是由基本数据类型所构成 设计出来的表都是简单的二维表 数据库设计的第二大范式 要求表中只有一个业务 ...

  6. 详解 Python 的二元算术运算,为什么说减法只是语法糖?

    原题 | Unravelling binary arithmetic operations in Python 作者 | Brett Cannon 译者 | 豌豆花下猫("Python猫&q ...

  7. String.format与搭配转化符的使用

    String的format语法搭配转化符,在格式化输出方面效果特别好,值得掌握. 例程: System.out.println("----C1---|----C2---|----C3---| ...

  8. leetcode刷题-58最后一个单词

    题目 给定一个仅包含大小写字母和空格 ' ' 的字符串 s,返回其最后一个单词的长度.如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词. 如果不存在最后一个单词,请返回 0 . 说明:一 ...

  9. python连接websocket wss

    def websocket_wss(): try: wss = create_connection(wss_url, timeout=10) if wss.status == 101: wss.sen ...

  10. springBoot 使用webSocket

    本文(2019年6月18日 飞快的蜗牛博客) 有许多人走着走着,就迷失了自己,所以不论发生了什么,有时候抱着自己去静下来想想,要好好的对待自己:"钱塘江上潮信来,今日方知我是我", ...