Pytorch神经网络基础

学习视频链接:【16 PyTorch 神经网络基础【动手学深度学习v2】】 https://www.bilibili.com/video/BV1AK4y1P7vs/?p=5&share_source=copy_web&vd_source=7d0117001ba4a138b2924a4a9803d9f5

学习笔记记录了P2-P4的代码和注释

P2:参数管理

P3:自定义层

P4:读写文件

#参数管理
#我们首先关注具有单隐藏层的多层感知机
import torch
from torch import nn

net = nn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,1))
x = torch.rand(size=(2,4)) #torch在定义层的时候就初始化了
torch.save(net.state_dict(),'mlp.params')#将模型的参数存储为一个叫做'mlp.params'的文件
net(x)
#参数访问
print(net[2].state_dict()) #查看第3层的参数
print(type(net[2].bias))#打印网络net中第三个子模块的偏置项(bias)的类型。这里的 .bias 是指代该层的偏置项参数。这行代码会输出偏置项参数的类型,通常是 torch.nn.Parameter 类型
print(net[2].bias.data)#打印了神经网络 net 中第三个子模块的偏置项参数的数值。.data 属性允许你直接访问参数张量的数值部分。这行代码会输出第三层的偏置项参数的数值
net[2].weight.grad == None#这行代码是在检查第三层的权重参数的梯度是否为 None。在 PyTorch 中,当你执行反向传播算法进行梯度计算之前,模型的参数的梯度值通常会被置为 None。这行代码的返回结果会是一个布尔值,如果权重参数的梯度为 None,则返回 True,否则返回 False

#一次性访问所有参数,包括参数名称、形状和数值
print(*[(name,param.shape) for name,param in net[0].named_parameters()]) #使用列表推导式,遍历了神经网络 net 中的第一个子模块(即第一个层),并打印了每个参数的名称和对应的形状
print(*[(name,param.shape) for name,param in net.named_parameters()]) #遍历了整个神经网络 net 中的所有子模块(所有层),并打印了每个参数的名称和对应的形状
#*号用于解包列表,将列表中的每个元组作为单独的参数传递给 print 函数
net.state_dict()['2.bias'].data#调用了 state_dict() 方法,获取了整个神经网络 net 的状态字典。然后使用索引操作符 [] 从状态字典中取出了第三个子模块(即第三层)的偏置项参数(bias)的张量数据部分。.data 属性用于获取张量的数值部分

'''
named_parameters(): 这是一个模型对象的方法,它返回一个迭代器,可以遍历模型中所有具有参数的层。
返回的迭代器产生的每个元素都是一个元组,其中包含了参数的名称和对应的参数tensor。
state_dict(): 这是一个模型对象的方法,用于获取模型的状态字典。状态字典是一个 Python 字典对象,其中包含了模型的所有可学习参数及其对应的数值。
迭代器(Iterator)是 Python 中一种对象,它可以在容器(如列表、元组、字典等)或者类似容器的对象上进行迭代(循环遍历)。
在 Python 中,迭代器通常使用 iter() 函数创建,然后使用 next() 函数来逐个访问容器中的元素

'''
#内置初始化
def init_normal(m):#定义了一个名为 init_normal 的函数,该函数接受一个参数 m
    if type(m) == nn.Linear: #检查参数 m 是否是 nn.Linear 类型的实例。nn.Linear 是 PyTorch 中表示线性层的类
        nn.init.normal_(m.weight,mean=0,std=0.01) #初始化函数 nn.init.normal_(),它用正态分布初始化权重。具体地,它初始化了参数 m 的权重 m.weight,并指定了正态分布的均值为 0,标准差为 0.01
        nn.init.zeros_(m.bias) #初始化函数 nn.init.zeros_(),它将参数 m 的偏置项初始化为零

net.apply(init_normal) #apply() 方法,该方法用于将一个函数应用到模型的每个子模块上。在这里,它将 init_normal 函数应用到神经网络 net 的每个子模块上,对每个线性层的权重和偏置项进行初始化。
net[0].weight.data[0],net[0].bias.data[0] #访问了神经网络 net 中第一个子模块(即第一个线性层)的权重和偏置项的第一个元素。
# .weight 和 .bias 属性用于访问线性层的权重和偏置项,而 .data 属性用于访问参数张量的数值部分。这行代码会返回第一个线性层的第一个权重和偏置项的值
#自定义初始化
def my_init(m):
    if type(m) == nn.Linear:
        print(
            "Init",
            *[(name,param.shape) for name,param in m.named_parameters()][0] #打印初始化的信息。它首先使用列表推导式 [(name,param.shape) for name,param in m.named_parameters()] 遍历 m 的所有参数,并将参数名称和形状组成一个列表。然后取列表中的第一个元素,这个元素是一个元组,包含了第一个参数的名称和形状。最后,使用 print 函数打印出 "Init" 字符串以及第一个参数的名称和形状
            nn.init.uniform_(m.weight,-10,10) #PyTorch 的初始化函数 nn.init.uniform_(),它用均匀分布初始化权重。具体地,它将 m 的权重 m.weight 初始化为在 [-10, 10] 范围内的均匀分布
            m.weight.data *= m.weight.data.abs() >=5 #对初始化后的权重进行了一个额外的操作。它将权重的绝对值大于等于 5 的部分保留,而小于 5 的部分置零。这样可以确保权重的初始值分布在一个较大的范围内,有助于模型的训练
            #*= 是一个复合赋值运算符,表示将左边的操作数与右边的操作数相乘,并将结果赋值给左边的操作数。在这个上下文中,m.weight.data 是一个张量,m.weight.data.abs() >= 5 也是一个张量,它包含了对权重绝对值取大于等于 5 的布尔值。m.weight.data.abs() >= 5,这将产生一个布尔张量,用于指示哪些元素的绝对值大于等于 5。 PyTorch 支持按元素的张量运算,相乘的结果将保留绝对值大于等于 5 的部分,而小于 5 的部分将变成零
        )

