人工神经元
用权重、偏置和激活函数把输入特征转换为一个输出。
学习目标
- 手算一个神经元输出
- 解释权重、偏置、激活
- 用 nn.Linear 验证
为什么需要这个概念
人工神经元把特征、权重、偏置和激活连接在同一个计算单元中。看懂这个单元,才能解释网络中的参数究竟作用在哪一步,而不是只会调用一个层的名称。
同一套参数可以同时处理一批样本,多个神经元并排组成一层。后续网络结构与训练过程,都可以从这个最小单元逐步展开。
学习前需要掌握
背景与问题
如果要根据两个特征给出一个分数,可以先让每个特征乘以一个权重,再把它们相加。问题在于,只有加权和时,无论叠多少层,整体仍可能只是一个线性关系。
激活函数把线性组合转换成非线性输出,让多层组合能够表示更复杂的关系。人工神经元是数学计算单元,不是对生物神经细胞全部机制的精确模拟。
概念定义
一个常见人工神经元先计算 z = w·x + b,再计算 y = f(z)。x 是本次输入,w 和 b 是可学习参数,f 是激活函数。先得到的 z 与激活后的 y 是两个不同对象。
权重决定各特征怎样参与组合,偏置移动响应的位置,激活函数决定怎样转换线性分数。训练通过损失与梯度调整参数;单次前向计算只产生输出,并不自动执行学习。
直观理解
可以把两个特征想成两条证据:一个权重为正,意味着该特征增大时会推高线性分数;另一个权重为负,意味着它会拉低分数。偏置为所有样本加入相同的基准项。
ReLU 把负的线性分数截成零、保留正值,因此同一个神经元在不同输入区域的响应方式不同。它不是“负特征没有用”,因为判断依据是整个加权和 z,而不是某个输入的正负。
核心原理
必须区分输入维度、神经元数量与样本数量。Linear(2, 1) 表示每个样本有两个输入特征、输出一个线性分数;输入两个样本时,输出形状为两行一列,不是两个输出神经元。
偏置能移动激活边界。对 ReLU 而言,是否输出零取决于 w·x+b 是否为正;改变 b 会改变边界的位置,但不改变输入特征的数量。
激活函数与损失函数职责不同。前者作用在网络内部或输出上,后者比较预测与目标并定义训练目标;选择哪一种输出激活,需要与任务和损失的输入约定一起考虑。
单个神经元的表达能力有限,增加深度也不意味着可以无视数据、优化与评估。先用可手算的小输入确认前向过程,是排查大网络错误的有效起点。
数学表达
核心公式
x 是输入,w 是权重,b 是偏置,f 是激活,y 是输出。
变量含义
x输入特征向量w可学习权重b可学习偏置f激活函数
计算步骤
- 1第一条样本:z = 0.5×2 − 1×3 + 1 = -1,所以 ReLU 输出 0。
- 2第二条样本:z = 0.5×2 − 1×1 + 1 = 1,所以 ReLU 输出 1。
- 3两条样本共用相同参数,输出变化来自输入不同,而不是模型在两次计算之间重新训练。
代码对应位置
示例 1显式设置参数,复现两个 ReLU 输出:把手算中的权重和偏置写进 Linear,避免随机初始化干扰数值核对。
变量解释
| 变量 | 含义 |
|---|---|
x | 输入特征向量 |
w | 可学习权重 |
b | 可学习偏置 |
f | 激活函数 |
完整数值示例
同一个 ReLU 神经元处理两个输入
已知条件
- 固定权重 w = [0.5, -1],偏置 b = 1。
- 第一条样本 x = [2, 3];第二条样本 x = [2, 1]。
- 使用 ReLU(z) = max(0, z),不进行训练。
计算步骤
- 第一条样本:z = 0.5×2 − 1×3 + 1 = -1,所以 ReLU 输出 0。
- 第二条样本:z = 0.5×2 − 1×1 + 1 = 1,所以 ReLU 输出 1。
- 两条样本共用相同参数,输出变化来自输入不同,而不是模型在两次计算之间重新训练。
计算结果
线性分数为 [-1, 1],经过 ReLU 后为 [0, 1]。批量输出形状为 [2, 1]。
处理前后对比
- 去掉 ReLU 时保留原始线性分数 -1 和 1;使用 ReLU 后,只有前者被截为 0。
- 权重与偏置如果采用随机初始化,就不能期待得到这里的固定数值;下面代码显式设置参数以便核对。
计算与实现步骤
- 准备输入
- 线性加权
- 加偏置
- 应用激活
- 通过损失反传梯度
代码实现
示例 1
显式设置参数,复现两个 ReLU 输出
example_01.py用途:把手算中的权重和偏置写进 Linear,避免随机初始化干扰数值核对。
import torch
from torch import nn
neuron = nn.Linear(2, 1)
with torch.no_grad():
neuron.weight.copy_(torch.tensor([[0.5, -1.0]]))
neuron.bias.fill_(1.0)
x = torch.tensor([[2.0, 3.0], [2.0, 1.0]])
z = neuron(x)
y = torch.relu(z)
print("z:", z.detach().flatten().tolist())
print("relu:", y.detach().flatten().tolist())代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
把手算中的权重和偏置写进 Linear,避免随机初始化干扰数值核对。
y- 目标标签或连续目标值。
Step 1 · 1–2 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
from torch import nnStep 2 · 4–12 行
输出中间参数、形状或最终指标,用于核对代码是否符合预期。
neuron = nn.Linear(2, 1)
with torch.no_grad():
neuron.weight.copy_(torch.tensor([[0.5, -1.0]]))
neuron.bias.fill_(1.0)
x = torch.tensor([[2.0, 3.0], [2.0, 1.0]])
z = neuron(x)
y = torch.relu(z)
print("z:", z.detach().flatten().tolist())
print("relu:", y.detach().flatten().tolist())预期输出或运行结果
z: [-1.0, 1.0] relu: [0.0, 1.0]
常见错误 · 4 条
- 把 Linear 的输出 z 与经过激活的输出 y 混为一谈。
- 把 batch 中样本数量当成神经元数量,或者忘记输入最后一维应与 in_features 一致。
- 随机初始化参数,却拿结果与固定参数的手算例直接比较。
- 认为加了激活就一定学到了有用规律,忽略单次前向没有更新任何参数。
实际应用
- MLP
- 卷积通道投影
常见错误
- 把 Linear 的输出 z 与经过激活的输出 y 混为一谈。
- 把 batch 中样本数量当成神经元数量,或者忘记输入最后一维应与 in_features 一致。
- 随机初始化参数,却拿结果与固定参数的手算例直接比较。
- 认为加了激活就一定学到了有用规律,忽略单次前向没有更新任何参数。
常见问题
偏置为什么重要?
它让决策边界不必经过原点。
权重越大越重要吗?
需结合输入尺度和其他特征解释。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。