news 2026/10/24 5:38:58

PyTorch 线性层nn.Linear底层数学原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyTorch 线性层nn.Linear底层数学原理

一、 原理代码

#coding:utf8importos os.environ['KMP_DUPLICATE_LIB_OK']='TRUE'importtorchimporttorch.nnasnnimportnumpyasnp""" numpy手动实现模拟一个线性层 """#搭建一个2层的神经网络模型#每层都是线性层classTorchModel(nn.Module):def__init__(self,input_size=3,hidden_size1=5,hidden_size2=2):super(TorchModel,self).__init__()#第一件事,定义要使用哪些网络层self.layer1=nn.Linear(input_size,hidden_size1)# 3 * 5self.layer2=nn.Linear(hidden_size1,hidden_size2)# 5 * 2defforward(self,x):#第二件事:定义这些网络层是如何组合的x=self.layer1(x)#shape: (batch_size, input_size) -> (batch_size, hidden_size1)y_pred=self.layer2(x)#shape: (batch_size, hidden_size1) -> (batch_size, hidden_size2)returny_pred#自定义模型classDiyModel:def__init__(self,w1,b1,w2,b2):self.w1=w1 self.b1=b1 self.w2=w2 self.b2=b2defforward(self,x):#x: 2 * 3, w1.T: 3 * 5 = 2*5 b1: 1 * 5hidden=np.dot(x,self.w1.T)+self.b1#1*5y_pred=np.dot(hidden,self.w2.T)+self.b2#1*2returny_pred#随便准备一个网络输入x=np.array([[3.1,1.3,1.2],[2.1,1.3,13]])#建立torch模型torch_model=TorchModel(3,5,2)print(torch_model.state_dict())print("-----------")#打印模型权重,权重为随机初始化torch_model_w1=torch_model.state_dict()["layer1.weight"].numpy()torch_model_b1=torch_model.state_dict()["layer1.bias"].numpy()torch_model_w2=torch_model.state_dict()["layer2.weight"].numpy()torch_model_b2=torch_model.state_dict()["layer2.bias"].numpy()print(torch_model_w1,"torch w1 权重")print(torch_model_b1,"torch b1 权重")print("-----------")print(torch_model_w2,"torch w2 权重")print(torch_model_b2,"torch b2 权重")print("-----------")#使用torch模型做预测torch_x=torch.FloatTensor(x)y_pred=torch_model.forward(torch_x)print("torch模型预测结果:",y_pred)# #把torch模型权重拿过来自己实现计算过程diy_model=DiyModel(torch_model_w1,torch_model_b1,torch_model_w2,torch_model_b2)# #用自己的模型来预测y_pred_diy=diy_model.forward(x)print("diy模型预测结果:",y_pred_diy)

二、解析计算步骤:np.dot(x, self.w1.T) + self.b1:手动执行矩阵乘法(输入 × 权重转置)并加上偏置。

假设我们有:

  • 输入 x:形状为(batch_size, input_features)的一个二维矩阵
  • 权重 w1:形状为(output_features, input_features)的二维矩阵
  • 偏置 b1:形状为(output_features,)的一维向量

np.dot(x, self.w1.T) + self.b1的执行过程如下:

  1. 转置权重:self.w1.T将权重转置为(input_features, output_features),这样矩阵乘法才能匹配维度。
  2. 矩阵乘法:np.dot(x, self.w1.T)得到形状(batch_size, output_features)的结果。
  3. 加偏置:将b1(形状(output_features,))广播到每一行,加到结果中。

具体例子

