# CNN-CIFAR100
# CNN模型,对CIFAR100数据集进行分类,三连球球啦!
(1)Tensorflow库构建CNN模型(下文简称CNN_tensorflow)
1)导入必要的库。题目要求使用Tensorflow库构建CNN模型。这里使用了 TensorFlow 和 Keras 库,以及 numpy 和 matplotlib 库用于数据处理和可视化。
```python
import tensorflow as tf
from tensorflow import keras
import numpy as np
from keras.datasets import cifar100
import matplotlib.pyplot as plt
```
2)加载 CIFAR-100 数据集
```python
(x_train, y_train),(x_test, y_test) = cifar100.load_data(label_mode='fine')
```
这里使用了 Keras 提供的 CIFAR-100 数据集加载函数。
在 cifar100.load_data() 函数中,label_mode 参数用于控制标签的加载方式。CIFAR-100 数据集中有两种标签,一种是精细标签(fine labels),共有100个类别,另一种是粗略标签(coarse labels),共有20个类别,每个粗略类别下面包含5个精细类别。因此,label_mode 参数可以取两个值:'fine' 和 'coarse'。
当 label_mode='fine' 时,load_data() 函数将加载精细标签,返回的训练集标签和测试集标签是包含类别序号(0-99)的一维数组。当 label_mode='coarse' 时,load_data() 函数将加载粗略标签,返回的训练集标签和测试集标签是包含粗略类别序号(0-19)的一维数组。
在上述代码中,label_mode='fine' 表示加载精细标签,即返回一个包含0-99之间整数的一维数组,每个整数代表一个类别。这样可以更准确地识别物体,因为共有100个不同的类别。
3)将训练集和测试集的像素值类型从整数转换为单精度浮点数类型。将像素值归一化到 [0, 1] 的范围内。使用了 Numpy 库提供的 astype() 函数来进行数据类型转换。
```python
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train = x_train / 255.0
x_test = x_test / 255.0
```
这是一个常见的数据预处理步骤,通常是为了将像素值归一化到 [0, 1] 的范围内,以便更好地进行模型训练。浮点数比整数更适合进行数学计算,在深度学习中,通常使用浮点数来存储数据。
4)定义卷积神经网络模型,包含两个卷积层、一个池化层、一个全连接层和一个 softmax 层。这里使用了 Keras 提供的 Sequential 模型,将各个层按顺序添加到模型中。
```python
model = keras.Sequential([
keras.layers.Conv2D(32, (3, 3), strides=1, activation='relu', input_shape=(32, 32, 3)),
keras.layers.Conv2D(64, (3, 3), activation='relu'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Dropout(0.5),
keras.layers.Flatten(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(100, activation='softmax')
])
```
在上述示例代码所构建地CNN模型中,各个层的功能如下:
Conv2D层:它有32个3x3大小的过滤器,步幅为1,激活函数为ReLU,输入形状为(32,32,3),表示输入数据是RGB图像。
Conv2D层:它有64个3x3大小的过滤器,激活函数为ReLU。这个卷积层的作用是将特征进一步提取出来。
MaxPooling2D层:使用2x2的池化窗口,从卷积层输出中提取最大值。它将卷积层的输出减小一半,减少了模型中的参数数量和计算负担。这里的大小为(2,2),表示每个2x2的像素块被压缩为单个像素,其值为所包含像素的最大值。
Dropout层:有助于减轻过拟合。dropout 可以将一定比例的输入单元随机设置为0,从而防止过度依赖于特定的输入单元。这里随机将50%的输入单元设置为0。
Flatten层:将卷积层输出的多维张量展平为一维张量,用于传递给全连接层。这是因为完全连接的层需要一维输入。
Dense层:包含128个神经元,应用ReLU激活函数。这个层接收来自之前的卷积和池化层的特征,并使用它们来学习数据的高级表示。
Dropout层:再次进行防止过拟合,随机将50%的输入单元设置为0。
Dense层:具有100个神经元和softmax激活函数。这是我们的输出层,用于分类任务。这里是100个类别的分类任务,因此我们有100个神经元,每个神经元代表一个类别。softmax 函数将每个神经元的输出转换为介于0和1之间的概率分布,以便可以解释为每个类别的预测概率。
下图是系统生成的模型结构图(含DROP_OUT层)和参数数量:


5)编译模型,定义损失函数和优化器。
```python
model.compile(optimizer=keras.optimizers.Adam(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
```
model.compile 是 Keras 中用来编译模型的函数,它有三个重要的参数:
optimizer: 优化器用来根据损失函数来更新模型的权重参数,使得模型的损失函数值不断降低,是用来指定训练过程中使用的优化算法,如 SGD、Adam 等。在本实例代码中,keras.optimizers.Adam() 表示使用 Adam 优化器,它是一种常用的随机梯度下降法变体,可以自适应地调整每个参数的学习率,以便更有效地优化模型。
loss: 损失函数,用来衡量模型的预测值与真实值之间的差异,作为优化算法的目标函数。在本示例代码中,sparse_categorical_crossentropy 是一种交叉熵损失函数,它在多分类问题中经常被使用。sparse_categorical_crossentropy 是一个分类问题的损失函数,适用于类别标签为整数编码的情况。
metrics: 评价指标,用来衡量模型的性能,如准确率、精确率、召回率等。在本例中,metrics=['accuracy'] 表示我们希望用准确率来衡量模型的性能。准确率指模型预测正确的样本数与总样本数的比例。因此,模型在训练过程中会输出每个 epoch 结束时的训练集和测试集准确率,以便我们可以了解模型的训练情况。
6)训练模型,使用 fit() 函数进行模型训练。这里设置了 10 个 epoch,即模型会对训练数据进行 10 次迭代训练。
```python
history = model.fit(x_train, y_train, epochs=10)
```
7)在测试集上评估模型,使用 evaluate() 函数计算模型在测试集上的损失和准确率。
```python
test_loss, test_acc = model.evaluate(x_test, y_test)
print('Test acc: %f' % test_acc)
```
(2)CNN_tensorflow实验结果
(1)直接输出结果
不加入DROP_OUT层:

加入DROP_OUT层:

(2)CNN_tensorflow在加入和不加入DROP_OUT层情况下的训练集上的loss和accuracy:
不加入DROP_OUT层:

加入DROP_OUT层:

发现加入DROP_OUT层之后,在训练集上的训练效果变差了,loss远大于不加入DROP_OUT层的情况;accuracy远小于不加入DROP_OUT层的情况,并且数值仅仅达到前者一半左右。
(3)CNN_tensorflow在加入和不加入DROP_OUT层情况下的测试集上的loss和accuracy:
不加入DROP_OUT层:
![image](https://github.com/neuljh/CNN-CIFAR100/assets/1329