目錄
一、引言
二、CGC(Customized Gate Control,定制門控網絡)
2.1 技術原理
2.2?技術優缺點
2.3 業務代碼實踐
2.3.1 業務場景與建模
2.3.2 模型代碼實現
2.3.3 模型訓練與推理測試
2.3.4 打印模型結構?
三、總結
一、引言
上一篇我們講了MMoE多任務網絡,通過對每一個任務塔建立Gate門控,對專家網絡進行加權平均,Gate門控起到了對多個共享專家重要度篩選的作用。在每輪反向傳播時,每個任務tower分別更新對應Gate的參數,以及共享專家的參數。模型主要起到了多目標任務平衡的作用。
今天我們重點將CGC(Customized Gate Control)定制門控網絡,核心思想是在MMoE基礎上,為每一個任務tower定制獨享專家,實用任務獨享專家與共享專家共同決定任務Tower的輸入,相比于MMoE僅用Gate門控表征任務Tower的方法,CGC引入獨享專家,對任務表征更加全面,又通過共享專家保證關聯性。
二、CGC(Customized Gate Control,定制門控網絡)
2.1 技術原理
CGC(Customized Gate Control)全稱為定制門控網絡,主要由多個任務塔、對應多組獨享專家網絡,對應多個門控網絡以及一組共享專家網絡,專家網絡組內可以包含多個專家MLP。核心原理:樣本input分別輸入共享專家MLP、獨立專家MLP、獨立專家對應門控網絡,門控網絡輸出為經過softmax的權重分布,維度對應共享專家數num_shared_experts和獨立專家數num_task_experts的和,通過對獨立專家輸出和共享專家輸出采用Gate門控加權平均后, 輸入到對應的任務Tower。每個任務Tower輸入自己對應的獨享專家、共享專家、門控加權平均的輸入。反向傳播時,每個任務更新自己獨享專家、獨享門控以及共享專家的參數。
- 共享專家網絡:樣本數據分別輸入num_shared_experts個專家網絡進行推理,每個共享專家網絡實際上是一個多層感知機(MLP),輸入維度為x,輸出維度為output_experts_dim。
- 獨享專家網絡:樣本數據分別輸入num_task_experts個專家網絡進行推理,每個共享專家網絡實際上是一個多層感知機(MLP),輸入維度為x,輸出維度為output_experts_dim。
- 門控網絡:樣本數據輸出各自任務對應的門控網絡,每個門控網絡可以是一個多層感知機,也可以是一個雙層的交叉,主要是為了輸出專家網絡的加權平均權重。
- 任務網絡:對于每一個Task,將各自對應num_shared_experts個共享專家和num_task_experts個獨立專家,基于對應gate門控網絡的softmax加權平均,作為各自Task的輸入,所有Task的輸入統一維度均為output_experts_dim。
2.2?技術優缺點
相較于MMoE網絡,CGC為每一個任務tower定制獨享專家,實用任務獨享專家與共享專家共同決定任務Tower的輸入,相比于MMoE僅用Gate門控表征任務Tower的方法,CGC引入獨享專家,對任務表征更加全面,又通過共享專家保證關聯性。
優點:
- 切斷任務tower與其他任務獨享專家的聯系,使得獨享專家能夠更專注的學習本任務內的知識與信息。比如切斷互動塔與點擊專家的聯系,只和互動專家同時迭代,讓互動目標的學習更加純粹。
- 獨享專家只受對應任務梯度的影響,不受其他任務梯度的影響,而共享專家可以被多個任務梯度同時更新。
- 本質上,CGC就是在MMoE上新增了獨享專家,MMoE僅有共享專家。
缺點:?
- 相較于PLE、SNR等,沒有學習到專家與專家之間的相互關系,層級堆疊不夠。
- 相較于DeepSeekMoE的路由方法,CGC還是過于定制化與單一話,專家組合不足。
2.3 業務代碼實踐
2.3.1 業務場景與建模
我們還是以小紅書推薦場景為例,針對一個視頻,用戶可以點紅心(互動),也可以點擊視頻進行播放(點擊),針對互動和點擊兩個目標進行多目標建模
我們構建一個100維特征輸入,1組共享專家網絡(含2個共享專家),2組獨享專家網絡(各含2個獨享專家),2個門控,2個任務塔的CGC網絡,用于建模多目標學習問題,模型架構圖如下:
??????????????
如架構圖所示,其中有幾個注意的點:
- num_shared_experts+num_task_experts:Gate的維度等于共享專家的維度加上任務獨享專家的維度。
- output_experts_dim:共享專家、獨享專家網絡的輸出維度和task網絡的輸入維度相同,task網絡承接的是專家網絡各維度的加權平均值,experts網絡與task網絡是直接對應關系。
- Softmax:Gate門控網絡對共享專家和獨享專家的偏好權重采用Softmax歸一化,保證專家網絡加權平均后值域相同
2.3.2 模型代碼實現
基于pytorch,實現上述CGC網絡架構,如下:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDatasetclass CGCModel(nn.Module):def __init__(self, input_dim, experts_hidden1_dim, experts_hidden2_dim, output_experts_dim, task_hidden1_dim, task_hidden2_dim, output_task1_dim, output_task2_dim, gate_hidden1_dim, gate_hidden2_dim, num_shared_experts, num_task_experts):super(CGCModel, self).__init__()# 初始化函數外使用初始化變量需要賦值,否則默認使用全局變量# 初始化函數內使用初始化變量不需要賦值 self.num_shared_experts = num_shared_expertsself.num_task_experts = num_task_expertsself.output_experts_dim = output_experts_dim# 初始化共享專家self.shared_experts_2 = nn.ModuleList([nn.Sequential(nn.Linear(input_dim, experts_hidden1_dim),nn.ReLU(),nn.Linear(experts_hidden1_dim, experts_hidden2_dim),nn.ReLU(),nn.Linear(experts_hidden2_dim, output_experts_dim),nn.ReLU()) for _ in range(num_shared_experts)])# 初始化任務1專家self.task1_experts_2 = nn.ModuleList([nn.Sequential(nn.Linear(input_dim, experts_hidden1_dim),nn.ReLU(),nn.Linear(experts_hidden1_dim, experts_hidden2_dim),nn.ReLU(),nn.Linear(experts_hidden2_dim, output_experts_dim),nn.ReLU()) for _ in range(num_task_experts)])# 初始化任務2專家self.task2_experts_2 = nn.ModuleList([nn.Sequential(nn.Linear(input_dim, experts_hidden1_dim),nn.ReLU(),nn.Linear(experts_hidden1_dim, experts_hidden2_dim),nn.ReLU(),nn.Linear(experts_hidden2_dim, output_experts_dim),nn.ReLU()) for _ in range(num_task_experts)])# 初始化門控網絡任務1self.gating1_network_2 = nn.Sequential(nn.Linear(input_dim, gate_hidden1_dim),nn.ReLU(),nn.Linear(gate_hidden1_dim, gate_hidden2_dim),nn.ReLU(),nn.Linear(gate_hidden2_dim, num_shared_experts+num_task_experts),nn.Softmax(dim=1))# 初始化門控網絡任務2self.gating2_network_2 = nn.Sequential(nn.Linear(input_dim, gate_hidden1_dim),nn.ReLU(),nn.Linear(gate_hidden1_dim, gate_hidden2_dim),nn.ReLU(),nn.Linear(gate_hidden2_dim, num_shared_experts+num_task_experts),nn.Softmax(dim=1))# 定義任務1的輸出層self.task1_head = nn.Sequential(nn.Linear(output_experts_dim, task_hidden1_dim),nn.ReLU(),nn.Linear(task_hidden1_dim, task_hidden2_dim),nn.ReLU(),nn.Linear(task_hidden2_dim, output_task1_dim),nn.Sigmoid()) # 定義任務2的輸出層self.task2_head = nn.Sequential(nn.Linear(output_experts_dim, task_hidden1_dim),nn.ReLU(),nn.Linear(task_hidden1_dim, task_hidden2_dim),nn.ReLU(),nn.Linear(task_hidden2_dim, output_task2_dim),nn.Sigmoid()) def forward(self, x):gates1 = self.gating1_network_2(x)gates2 = self.gating2_network_2(x)#定義專家網絡輸出作為任務塔輸入batch_size, _ = x.shapetask1_inputs = torch.zeros(batch_size, self.output_experts_dim)task2_inputs = torch.zeros(batch_size, self.output_experts_dim)for i in range(self.num_shared_experts):task1_inputs += self.shared_experts_2[i](x) * gates1[:, i].unsqueeze(1) + self.task1_experts_2[i](x) * gates1[:, i+self.num_shared_experts].unsqueeze(1)task2_inputs += self.shared_experts_2[i](x) * gates2[:, i].unsqueeze(1) + self.task2_experts_2[i](x) * gates2[:, i+self.num_shared_experts].unsqueeze(1)task1_outputs = self.task1_head(task1_inputs)task2_outputs = self.task2_head(task2_inputs)return task1_outputs, task2_outputs# 實例化模型對象
experts_hidden1_dim = 64
experts_hidden2_dim = 32
output_experts_dim = 16
gate_hidden1_dim = 16
gate_hidden2_dim = 8
task_hidden1_dim = 32
task_hidden2_dim = 16
output_task1_dim = 1
output_task2_dim = 1
num_shared_experts = 2
num_task_experts = 2# 構造虛擬樣本數據
torch.manual_seed(42) # 設置隨機種子以保證結果可重復
input_dim = 100
num_samples = 1024
X_train = torch.randint(0, 2, (num_samples, input_dim)).float()
y_train_task1 = torch.rand(num_samples, output_task1_dim) # 假設任務1的輸出維度為1
y_train_task2 = torch.rand(num_samples, output_task2_dim) # 假設任務2的輸出維度為1# 創建數據加載器
train_dataset = TensorDataset(X_train, y_train_task1, y_train_task2)
train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True)model = CGCModel(input_dim, experts_hidden1_dim, experts_hidden2_dim, output_experts_dim, task_hidden1_dim, task_hidden2_dim, output_task1_dim, output_task2_dim, gate_hidden1_dim, gate_hidden2_dim, num_shared_experts, num_task_experts)# 定義損失函數和優化器
criterion_task1 = nn.MSELoss()
criterion_task2 = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 訓練循環
num_epochs = 100
for epoch in range(num_epochs):model.train()running_loss = 0.0for batch_idx, (X_batch, y_task1_batch, y_task2_batch) in enumerate(train_loader):# 前向傳播: 獲取預測值#print(batch_idx, X_batch )#print(f'Epoch [{epoch+1}/{num_epochs}-{batch_idx}], Loss: {running_loss/len(train_loader):.4f}')outputs_task1, outputs_task2 = model(X_batch)# 計算每個任務的損失loss_task1 = criterion_task1(outputs_task1, y_task1_batch)loss_task2 = criterion_task2(outputs_task2, y_task2_batch)total_loss = loss_task1 + loss_task2# 反向傳播和優化optimizer.zero_grad()total_loss.backward()optimizer.step()running_loss += total_loss.item()if epoch % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}')print(model)
#for param_tensor in model.state_dict():
# print(param_tensor, "\t", model.state_dict()[param_tensor].size())
# 模型預測
model.eval()
with torch.no_grad():test_input = torch.randint(0, 2, (1, input_dim)).float() # 構造一個測試樣本pred_task1, pred_task2 = model(test_input)print(f'互動目標預測結果: {pred_task1}')print(f'點擊目標預測結果: {pred_task2}')
相比于上一篇MMoE中的代碼,CGC復雜了很多,新增了2組獨享專家,且在門控與獨享、共享專家加權平均計算的時候需要進行處理,很容易出問題。
2.3.3 模型訓練與推理測試
運行上述代碼,模型啟動訓練,Loss逐漸收斂,測試結果如下:
2.3.4 打印模型結構????????
三、總結
本文詳細介紹了CGC多任務模型的算法原理、算法優勢,他是下一篇PLE多層多任務模型的基礎,并以小紅書業務場景為例,構建CGC網絡結構并使用pytorch代碼實現對應的網絡結構、訓練流程。相比于MMoE,CGC新增獨享專家網絡,通過gate門控的串聯,切斷任務Tower與其他任務獨享專家的聯系,使得獨享專家能夠更專注的學習本任務內的知識與信息。
如果您還有時間,歡迎閱讀本專欄的其他文章:
【深度學習】多目標融合算法(一):樣本Loss加權(Sample Loss Reweight)
【深度學習】多目標融合算法(二):底部共享多任務模型(Shared-Bottom Multi-task Model)????????
【深度學習】多目標融合算法(三):混合專家網絡MOE(Mixture-of-Experts)?
?【深度學習】多目標融合算法(四):多門混合專家網絡MMOE(Multi-gate Mixture-of-Experts)???????