• Pytorch实现MNIST字符识别


    第一种方法

    1.读取数据

    1. import torch
    2. from torchvision import transforms
    3. from torchvision import datasets
    4. from torch.utils.data import DataLoader
    5. import torch.nn.functional as F
    6. import torch.optim as optim
    7. import random
    8. import matplotlib.pyplot as plt
    9. batchSize=64
    10. transform=transforms.Compose([
    11. transforms.ToTensor(),
    12. #均值=0.1307,标准差=0.3081
    13. transforms.Normalize((0.1307,),(0.3081,))
    14. ])
    15. train_dataset=datasets.MNIST(root="data/mnist",
    16. train=True,
    17. download=True,
    18. transform=transform)
    19. train_loader=DataLoader(train_dataset,
    20. shuffle=True,
    21. batch_size=batchSize)
    22. test_dataset=datasets.MNIST(root="data/mnist",
    23. train=False,
    24. download=True,
    25. transform=transform)
    26. test_loader=DataLoader(test_dataset,
    27. shuffle=True,
    28. batch_size=batchSize)

    2.随机显示一个数字

    1. def showRandomPictures(train_loader):
    2. data_iter=iter(train_loader)
    3. images,labels=data_iter.__next__()
    4. # Choose a random index from the batch
    5. random_index = random.randint(0, batchSize - 1)
    6. # Display the transformed image
    7. transformed_image = images[random_index].squeeze().numpy()
    8. transformed_image = (transformed_image * 0.3081) + 0.1307 # Inverse normalization
    9. plt.imshow(transformed_image, cmap='gray') # Assuming MNIST images are grayscale
    10. plt.title(f"Label: {labels[random_index].item()}")
    11. plt.show()
    12. showRandomPictures(train_loader)

     

    3.定义模型和超参数

    1. class Net(torch.nn.Module):
    2. def __init__(self) -> None:
    3. super(Net,self).__init__()
    4. self.layer1=torch.nn.Linear(784,512)
    5. self.layer2=torch.nn.Linear(512,256)
    6. self.layer3=torch.nn.Linear(256,128)
    7. self.layer4=torch.nn.Linear(128,64)
    8. self.layer5=torch.nn.Linear(64,10)
    9. def forward(self,x):
    10. x=x.view(-1,784)
    11. x=F.relu(self.layer1(x))
    12. x=F.relu(self.layer2(x))
    13. x=F.relu(self.layer3(x))
    14. x=F.relu(self.layer4(x))
    15. x=self.layer5(x)
    16. return x
    17. model=Net()
    18. criterion=torch.nn.CrossEntropyLoss()
    19. optimizer=optim.SGD(model.parameters(),lr=0.01,momentum=0.5)

    4.训练步骤

    1. def train(epoch):
    2. running_loss=0.0
    3. for batch_idx,data in enumerate(train_loader,0):
    4. inputs,target=data
    5. optimizer.zero_grad()
    6. outputs=model(inputs)
    7. loss=criterion(outputs,target)
    8. loss.backward()
    9. optimizer.step()
    10. running_loss+=loss.item()
    11. if batch_idx%300==299:
    12. print(f"[epoch={epoch+1}, batch_index={batch_idx+1}, training_loss={running_loss/300}]")
    13. running_loss=0.0

    5.测试步骤 

    1. accuracyHistory=[]
    2. def test():
    3. correct=0
    4. total=0
    5. with torch.no_grad():
    6. for data in test_loader:
    7. images,labels=data
    8. outputs=model(images)
    9. #每一行的最大值的下标[max,maxIndex]
    10. _,predicted=torch.max(outputs.data,dim=1)
    11. #label.size(0)是batch_size
    12. total+=labels.size(0)
    13. correct+=(predicted==labels).sum().item()
    14. print(f"Accuracy on test set:{100*correct/total}")
    15. accuracyHistory.append(100*correct/total)

    6.主方法执行

    1. if __name__=="__main__":
    2. for epoch in range(10):
    3. train(epoch)
    4. test()
    5. plt.plot(accuracyHistory)
    6. plt.show()

     7.运行结果

    1. [epoch=1, batch_index=300, training_loss=2.223298035860062]
    2. [epoch=1, batch_index=600, training_loss=0.9641364443302155]
    3. [epoch=1, batch_index=900, training_loss=0.43318099692463874]
    4. Accuracy on test set:88.38
    5. ....
    6. Accuracy on test set:97.34
    7. [epoch=8, batch_index=300, training_loss=0.05266832955181599]
    8. [epoch=8, batch_index=600, training_loss=0.05094206769950688]
    9. [epoch=8, batch_index=900, training_loss=0.053400517796787124]
    10. Accuracy on test set:97.49
    11. [epoch=9, batch_index=300, training_loss=0.036180642331019044]
    12. [epoch=9, batch_index=600, training_loss=0.04376721960259602]
    13. [epoch=9, batch_index=900, training_loss=0.04324531762007003]
    14. Accuracy on test set:97.55
    15. [epoch=10, batch_index=300, training_loss=0.02999880815623328]
    16. [epoch=10, batch_index=600, training_loss=0.0335875346181759]
    17. [epoch=10, batch_index=900, training_loss=0.03751158087824782]
    18. Accuracy on test set:97.61

    第二种方法

    1.下载mnist.pkl.gz 

    网址:http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz

    数据集文件夹路径是data2/mnist/mnist.pkl.gz

     2.读取数据

    1. from pathlib import Path
    2. import matplotlib.pyplot as plt
    3. DATA_PATH=Path("./data2")
    4. PATH=DATA_PATH / "mnist"
    5. FILENAME="mnist.pkl.gz"
    6. import pickle
    7. import gzip
    8. with gzip.open((PATH/FILENAME).as_posix(),"rb") as f:
    9. ((x_train,y_train),(x_valid,y_valid),_)=pickle.load(f,encoding="latin-1")
    10. #x_train(500,784),y_train(5000,) x_valid(10000, 784),y_valid(10000,)

    随机显示一个数字

    1. #==========28*28=784========随机显示数字5
    2. import matplotlib.pyplot as plt
    3. import numpy as np
    4. plt.imshow(x_train[50].reshape((28,28)),cmap="gray")
    5. plt.show()

     

    数据转为tensor

    1. #=================数据转为tensor才能参与建模训练===
    2. import torch
    3. x_train,y_train,x_valid,y_valid=map(
    4. torch.tensor, (x_train,y_train,x_valid,y_valid)
    5. )

    3.设置损失函数为交叉熵函数

    1. #=====torch.nn.functional==========
    2. import torch.nn.functional as F
    3. loss_func=F.cross_entropy

    4.创建Model类

    1. from torch import nn
    2. class Mnist_NN(nn.Module):
    3. def __init__(self):
    4. super().__init__()
    5. self.hidden1=nn.Linear(784,128)
    6. self.hidden2=nn.Linear(128,256)
    7. self.out=nn.Linear(256,10)
    8. self.dropout=nn.Dropout(0.5)
    9. def forward(self,x):
    10. x=F.relu(self.hidden1(x))
    11. #全连接层+droput,防止过拟合
    12. x=self.dropout(x)
    13. x=F.relu(self.hidden2(x))
    14. x=self.dropout(x)
    15. x=self.out(x)
    16. return x
    17. # Mnist_NN(
    18. # (hidden1): Linear(in_features=784, out_features=128, bias=True)
    19. # (hidden2): Linear(in_features=128, out_features=256, bias=True)
    20. # (out): Linear(in_features=256, out_features=10, bias=True)
    21. # (dropout): Dropout(p=0.5, inplace=False)
    22. # )
    23. # net=Mnist_NN()
    24. # print(net)

    打印一下这网络长什么样

    1. net=Mnist_NN()
    2. print(net)
    3. #打印定义好的名字和w和b
    4. for name,parameter in net.named_parameters():
    5. print(name,parameter,parameter.size())
    1. Mnist_NN(
    2. (hidden1): Linear(in_features=784, out_features=128, bias=True)
    3. (hidden2): Linear(in_features=128, out_features=256, bias=True)
    4. (out): Linear(in_features=256, out_features=10, bias=True)
    5. (dropout): Dropout(p=0.5, inplace=False)
    6. )
    7. hidden1.weight Parameter containing:
    8. tensor([[-1.7000e-02, -7.5721e-03, -1.7358e-03, ..., 7.6538e-03,
    9. ..........
    10. out.weight Parameter containing:
    11. tensor([[-0.0173, 0.0522, 0.0494, ..., -0.0579, -0.0439, -0.0522],
    12. ....
    13. requires_grad=True) torch.Size([10, 256])
    14. out.bias Parameter containing:
    15. tensor([-0.0154, -0.0028, -0.0574, -0.0608, -0.0276, 0.0483, 0.0503, 0.0112,
    16. -0.0352, -0.0498], requires_grad=True) torch.Size([10])

    5.使用TensorDataset和DataLoader,封装成一个batch的数据集

    1. from torch.utils.data import TensorDataset
    2. from torch.utils.data import DataLoader
    3. bs=64
    4. train_ds=TensorDataset(x_train,y_train)
    5. # train_dl=DataLoader(train_ds,batch_size=bs,shuffle=True)
    6. valid_ds=TensorDataset(x_valid,y_valid)
    7. # valid_dl=DataLoader(valid_ds,batch_size=bs*2)
    8. def get_data(train_ds,valid_ds,bs):
    9. return (
    10. DataLoader(train_ds,batch_size=bs,shuffle=True),
    11. DataLoader(valid_ds,batch_size=bs*2)
    12. )

    6.定义训练步骤

    1. import numpy as np
    2. val_losses=[]
    3. #steps:迭代次数,step相当于epoch
    4. def fit(steps,model,loss_func,opt,train_dl,valid_dl):
    5. for step in range(steps):
    6. model.train() #更新w和b
    7. #xb(64,784) yb(64),xb和yb都是tensor
    8. for xb,yb in train_dl:
    9. loss_batch(model,loss_func,xb,yb,opt)
    10. #evaluate 模式,dropout和BatchNum不会工作
    11. model.eval() #不更新w和b
    12. with torch.no_grad():
    13. #losses:nums=(loss,batch),(loss,batch)....
    14. losses,nums =zip(
    15. *[loss_batch(model,loss_func,xb,yb) for xb,yb in valid_dl]
    16. )
    17. #总的验证集的平均损失
    18. val_loss=np.sum(np.multiply(losses,nums)) / np.sum(nums)
    19. val_losses.append(val_loss)
    20. print("当前step:"+str(step),"验证集损失"+str(val_loss))
    21. from torch import optim
    22. def get_model():
    23. model=Mnist_NN()
    24. #返回模型和优化器optim.SGD(model.parameters() , lr=0.001)
    25. return model,optim.Adam(model.parameters() , lr=0.001)
    26. def loss_batch(model, loss_func ,xb,yb, opt=None):
    27. #根据预测值和真实值计算loss
    28. loss=loss_func( model(xb) , yb )
    29. if opt is not None:
    30. loss.backward() #反向传播求梯度
    31. opt.step() #更新参数
    32. opt.zero_grad() #梯度清零,避免影响下一次的更新参数
    33. return loss.item(), len(xb)

    7.开始训练模型

    1. train_dl,valid_dl=get_data(train_ds,valid_ds,bs)
    2. model,opt=get_model()
    3. fit(20,model ,loss_func,opt,train_dl,valid_dl)
    4. correct=0
    5. total=0
    6. #xb(128,784) , yb(128)
    7. for xb,yb in valid_dl:
    8. #output(128,10),每一批128个样例,10个概率
    9. output=(model(xb))
    10. # print(output.shape)
    11. # print(output)
    12. #predicted==预测概率中最大的值的索引
    13. _,predicted=torch.max(output.data,1) #最大的值和索引
    14. # print(predicted)
    15. #size(0)==64,item()脱离tensor
    16. total+=yb.size(0)
    17. correct+=(predicted==yb).sum().item()
    18. print("Accuracy of network on the 10000 test image :%d %%" %(
    19. 100*correct / total
    20. ))
    21. plt.figure()
    22. plt.title("loss during training")
    23. plt.plot(np.arange(1,21,1),val_losses)
    24. plt.show()
    1. 当前step:0 验证集损失0.19325110550522803
    2. 当前step:1 验证集损失0.13869898459613322
    3. 当前step:2 验证集损失0.11913147141262889
    4. 当前step:3 验证集损失0.10589157585203647
    5. 当前step:4 验证集损失0.09970801477096974
    6. 当前step:5 验证集损失0.09848284918610006
    7. 当前step:6 验证集损失0.08794679024070501
    8. 当前step:7 验证集损失0.08894123120522127
    9. 当前step:8 验证集损失0.0905570782547351
    10. 当前step:9 验证集损失0.0877237871955149
    11. 当前step:10 验证集损失0.08790379901565612
    12. 当前step:11 验证集损失0.08826288345884532
    13. 当前step:12 验证集损失0.08438722904250026
    14. 当前step:13 验证集损失0.08695273711904883
    15. 当前step:14 验证集损失0.08459821079988032
    16. 当前step:15 验证集损失0.08047270769253373
    17. 当前step:16 验证集损失0.0862937849830836
    18. 当前step:17 验证集损失0.08164657156261383
    19. 当前step:18 验证集损失0.08109720230847597
    20. 当前step:19 验证集损失0.08208743708985858
    21. Accuracy of network on the 10000 test image :97 %

  • 相关阅读:
    MapStruct的使用
    vue+elementui实现el-input动画效果
    传输层(UDP协议,TCP协议三次握手、四次挥手)
    Apache Paimon 主键表解析
    Java IDEA java.lang.IllegalStateException: Failed to introspect Class报错原因和解决办法
    认识etcd
    Pytorch深度学习 - 学习笔记
    这几道SQL面试题秒杀大部分的0年工作经验的毕业生
    【探花交友】注册登录需求分析、短信验证码
    常见的几种限流算法代码实现(JAVA)
  • 原文地址:https://blog.csdn.net/m0_46306264/article/details/132966618