Pytorch、TensorFlow、Keras框架下使用卷积神经网络实现MNIST分类(附所有实现代码)
创建CNN网络整体思路:
全部运行代码如下:
#基于Pytorch框架实现卷积神经网络的mnist分类
#Author J.A.
#Data 2022.2.8
#加入可视化内容
#导入相关包
import torch
import os
import torch.nn as nn
import torchvision
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
#设置超参数
epoch = 3
batch_size = 50
lr = 0.001
download_mnist = False #因为已经下载过了
#进行数据处理
#首先判断是否已存在路径或者路径存在但是内容是否为空
if not(os.path.exists('./mnist/')) or not os.listdir('./mnist/'):
download_mnist = True
train_data = torchvision.datasets.MNIST(
root = './mnist/',
train = True,
transform = torchvision.transforms.ToTensor(), #将其转变为tensor张量
download = download_mnist,
)
#给出示例
print(train_data.train_data.size()) #(60000, 28, 28)
print(train_data.train_labels.size()) #(60000)
plt.imshow(train_data.train_data[0].numpy(), cmap = 'gray')
plt.title('%i' % train_data.train_labels[0])
plt.show()
#加载数据
train_loader = DataLoader(dataset = train_data, batch_size = batch_size, shuffle = True)
#挑选2500样本测试模型
test_data = torchvision.datasets.MNIST(root='./mnist/', train = False)
#利用unsqueeze()函数扩展维度将(2500,28,28)扩展为(2500,1,28,28)
test_x = torch.unsqueeze(test_data.test_data, dim = 1).type(torch.FloatTensor)[:2500] / 255.
test_y = test_data.test_labels[:2500]
#构建CNN模型,定义一个类
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.Conv1 = nn.Sequential( #输入尺寸维度(1,28,28)
nn.Conv2d(
in_channels = 1, #灰度图像通道为1
out_channels = 16, #卷积核数量为16
kernel_size = 5, #卷积核尺寸 5*5
stride = 1, #步长为1
padding = 2, #填充为2
), #当前维度(16,28,28)
nn.ReLU(), #配置激活函数
nn.MaxPool2d(kernel_size = 2), #添加最大池化层
) #当前维度(16,14,14)】
self.Conv2 = nn.Sequential(
nn.Conv2d(16, 32, 5, 1, 2), #当前维度尺寸(32,14,14)
nn.ReLU(),
nn.MaxPool2d(2), #当前维度尺寸(32,7,7)
)
self.out = nn.Linear(32 * 7 * 7, 10) #添加全连接层(1568,10)
def forward(self, x):
x = self.Conv1(x)
x = self.Conv2(x)
x = x.view(x.size(0), -1)
output = self.out(x)
return output, x #返回的x值用于后续可视化
#开始实例化函数
cnn = CNN()
#查看cnn结构
print(cnn)
#设置损失函数,优化器等
optimizer = torch.optim.Adam(cnn.parameters(), lr = lr)
loss_func = nn.CrossEntropyLoss()
#接下来配置可视化内容可忽略
from matplotlib import cm
try: from sklearn.manifold import TSNE; HAS_SK = True
except: HAS_SK = False; print('Please install sklearn for layer visualization')
def plot_with_labels(lowDWeights, labels):
plt.cla()
X, Y = lowDWeights[:, 0], lowDWeights[:, 1]
for x, y, s in zip(X, Y, labels):
c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer'); plt.show(); plt.pause(0.01)
plt.ion()
#开始训练模型
for epoch in range(epoch): #迭代模型
for step, (b_x, b_y) in enumerate(train_loader): #将train_loader数据传入模型
output = cnn(b_x)[0]
loss = loss_func(output,b_y) #计算损失值
optimizer.zero_grad() #优化器梯度置零
loss.backward() #反向传播,计算梯度
optimizer.step() #更新梯度值
#打印结果值
if step % 50 == 0:
test_output, last_layer = cnn(test_x)
pred_y = torch.max(test_output, 1)[1].data.numpy() #输出最大值,()里边1表示每一行取最大值,
# 其次[1]表示对于取得结果取其索引也就是对应下标为1的数组
accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('Epoch:', epoch, '|train loss: %.4f' %loss.data.numpy(), '|test accuracy: %.2f' % accuracy)
if HAS_SK:
# Visualization of trained flatten layer (T-SNE)
tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000)
plot_only = 500
low_dim_embs = tsne.fit_transform(last_layer.data.numpy()[:plot_only, :])
labels = test_y.numpy()[:plot_only]
plot_with_labels(low_dim_embs, labels)
plt.ioff()
#打印10个测试数据集中的数据
test_output, _ = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy()
print(pred_y, 'Prediction Number')
print(test_y[:10].numpy(),'Real Number')
torch.Size([60000, 28, 28])
torch.Size([60000])
CNN(
(Conv1): Sequential(
(0): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(Conv2): Sequential(
(0): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(out): Linear(in_features=1568, out_features=10, bias=True)
)
Epoch: 0 |train loss: 2.3102 |test accuracy: 0.15
Epoch: 0 |train loss: 0.5123 |test accuracy: 0.80
...
Epoch: 2 |train loss: 0.0223 |test accuracy: 0.98
Epoch: 2 |train loss: 0.0308 |test accuracy: 0.98
[7 2 1 0 4 1 4 9 5 9] Prediction Number
[7 2 1 0 4 1 4 9 5 9] Real Number
Process finished with exit code 0
在TensorFlow框架下搭建神经网络思路步骤如下:
全部示例代码如下:
#基于TensorFlow框架实现卷积神经网络的mnist分类
#Author J.A.
#Data 2022.2.7
#加入可视化内容
#导入相关包
import tensorflow as tf
#引入mnist数据集
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt
#定义一个随机种子
tf.set_random_seed(1)
np.random.seed(1)
#定义批处理集大小,学习率
batch_size = 50
lr = 0.001
#加载mnist数据集,并选择为one-hot编码
mnist = input_data.read_data_sets('./mnist', one_hot = True)
test_x = mnist.test.images[:2500]
test_y = mnist.test.labels[:2500]
#画图示例
print(mnist.train.images.shape) #(55000,28*28)
print(mnist.train.labels.shape) #(55000,10)
plt.imshow(mnist.train.images[0].reshape(28,28),cmap='gray')
plt.title('%i' % np.argmax(mnist.train.labels[0]))
plt.show()
#加载数据以及预处理
tf_x = tf.placeholder(tf.float32,[None,28*28]) / 255. #placeholder插入值
image = tf.reshape(tf_x,[-1,28,28,1]) #[batch,heigth,width,channel]
tf_y = tf.placeholder(tf.int32,[None,10]) #输入y
#构建CNN模型
#网络第一层
Conv1 = tf.layers.conv2d( #此时特征维度(28,28,1)
inputs = image,
filters = 16,
kernel_size = 5,
strides = 1,
padding = 'same', #padding为same时,不改变特征图长宽
activation = tf.nn.relu
) #此时特征维度(28,28,16)
Pool1 = tf.layers.max_pooling2d(
Conv1,
pool_size=2,
strides=2,
) #此时特征维度(14,14,16)
#网络第二层
Conv2 = tf.layers.conv2d(Pool1, 32, 5, 1, 'same',activation=tf.nn.relu) #此时特征维度(14,14,32)
Pool2 = tf.layers.max_pooling2d(Conv2, 2, 2) #此时特征维度(7,7,32)
flatten = tf.reshape(Pool2, [-1, 7*7*32]) #加入全连接层维度为(1568)
output = tf.layers.dense(flatten, 10) #输出层维度(10)
#定义损失函数以及优化器
loss = tf.losses.softmax_cross_entropy(onehot_labels = tf_y, logits = output)
train_op = tf.train.AdamOptimizer(lr).minimize(loss)
#定义评估指标
accuracy = tf.metrics.accuracy( #return(acc, update_op),and create 2 local variables
labels =tf.argmax(tf_y, axis = 1), predictions = tf.argmax(output, axis = 1),)[1]
#构建图,Session会话
sess = tf.Session()
#此处的local_variables_initializer()是为了accuracy_op
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init_op) #初始化图的变量
#构建模型可视化(可忽略)
from matplotlib import cm
try: from sklearn.manifold import TSNE; HAS_SK = True
except: HAS_SK = False; print('\nPlease install sklearn for layer visualization\n')
def plot_with_labels(lowDWeights, labels):
plt.cla(); X, Y = lowDWeights[:, 0], lowDWeights[:, 1]
for x, y, s in zip(X, Y, labels):
c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer'); plt.show(); plt.pause(0.01)
plt.ion()
#运行模型
for step in range(800):
b_x, b_y = mnist.train.next_batch(batch_size)
_, loss_ = sess.run([train_op, loss], {tf_x: b_x, tf_y: b_y})
if step % 50 == 0:
accuracy_, flatten_representation = sess.run([accuracy, flatten], {tf_x: test_x, tf_y: test_y})
print('Step:', step, '|train loss: %.4f' % loss_, '|test accuracy: %.2f' % accuracy_)
if HAS_SK:
# Visualization of trained flatten layer (T-SNE)
tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000);
plot_only = 800
low_dim_embs = tsne.fit_transform(flatten_representation[:plot_only, :])
labels = np.argmax(test_y, axis=1)[:plot_only];
plot_with_labels(low_dim_embs, labels)
plt.ioff()
#在测试集中打印10个预测值
test_output = sess.run(output, {tf_x: test_x[:10]})
pred_y = np.argmax(test_output, 1)
print(pred_y, 'prediction number')
print(np.argmax(test_y[:10], 1), 'real number')
(55000, 784)
(55000, 10)
Step: 0 |train loss: 2.2956 |test accuracy: 0.13
Step: 50 |train loss: 0.3620 |test accuracy: 0.47
...
Step: 650 |train loss: 0.0490 |test accuracy: 0.87
Step: 700 |train loss: 0.0273 |test accuracy: 0.88
Step: 750 |train loss: 0.0909 |test accuracy: 0.88
[7 2 1 0 4 1 4 9 5 9] prediction number
[7 2 1 0 4 1 4 9 5 9] real number
Process finished with exit code 0
思路:
全部代码如下:
'''
#基于Keras实现卷积神经网络的mnist分类
#Author J.A.
#Data 2022.2.6
#在Tensorflow下实现Keras
#导入相关包
import numpy as np
#设置随机种子
np.random.seed(2022)
from tensorflow.keras.datasets import mnist #从Keras的datasets库导入mnist数据集
#from tensorflow.keras.utils import np_utils
from tensorflow.python.keras.utils.np_utils import to_categorical
from tensorflow.keras.models import Sequential
#引入Keras模型框架以及卷积层、激活函数、池化层、全连接层等
from tensorflow.keras.layers import Dense, Activation, Convolution2D, MaxPool2D,Flatten
from tensorflow.keras.optimizers import Adam
#training X.shape为(60000,28*28), Y.shape(60000,)
#test X.shape为(10000,28*28),Y.shape(10000,)
(X_train, y_train),(X_test, y_test) = mnist.load_data() #载入数据
#对数据进行最简单的处理
#对训练集数据进行预处理,(-1是指smaple数据,-1指全部数据,1是指一维图像,
# 28*28是指数据大小()/255进行均值处理)
X_train = X_train.reshape(-1,1,28,28) / 255.
X_test = X_test.reshape(-1,1,28,28) / 255.
#将其转变为ONE-Hot编码
y_train = to_categorical(y_train, num_classes = 10)
y_test = to_categorical(y_test, num_classes = 10)
#创建CNN模型
model = Sequential()
#添加卷积层、激活函数、池化层等
# Conv layer1
model.add(Convolution2D(
batch_input_shape=(None, 1, 28, 28),
filters = 32, #卷积核数量
kernel_size = 5, #卷积核大下
strides = 1, #步长
padding = 'same', #降维操作
data_format = 'channels_first',
)) #维度关系 (32,28,28)
model.add(Activation('relu'))
model.add(MaxPool2D(
pool_size = 2, #卷积核大下
strides = 2, #步长
padding = 'same', #降维操作
data_format = 'channels_first',
)) #维度关系(32,14,14)
# Conv layer2
model.add(Convolution2D(64, 5, strides = 1, padding = 'same',data_format='channels_first'))
#维度关系(64, 14, 14)
model.add(Activation('relu'))
model.add(MaxPool2D(2,2,'same',data_format='channels_first'))
#维度关系(64,7,7)
#添加全连接层1
model.add(Flatten()) #维度关系64*7*7=3136, output shape(1024)
model.add(Dense(1024))
model.add(Activation('relu'))
#添加全连接层2
model.add(Dense(10)) #维度关系(10)
model.add(Activation('softmax'))
#定义优化器
adam = Adam(lr = 1e-4)
#模型配置
model.compile(optimizer = adam,
loss = 'categorical_crossentropy',
metrics = ['accuracy'])
print('Training------------Begin!!!')
#运行模型
model.fit(X_train, y_train, epochs = 1, batch_size = 64,)
print('\nTesting----------Begin!!!')
#评估模型
loss, accuracy = model.evaluate(X_test, y_test)
#打印运行结果
print('\ntest loss: ', loss)
print('\ntest accuracy: ', accuracy)
基于Keras的mnist数据集分类运行结果如下:
10000/10000 [==============================] - 3s 296us/sample - loss: 0.0853 - acc: 0.9752
test loss: 0.08534580951035023
test accuracy: 0.9752
Process finished with exit code 0