目录

补充知识点

torch.nn.LogSoftmax()

 torchvision.transforms

transforms.Compose

transforms.ToTensor

transforms.Normalize(mean, std)

torchvision.datasets

MNIST(手写数字数据集)

torch.utils.data.DataLoader

torch.nn.NLLLoss() 

torch.nn.CrossEntropyLoss()

torch.nn.NLLLoss() 

enumerate() 函数

next() 函数

pytorch中.detach()

torch.squeeze()

torch.optim.SGD 

独热编码

代码实现

bp网络的搭建

建立我们的神经网络对象

预测

完整代码

结果极其图像显示

补充知识点

torch.nn.LogSoftmax()

torch.nn.LogSoftmax()和我们的softmax差不多只不过就是最后加入了一个log,关于softmax的详情大家可以看这一篇博客深度学习之感知机,激活函数,梯度消失,BP神经网络

我们只需要知道里面的一些常用参数就好,一般就是这个dim

下面是softmax的logsoftmax和他一样。

 torchvision.transforms

这个是一个功能强大的数据处理集合库

这里主要说一下transforms.Compose还有transforms.ToTensor以及transforms.Normalize(mean, std)

transforms.Compose

这个功能函数可以看作一个功能函数容器,它里面可以放多个功能函数(多个的话应该把这些功能函数放在一个列表内),当该功能函数定义好后,其内部的其他功能函数也会随之按我们给定的要求定义好,当我们调用compose的实例的时候,就会按照我们在容器内部摆放的顺序,从左至右的依次调用功能函数

transforms.ToTensor

用于对载入的图片数据进行类型转换,将之前PIL图片的数据(应该是np.array()类型的)转换成Tensor数据类型的张量,以便于我们后续的数据使用

(补充:PIL默认输出的图片格式为 RGB)

(下面图片内容来自网络,侵权必删。)

transforms.Normalize(mean, std)

数据归一化处理。

下面是我在学习过程中遇到的问题:

1.归一化就是要把图片3个通道中的数据整理到[-1, 1]或者[0,1]区间,x = (x - mean(x))/std(x)只要输入数据集x就可以直接算出来,为什么Normalize()函数的mean和std(标准差)还需要我们手动输入数值呢?

我的理解是,我们一开始就算好可以极大的减少运算量,如果我们自动的让他算的话,我们这个每一个图片都要算,这样运算量就极大。

2.RGB单个通道的值是[0, 255],所以一个通道的均值应该在127附近才对。我们接下来的代码如下图所示

所填的是0.5,0.5,这是为什么?

 因为我们应用了torchvision.transforms.ToTensor,他会将数据归一化到[0,1](是将数据除以255),transforms.ToTensor( )会把HWC会变成C *H *W(拓展:格式为(h,w,c),像素顺序为RGB),所以我们就应该输入0.5,0.5

(该图片内容来自网络,侵权璧必删)

我们一般来说只需了解一些常用的库函数,我们这里只是提一下我们这次会用到的函数,其余的函数若想了解的话,推荐大家看这位作者写的博客PyTorch之torchvision.tra()nsforms详解[原理+代码实现]-CSDN博客

torchvision.datasets

这里面包含了一些我们目前常用的一些数据集

我们这里主要讲一下mnist 

MNIST(手写数字数据集)

MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据。

在我们pytorch里面的torchvision里面是有的,我们可以直接用。

torchvision.datasets.MNIST(root, train=True, transform=None, target_transform=None, download=False)

相关参数:

root:就是我们从网上下载的数据集所放的目录,也就是文件路径

train:train=True意思就是下载的是训练集,如果train=Flase,那就是下载的是测试集

transform: 因为我们的数据直接下载过后一般都是要进行处理,所以这个后面跟的是一个transforms数据处理函数的一个实例化对象

download:为True就是从网络上下载数据集保存在我们的root路径中,为False就是不下载。

其余参数可自行查阅

torch.utils.data.DataLoader

(图片内容来自网络,侵权必删)

(其实我们记住常用的,dataset,batch_size,shuffle这三个常用的参数就好了)

torch.nn.NLLLoss() 

torch.nn.CrossEntropyLoss()

首先我们要了解交叉熵损失函数,torch.nn.CrossEntropyLoss()。

什么是熵?

熵是用来描述一个系统的混乱程度,通过交叉熵我们就能够确定预测数据与真是数据之间的相近程度。交叉熵越小,表示数据越接近真实样本。

(预测的概率就是我们的预测值的准确值)

