pytorch学习6-卷积神经网络实现mnist手写数字识别

卷积神经网络实现mnist手写数字识别


卷积神经网络的结构为

ConvNet(
(layer1): Sequential(
(0): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(layer2): Sequential(
(0): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(fc): Linear(in_features=1568, out_features=10, bias=True)
)

import torch 
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms


# Device configuration
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

# Hyper parameters
num_epochs = 5
num_classes = 10
batch_size = 100
learning_rate = 0.001

# MNIST dataset
train_dataset = torchvision.datasets.MNIST(root='../../data/',
                                           train=True, 
                                           transform=transforms.ToTensor(),
                                           download=True)

test_dataset = torchvision.datasets.MNIST(root='../../data/',
                                          train=False, 
                                          transform=transforms.ToTensor())

# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                          batch_size=batch_size, 
                                          shuffle=False)

# Convolutional neural network (two convolutional layers)
class ConvNet(nn.Module):
    def __init__(self, num_classes=10):
        super(ConvNet, self).__init__()
        # nn.Sequential()定义一个时序容器,按顺序执行
        # 第一个大层,包含卷积,批处理,激活,池化
        self.layer1 = nn.Sequential(
            # minist数据集像素为28*28
            # Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
            # in_channels 输入的通道,out_channels输出的通道,同时也是卷积核的个数
            # 卷积过程,先padding,再kernal和map对齐,再卷积运算。
            nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
            # 经过一层卷积,28*28*1->28*28*16,因为stride=1,padding=2
            # BatchNorm2d,16位特征数,将这16个通道归一化
            nn.BatchNorm2d(16),
            nn.ReLU(),
            # 步长为2,所以最大池化后28/2=14
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            # 池化的步长为2,所以最大池化后14/2=7
            nn.MaxPool2d(kernel_size=2, stride=2))
        # 传入7*7*32个输入,接10个输出
        self.fc = nn.Linear(7*7*32, num_classes)
    # 定义前向传播,这里要一层一层的传入实参,参数x为模型的输入
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.reshape(out.size(0), -1)
        # 这里fc为什么输入一个参数
        out = self.fc(out)
        # 返回模型的输出
        return out

model = ConvNet(num_classes).to(device)
# 打印模型结构
print(model)
# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# Train the model
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        
        # 前向传播,并得到模型的输出和损失
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # 反向传播及优化损失
        # 将梯度置0
        optimizer.zero_grad()
        # 误差反向传播
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

# Test the model
model.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
    print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

# Save the model checkpoint,保存模型操作,序列化
torch.save(model.state_dict(), 'model.ckpt')

output:
Epoch [1/5], Step [100/600], Loss: 0.3434
Epoch [1/5], Step [200/600], Loss: 0.1523
Epoch [1/5], Step [300/600], Loss: 0.0984
Epoch [1/5], Step [400/600], Loss: 0.1279
Epoch [1/5], Step [500/600], Loss: 0.1632
Epoch [1/5], Step [600/600], Loss: 0.0438
Epoch [2/5], Step [100/600], Loss: 0.0173
Epoch [2/5], Step [200/600], Loss: 0.1028
Epoch [2/5], Step [300/600], Loss: 0.0338
Epoch [2/5], Step [400/600], Loss: 0.0202
Epoch [2/5], Step [500/600], Loss: 0.0782
Epoch [2/5], Step [600/600], Loss: 0.0509
Epoch [3/5], Step [100/600], Loss: 0.0721
Epoch [3/5], Step [200/600], Loss: 0.1173
Epoch [3/5], Step [300/600], Loss: 0.0181
Epoch [3/5], Step [400/600], Loss: 0.0115
Epoch [3/5], Step [500/600], Loss: 0.0083
Epoch [3/5], Step [600/600], Loss: 0.0271
Epoch [4/5], Step [100/600], Loss: 0.0207
Epoch [4/5], Step [200/600], Loss: 0.0679
Epoch [4/5], Step [300/600], Loss: 0.0222
Epoch [4/5], Step [400/600], Loss: 0.0169
Epoch [4/5], Step [500/600], Loss: 0.0666
Epoch [4/5], Step [600/600], Loss: 0.0187
Epoch [5/5], Step [100/600], Loss: 0.0146
Epoch [5/5], Step [200/600], Loss: 0.0018
Epoch [5/5], Step [300/600], Loss: 0.0211
Epoch [5/5], Step [400/600], Loss: 0.0028
Epoch [5/5], Step [500/600], Loss: 0.0250
Epoch [5/5], Step [600/600], Loss: 0.0060
Test Accuracy of the model on the 10000 test images: 99.06 %

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要用卷积神经网络实现mnist手写体识别,首先需要准备好mnist数据集。然后,可以使用Python中的深度学习框架,如TensorFlow或PyTorch,来构建卷积神经网络模型。在模型中,需要使用卷积层、池化层和全连接层等组件,以及激活函数和优化器等工具,来训练模型。最后,可以使用测试集来评估模型的准确率,并对模型进行调整和优化。 ### 回答2: MNIST手写体识别是计算机视觉领域中最具有代表性的数据集之一,它包含了大量手写体数字,提供了一个很好的实验平台来测试各种计算机视觉算法的性能。卷积神经网络(CNN)已经成为图像识别的主流算法之一,它能够有效地提取图像的特征,从而实现高准确率的分类。下面我们就如何使用CNN实现MNIST手写体识别进行简要介绍。 首先需要准备好MNIST数据集,它包含了6万张训练图片和1万张测试图片。每个图片的大小为28x28像素,并且每个像素点的灰度值都在0-255之间。在这里我们使用TensorFlow深度学习框架来实现手写体识别。 我们先定义输入层,输入层的大小应该是28x28。然后我们添加一层卷积层,卷积核的大小一般是3x3,4x4或者5x5。这一层用来提取图片的特征。接着添加池化层,通常使用最大池化,它的大小一般是2x2。最大池化可以在不损失信息的前提下减小图片的尺寸,从而降低网络的复杂度。接下来,可以再添加几层卷积池化层来进一步提取特征。最后,添加一个全连接层,用来连接所有的卷积池化层,使得网络能够输出一个确定的类别。最后输出层的节点数应该是10,对应10种数字分类。 在进行训练之前需要先对数据进行预处理。一般来说,我们需要将每个像素点的像素值除以255,然后将每张图片展开成一个向量。接下来,我们可以使用随机梯度下降(SGD)算法来进行训练,对于每一次训练迭代,我们需要从训练集中随机抽取一批数据来进行训练,这个批量大小一般是32或64,然后使用反向传播算法来计算误差并更新参数。 最后,在测试集上进行结果评估。分类准确率是衡量分类器优秀度的标准,正确率越高,说明CNN网络性能越好。如果最终结果仍无法满足需求,可以通过增加网络深度、增加卷积核数量等手段来提高准确率。 从以上步骤可以看出,卷积神经网络是一种非常有效的图像识别算法,通过合理的设计网络体系和训练方法,能够在视觉任务中达到很高的精度,并且在实用领域得到了广泛应用。 ### 回答3: MNIST手写数字识别是深度学习中最常见的任务之一,可以训练一个卷积神经网络(CNN)来实现这个任务。 首先,需要安装并导入必要的库,如tensorflow和numpy。接着,加载MNIST数据集,数据集包括60000张训练图片和10000张测试图片,每张图片大小为28x28像素,通过如下代码进行加载: ``` import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('MNIST_data', one_hot=True) ``` 然后,定义CNN的网络结构,输入图片是一个28x28的矩阵,把它们作为CNN的输入,具有卷积层、激活函数和池化层,最终输出一个10维向量,用来表示输入图片所表示的数字分类。CNN的结构如下: ``` # 定义CNN结构 input_image = tf.placeholder(tf.float32, [None, 784]) # 输入数据为28x28的张量,把它们拉成一维的向量 input_label = tf.placeholder(tf.float32, [None, 10]) # 标签为10-d向量 input_image_reshape = tf.reshape(input_image, [-1, 28, 28, 1]) # 将拉成的向量重塑为28x28的张量 # 第1个卷积层 conv_1 = tf.layers.conv2d(inputs=input_image_reshape, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool_1 = tf.layers.max_pooling2d(inputs=conv_1, pool_size=[2, 2], strides=2) # 第2个卷积层 conv_2 = tf.layers.conv2d(inputs=pool_1, filters=64, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool_2 = tf.layers.max_pooling2d(inputs=conv_2, pool_size=[2, 2], strides=2) # 扁平化层 pool_flat = tf.reshape(pool_2, [-1, 7 * 7 * 64]) # 全连接层 dense = tf.layers.dense(inputs=pool_flat, units=1024, activation=tf.nn.relu) dropout = tf.layers.dropout(inputs=dense, rate=0.4) # 输出层 output = tf.layers.dense(inputs=dropout, units=10) ``` 接着,定义CNN的损失函数和优化器,使用交叉熵代价函数,通过梯度下降法来更新网络中的权重参数: ``` # 定义损失函数 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=input_label, logits=output)) # 定义优化器 train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss) ``` 最后,使用训练集对CNN进行训练,训练过程中进行多次迭代,每次迭代使用一个batch的样本进行训练: ``` # 模型训练 sess = tf.InteractiveSession() tf.global_variables_initializer().run() for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={input_image: batch_xs, input_label: batch_ys}) # 计算测试集分类准确率 correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(input_label, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print(sess.run(accuracy, feed_dict={input_image: mnist.test.images, input_label: mnist.test.labels})) ``` 到这里,就完成了MNIST手写数字识别任务的实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值