设:

  • x有 2 个样本,每个样本有 3 个特征:
    x = [[1, 2, 3], [4, 5, 6]]
  • w1有 2 个输出神经元,每个接收 3 个输入:
    w1 = [[0.1, 0.2, 0.3], # 第一个输出神经元的权重 [0.4, 0.5, 0.6]] # 第二个输出神经元的权重
  • b1有 2 个偏置:
    b1 = [0.1, -0.2]
第一步:转置权重
w1.T = [[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]
第二步:矩阵乘法np.dot(x, w1.T)

计算每个样本与转置权重的点积:

  • 样本1[1,2,3]:

    • 对第一个输出神经元:1*0.1 + 2*0.2 + 3*0.3 = 0.1+0.4+0.9 = 1.4
    • 对第二个输出神经元:1*0.4 + 2*0.5 + 3*0.6 = 0.4+1.0+1.8 = 3.2
  • 样本2[4,5,6]:

    • 对第一个输出神经元:4*0.1 + 5*0.2 + 6*0.3 = 0.4+1.0+1.8 = 3.2
    • 对第二个输出神经元:4*0.4 + 5*0.5 + 6*0.6 = 1.6+2.5+3.6 = 7.7

所以np.dot(x, w1.T)结果为:

[[1.4, 3.2], [3.2, 7.7]]
第三步:加上偏置b1 = [0.1, -0.2]
  • 第一行:[1.4+0.1, 3.2-0.2] = [1.5, 3.0]
  • 第二行:[3.2+0.1, 7.7-0.2] = [3.3, 7.5]

最终结果:

[[1.5, 3.0], [3.3, 7.5]]

为什么用转置?

因为权重通常以(输出维度, 输入维度)形式存储(每行对应一个输出神经元),而矩阵乘法要求“输入特征数”与“权重列数”匹配。转置后变为(输入维度, 输出维度),使得x (批量, 输入特征)能直接相乘得到(批量, 输出维度)。

这个操作等价于:

# 手动循环版本output=np.zeros((x.shape[0],w1.shape[0]))foriinrange(x.shape[0]):# 遍历样本forjinrange(w1.shape[0]):# 遍历输出神经元output[i,j]=np.dot(x[i],w1[j])+b1[j]

三、代码的详细逻辑拆解:

这段代码的核心目的是验证 PyTorch 框架底层线性层(Linear Layer)的数学原理,并演示如何将 PyTorch 的模型权重提取出来,用纯 NumPy 手动复现完全相同的计算过程。

简单来说,它在做一件事:“黑盒”拆解与“白盒”复现。它证明了nn.Linear本质上就是矩阵乘法加上偏置项。

1. 环境设置

os.environ['KMP_DUPLICATE_LIB_OK']='TRUE'
  • 作用:这是一个常见的“补丁”。在 macOS 或某些 Linux 环境下,当 Python 同时加载了多个包含 OpenMP 库的动态库(如 NumPy 和 PyTorch)时,可能会发生冲突导致崩溃。这行代码强制允许这种重复加载,防止程序报错。

2. 定义两个模型

代码定义了两个功能相同但实现方式不同的模型:

A.TorchModel(PyTorch 标准实现)
  • 结构:一个包含两层全连接层(Linear Layer)的神经网络。
    • layer1: 输入 3 维 -> 输出 5 维。
    • layer2: 输入 5 维 -> 输出 2 维。
  • 特点:使用nn.Module类,内部自动处理权重初始化、前向传播(forward)等逻辑。
  • 数学本质:y=xWT+by = xW^T + by=xWT+b(注意 PyTorch 中Linear层的权重矩阵形状是(out_features, in_features),所以在计算时实际上是x⋅WTx \cdot W^Tx⋅WT)。
B.DiyModel(NumPy 手动实现)
  • 结构:一个普通的 Python 类,没有继承nn.Module。
  • 参数:直接接收权重矩阵 (w1,w2) 和偏置向量 (b1,b2)。
  • 核心逻辑 (forward):
    • np.dot(x, self.w1.T) + self.b1:手动执行矩阵乘法(输入×\times×权重转置)并加上偏置。
    • 这里显式地写出了线性层的数学公式,用于验证 PyTorch 内部是如何计算的。

3. 数据准备与模型初始化

x=np.array([[3.1,1.3,1.2],[2.1,1.3,13]])# 2个样本,每个3维torch_model=TorchModel(3,5,2)
  • 创建了一个具体的输入数据x(2行3列)。
  • 实例化了 PyTorch 模型。此时,layer1和layer2的权重和偏置是随机初始化的(因为没给weight和bias参数)。

4. 提取权重 (关键步骤)

torch_model_w1=torch_model.state_dict()["layer1.weight"].numpy()# ... 依次提取 w1, b1, w2, b2
  • 目的:从 PyTorch 的“黑盒”中把具体的数值(权重矩阵和偏置向量)拿出来。
  • 转换:.numpy()将 PyTorch 的 Tensor 转换为 NumPy 数组,以便在DiyModel中使用。
  • 注意维度:
    • layer1.weight的形状是(5, 3)(out, in)。
    • 在DiyModel的np.dot(x, w1.T)中,w1.T变成了(3, 5),正好匹配输入x的列数。这验证了 PyTorch 的存储方式。

5. 预测与对比

  1. PyTorch 预测:
    • 将x转为 Tensor。
    • 调用torch_model.forward()。
    • 得到结果y_pred。
  2. NumPy 预测:
    • 将刚才提取的w1, b1, w2, b2传入DiyModel。
    • 调用diy_model.forward(x)。
    • 得到结果y_pred_diy。

6. 预期结果

代码最后会打印两行结果:

  • torch模型预测结果:
  • diy模型预测结果:

这两组结果应该是完全一致的(在浮点数精度范围内)。

总结:这段代码想说明什么?

  1. 揭示本质:nn.Linear并不是什么魔法,它的底层就是y=xWT+by = xW^T + by=xWT+b的矩阵运算。
  2. 权重互通:PyTorch 的模型参数可以无缝导出到 NumPy 进行自定义计算,反之亦然(只要维度对齐)。
  3. 调试与理解:通过手动复现,开发者可以深入理解神经网络每一层的数据流向和变换过程,这对于调试模型或实现自定义算子非常有帮助。

一句话概括:这段代码展示了如何用纯数学公式(NumPy)完美复刻 PyTorch 线性层的计算过程,证明了框架底层的数学原理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 5:38:57

老师一走学员从头学?培训机构缺的是教学进度台账

培训机构最怕的场景之一,不是招不到学生,而是老师突然走了。人走了还能再招,可这批学员学到哪了、谁卡在哪个知识点上,往往随着老师一起消失。新老师接手的第一句话常常是"这个班讲到哪了",而没人答得上来。…

作者头像 李华
网站建设 2026/10/24 5:37:17

被爱着的大肥鱼,是我们童年时想成为的自己

「我去吃饭,测完告诉我就行。」这是 DeepSeek 干完活以后说的话。今年 8 月,有人用它跑任务,代码写完后,测试这一步就留给了用户,她自己竟然跑去吃饭了。一个 AI 敢把测试工作留给用户,用户肯定要骂人。可「…

作者头像 李华
网站建设 2026/10/24 5:30:37

Agent演化史(一):剥掉营销话术后,智能体只剩 34 行代码

【Agent演化史 一】90% 的"智能体"是假的:剥掉话术后,它只剩 34 行代码 本篇是《智能体演化史》系列第 1 篇 系列主线不是"某年出现了某技术",而是"因为上一步崩了,所以下一步才出现"。 全系列共用…

作者头像 李华
网站建设 2026/10/24 5:30:36

StateGraph 基础:先定义状态再画图

个人主页&#xff1a;> for_ever_love__ <&#xff08;欢迎各位大佬莅临&#x1f60a;&#xff09; 其他栏目: > 大模型开发从0到1 < 其他栏目: > iOS项目总结大全 < 其他栏目: > 我想学python了 < 其他栏目: > iOS UI < 文章目录StateGraph 基础…

作者头像 李华