练习6-自定义层与自定义块(李沐代码解析)

沐神文章与代码链接:
https://zh-v2.d2l.ai/chapter_deep-learning-computation/model-construction.html#id3

1.块是什么:

一个“块”可能指的是一系列层的组合

2.块的功能:

1. 将输入数据作为其前向传播函数的参数。
    
2. 通过前向传播函数来生成输出。请注意,输出的形状可能与输入的形状不同。例如,我们上面模型中的第一个全连接的层接收任意维的输入,但是返回一个维度256的输出。
    
3. 计算其输出关于输入的梯度,可通过其反向传播函数进行访问。通常这是自动发生的。
    
4. 存储和访问前向传播计算所需的参数。
    
5. 根据需要初始化模型参数

3.定义块的步骤:

1.定义构造函数---初始化各种层和参数
2.定义前向传播函数---神经网络通过前向传播函数来定义数据如何在网络中流动。

代码解析1:

class MLP(nn.Module):
    # 用模型参数声明层。这里,我们声明两个全连接的层
    def __init__(self):
        # 调用MLP的父类Module的构造函数来执行必要的初始化。
        # 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
        super().__init__()
        self.hidden = nn.Linear(20, 256)  # 隐藏层
        self.out = nn.Linear(256, 10)  # 输出层

    # 定义模型的前向传播,即如何根据输入X返回所需的模型输出
    def forward(self, X):
        # 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。
        return self.out(F.relu(self.hidden(X)))

X=torch.rand(1,20)
net = MLP()
net(X)
net=MLP()时
1.启动__init__函数
	1.1 启动super().__init__(),负责基础的初始化
	1.2 定义两个层 self.hidden self.out



net(X)时
2.调用forward函数
	将输入X传给self.hidden
	将self.hidden的输出传给self.out

注意:
1.F.relu()=torch.nn.functional.relu()
2.在定义两个层是就对层的参数进行了默认的初始化策略 (如果想要更改初始化策略需要,新创建一个初始化函数然后应用 如下)

#使用Xavier均匀初始化方法初始化权重,使用零初始化方法初始化偏置
def init_weights(m): 
		if type(m) == nn.Linear: 
			init.xavier_uniform_(m.weight) 
			init.zeros_(m.bias) # 应用初始化函数

net.apply(init_weights)

代码解析2:

class FixedHiddenMLP(nn.Module):
    def __init__(self):
        super().__init__()
        # 不计算梯度的随机权重参数。因此其在训练期间保持不变
        self.rand_weight = torch.rand((20, 20), requires_grad=False)
        self.linear = nn.Linear(20, 20)

    def forward(self, X):
        X = self.linear(X)
        # 使用创建的常量参数以及relu和mm函数
        X = F.relu(torch.mm(X, self.rand_weight) + 1)
        # 复用全连接层。这相当于两个全连接层共享参数
        X = self.linear(X)
        # 控制流
        while X.abs().sum() > 1:
            X /= 2
        return X.sum()

X=torch.rand(1,20)
net = FixedHiddenMLP()
net(X)
如何理解:定义块的目的:便是可以在多个层之间加上灵活的处理
__init__
	1.self.rand_weight = torch.rand((20, 20), requires_grad=False)创建了一个20x20的矩阵,且做了随机初始化之后,规定该矩阵的值不会变化
	2.定义了线性层

__forward__
	通过定义块定义了类似于(但下面的代码肯定是不可行的)
		X=Sequential(Linear(20,20),F.relu(torch.mm(X, self.rand_weight) + 1),Linear(20,20))
		
		while X.abs().sum() >1:
			x/=2
		retun X.sum()



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值