参数随机初始化方法:xavier_init()

初始化方法由Bengio等人在2010年的论文《Understanding the difficulty of training deep feedforward neural networks》中提出。

它为了保证前向传播和反向传播时每一层的方差一致,根据每层的输入个数和输出个数来决定参数随机初始化的分布范围,是一个通过该层的输入和输出参数个数得到的分布范围内的均匀分布。
公式如下:

U[6nin+nout,6nin+nout]U[−6nin+nout,6nin+nout]

其中:ninninnoutnout 分别表示该层输入和输出的参数(权重)个数。
具体推导如下:
假设某层激活函数为线性(非线性与之类似),输入输出关系如下:
y=i=1nwixi+by=∑i=1nwixi+b

定义D(xi)D(xi)D(wi)D(wi) 分别为随机变量 xixiwiwi 的方差,根据方差公式有:
D(wixi)=E(wi)2D(xi)+E(xi)2D(wi)+D(wi)D(xi)D(wixi)=E(wi)2D(xi)+E(xi)2D(wi)+D(wi)D(xi)

设计网络时,我们通常会用一些tricks使每层的输入和权值的均值为0,,则有:
D(wixi)=D(wi)D(xi)D(wixi)=D(wi)D(xi)

假设输入xixi和权值wiwi 独立同分布:
D(y)=nD(wi)D(xi)D(y)=nD(wi)D(xi)

由于输入和输出方差相同: D(y)=D(x)D(y)=D(x) ,所以有:
D(w)=1nD(w)=1n

对于多层网络,正向传播时第 i 层的输出方差 D(yi)D(yi) 可用前面各层方差的乘积表示:
D(yi)=D(xi)k=0i1nkD(wk)D(yi)=D(xi)∏k=0i−1nkD(wk)

其中,D(xi)D(xi) 为第 i 层的输入,nknkwkwk 分别为前面第 k 层的参数数量和长度为 nknk 的权值向量。

反向传播时,与正向传播类似:

D(Lwi)=D(Lwm)p=imnp+1D(wp)D(∂L∂wi)=D(∂L∂wm)∏p=imnp+1D(wp)

其中,L 为最高层第 m 层的损失函数。

对于每一层的权值向量 wiwi,正向与反向传播的方差 D(xi)D(xi) 相等:

niD(wi)=1niD(wi)=1
ni+1D(wi)=1ni+1D(wi)=1

由于通常相邻两层的权重参数的数量不同,因此选择:
D(wi)=2ni+ni+1D(wi)=2ni+ni+1

