尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

一只菜鸟学机器学习的日记:入门深度学习计算

一只菜鸟学机器学习的日记:入门深度学习计算
📅 发布时间:2026/6/20 0:28:45
本文浅谈了层与块、简单参数管理、延迟初始化

本文以作者阅读《Dive into Deep Learning》为线索,融合串联了自身理解感悟、原始论文、优秀文章等。如有无意侵权,请联系本人删除。

深度学习计算

看看基础概念:层与块

显然,一个线性模型只会有一个输出:

\[Input \xrightarrow{一组参数}标量输出 \]

我们通过更新参数,优化某些目标函数,如loss

那么复杂模型、多个输出应该如何处理呢?
我们引入块,可以理解成 class,以便将多个层结合成块。
每个块:

  • 有前向传播函数
  • 有反向传播函数
  • 储存必须的参数

参数管理

以此为例,

net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))

这是单隐藏层的MLP

我们可以嵌套多个block :

def block1():return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),nn.Linear(8, 4), nn.ReLU())
def block2():net = nn.Sequential()for i in range(4):net.add_module(f'block {i}', block1())return net
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))

那么这里 rgnet 的参数就是

Sequential((0): Sequential((block 0): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 1): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 2): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 3): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU()))(1): Linear(in_features=4, out_features=1, bias=True)
)

那么很显然,这是一个嵌套的大 Sequential
所以可以当成一个3维张量:
rgnet[0][3][3]
这就是最大索引
下面是简单的初始化:

def init_normal(m):if type(m) == nn.Linear:nn.init.normal_(m.weight, mean=0, std=0.01)nn.init.zeros_(m.bias)
net.apply(init_normal)

只用了自带的normal初始化,\(\text{weight}\sim\mathcal{N}(0,0.01)\),并设置\(\text{bias}=0\)

为了多层间共享参数,我们可以设置一个稠密层,有点像MySQL(雾)中的多表共用主键。

shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),shared, nn.ReLU(),shared, nn.ReLU(),nn.Linear(8, 1))

这样共享了一个稠密层shared,这就意味着net[2].weight和net[4].weight是完全等价的。这里的等价意味着不仅初始值一样,过程中修改任何一个参数,两个都会变动,即对象等价。至于它的梯度,是net[2]和net[4],即第3层和第5层梯度之和:

\[\frac{\partial \mathcal{L}}{\partial W_{shared}} = \sum_{i=1}^{n} \frac{\partial \mathcal{L}}{\partial W_i} \]

其中 \(n\) 是共享该权重的层数。
以上文代码为例:
前向传播:

\[\begin{align*} h^{(1)} &= W_1 x + b_1 \\ a^{(1)} &= \text{ReLU}(h^{(1)}) \\ h^{(2)} &= W_{\text{shared}} a^{(1)} + b_{\text{shared}} \\ a^{(2)} &= \text{ReLU}(h^{(2)}) \\ h^{(3)} &= W_{\text{shared}} a^{(2)} + b_{\text{shared}} \\ a^{(3)} &= \text{ReLU}(h^{(3)}) \\ y &= W_{\text{out}} a^{(3)} + b_{\text{out}} \end{align*} \]

反向传播:

\[\begin{split} &对于共享参数 W_{\text{shared}},梯度来自两条路径:\\&\frac{\partial \mathcal{L}}{\partial W_{\text{shared}}} = \underbrace{\frac{\partial \mathcal{L}}{\partial h^{(3)}} \cdot \frac{\partial h^{(3)}}{\partial W_{\text{shared}}}}_{\text{(3)}} + \underbrace{\frac{\partial \mathcal{L}}{\partial h^{(2)}} \cdot \frac{\partial h^{(2)}}{\partial W_{\text{shared}}}}_{\text{(2)}} \end{split} \]

因此

id(net[2].weight) == id(net[4].weight)

返回为True

延迟初始化

我们很难在编写MLP的时候就能确认输入维度,那不妨在第一次模型传递时再初始化参数。
此外,如果模型的参数太多,为了防止构建时太占内存,我们可以现场分配。
对于Pytorch,我们使用LazyLinear以实现惰性初始化参数。

class LazyLinear(nn.Module):def __init__(self):super().__init__()self.linear = Noneself.net = nn.Sequential(nn.ReLU(),nn.Linear(32, 10))def forward(self, data):if self.linear is None:self.linear = nn.Linear(in_features=data.shape[-1],out_features=32)return self.net(self.linear(data))

