文章目录
- MNIST
- 导入必要的包
-
- 加载数据
- 可视化数据集
- 查看数据集的分布
- 开始训练
- 使用数据外的图来测试
- 图片可视化
- 转化灰度图的可视化
- 可视化卷积层的特征图
-
- [第一层卷积 conv1 和 pool1](#第一层卷积 conv1 和 pool1)
- [第二层卷积 conv2 和 pool2](#第二层卷积 conv2 和 pool2)
MNIST
MNIST(Modified National Institute of Standards and Technology database)是一个经典的手写数字数据集,通常用于计算机视觉和机器学习的基准测试。以下是关于MNIST数据集的介绍:
数据集内容:
MNIST数据集包含了大约70000张28x28像素的手写数字图片。
这些图片包括了从0到9的10个不同数字,每个数字都有大约7000张图片。
用途:
MNIST数据集通常用于图像分类任务,目标是将手写数字图片分为0到9的10个类别。
它被广泛用于测试和验证各种图像处理和机器学习算法,特别是深度学习模型。
数据特点:
- 每张图片都是灰度图像,即只有一个颜色通道(黑白)。
- 图像的大小固定为28x28像素,总共784个像素。
- 每个像素的值在0到255之间,表示像素的亮度。
挑战:
MNIST数据集相对较小,对于现代深度学习模型来说,通常被认为是一个相对简单的任务。
然而,MNIST仍然具有一定的挑战性,因为手写数字的风格和字体会有很大的差异,有些数字可能写得非常潦草或难以识别。
应用领域:
MNIST数据集通常用于教育和研究,帮助初学者理解图像分类和深度学习概念。
它还可以作为一个基准测试数据集,用于验证新的机器学习算法或深度学习架构的性能。
https://classic.d2l.ai/chapter_convolutional-neural-networks/lenet.html
python
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
def leNet_model():
model = Sequential()
model.add(Conv2D(30, (5, 5), input_shape=(28, 28, 1), activation='relu')) # 24*24*30
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(15, (3, 3), activation='relu')) # 15*30*3*3
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(500, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
# 使用Adam优化器,学习率为0.01
optimizer = Adam(learning_rate=0.01)
# 编译模型,使用交叉熵损失函数和准确率作为指标
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
return model
model = leNet_model()
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_6 (Conv2D) (None, 24, 24, 30) 780
max_pooling2d_6 (MaxPoolin (None, 12, 12, 30) 0
g2D)
conv2d_7 (Conv2D) (None, 10, 10, 15) 4065
max_pooling2d_7 (MaxPoolin (None, 5, 5, 15) 0
g2D)
flatten_3 (Flatten) (None, 375) 0
dense_5 (Dense) (None, 500) 188000
dropout_3 (Dropout) (None, 500) 0
dense_6 (Dense) (None, 10) 5010
=================================================================
Total params: 197855 (772.87 KB)
Trainable params: 197855 (772.87 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
导入必要的包
bash
!pip install Keras==2.0.6
!pip install np_utils
python
import numpy as np
import matplotlib.pyplot as plt
import keras
from keras.datasets import mnist
from keras.utils.np_utils import to_categorical
import random
from keras.models import Model
加载数据
python
# 设置随机种子,以确保结果可重复
np.random.seed(0)
# 使用Keras的mnist.load_data()加载MNIST数据集,将数据集分为训练集和测试集
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 打印训练集和测试集的形状(维度)
print(X_train.shape) #(60000, 28, 28)
print(X_test.shape) #(10000, 28, 28)
可视化数据集
python
# 创建一个空列表用于存储每个数字类别的样本数量
num_of_samples = []
# 定义图形中的列数和数字类别总数
cols = 5
num_classes = 10
# 创建一个图形子图,包含num_classes行和cols列
fig, axs = plt.subplots(nrows=num_classes, ncols=cols, figsize=(5, 10))
fig.tight_layout()
# 遍历每列和每个数字类别
for i in range(cols):
for j in range(num_classes):
# 从训练集中选择特定类别的图像
x_selected = X_train[y_train == j]
# 随机选择一张图像并显示在子图中
axs[j][i].imshow(x_selected[random.randint(0, (len(x_selected) - 1)), :, :], cmap=plt.get_cmap('gray'))
axs[j][i].axis("off")
if i == 2:
axs[j][i].set_title(str(j)) # 在中间列添加标题
num_of_samples.append(len(x_selected)) # 记录每个类别的样本数量
# 打印每个数字类别的样本数量
print(num_of_samples)
# 创建一个新的图形,用于显示样本数量
plt.figure(figsize=(12, 4))
生成5示例和10个种类
查看数据集的分布
python
# 使用Matplotlib绘制柱状图,展示训练数据集中各个类别的样本数量分布
plt.bar(range(0, num_classes), num_of_samples) # 创建柱状图,x轴为类别编号,y轴为样本数量
plt.title("Distribution of the train dataset") # 设置图表标题
plt.xlabel("Class number") # 设置x轴标签
plt.ylabel("Number of images") # 设置y轴标签
plt.show() # 显示柱状图
# 重新调整图像数据的形状,以匹配卷积神经网络(CNN)的输入要求
X_train = X_train.reshape(60000, 28, 28, 1) # 将训练数据集的形状重塑为(样本数量, 28, 28, 1)
X_test = X_test.reshape(10000, 28, 28, 1) # 将测试数据集的形状重塑为(样本数量, 28, 28, 1)
# 对训练和测试标签进行独热编码,以适应多类别分类任务
y_train = to_categorical(y_train, 10) # 将训练标签独热编码为(样本数量, 10)
y_test = to_categorical(y_test, 10) # 将测试标签独热编码为(样本数量, 10)
# 数据归一化:将图像像素值从0到255的范围缩放到0到1的范围,有助于模型训练
X_train = X_train / 255 # 训练数据集归一化处理
X_test = X_test / 255 # 测试数据集归一化处理
开始训练
history = model.fit(X_train, y_train,\
epochs=10, validation_split = 0.1, batch_size = 400,\
verbose = 1, shuffle = True)
参数 | 描述 |
---|---|
X_train | 训练数据 |
y_train | 训练标签 |
epochs | 训练的轮数 |
validation_split | 将训练数据的一部分用于验证的比例 |
batch_size | 每个小批量的样本数量 |
verbose | 控制训练过程中的输出信息级别 |
shuffle | 是否在每轮训练前随机打乱训练数据 |
画出loss图
python
# 使用Matplotlib绘制训练过程中的损失曲线
plt.plot(history.history['loss']) # 绘制训练集上的损失值曲线
plt.plot(history.history['val_loss']) # 绘制验证集上的损失值曲线
plt.legend(['loss', 'val_loss']) # 添加图例,标记曲线含义
plt.title('Loss') # 设置图表标题为"Loss"
plt.xlabel('epoch') # 设置x轴标签为"epoch",表示训练轮数
画出accuracy图
python
# 使用Matplotlib绘制训练过程中的准确率曲线
plt.plot(history.history['accuracy']) # 绘制训练集上的准确率曲线
plt.plot(history.history['val_accuracy']) # 绘制验证集上的准确率曲线
plt.legend(['accuracy', 'val_accuracy']) # 添加图例,标记曲线含义
plt.title('Accuracy') # 设置图表标题为"Accuracy",表示准确率曲线的含义
plt.xlabel('epoch') # 设置x轴标签为"epoch",表示训练轮数
使用数据外的图来测试
给图片加点noise,看看测试结果
图片可视化
python
import requests # 导入 requests 库,用于发送 HTTP 请求
from PIL import Image # 导入 PIL 库,用于图像处理
import numpy as np # 导入 NumPy 库,用于数组操作
import matplotlib.pyplot as plt # 导入 Matplotlib 库,用于图像显示
# 指定要下载的图像的URL
url = "https://colah.github.io/posts/2014-10-Visualizing-MNIST/img/mnist_pca/MNIST-p1815-4.png"
# 发送HTTP GET请求,获取图像数据,stream=True 表示以流的方式获取数据
response = requests.get(url, stream=True)
# 打印HTTP响应状态码,以确认是否成功获取图像数据
print(response)
# 使用PIL库打开图像,并将数据存储在img对象中
img = Image.open(response.raw)
# 使用Matplotlib显示图像,指定灰度色彩映射
plt.imshow(img, cmap=plt.get_cmap('gray'))
# 将图像转换为NumPy数组
img_array = np.asarray(img)
# 打印图像数组的形状,以了解图像的尺寸和通道数
print(img_array.shape)
转化灰度图的可视化
python
import cv2
resized = cv2.resize(img_array,(28,28)) #通过opencv像素
gray_scale = cv2.cvtColor(resized,cv2.COLOR_BGR2GRAY)#取灰度值
image = cv2.bitwise_not(gray_scale)# 对灰度图像进行按位取反操作,即将图像中的白色像素变为黑色,黑色像素变为白色
plt.imshow(gray_scale,cmap=plt.get_cmap("gray")) #将图片显示位黑白
python
image = image/255
image = image.reshape(1,28,28,1) #让他和我们训练得时候一样
prediction = np.argmax(model.predict(image))#多类数据集得预测模型
print("预测结果: ",str(prediction))
1/1 [==============================] - 0s 18ms/step
预测结果数字: 4
python
#看测试结果
score = model.evaluate(X_test,y_test,verbose=0)
print(type(score))
print('Test socre', score[0])
print('Test accuracy',score[1])
可视化卷积层的特征图
python
# 利用 Model API 获取模型中间层的输出
# 创建两个新的模型,layer1 和 layer2,分别将输入和输出连接到模型的第一个和第三个层
layer1 = Model(inputs=model.layers[0].input, outputs=model.layers[0].output)
layer2 = Model(inputs=model.layers[0].input, outputs=model.layers[2].output)
# 使用 layer1 和 layer2 对输入图像进行预测,获取中间层的输出
visual_layer1, visual_layer2 = layer1.predict(image), layer2.predict(image)
# 打印中间层的输出形状
print(visual_layer1.shape)
print(visual_layer2.shape)
第一层卷积 conv1 和 pool1
python
# 创建一个 10x6 的大图,用于显示多个特征图
plt.figure(figsize=(10, 6))
# 循环遍历每个卷积核的特征图
for i in range(30):
# 在大图中创建子图,6行5列,i+1 表示子图的位置
plt.subplot(6, 5, i+1)
# 显示特征图,使用 'jet' 色彩映射以增强可视化效果
plt.imshow(visual_layer1[0, :, :, i], cmap=plt.get_cmap('jet'))
# 关闭坐标轴
plt.axis('off')
# 显示整个图像
plt.show()
这段代码通过循环遍历第一层卷积层的每个卷积核(共30个),并将其特征图可视化显示出来。每个特征图都以不同的颜色显示,通过色彩映射('jet')可以增强特征图的可视化效果。这有助于理解卷积层在图像中检测到的不同特征或模式。
通过在 plt.subplot() 中设置合适的行列数和位置,可以将多个特征图显示在同一图像中,以便一次性查看多个特征。这种可视化方法有助于深入了解神经网络的特征提取过程。
第二层卷积 conv2 和 pool2
python
plt.figure(figsize=(10,6))
for i in range(15):
plt.subplot(3,5,i+1)
plt.imshow(visual_layer2[0,:,:,i],cmap=plt.get_cmap('jet'))
plt.axis('off')