为了满足在某个关于原点对称的范围内实现均匀分布,所以Xavier的初始化为在如下范围内的均匀分布:
U[6nin+nout,6nin+nout]U[−6nin+nout,6nin+nout]
<think> 我们有一个SelfAttention_v2模块,它使用nn.Linear层作为可训练权重矩阵。 训练过程通常包括以下步骤: 1. 定义模型(已经定义) 2. 准备数据(假设已有) 3. 定义损失函数和优化器 4. 进行训练循环:前向传播、计算损失、反向传播、优化器更新 下面我们将展示如何将这个自注意力模块整合到一个简单的模型中进行训练。 假设我们的任务是一个简单的序列到序列的任务(比如序列分类),我们使用一个仅包含自注意力的模型。 为了简单起见,我们假设输入是一个批量的序列,每个序列有固定长度,每个时间步的特征维度是d_in。 输出我们取上下文向量的最后一个时间步(或者使用池化)然后通过一个线性层得到分类结果。 我们构建一个简单的分类模型,包含一个自注意力层和一个线性分类层。 注意:自注意力层输出的是与输入序列长度相同的上下文向量序列。我们可以选择不同的方法得到整个序列的表示,比如取最后一个时间步,或者进行平均池化等。 以下是一个示例模型: </think> 要对`SelfAttention_v2`模块中的权重矩阵进行训练,需要将其整合到完整的神经网络中,定义损失函数和优化器,并进行训练循环。以下是完整的训练流程: ### 训练步骤及代码实现 ```python import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset # 1. 创建包含自注意力机制的完整模型 class AttentionModel(nn.Module): def __init__(self, d_in, d_out, num_classes): super().__init__() self.attention = SelfAttention_v2(d_in, d_out) # 自注意力层 self.classifier = nn.Linear(d_out, num_classes) # 分类层 def forward(self, x): # 输入x形状: (batch_size, seq_len, d_in) context = self.attention(x) # 输出: (batch_size, seq_len, d_out) # 池化操作 (取每个序列最后一个时间步的输出) pooled = context[:, -1, :] # 输出: (batch_size, d_out) return self.classifier(pooled) # 输出: (batch_size, num_classes) # 2. 准备模拟数据 batch_size, seq_len, d_in = 32, 10, 64 num_classes = 5 num_samples = 1000 # 生成随机数据 X = torch.randn(num_samples, seq_len, d_in) y = torch.randint(0, num_classes, (num_samples,)) dataset = TensorDataset(X, y) dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) # 3. 初始化模型、损失函数和优化器 model = AttentionModel(d_in, d_out=32, num_classes=num_classes) criterion = nn.CrossEntropyLoss() # 分类任务常用损失函数 optimizer = optim.Adam(model.parameters(), lr=0.001) # 使用Adam优化权重 # 4. 训练循环 num_epochs = 10 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) for epoch in range(num_epochs): model.train() total_loss = 0 for batch_x, batch_y in dataloader: batch_x, batch_y = batch_x.to(device), batch_y.to(device) # 前向传播 outputs = model(batch_x) loss = criterion(outputs, batch_y) # 反向传播 optimizer.zero_grad() # 清除历史梯度 loss.backward() # 计算梯度 optimizer.step() # 更新权重 (包括W_query/W_key/W_value) total_loss += loss.item() print(f"Epoch {epoch+1}/{num_epochs}, Loss: {total_loss/len(dataloader):.4f}") # 5. 保存训练后的权重 (可选) torch.save(model.state_dict(), "attention_model.pth") ``` ### 关键训练机制说明 1. **权重更新原理**: - 通过`loss.backward()`计算所有权重(包括`W_query`/`W_key`/`W_value`)的梯度 - `optimizer.step()`使用梯度下降算法更新权重 - 初始化方法Xavier)确保训练初期梯度稳定传播 2. **梯度流动路径**: ```mermaid graph LR A[分类器梯度] --> B[SelfAttention_v2.context_vec] B --> C[W_value梯度] B --> D[attn_weights梯度] D --> E[W_query梯度] D --> F[W_key梯度] ``` 3. **训练细节**: - **学习率**:Adam优化器默认0.001,可根据任务调整 - **批次大小**:影响梯度稳定性(示例中batch_size=32) - **设备选择**:自动检测GPU加速训练 - **权重保存**:训练后保存模型参数供后续使用 ### 参数冻结/部分训练技巧 若只想训练注意力权重而冻结其他层: ```python # 冻结分类器层 for param in model.classifier.parameters(): param.requires_grad = False # 仅优化注意力权重 optimizer = optim.Adam(model.attention.parameters(), lr=0.001) ``` ### 验证训练效果 ```python model.eval() # 切换到评估模式 with torch.no_grad(): test_output = model(X_test) accuracy = (test_output.argmax(dim=1) == y_test).float().mean() print(f"Test Accuracy: {accuracy:.4f}") ``` ### 核心训练要素总结 | 组件 | 作用 | 是否可训练 | |------|------|------------| | `W_query` | 生成查询向量 | ✅ 是 | | `W_key` | 生成键向量 | ✅ 是 | | `W_value` | 生成值向量 | ✅ 是 | | 分类器 | 最终分类层 | ✅ 是 | | 优化器 | 更新权重 | 控制机制 | | 损失函数 | 指导优化方向 | 评估标准 | 通过反向传播算法,PyTorch会自动计算所有`nn.Linear`层(包括自注意力中的三个权重矩阵)的梯度并更新其参数值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值