net.apply(my_init) #使用 apply() 方法,将 my_init 函数应用到神经网络 net 的每个子模块上,对每个线性层的权重进行初始化
net[0].weight[:2] #访问了神经网络 net 中第一个子模块(即第一个线性层)的权重的前两个元素。
    # .weight 属性用于访问线性层的权重,[:2] 表示取前两个元素。这行代码会返回第一个线性层的权重的前两个元素

#暴力参数赋值初始化
net[0].weight.data[:] +=1 #将神经网络 net 中第一个子模块(即第一个线性层)的权重张量中的每个元素都加上 1。
    # net[0].weight.data 表示获取第一个子模块的权重张量,[:] 代表取出张量的所有元素,然后 += 1 表示对取出的所有元素都加上 1
net[0].weight.data[0,0] = 42 #神经网络 net 中第一个子模块(即第一个线性层)的权重张量中第一个元素的第一个值(即第一个权重)设置为 42。
    # net[0].weight.data[0, 0] 表示获取权重张量中第一行第一列的元素,并将其设置为 42
net[0].weight.data[0] #获取神经网络 net 中第一个子模块(即第一个线性层)的权重张量的第一行。
    # net[0].weight.data[0] 表示获取权重张量的第一行,即获取第一个子模块的权重中的第一行权重

#参数绑定
shared = nn.Linear(8,8)
net = nn.Sequential(nn.Linear(4,8),nn.ReLU(),shared,nn.ReLU(),shared,
                    nn.ReLU(),nn.Linear(8,1))

net(x)
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0,0] = 100
print(net[2].weight.data[0]) ==net[4].weight.data[0]

#自定义层,构造一个没有任何参数的自定义层
import torch
from torch import nn
import torch.nn.functional as F

class CentereLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self,X):
        return X ~ X.mean()

layer = CentereLayer()
layer(torch.FloatTensor([1,2,3,4,5]))

#将层作为组件并构建更复杂的模型中
net = nn.Sequential(nn.Linear(8,128),CentereLayer())
#定义了一个神经网络 net,它是一个序列模型(nn.Sequential)。该序列模型由两个层组成,
    # 第一个层是一个线性层 nn.Linear(8, 128),它将输入维度为 8 的数据映射到输出维度为 128 的数据,第二个层是 CentereLayer()
Y = net(torch.rand(4,8))
Y.mean() #计算了输出结果 Y 的均值。 Y.mean() 调用了 PyTorch 的 mean() 方法,用于计算张量中所有元素的平均值。
    # 这里计算的是神经网络对输入数据的预测结果的均值,即神经网络在这个数据集上的平均输出

#带参数的图层
class MyLinear(nn.Module):
    def __init__(self,in_units,units):#MyLinear 类的构造函数,它接受两个参数 in_units 和 units,分别表示输入特征的数量和输出特征的数量
        super().__init__()
        self.weight = nn.Parameter(torch.randn(in_units,units))#创建了一个名为 weight 的参数,并将其添加到 MyLinear 类中。参数的形状是 (in_units, units),使用 torch.randn() 函数生成随机张量作为参数的初始值,并将其封装为 nn.Parameter 类型。
        # 这样做的目的是将参数标记为模型的可学习参数,从而在模型训练过程中可以自动更新参数的值
        self.bias = nn.Parameter(torch.randn(units,))#创建了一个名为 bias 的参数,并将其添加到 MyLinear 类中。参数的形状是 (units,),表示一个一维向量,同样使用 torch.randn() 函数生成随机张量作为参数的初始值,并将其封装为 nn.Parameter 类型

    def forward(self,X):
        linear = torch.matmul(X,self.weight.data) + self.bias.data #执行了线性变换操作,首先使用 torch.matmul() 函数计算输入张量 X 与权重参数 self.weight 的矩阵乘积,然后加上偏置参数 self.bias。.data 属性用于获取参数张量的数值部分
        return F.relu(linear)

dense = MyLinear(5,3)
dense.weight

#使用自定义层直接执行正向传播计算
dense(torch.rand(2,5))

#使用自定义层构建模型
net = nn.Sequential(MyLinear(64,8),MyLinear(8,1))
net(torch.rand(2,64))

#读写文件
#加载和保存张量
import torch
from torch import nn
from torch.nn import functional as F

x=torch.arange(4)
torch.save(x,'x-file') #存储

x2=torch.load('x-file') #加载
x2

#存储一个张量列表,然后把他们读回内存
y=torch.zero(4)
torch.save([x,y],'x-files')
x2,y2=torch.load('x-files')
(x2,y2)
#写入或读取从字符串映射到张量的字典
mydict=c{'x':x,'y':y}
torch.save(mydict,'mydict')
mydict2=torch.load('mydict')
mydict2

#
torch.save(net.state_dict(), 'mlp.params')  # 将模型的参数存储为一个叫做'mlp.params'的文件
#实例化了原始多层感知机模型的一个备份。直接读取文件中存储的参数
clone=MLP() #声明一下
clone.load_state_dict(torch.load("mlp.params"))
clone.eval()

Y_clone==clone(X)
Y_clone==Y

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值