llama源码学习·model.py[5]FeedForward前馈神经网络
一、model.py中FeedForward部分源码
class FeedForward(nn.Module):
def __init__(
self,
dim: int,
hidden_dim: int,
multiple_of: int,
ffn_dim_multiplier: Optional[float],
):
super().__init__()
hidden_dim = int(2 * hidden_dim / 3)
# custom dim factor multiplier
if ffn_dim_multiplier is not None:
hidden_dim = int(ffn_dim_multiplier * hidden_dim)
hidden_dim = multiple_of * ((hidden_dim + multiple_of - 1) // multiple_of)
self.w1 = ColumnParallelLinear(
dim, hidden_dim, bias=False, gather_output=False, init_method=lambda x: x
)
self.w2 = RowParallelLinear(
hidden_dim, dim, bias=False, input_is_parallel=True, init_method=lambda x: x
)
self.w3 = ColumnParallelLinear(
dim, hidden_dim, bias=False, gather_output=False, init_method=lambda x: x
)
def forward(self, x):
return self.w2(F.silu(self.w1(x)) * self.w3(x))
二、FeedForward算法原理
1.结构
-
输入层:
接受外部的输入信号,并将信号传递到网络的下一层
-
隐藏层
在输入层和输出层之间,可以有多个隐藏层。每个隐藏层的节点将前一层的输出作为输入,进行一定的线性和非线性变换,然后将结果传递给下一层。
-
输出层
输出层的节点将最后一个隐藏层的输出作为输入,进行变换后,产生网络输出
2.正向传播(Forward Propagetion)
- 从输入层开始,将输入数据传递给第一个隐藏层
- 每个隐藏层节点将前一层的输出作为输入,进行线性变换(例如,经过权重矩阵和偏置),然后应用一个非线性激活函数(例如 R e L U ReLU ReLU 或者 S i g m o i d Sigmoid Sigmoid 等)
- 重复上一个步骤,直到数据到达输出层。输出层通常会进行一次线性变换,然后可能会应用一个激活函数,例如 s o f t m a x softmax softmax ,以得到分类概率
3.反向传播(Backpropagation)
- 在网络的输出层,计算损失函数(例如,交叉熵损失)以衡量网络输出与真实标签的差异。
- 从输出层开始,向后传播误差,计算每一层的梯度,并根据这些梯度更新网络参数
4.作用
-
函数逼近
FNN能够逼近任意复杂度函数,是一种强大的函数逼近器
-
分类和回归
可用于分类任务和回归任务
-
特征转换
能够学习到输入数据的非线性特征表示
三、代码注释
class FeedForward(nn.Module):
def __init__(
self,
# 输入和输出的维度
dim: int,
# 隐藏层的维度
hidden_dim: int,
# 用于调整隐藏层的维度,使其成为multiple_of的倍数。这可以确保在使用分布式处理或硬件优化时能够获得更好的性能。
multiple_of: int,
# 用于控制隐藏层维度的缩放。如果提供了此参数,将使用此参数来乘以隐藏层的维度。
ffn_dim_multiplier: Optional[float],
):
super().__init__()
# 将隐藏层维度设置为原始维度的2/3
hidden_dim = int(2 * hidden_dim / 3)
# 根据 ffn_dim_multiplier 进行缩放
if ffn_dim_multiplier is not None:
hidden_dim = int(ffn_dim_multiplier * hidden_dim)
# 将hidden_dim调整为最接近的multiple_of的倍数(且不小于 hidden_dim)
hidden_dim = multiple_of * ((hidden_dim + multiple_of - 1) // multiple_of)
假如现在的 hidden_dim
是 820,multiple_of
是256,但是我们期待的 hidden_dim
应该是 multiple_of
的倍数,所以我们期待的 hidden_dim
应该是 1024。
首先计算 hidden_dim + multiple_of - 1
得到 820 + 256 - 1 = 1075
,然后用 1075 // multiple_of
得到 4,用 4 * multiple_of
就是我们所期待的 hidden_dim
的大小 1024。
# 并行版本的全连接层,可以在多个设备上分别进行计算,以便处理大型模型。
self.w1 = ColumnParallelLinear(
dim, hidden_dim, bias=False, gather_output=False, init_method=lambda x: x
)
self.w2 = RowParallelLinear(
hidden_dim, dim, bias=False, input_is_parallel=True, init_method=lambda x: x
)
self.w3 = ColumnParallelLinear(
dim, hidden_dim, bias=False, gather_output=False, init_method=lambda x: x
)
def forward(self, x):
return self.w2(F.silu(self.w1(x)) * self.w3(x))
在 [llama源码学习·model.py2]SwiGLU激活函数_llama激活函数】-CSDN博客 介绍过
S
w
i
G
L
U
SwiGLU
SwiGLU 激活函数,这里的 F.silu(self.w1(x)) * self.w3(x)
就是对输入应用了
S
w
i
G
L
U
SwiGLU
SwiGLU 激活函数。