torch.nn.NLLLoss() 

 torch.nn.NLLLoss输入是一个对数概率向量和一个目标标签,它与torch.nn.CrossEntropyLoss的关系可以描述为:

假设有张量x,先softmax(x)得到y,然后再log(y)得到z,然后我们已知标签b,则:

NLLLoss(z,b)=CrossEntropyLoss(x,b)

代码:

nllloss = nn.NLLLoss()

predict = torch.Tensor([[2, 3, 1],

[3, 7, 9]])

predict = torch.log(torch.softmax(predict, dim=-1))

label = torch.tensor([1, 2])

nllloss(predict, label)

运行结果:tensor(0.2684)

而我们用 torch.nn.CrossEntropyLoss

cross_loss = nn.CrossEntropyLoss()

predict = torch.Tensor([[2, 3, 1],

[3, 7, 9]])

label = torch.tensor([1, 2])

cross_loss(predict, label)

运行结果: tensor(0.2684)

enumerate() 函数

这是python的一个内置函数。

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

Python 2.3. 以上版本可用,2.6 添加 start 参数。

enumerate(sequence, [start=0])

sequence -- 一个序列、迭代器或其他支持迭代对象。

start -- 下标起始位置的值。

例如:

>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']

>>> list(enumerate(seasons))

[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]

>>> list(enumerate(seasons, start=1))       # 下标从 1 开始

[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

next() 函数

python的内置函数

next() 返回迭代器的下一个项目。

next() 函数要和生成迭代器的 iter() 函数一起使用。

返回值:返回下一个项目。

next(iterable[, default])

iterable -- 可迭代对象

default -- 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。

例如:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

# 首先获得Iterator对象:

it = iter([1, 2, 3, 4, 5])

# 循环:

while True:

try:

# 获得下一个值:

x = next(it)

print(x)

except StopIteration:

# 遇到StopIteration就退出循环

break

结果:

1

2

3

4

5

pytorch中.detach()

在 PyTorch 中,detach() 方法用于返回一个新的 Tensor,这个 Tensor 和原来的 Tensor 共享相同的内存空间,但是不会被计算图所追踪,也就是说它不会参与反向传播,不会影响到原有的计算图,这使得它成为处理中间结果的一种有效方式,通常在以下两种情况下使用:

第一:在计算图中间,需要截断反向传播的梯度计算时。例如,当计算某个 Tensor 的梯度时,我们希望在此处截断反向传播,而不是将梯度一直传递到计算图的顶部,从而减少计算量和内存占用。此时可以使用 detach() 方法将 Tensor 分离出来。

第二:在将 Tensor 从 GPU 上拷贝到 CPU 上时,由于 Tensor 默认是在 GPU 上存储的,所以直接进行拷贝可能会导致内存不一致的问题。此时可以使用 detach() 方法先将 Tensor 分离出来,然后再将分离出来的 Tensor 拷贝到 CPU 上。

torch.squeeze()

详情请看这篇博客深度学习之张量的处理(代码笔记)

torch.optim.SGD 

torch.optim.SGD 是 PyTorch 中用于实现随机梯度下降(Stochastic Gradient Descent,SGD)优化算法的类。SGD 是一种常用的优化算法。

原理部份可以看我的这篇博客:机器学习优化算法(深度学习)-CSDN博客

我们主要介绍一下常用的参数:

torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)

(图片内容来自网络,侵权必删) 

独热编码

就是如果是0-9这十个数,那我们就用[1,0,0,0,0,0,0,0,0,0]表示0,[0,1,0,0,0,0,0,0,0,0]表示1,等等

其余同理

代码实现

关于bp神经网络的原理,我们可以看这篇博客:深度学习之感知机,激活函数,梯度消失,BP神经网络-CSDN博客

我们接下来就只是讲解代码实现。

bp网络的搭建

#搭建bp神经网络

class BPNetwork(torch.nn.Module):

def __init__(self):

super(BPNetwork,self).__init__()

#我们的每张图片都是28*28也就是784个像素点

#第一个隐藏层

self.linear1=torch.nn.Linear(784,128)

#激活函数,这里选择Relu

self.relu1=torch.nn.ReLU()

#第二个隐藏层

self.linear2=torch.nn.Linear(128,64)

#激活函数

self.relu2=torch.nn.ReLU()

#第三个隐藏层:

self.linear3=torch.nn.Linear(64,32)

# 激活函数

self.relu3 = torch.nn.ReLU()

#输出层

self.linear4=torch.nn.Linear(32,10)

# 激活函数

self.softmax=torch.nn.LogSoftmax()

#前向传播

