欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 从PyTorch官方的一篇教程说开去(5 - 神经网络 torch.nn)

从PyTorch官方的一篇教程说开去(5 - 神经网络 torch.nn)

2025/1/19 12:56:02 来源:https://blog.csdn.net/jomoly/article/details/140808392  浏览:    关键词:从PyTorch官方的一篇教程说开去(5 - 神经网络 torch.nn)

神经网络长啥样?有没有四只眼睛八条腿?

借图镇楼 - 

真的是非常经典,可以给下面的解释省掉很多力气。

分3个维度阐述 - 

1)输入数据集。假如你自己去微调一下大模型就知道,最开始的一步就是要准备(足够大的)数据集,比如百度就要求1kw条+的数据集,否则就不给你训练。PyTorch官方的数据集是用的著名的FashionMNIST,这是一个由许多28pixel * 28pixel的黑白像素组成的图片(img),类似于windows中的缩略图,每一个图片有标记(label),以及序号(idx)。

感兴趣的您也可以自行下载,下载来的是压缩格式.gz,里面图片是用PIL格式存储的单一二进制文件。如果想看看这些黑白缩略图长啥样呢,可以下载和渲染看看 - 

import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plttraining_data = datasets.FashionMNIST(root="drive/MyDrive/",train=True,download=True,transform=ToTensor()
)test_data = datasets.FashionMNIST(root="drive/MyDrive/",train=False,download=True,transform=ToTensor()
)

labels_map = {0: "T-Shirt",1: "Trouser",2: "Pullover",3: "Dress",4: "Coat",5: "Sandal",6: "Shirt",7: "Sneaker",8: "Bag",9: "Ankle Boot",
}
figure = plt.figure(figsize=(8, 8))
cols, rows = 3, 3
for i in range(1, cols * rows + 1):sample_idx = torch.randint(len(training_data), size=(1,)).item()print(sample_idx)img, label = training_data[sample_idx]figure.add_subplot(rows, cols, i)plt.title(labels_map[label])plt.axis("off")plt.imshow(img.squeeze(), cmap="gray")
plt.show()

2)输入有了。对于以上数据集,那就是一大堆784的数组或者列表。你需要把这个转化为1x784的tensor张量或者矢量或者向量,被称为flatten层,也就是把所有信息一维化或者叫扁平化。tensor这个词我们回头专门讨论一下,现在理解为多维数组就好。

那接下来整几层网络?分别干啥用?每一层多少个神经元?最后的输出咋整?

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transformsclass NeuralNetwork(nn.Module):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.linear_relu_stack = nn.Sequential(nn.Linear(28*28, 512), nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),)def forward(self, x):x = self.flatten(x)logits = self.linear_relu_stack(x)return logitsy=nn.Linear(28*28, 512)
print(y,"\n")
z=nn.ReLU(y)
print(z,"\n")

以上是官方的代码,初始化第二层用了512,这个用来存储输出的特征数量,那么784个数用512个特征是否足够表达呢?会不会欠拟合or过拟合呢?这个就完全是经验值了,或者说,要根据你特定的场景或者模型来跑跑看了。反正本例中,每个输入图像通过这个层后,会被转换成一个包含512个数值的向量。中间的隐藏层,是为了方便把输入过渡到输出,你把数字换成1024也完全没有毛病(有可能你的显卡会对你提出抗议,给你穿个小鞋啥的)

本例的输出是为了统计图像的类别,类别一共有10类,从0-T-shirt到9-踝靴,所以输出用10位来表达足够,这里采用了一种被成为one-hot编码的常用的数据表示方法,One-hot编码将分类数据表示为二进制(0和1)的格式,其中每个类别由一个唯一的二进制向量表示,该向量的长度等于类别的总数。例如,假设我们有一个包含三个可能类别的数据集:A、B和C。我们可以用以下one-hot编码表示它们:

  • 类别 A: [1, 0, 0]
  • 类别 B: [0, 1, 0]
  • 类别 C: [0, 0, 1]

3)综上,我们根据输入输出的形式,设计了一个4层(线性化+输入层,隐藏中间层1,隐藏中间层2,输出层)。现在问题来了,这个稚嫩的神经网络怎么干活呢?它怎么不断的学习和奖惩,从而准确的看到个图就报出类别名呢?

因为用了torch库,所以一些细节在代码中被隐藏了。

比如,为了把784个像素和512个特征值对应起来,其实隐含生成了一个权重矩阵和偏置向量。权重是一个矩阵,其行数等于输出特征数(512),列数等于输入特征数(784)。偏置是一个长度为输出特征数(512)的向量。

这个就和上一章节中我们讨论过的玩游戏的AI的脑子对应上了。我们需要初始化权重矩阵(全0或者全1),和偏置向量(从0或者1开始)。然后使用贪婪算法和梯度下降算法,不断的迭代优化。

呃,还漏了一点,激活函数ReLU(),这个是为了让我们的初始化和迭代过程更加平滑一点,避免0或者1产生一些诸如“死亡神经元”之类的算法缺陷(即当输入为负时,梯度为零,导致部分神经元停止更新。)。激活函数有很多种,默认的是f(x) = max(0, x),也就是在x大于0时直接输出x,小于0时输出0。它简单且计算效率高,是当前最流行的激活函数之一,尤其适用于隐藏层。其实可以选择的激活函数还有很多,比如Tanh,Exponential,Sigmoid等等。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com