Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TensorFlow2.0 实战强化专栏(二):CIFAR-10项目

TensorFlow2.0 实战强化专栏(二):CIFAR-10项目

作者头像
磐创AI
发布于 2020-03-04 08:09:25
发布于 2020-03-04 08:09:25
1.1K00
代码可运行
举报
运行总次数:0
代码可运行
作者 | 小猴锅

出品 | 磐创AI团队

CIFAR-10项目

Alex Krizhevsky,Vinod Nair和Geoffrey Hinton收集了8000万个小尺寸图像数据集,CIFAR-10和CIFAR-100分别是这个数据集的一个子集(http://www.cs.toronto.edu/~kriz/cifar.html)。CIFAR-10数据集由10个类别共60000张彩色图片组成,其中每张图片的大小为32X32,每个类别分别6000张。

图1 cifar-10数据集中部分样本可视化

我们首先下载CIFAR-10数据集(http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz),解压之后如图2所示。其中“data_batch_1”至“data_batch_5”是训练文件,每个文件分别有10000个训练样本,共计50000个训练样本,“test_batch”是测试文件,包含了10000个测试样本。

图2 CIFAR-10数据集文件

  • 数据预处理

我们先导入需要用到的包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1  import tensorflow as tf
2  import numpy as np
3  import pickle
4  import os

由于这些数据文件是使用“cPickle”进行存储的,因此我们需要定义一个函数来加载这些数据文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
5  def get_pickled_data(data_path):
6      data_x = []
7      data_y = []
8      with open(data_path, mode='rb') as file:
9          data = pickle.load(file, encoding='bytes')
10          x = data[b'data']
11          y = data[b'labels']
12          # 将3*32*32的数组变换为32*32*3
13          x = x.reshape(10000, 3, 32, 32)\
14              .transpose(0, 2, 3, 1).astype('float')
15          y = np.array(y)
16          data_x.extend(x)
17          data_y.extend(y)
18      return data_x, data_y

接下来我们定义一个“prepare_data”函数用来获取训练和测试数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
19  def prepare_data(path):
20      x_train = []
21      y_train = []
22      x_test = []
23      y_test = []
24      for i in range(5):
25          # train_data_path为训练数据的路径
26          train_data_path = os.path.join(path, ('data_batch_'+str(i + 1)))
27          data_x, data_y = get_pickled_data(train_data_path)
28          x_train += data_x
29          y_train += data_y
30      # 将50000个list型的数据样本转换为ndarray型
31      x_train = np.array(x_train)
32  
33      # test_data_path为测试文件的路径
34      test_data_path = os.path.join(path, 'test_batch')
35      x_test, y_test = get_pickled_data(test_data_path)
36      x_test = np.array(x_test)
37  
38      return x_train, y_train, x_test, y_test
  • 模型搭建

在这个项目里我们将使用RasNet模型,RasNet我们简单的介绍过,它是一个残差网络,一定程度上解决了网络过深后出现的退化问题(论文地址:https://arxiv.org/abs/1512.03385)。ResNet的基本结构是如图3所示的“残差块(residual block)”,右侧是针对50层以上网络的优化结构。

图3 残差块(residual block)

图4所示是一个34层的ResNet的网络结构,ResNet的提出者以VGG-19模型(图4左)为参考,设计了一个34层的网络(图4中),并进一步构造了34层的ResNet(图4右),34层是按有参数更新的层来计算的,图4所示的34层ResNet中有参数更新的层包括第1层卷积层,中间残差部分的32个卷积层,以及最后的一个全连接层。

如图4所示,ResNet中主要使用的是3X3的卷积核,并遵守着两个简单的设计原则:(1)对于每一层卷积层,如果输出的特征图尺寸相同,那么这些层就使用相同数量的滤波器;(2)如果输出的特征图尺寸减半了,那么卷积核的数量加增加一倍,以便保持每一层的时间复杂度。

ResNet的第一层是66个7X7的卷积核,滑动步长为2;接着是一个步长为2的池化层;再接着是16个残差块,共32个卷积层,根据卷积层中卷积核数量的不同可以分为4个部分,每个部分的衔接处特征图的尺寸都缩小了一半,因此卷积核的数量也相应地增加了一倍;残差部分之后是一个池化层,采用平均池化;最后是一个全连接层,并用softmax作为激活函数,得到分类结果。

图4 ResNet34的网络结构

接下来我们先定义残差块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1  class residual_lock(tf.keras.layers.Layer):
2      def __init__(self, filters, strides=1):
3          super(residual_lock, self).__init__()
4          self.conv1 = tf.keras.layers.Conv2D(filters=filters,
5                                              kernel_size=(3, 3),
6                                              strides=strides,
7                                              padding="same")
8          # 规范化层:加速收敛,控制过拟合
9          self.bn1 = tf.keras.layers.BatchNormalization()
10          self.conv2 = tf.keras.layers.Conv2D(filters=filters,
11                                              kernel_size=(3, 3),
12                                              strides=1,
13                                              padding="same")
14          # 规范化层:加速收敛,控制过拟合
15          self.bn2 = tf.keras.layers.BatchNormalization()
16          # 残差块的第一个卷积层中,卷积核的滑动步长为2时,输出特征图大小减半,
17          # 需要对残差块的输入使用步长为2的卷积来进行下采样,从而匹配维度
18          if strides != 1:
19              self.downsample = tf.keras.Sequential()
20  self.downsample.add(tf.keras.layers.Conv2D(filters=filters, kernel_size=(1, 1), strides=strides))
21  self.downsample.add(tf.keras.layers.BatchNormalization())
22          else:
23              self.downsample = lambda x: x
24  
25      def call(self, inputs, training=None):
26          # 匹配维度
27          identity = self.downsample(inputs)
28  
29          conv1 = self.conv1(inputs)
30          bn1 = self.bn1(conv1)
31          relu = tf.nn.relu(bn1)
32          conv2 = self.conv2(relu)
33          bn2 = self.bn2(conv2)
34  
35          output = tf.nn.relu(tf.keras.layers.add([identity, bn2]))
36  
37          return output

接着我们定义一个函数用来组合残差块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
38  def build_blocks(filters, blocks, strides=1):
39      """组合相同特征图大小的残差块"""
40      res_block = tf.keras.Sequential()
41      # 添加第一个残差块,每部分的第一个残差块的第一个卷积层,其滑动步长为2
42      res_block.add(residual_lock(filters, strides=strides))
43  
44      # 添加后续残差块
45      for _ in range(1, blocks):
46          res_block.add(residual_lock(filters, strides=1))
47  
48      return res_block

定义好残差块和组合组合残差块的函数后,我们就可以实现具体的ResNet模型了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
49  class ResNet(tf.keras.Model):
50      """ResNet模型"""
51      def __init__(self, num_classes=10):
52          super(ResNet, self).__init__()
53  
54          self.preprocess = tf.keras.Sequential([
55              tf.keras.layers.Conv2D(filters=64,
56                                     kernel_size=(7, 7),
57                                     strides=2,
58                                     padding='same'),
59              # 规范化层:加速收敛,控制过拟合
60              tf.keras.layers.BatchNormalization(),
61  tf.keras.layers.Activation(tf.keras.activations.relu),
62              # 最大池化:池化操作后,特征图大小减半
63              tf.keras.layers.MaxPool2D(pool_size=(3, 3),strides=2)
64          ])
65  
66          # 组合四个部分的残差块
67          self.blocks_1 = build_blocks(filters=64, blocks=3)
68  self.blocks_2 = build_blocks(filters=128, blocks=4,strides=2)
69          self.blocks_3 = build_blocks(filters=256, blocks=6, strides=2)
70          self.blocks_4 = build_blocks(filters=512, blocks=3, strides=2)
71  
72          # 平均池化
73          self.avg_pool = tf.keras.layers.GlobalAveragePooling2D()
74          # 最后的全连接层,使用softmax作为激活函数
75  self.fc=tf.keras.layers.Dense(units=num_classes,activation=tf.keras.activations.softmax)
76  
77      def call(self, inputs, training=None):
78          preprocess = self.preprocess(inputs)
79          blocks_1 = self.blocks_1(preprocess)
80          blocks2 = self.blocks_2(blocks_1)
81          blocks3 = self.blocks_3(blocks2)
82          blocks4 = self.blocks_4(blocks3)
83          avg_pool = self.avg_pool(blocks4)
84          out = self.fc(avg_pool)
85  
86          return out

这里ResNet模型的实现完全依照图4中34层的ResNet模型结构。

  • 模型训练

最后我们实现模型的训练部分:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
87  if __name__ == '__main__':
88      model = ResNet()
89      model.build(input_shape=(None, 32, 32, 3))
90      model.summary()
91  
92      # 数据集路径
93      path = "./cifar-10-batches-py"
94  
95      # 数据载入
96      x_train, y_train, x_test, y_test = prepare_data(path)
97      # 将类标进行one-hot编码
98      y_train = tf.keras.utils.to_categorical(y_train, 10)
99      y_test = tf.keras.utils.to_categorical(y_test, 10)
100  
101      model.compile(loss='categorical_crossentropy',
102                    optimizer=tf.keras.optimizers.Adam(),
103                    metrics=['accuracy'])
104  
105      # 动态设置学习率
106      lr_reducer = tf.keras.callbacks.ReduceLROnPlateau(
107          monitor='val_accuracy',
108          factor=0.2, patience=5,
109          min_lr=0.5e-6)
110      callbacks = [lr_reducer]
111  
112      # 训练模型
113      model.fit(x_train, y_train,
114                batch_size=50, epochs=20,
115                verbose=1, callbacks=callbacks,
116                validation_data=(x_test, y_test),
117                shuffle=True)

在第106行代码中我们设置了动态学习率,并通过“callbacks”传递给模型。“tf.keras.callbacks.ReduceLROnPlateau”函数可以用来动态调整学习率,参数“monitor”是我们要监测的指标,“factor”是调整学习率时的参数(新的学习率=旧的学习率*factor),“patience”个回合后如果“monitor”指定的指标没有变化,则对学习率进行调整,“min_lr”限定了学习率的下限。

训练过程的Accuracy和Loss的变化如下:

图5 ResNet34训练过程中Accuracy和Loss的变化

(橙色为训练集,蓝色为验证集)

最终在验证集上的准确率为76.12%,有过拟合的现象,准确率还有提升的空间。有兴趣进一步提升分类效果的读者可以尝试如下方法:

1) 数据集增强:通过旋转、平移等操作来扩充数据集;

2) 参数微调:包括训练的回合数、学习率等;