def forward(self,x):

#修改每一个批次的样本集尺寸,修改为64*784,因为我们的图片是28*28

x=x.reshape(x.shape[0],-1)

#前向传播

x=self.linear1(x)#784*128

x=self.relu1(x)

x=self.linear2(x)#128*64

x=self.relu2(x)

x=self.linear3(x)#64*32

x=self.relu3(x)

x=self.linear4(x)#输出层32*10

x=self.softmax(x)#最后输出的数值我们需要利用到独热编码的思想

#上面的这些都可以这几使用x=self.model(x)来代替,为什么能用它,我的理解是,我们继承的class moudle 然后对立面写好的模型框架进行定义,而这个方法就是可以直接调用我们定义好的神经网络

return x

(一些关键点都在注释上)

搭建这次的BP神经网络我的隐藏层有三层,分别是128,64,32个神经元,因为我们的图片是28*28=784得,我们需要把其展开成一维,所以第一层网络是784*128得,这样输入层中每一行代表一个样本(或者说一张图片得所有像素点),因为我们的每个神经元都有一个参数,第一层网络中每一列都是一个神经元对应的参数,所以最后就是n*784和784*128两个矩阵相乘,最后得到n*128得矩阵,以此类推,最后因为我们的输出要用到独热编码的思想,所以我们的输出层调整为10个神经元,或者说最后得线性网络是32*10。

建立我们的神经网络对象

#建立我们的神经网络对象

model=BPNetwork()

#定义损失函数

critimizer=torch.nn.NLLLoss()

#定义优化器

optimizer=torch.optim.SGD(model.parameters(),lr=0.003,momentum=0.9)

epochs=15#循环得轮数

#每轮抽取次数的和

a=0

loss_=[]

a_=[]

font = font_manager.FontProperties(fname="C:\\Users\\ASUS\\Desktop\\Fonts\\STZHONGS.TTF")

for i in range(epochs):

# 损失值参数

sumloss = 0

for imges,labels in trainload:

a+=1

#前向传播

output=model(imges)

#反向传播

loss=critimizer(output,labels)

loss.backward()

#参数更新

optimizer.step()

#梯度清零

optimizer.zero_grad()

#损失累加

sumloss+=loss.item()

loss_.append(sumloss)

a_.append(a)

print(f"第{i+1}轮的损失:{sumloss},抽取次数和:{a}")

plt.figure()

plt.plot(a_,loss_)

plt.title('损失值随着抽取总次数得变化情况:',fontproperties=font, fontsize=18)

plt.show()

注意看注释。

SGD还有损失函数等等上面的补充内容里面都有说明,这里不在多加阐述。

预测

#开始预测

example=enumerate(testLoad)#从测试集里面随机抽64份并且记录下来里面的内容和下标

batch_index,(imagess,labelss)=next(example)

# bath_index=0

# imagess=0

# labelss=0

# for i,j in example:

# bath_index=i

# (imagess, labelss)=j

fig=plt.figure()

for i in range(64):

pre=model(imagess[i])#预测

#第一张图片对应的pre得格式:

# print(pre)

# tensor([[-2.7053e+01, -1.1105e-03, -1.2767e+01, -1.1126e+01, -1.6005e+01,

# -2.0953e+01, -2.3342e+01, -6.8246e+00, -1.2127e+01, -1.6131e+01]],

# grad_fn= < LogSoftmaxBackward0 >)

#接下来我们要用到独热编码的思想,我们取最大的数,也就是最高的概率对应得下标,就相当于这个最高概率对应得独热编码里面的1,其他是0

pro = list(pre.detach().numpy()[0])

pre_label=pro.index(max(pro))

#print(pre_label)

(注意看注释)

我们实际上也可以不用next()我们可以直接用for循环比如这样。

import d2l.torch as d2l

import math

import torch

from torch.utils.data import DataLoader

import torchvision

from torchvision import transforms

from torch.utils.data import DataLoader

transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.5,0.5)])

traindata=torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集',train=True,download=True,transform=transform)#训练集60,000张用于训练

testdata=torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集',train=False,download=True,transform=transform)#测试集10,000张用于测试

#利用DataLoader加载数据集

trainload=DataLoader(dataset=traindata,shuffle=True,batch_size=64)

testLoad=DataLoader(dataset=testdata,shuffle=False,batch_size=64)

example=enumerate(testLoad)#从测试集里面随机抽64份并且记录下来里面的内容和下标

a=0

images=0

labelss=0

for i,j in example:

a+=1

index = i

(imagess, labelss) = j

print(imagess[0])

