Mnist手写数字识别(Pytorch实现,线性神经网络版,超详细代码备注)

1、先看实现效果
迭代3轮的准确率
在这里插入图片描述
loss图
在这里插入图片描述
随便取一个数据预测
在这里插入图片描述
预测结果:
在这里插入图片描述
2、实现代码
需要的库

#导入torch库,用于搭建神经网络
import torch
import torch.nn as nn
from torch.utils.data import Dataset
#导入pandas库,用于读取CSV文件
import pandas
#导入matplotlib用于绘图
import matplotlib.pyplot as plt

数据集管理类(用于管理mnist数据集和绘图)

class MnistDataset(Dataset):
    """管理minist数据集"""
    def __init__(self,filename):
        """重写init方法,用于读取文件"""
        self.fileobject = pandas.read_csv(filename)
    def __len__(self):
        """重写len方法,用于返回文件数据对象的长度"""
        len = len(self.fileobject)
        return len
    def __getitem__(self, index):
        """重写__getitem__,用于返回返回文件里面的内容"""
        # 读取一副图像的标签
        label = self.fileobject.iloc[index,0]
        #读取一副图像的数据
        data = self.fileobject.iloc[index,1:]
        #将标签改为one_hot编码
        one_hot_label = torch.zeros((10))
        one_hot_label[label] = 1.0
        #将图像数据转为FloatTensor格式,并且归一化为0~1区间
        img_data = torch.FloatTensor(data.values)/255.0

        #返回图片标签、图片标签对应的one_hot编码、图片数据
        return label,one_hot_label,img_data

    def plot_image(self,index):
        """绘制图像"""
        #得到标签
        label = self.fileobject.iloc[index,0]
        #得到图像
        img = self.fileobject.iloc[index,1:].values.reshape(28,28)
        #画标题
        plt.title('label = '+str(label))
        #画图像
        plt.imshow(img,cmap='Blues')
        plt.show()

线性神经网络
就3层,输入层(784个节点)->隐藏层(200个节点)->输出层(100个节点)

class MnistNet(nn.Module):
    """Mnist分类器"""
    def __init__(self):
        """重写init方法,用于搭建模型"""
        #初始化父类
        super().__init__()
        #定义神经网络模型784->200->10
        self.model = nn.Sequential(
            nn.Linear(28*28,200),
            nn.Sigmoid(),
            nn.Linear(200,10),
            nn.Sigmoid()
        )
        #定义损失函数,选择均方差误差
        self.loss = torch.nn.MSELoss()
        #定义优化器,选择随机梯队下降,步长0.01
        self.opt = torch.optim.SGD(self.parameters(),lr=0.01)
        #记录迭代次数
        self.count = 0
        #记录迭代时loss的值
        self.progress = []

    def forward(self,inputs):
        """网络前向传播"""
        outputs = self.model(inputs)
        return outputs

    def train(self,inputs,targets):
        """网络训练"""
        #得到预测输出
        outputs = self.forward(inputs)
        #得到损失值
        loss = self.loss(outputs,targets)
        #梯度归零,否则会叠加
        self.opt.zero_grad()
        #反向传播
        loss.backward()
        #更新权重
        self.opt.step()
        #记录迭代次数
        self.count += 1
        #每10次迭代,记录一次loss
        if self.count%10 == 0:
            self.progress.append(loss.item())
        #每10000次迭代,输出迭代次数
        if self.count%10000 == 0:
            print('count = ',self.count)

    def plot_loss(self):
        """画出loss的值"""
        df  = pandas.DataFrame(self.progress,columns=['loss'])
        df.plot(ylim=(0,1.0),figsize=(16,8),alpha=0.1,marker='.',grid=True,yticks=(0,0.25,0.5))
        plt.show()

主函数

if __name__ == '__main__':
    """训练阶段"""
    #读取训练集
    mnist_data_train = MnistDataset('mnist_train.csv')
    #创建神经网络
    mnistNet = MnistNet()
    #迭代次数
    epochs = 3
    #在MNIST数据集训练网络
    for i in range(epochs):
        print('traing epoch ',i+1,'of',epochs)
        for label,one_hot_label,img_data in mnist_data_train:
            mnistNet.train(img_data,one_hot_label)
    #绘制loss
    mnistNet.plot_loss()
    """预测一副图像"""
    #读取测试集
    mnist_data_test = MnistDataset('mnist_test.csv')
    #选择一副图片
    img_num = 5
    #得到其本身的值,mnist_data_test[i][j]返回的是__getitem__方法的返回值
    label_real = mnist_data_test[img_num][0]
    #绘制这副图像
    mnist_data_test.plot_image(img_num)
    #预测这副图片的值
    input = mnist_data_test[img_num][2]
    output_predict = mnistNet.forward(input).detach()
    print('real label = ',label_real,' predict label = ',str(output_predict.argmax().numpy()))
    #绘制输出张量
    pandas.DataFrame(output_predict.numpy()).plot(kind='bar',legend=False,ylim=(0.1))
    plt.show()
    """得到准确率"""
    #记录预测正确数,预测总数
    true_sum = 0
    sum = 0
    #得到准确率
    for label,one_hot_label,img_data in mnist_data_test:
        #得到预测值
        predict = mnistNet.forward(img_data).detach().numpy()
        if predict.argmax() == label:#预测和理想值一样
            true_sum += 1
        sum += 1
    print('all simple = ',sum)
    print('it\'s true = ',true_sum)
    print('accuracy = ',true_sum/sum*100.0,'%')

3、最后附上Mnist数据集
百度网盘
提取码:ZYYY
把两个文件放在项目根目录即可

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Python中的TensorFlow或PyTorch框架来实现手写数字图片识别。以下是一个使用TensorFlow实现的示例代码: ```python import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 加载MNIST数据集 mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) # 定义输入和输出的占位符 x = tf.placeholder(tf.float32, [None, 784]) y_ = tf.placeholder(tf.float32, [None, 10]) # 定义模型 W1 = tf.Variable(tf.truncated_normal([784, 256], stddev=0.1)) b1 = tf.Variable(tf.zeros([256])) h1 = tf.nn.relu(tf.matmul(x, W1) + b1) W2 = tf.Variable(tf.truncated_normal([256, 64], stddev=0.1)) b2 = tf.Variable(tf.zeros([64])) h2 = tf.nn.relu(tf.matmul(h1, W2) + b2) W3 = tf.Variable(tf.truncated_normal([64, 10], stddev=0.1)) b3 = tf.Variable(tf.zeros([10])) y = tf.matmul(h2, W3) + b3 # 定义损失函数和优化器 cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)) train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) # 定义准确率 correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 训练模型 sess = tf.InteractiveSession() tf.global_variables_initializer().run() for i in range(10000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) if i % 1000 == 0: train_accuracy = accuracy.eval(feed_dict={x: batch_xs, y_: batch_ys}) print("step %d, training accuracy %g" % (i, train_accuracy)) # 测试模型 test_accuracy = accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print("test accuracy %g" % test_accuracy) ``` 这个模型使用了三层非线性神经网络,其中第一层有256个神经元,第二层有64个神经元,输出层有10个神经元,对应于10个数字。训练过程中使用了Adam优化器和交叉熵损失函数。最终测试准确率可以达到98%以上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值