3) 修改模型:可以尝试在ResNet32的基础上修改模型的结构,或者替换其它网络模型;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 磐创AI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
卷积_ResNet
刚才边写这个,别跑程序,偏偏没有选择自动保存,因此没得了,一个字也没有给我留下来,消耗了我所有的耐心。
火星娃统计
2021/11/02
3310
【连载15】Residual Networks、Maxout Networks和Network in Network
残差网络在《Deep Residual Learning for Image Recognition》中被第一次提出,作者利用它在ILSVRC 2015的ImageNet 分类、检测、定位任务以及COCO 2015的检测、图像分割任务上均拿到第一名,也证明ResNet是比较通用的框架。
lujohn3li
2020/03/06
6030
【连载15】Residual Networks、Maxout Networks和Network in Network
经典神经网络 | ResNet 论文解析及代码实现
论文题目:Deep Residual Learning for Image Recognition
墨明棋妙27
2022/09/23
7450
CIFAR-10数据集 图像识别
之前我是在CPU上跑Tensorflow,计算速度着实让人捉急。最近更新了显卡驱动,安装了CUDA和 GPU版的TensorFlow,同样的神经网络结构,学习速度有了百倍提升。
用户6021899
2019/12/25
1.3K0
Tensorflow2.0使用Resnet18进行数据训练
为了数据获取方便,这里使用的是CIFAR10的数据,可以在代码中直接使用keras.datasets.cifar10.load_data()方法获取,非常的方便
陶陶name
2022/05/12
8450
深入解析EfficientNet:高效深度学习网络与ResNet的对比(使用keras进行代码复现,并使用cifar10数据集进行实战)
在深度学习领域,卷积神经网络(CNN)是解决图像分类、目标检测等问题的关键技术之一。近年来,随着深度学习的不断发展,新的网络架构不断涌现。在众多网络架构中,EfficientNet和ResNet都成为了深度学习模型的佼佼者,分别在高效性和深度特性上得到了广泛应用。本文将详细介绍EfficientNet,并与经典的ResNet进行对比,分析它的架构、使用场景、适用问题及实例。
机器学习司猫白
2025/03/05
4050
深入解析EfficientNet:高效深度学习网络与ResNet的对比(使用keras进行代码复现,并使用cifar10数据集进行实战)
04.卷积神经网络 W2.深度卷积网络:实例探究(作业:Keras教程+ResNets残差网络)
Keras 是更高级的框架,对普通模型来说很友好,但是要实现更复杂的模型需要 TensorFlow 等低级的框架
Michael阿明
2021/02/19
7730
从零开始构建:使用CNN和TensorFlow进行人脸特征检测
人脸检测系统在当今世界中具有巨大的用途,这个系统要求安全性,可访问性和趣味性!今天,我们将建立一个可以在脸上绘制15个关键点的模型。
deephub
2020/05/09
1.1K0
从零开始构建:使用CNN和TensorFlow进行人脸特征检测
TensorFlow 2 和 Keras 高级深度学习:1~5
在第一章中,我们将介绍在本书中将使用的三个深度学习人工神经网络。 这些网络是 MLP,CNN 和 RNN(在第 2 节中定义和描述),它们是本书涵盖的所选高级深度学习主题的构建块,例如自回归网络(自编码器,GAN 和 VAE),深度强化学习 ,对象检测和分割以及使用互信息的无监督学习。
ApacheCN_飞龙
2023/04/26
2.1K0
从cifar10分类入门深度学习图像分类(Keras)
之前需要做一个图像分类模型,因为刚入门,拿cifar10数据集练了下手,试了几种优化方案和不同的模型效果,这里就统一总结一下这段学习经历。
Cloudox
2021/11/23
1.5K0
从cifar10分类入门深度学习图像分类(Keras)
Tensorflow2.0
tf.test.is_gpu_available() # 判断gpu可用与否 ``` 2. 从镜像配置 ```shell # 云端的系统镜像直接有开发环境 # 升级tensorflow 版本 pip install --upgrade tensorflow-gpu==2.0.0 pip3 install --upgrade tensorflow-gpu==2.0.0 ```
Dean0731
2020/05/25
1.7K0
Tensorflow2.0
【深度残差收缩网络】超简单Keras代码
从本质上讲,深度残差收缩网络属于卷积神经网络,是深度残差网络(deep residual network, ResNet)的一个变种。它的核心思想在于,在深度学习进行特征学习的过程中,剔除冗余信息是非常重要的;软阈值化是一种非常灵活的、删除冗余信息的方式。
用户6831054
2019/12/31
2.3K0
【深度残差收缩网络】超简单Keras代码
ResNet50及其Keras实现
你或许看过这篇访问量过12万的博客ResNet解析,但该博客的第一小节ResNet和吴恩达的叙述完全不同,因此博主对这篇博文持怀疑态度,你可以在这篇博文最下面找到提出该网络的论文链接,这篇博文可以作为研读这篇论文的基础。
Steve Wang
2019/05/28
6.5K0
ResNet50及其Keras实现
ResNet18-TensorFlow[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/144894.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/30
2400
Tensorflow2.0实现VGG13
训练大概50epoch,这里仅仅展示20个,可以看到,验证准确率是在不断的上升的,后面的数据就不展示了,我也没训练完,有兴趣的可以接着跑将模型保存一下,有时间再接着训练
陶陶name
2022/05/12
2460
深度残差收缩网络:一种新的深度注意力机制算法(附代码)
本文简介了一种新的深度注意力算法,即深度残差收缩网络(Deep Residual Shrinkage Network)。从功能上讲,深度残差收缩网络是一种面向强噪声或者高度冗余数据的特征学习方法。本文首先回顾了相关基础知识,然后介绍了深度残差收缩网络的动机和具体实现,希望对大家有所帮助。
用户7107719
2020/03/21
7K0
深度残差收缩网络:一种新的深度注意力机制算法(附代码)
Build Residual Networks
我们将使用残差网络建立一个很深的卷积神经网络,理论上而言越深的网络可以表示更加复杂的函数,但是训练也更加困难。Residual Networks可以让我们训练更深的网络。
小飞侠xp
2018/08/29
1.1K0
ResNet18代码实现[通俗易懂]
from tensorflow.keras import layers, Sequential, Model, datasets, optimizers
全栈程序员站长
2022/08/24
1K0
TensorFlow (2) CIFAR-10 简单图像识别
本文主要学习获取 CIFAR-10 数据集,通过简单的模型对数据集进行训练和识别。
coding01
2021/02/24
1.4K0
神奇的Batch Normalization 仅训练BN层会发生什么
最近,我阅读了arXiv平台上的Jonathan Frankle,David J. Schwab和Ari S. Morcos撰写的论文“Training BatchNorm and Only BatchNorm: On the Expressive Power of Random Features in CNNs”。这个主意立刻引起了我的注意。到目前为止,我从未将批标准化(BN)层视为学习过程本身的一部分,仅是为了帮助深度网络实现优化和提高稳定性。经过几次实验,我发现我错了。在下文中,我将展示我复制的论文的结果以及从中学到的东西。
deephub
2020/05/09
9670
神奇的Batch Normalization 仅训练BN层会发生什么
相关推荐
卷积_ResNet
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档