深度学习笔记1:实现第一个深度神经网络的正向传播
Torch架构图

学习的内容实在torch.nn这个模块下,所以就学习使用封装好的torch.nn模块来实现第一个深度神经网络的正向传播。
数据集设计
| 数据量 | 特征数 | 标签量 |
|---|---|---|
| 500 | 20 | 3 |
神经网络设计
| 网络层次 | 神经元个数 | 所在层激活函数 |
|---|---|---|
| 输入层 | 20 | - |
| 第一层 | 13 | Relu |
| 第二层 | 8 | sigmoid |
| 第三层(输出层) | 3 | softmax |
其中,输入层神经元个数由数据集特征数决定,经过一个三层神经网络,最后输出一个三分类。
代码设计
导包
import torch
import torch.nn as nn
from torch.nn import functional as F
定义数据集
torch.random.manual_seed(420)
X=torch.rand((500,20),dtype=torch.float32) #X是数据集,一共500行20列,500个样本20个特征
y=torch.randint(low=0,high=3,size=(500,1),dtype=torch.float32)
#y是标签,从0,1,2三个数值里面选一个,大小是500行1列
使用随机数种子,随机生成一组数据,便于后续复现过程。


定义神经网络架构
class Model(nn.Module):
def __init__(self,in_features=10,out_features=2):
"""
in_features:输入层上的神经元数目
out_features:输出层上的神经元数目
"""
super(Model,self).__init__()
self.linear1 = nn.Linear(in_features,13,bias=True) #隐藏层第一层
self.linear2 = nn.Linear(13,8,bias=True)#隐藏层第二层
self.output = nn.Linear(8,out_features,bias=True)#隐藏层第三层,输出层
def forward(self,x):#神经网络的前向传播
z1 = self.linear1(x)
sigma1=torch.relu(z1)
z2 = self.linear2(sigma1)
sigma2 = torch.sigmoid(z2)
z3 = self.output(sigma2)
sigma3 = F.softmax(z3,dim=1)
return sigma3
通过定义一个Model类,用它来继承nn.Module类来完成神经网络的架构设计。
定义解释
① __init__是定义类本身,只要这个类被实例化,那一瞬间就会被执行。
super()参数解释:super(请查找目前这个类的父亲,请使用找到的父类来替换目前的类)
super()方法必须调用,否则无法使用使用 PyTorch 的核心功能。
输入层不用写,直接定义两个隐藏层,和最后的输出层,正好三层神经网络。
nn.Linear()参数解释:nn.Linear(两层之间左边输入神经元的个数,两层之间右边接收神经元的个数,是否具有偏置项bias)
nn.Linear()是 PyTorch 的线性层(全连接层),功能是计算y = x·W + b(W为权重矩阵,b为偏置项)。
②forward,神经网络的前向传播,定义整个神经网络的前进过程,init被执行完毕后,就可以被调用使用。
数据流动步骤
1.输入X,形状(500,20),传入linear1计算得到z1,从输入层传到了第一层
2.在第一层使用Relu函数对z1进行处理,得到sigma1,其将作为去往下一层的输入
3.sigma1传入linear2计算得到z2,从第一层传到了第二层
4.在第二层使用sigmoid函数对z2进行处理,得到sigma2,将其作为去往下一层的输入
5.sigma2传入output计算得到z3,从第二层传到了输出层
6.在输出层使用softmax函数对ze进行处理,得到sigma3,作为神经网络的总输出
实例化神经网络
input_ = X.shape[1] #特征的数目
output_ = len(y.unique()) #分类的数目
shape[1]获取数据集的列数,即数据集的特征总数
y.unique()获取标签所有不同取值的集合,即三个分类:0,1,2;使用len()方法获取集合总数3。

torch.manual_seed(420)
net = Model(in_features=input_, out_features=output_)
代码执行的一瞬间,net被创建,并且类中的linear层就已经自动定义好了随机的w和b,需要随机数种子方便复现。
#前向传播
net.forward(X)
调用forward()方法,传入X数据集,运行神经网络。
输出结果

输出结果是一个(500,3)形状的矩阵,每一行代表一个样本,每一列代表这个样本所属类别的概率。
加餐
对权重矩阵的理解

输入的数据集是X(500,20),输入到神经网络后,会自动进行一次转置,成(20,500)的结构,此时才可以和线性层上的权重矩阵w进行相乘,获得正确的与下一层神经元对应的结构
第一个线性层的权重矩阵(13,20),对应输入层20个神经元,第一层13个神经元
第二个线性层的权重矩阵(8,13),对应第一层13个神经元,第二层8个神经元
第三个线性层的权重矩阵(3,8),对应第二层8个神经元,输出层3个神经元
正好是相反的,所以权重矩阵才这么个样子
在最后获得(3,500)的结构后,最后输出时会重新进行一次转置,变为(500,3)的结构输出结果
对偏置项的理解

对继承方法的理解
通过使用super函数,神经网络模型从nn.Module那里继承了很多有用的属性和方法。首先, 如果不加super函数,神经网络的向前传播是无法运行的。nn.Module类的定义代码有一千多行,其__init__函数中有许多复杂的内容需要被继承,因此super函数 一定不能漏下。
继承的有用的方法:
#属性的继承
net.training #是否用于训练
#方法的继承
net.cuda() #网络转移到gpu上运行
net.cpu() #网络转移到cpu上运行
net.apply() #对__init__中的所有对象(全部层)都执行同样的操作
net.parameters() #一个迭代器,可以通过循环的方式查看里面究竟是什么内容
for param in net.parameters():
print(param) #可以查看每一层的权重矩阵,偏置都是什么之类的
总结
再接再厉,冲鸭!
更多推荐


所有评论(0)