\[输入(5, 20)\xrightarrow{\text{self.linear}}(5, 30)\xrightarrow{\text{nn.ReLU}}(5, 30)\xrightarrow{\text{nn.Linear}}(5, 10) \]

避坑点:如果你试图

self.net = nn.Sequential(self.linear, nn.ReLU(),nn.Linear(32, 10))

,而后直接调用self.net(data),有很大问题:

  • 初始化时是None,不是nn.Module的子类模块,无法会报错
  • 如果通过一些方法初始化成功,forward中更新self.linear时Sequential里面的不会更新

你可以直接调用pytorch的LazyLinear:

self.linear = nn.LazyLinear(out_features = 10)

注:延后初始化的变量或层,在第一次运行后,一般来说,不能再改变其形状

此外,这也是一种延后初始化,是合法的:

net = nn.Sequential(nn.Linear(20, 256), nn.ReLU(),nn.LazyLinear(128), nn.ReLU(),nn.LazyLinear(10)
)

我们用一个例题结束这一小节:
\(设计一个接受输入并计算张量降维的层,它返回\space y_k = \sum_{i, j} W_{ijk} x_i x_j\)
我最开始理解为简单的张量求和降维(显然不对)

class ReduceDim(nn.Module):def __init__(self):super().__init__()def forward(self, X):return X.sum(dim=[1, 2])

然而,题目的意思是

  • 输入:一维向量x
  • 权重:三维张量 W,形状为 (n, n, m)
  • 输出:一维向量 y
    有运算:

\[y_k=x_1x_1\cdot W_{11k}+x_1x_2\cdot W_{12k}+x_1x_3\cdot W_{13k}+\dots+x_nx_n\cdot W_{nnk} \]

为了简化运算,我们使用爱因斯坦求和 einsum 标记。
这里这个文章很好:看图学 AI:einsum 爱因斯坦求和约定到底是怎么回事? - 知乎
故在此不再赘述。
用了这个标记法,我们可以直接简化计算式:

y = torch.einsum('bi,ijK,bj->bK', x, self.W, x)
return y

简单理解一些这个求和表达式:

  • 爱因斯坦求和规则:在输出标记中不出现的维度会被求和掉
  • 输入标记:bi, ijK, bj
  • 输出标记:bK
  • 被求和的梯度:i 和 j (输入中出现但是输出中不出现)
    这就是那个题目要求的公式。
    等价代码:
result = torch.zeros(x.shape, W.shape[2])
for b in range(x.shape):for k in range(W.shape[2]):total = 0for i in range(x.shape):for j in range(x.shape):total += x[b,i] * W[i,j,k] * x[b,j]result[b,k] = total

综上我们有了:

class BilinearLayer(nn.Module):def __init__(self, input_dim, output_dim):super().__init__()self.W = nn.Parameter(torch.randn(input_dim, input_dim,output_dim))self.input_dim = input_dimself.output_dim = output_dimdef forward(self, x):y = torch.einsum('bi,ijK,bj->bK', x, self.W, x)return y
model = BilinearLayer(input_dim=3, output_dim=2)
x = torch.tensor([[1.0, 2.0, 3.0]])
print("Input:", x)
print("Output:", model(x))

相关新闻

  • 从此多了一个新选择
  • 20232306 2025-2026-2 《网络与系统攻防技术》实验八实验报告
  • 论文解读-《FoSR First-order spectral rewiring for addressing oversquashing in GNNs》 - zhang

最新新闻

  • 道路运输许可证丢了登报怎么线上办理?正规办理渠道与流程 - 速递信息
  • Claude Opus 4.7深度解析:长上下文、自主检查与多模态语义编织
  • 嵌入式GUI开发实战:Alpha混合与位图绘制优化指南
  • 2026 年 6 月亨得利最新官方正式深度辟谣|拆解虚假资讯牟利底层逻辑,亨得利全直营门店资质全景深度解析 - 亨得利官方维修中心
  • 费亨得利官方公正辟谣|2026年6月最新声明:亨得利全国正规服务渠道权威公示 - 亨得利官方维修中心
  • iOS自动化测试演进:从WDA底层原理到Appium实战框架选型

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号