print('数据集中抽取的64份数据的纯数据部份的尺寸:',imagess.shape)

print(imagess[0].shape)

print(labelss[0])

print(labelss[0].shape)

if a==1:

break

这样得到的结果我们可以看到:

D:\Anaconda3\envs\pytorch\python.exe D:\learn_pytorch\prictice.py

tensor([[[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -0.3412,

0.4510, 0.2471, 0.1843, -0.5294, -0.7176, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, 0.7412,

0.9922, 0.9922, 0.9922, 0.9922, 0.8902, 0.5529, 0.5529,

0.5529, 0.5529, 0.5529, 0.5529, 0.5529, 0.5529, 0.3333,

-0.5922, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -0.4745,

-0.1059, -0.4353, -0.1059, 0.2784, 0.7804, 0.9922, 0.7647,

0.9922, 0.9922, 0.9922, 0.9608, 0.7961, 0.9922, 0.9922,

0.0980, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -0.8667, -0.4824, -0.8902,

-0.4745, -0.4745, -0.4745, -0.5373, -0.8353, 0.8510, 0.9922,

-0.1686, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -0.3490, 0.9843, 0.6392,

-0.8588, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -0.8275, 0.8275, 1.0000, -0.3490,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, 0.0118, 0.9922, 0.8667, -0.6549,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -0.5373, 0.9529, 0.9922, -0.5137, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, 0.0431, 0.9922, 0.4667, -0.9608, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -0.9294, 0.6078, 0.9451, -0.5451, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -0.0118, 0.9922, 0.4275, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-0.4118, 0.9686, 0.8824, -0.5529, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -0.8510,

0.7333, 0.9922, 0.3020, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -0.9765, 0.5922,

0.9922, 0.7176, -0.7255, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -0.7020, 0.9922,

0.9922, -0.3961, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -0.7569, 0.7569, 0.9922,

-0.0980, -0.9922, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, 0.0431, 0.9922, 0.9922,

-0.5922, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -0.5216, 0.8980, 0.9922, 0.9922,

-0.5922, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -0.0510, 0.9922, 0.9922, 0.7176,

-0.6863, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -0.0510, 0.9922, 0.6235, -0.8588,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000],

[-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000,

-1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000, -1.0000]]])

数据集中抽取的64份数据的纯数据部份的尺寸: torch.Size([64, 1, 28, 28])

torch.Size([1, 28, 28])

tensor(7)

torch.Size([])

进程已结束,退出代码0

 我们可以看到一张图片得数据格式(这里面是已经归一化处理过的),因为我们的手写字体识别是单通道的灰度图,所以size是[1,28,28],这里很正确,对于彩色图三通道得来说,会有些不一样。

完整代码

import matplotlib.pyplot as plt

from matplotlib import font_manager

print('BP识别MNIST任务说明---------------------')

import torch

from torch.utils.data import DataLoader

import torchvision

from torchvision import transforms

#导入数据集并且进行数据处理

transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.5,0.5)])

traindata=torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集',train=True,download=True,transform=transform)#训练集60,000张用于训练

testdata=torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集',train=False,download=True,transform=transform)#测试集10,000张用于测试

#利用DataLoader加载数据集

trainload=DataLoader(dataset=traindata,shuffle=True,batch_size=64)

testLoad=DataLoader(dataset=testdata,shuffle=False,batch_size=64)

#搭建bp神经网络

class BPNetwork(torch.nn.Module):

def __init__(self):

super(BPNetwork,self).__init__()

#我们的每张图片都是28*28也就是784个像素点

#第一个隐藏层

self.linear1=torch.nn.Linear(784,128)

#激活函数,这里选择Relu

self.relu1=torch.nn.ReLU()

#第二个隐藏层

self.linear2=torch.nn.Linear(128,64)

#激活函数

self.relu2=torch.nn.ReLU()

#第三个隐藏层:

self.linear3=torch.nn.Linear(64,32)

# 激活函数

self.relu3 = torch.nn.ReLU()

#输出层

self.linear4=torch.nn.Linear(32,10)

# 激活函数

self.softmax=torch.nn.LogSoftmax()

#前向传播

def forward(self,x):

#修改每一个批次的样本集尺寸,修改为64*784,因为我们的图片是28*28

x=x.reshape(x.shape[0],-1)

#前向传播

x=self.linear1(x)#784*128

x=self.relu1(x)

x=self.linear2(x)#128*64

x=self.relu2(x)

x=self.linear3(x)#64*32

x=self.relu3(x)

x=self.linear4(x)#输出层32*10

