0
点赞
收藏
分享

微信扫一扫

TensorFlow2学习九、实现基础CNN

一、简介

本文实现基础Convolutional Neural Network (CNN),数据集使用 CIFAR images。
卷积神经网络是一种多层神经网络,擅长处理图像特别是大图像的相关机器学习问题,它通过一系列方法,将数据量庞大的图像识别问题不断降维,最终使其能够被训练。CNN最早由Yann LeCun提出并应用在手写字体识别上(MINST)。LeCun提出的网络称为LeNet,其网络结构如下:
TensorFlow2学习九、实现基础CNN_全连接

典型的卷积网络,由卷积层、池化层、全连接层组成。其中卷积层与池化层配合,组成多个卷积组,逐层提取特征,最终通过若干个全连接层完成分类。

1. 卷积

TensorFlow2学习九、实现基础CNN_池化_02

如图所示,我们有一个5x5的图像,我们用一个3x3的卷积核:

1  0  1

0  1  0

1  0  1

来对图像进行卷积操作(可以理解为有一个滑动窗口,把卷积核与对应的图像像素做乘积然后求和),得到了3x3的卷积结果。

这个过程我们可以理解为我们使用一个过滤器(卷积核)来过滤图像的各个小区域,从而得到这些小区域的特征值。

在实际训练过程中,卷积核的值是在学习过程中学到的。

2. 池化

池化简单的说就是下采样。池化的过程如下图所示:

TensorFlow2学习九、实现基础CNN_卷积_03

上图中,我们可以看到,原始图片是20x20的,我们对其进行下采样,采样窗口为10x10,最终将其下采样成为一个2x2大小的特征图。

之所以这么做的原因,是因为即使做完了卷积,图像仍然很大(因为卷积核比较小),所以为了降低数据维度,就进行下采样。

之所以能这么做,是因为即使减少了许多数据,特征的统计属性仍能够描述图像,而且由于降低了数据维度,有效地避免了过拟合。

在实际应用中,池化根据下采样的方法,分为最大值下采样(Max-Pooling)与平均值下采样(Mean-Pooling)。

3. 全连接层 (fully connected layers,FC)

在整个卷积神经网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的“分布式特征表示”映射到样本标记空间的作用。在实际使用中,全连接层可由卷积操作实现:对前层是全连接的全连接层可以转化为卷积核为1x1的卷积;而前层是卷积层的全连接层可以转化为卷积核为hxw的全局卷积,h和w分别为前层卷积结果的高和宽。

4. CIFAR10介绍

该数据集共有60000张彩色图像,这些图像是32*32,分为10个类,每类6000张图。这里面有50000张用于训练,构成了5个训练批,每一批10000张图;另外10000用于测试,单独构成一批。测试批的数据里,取自10类中的每一类,每一类随机取1000张。抽剩下的就随机排列组成了训练批。注意一个训练批中的各类图像并不一定数量相同,总的来看训练批,每一类都有5000张图。

二、TensorFlow2.0实现的基础cnn

1. 导入tensorflow

import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

2. 下载CIFAR10数据集

(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0

3. 查看数据

这里显示25张图片和其分类,看看分类是否正确:

class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer','dog', 'frog', 'horse', 'ship', 'truck']

plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
# The CIFAR labels happen to be arrays,
# which is why you need the extra index
plt.xlabel(class_names[train_labels[i][0]])
plt.show()

4. 创建模型和池化层

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# 显示模型信息
model.summary()

TensorFlow2学习九、实现基础CNN_池化_04

上面可以看到每个池化层输出是3维张量(高, 宽,通道数). 每个池化层输出的通道数取闷在于第一个变量值(如32,64). 如果算力足够,可以为每个池化层添加更多的通道数.

5. 全连接层

model.add(layers.Flatten()) # 3维 转为 1维
model.add(layers.Dense(64, activation='relu')) # 激活函数relu
model.add(layers.Dense(10, activation='softmax')) # 激活函数softmax CIFAR有10个类别输出,所以softmax这里参数设置为10
# 再看看模型情况
model.summary()

TensorFlow2学习九、实现基础CNN_卷积_05

6. 编译和训练模型

model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])

history = model.fit(train_images, train_labels, epochs=10,
validation_data=(test_images, test_labels))

7. 评估模型

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')

test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

TensorFlow2学习九、实现基础CNN_卷积_06

打印准确率:

print(test_acc)

作为对比,可以在这里看到TensorFlow1.0实现基础CNN的代码:​


举报

相关推荐

0 条评论