x=self.softmax(x)#最后输出的数值我们需要利用到独热编码的思想

#上面的这些都可以这几使用x=self.model(x)来代替,为什么能用它,我的理解是,我们继承的class moudle 然后对立面写好的模型框架进行定义,而这个方法就是可以直接调用我们定义好的神经网络

return x

#建立我们的神经网络对象

model=BPNetwork()

#定义损失函数

critimizer=torch.nn.NLLLoss()

#定义优化器

optimizer=torch.optim.SGD(model.parameters(),lr=0.003,momentum=0.9)

epochs=15

#每轮抽取次数的和

a=0

loss_=[]

a_=[]

font = font_manager.FontProperties(fname="C:\\Users\\ASUS\\Desktop\\Fonts\\STZHONGS.TTF")

for i in range(epochs):

# 损失值参数

sumloss = 0

for imges,labels in trainload:

a+=1

#前向传播

output=model(imges)

#反向传播

loss=critimizer(output,labels)

loss.backward()

#参数更新

optimizer.step()

#梯度清零

optimizer.zero_grad()

#损失累加

sumloss+=loss.item()

loss_.append(sumloss)

a_.append(a)

print(f"第{i+1}轮的损失:{sumloss},抽取次数和:{a}")

plt.figure()

plt.plot(a_,loss_)

plt.title('损失值随着抽取总次数得变化情况:',fontproperties=font, fontsize=18)

plt.show()

#开始预测

example=enumerate(testLoad)#从测试集里面随机抽64份并且记录下来里面的内容和下标

batch_index,(imagess,labelss)=next(example)

# bath_index=0

# imagess=0

# labelss=0

# for i,j in example:

# bath_index=i

# (imagess, labelss)=j

fig=plt.figure()

for i in range(64):

pre=model(imagess[i])#预测

#第一张图片对应的pre得格式:

# print(pre)

# tensor([[-2.7053e+01, -1.1105e-03, -1.2767e+01, -1.1126e+01, -1.6005e+01,

# -2.0953e+01, -2.3342e+01, -6.8246e+00, -1.2127e+01, -1.6131e+01]],

# grad_fn= < LogSoftmaxBackward0 >)

#接下来我们要用到独热编码的思想,我们取最大的数,也就是最高的概率对应得下标,就相当于这个最高概率对应得独热编码里面的1,其他是0

pro = list(pre.detach().numpy()[0])

pre_label=pro.index(max(pro))

#print(pre_label)

#图像显示

img=torch.squeeze(imagess[i]).numpy()

plt.subplot(8,8,i+1)

plt.tight_layout()

plt.imshow(img,cmap='gray',interpolation='none')

plt.title(f"预测值:{pre_label}",fontproperties=font, fontsize=9)

plt.xticks([])

plt.yticks([])

plt.show()

结果及其图像显示

D:\Anaconda3\envs\pytorch\python.exe D:\learn_pytorch\学习过程\第四周的代码\代码一:BP识别MNIST任务说明.py

BP识别MNIST任务说明---------------------

D:\learn_pytorch\学习过程\第四周的代码\代码一:BP识别MNIST任务说明.py:49: UserWarning: Implicit dimension choice for log_softmax has been deprecated. Change the call to include dim=X as an argument.

x=self.softmax(x)#最后输出的数值我们需要利用到独热编码的思想

第1轮的损失:815.2986399680376,抽取次数和:938

第2轮的损失:281.06414164602757,抽取次数和:1876

第3轮的损失:205.76270231604576,抽取次数和:2814

第4轮的损失:159.9431014917791,抽取次数和:3752

第5轮的损失:131.47989665158093,抽取次数和:4690

第6轮的损失:109.93954652175307,抽取次数和:5628

第7轮的损失:95.26143277343363,抽取次数和:6566

第8轮的损失:85.17149402853101,抽取次数和:7504

第9轮的损失:75.1239058477804,抽取次数和:8442

第10轮的损失:68.23363681556657,抽取次数和:9380

第11轮的损失:60.05981844640337,抽取次数和:10318

第12轮的损失:54.82598690944724,抽取次数和:11256

第13轮的损失:51.70861432119273,抽取次数和:12194

第14轮的损失:46.613128249999136,抽取次数和:13132

第15轮的损失:43.05269447225146,抽取次数和:14070

进程已结束,退出代码0

 可以看到,经过15轮得训练后,我们基本上已经完全能识别出来了。

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。

大家都在找:

深度学习:深度学习策略

神经网络:神经网络控制

人工智能:人工智能之父