两种多任务学习模式:基于硬约束的多任务学习和基于软约束的多任务学习。
基于硬约束的多任务学习
通过自定义的优化器或投影操作来确保模型输出严格满足约束条件。
import torch
import torch.nn as nn
import torch.optim as optim
# 多任务学习模型
class MultiTaskModel(nn.Module):
def __init__(self):
super(MultiTaskModel, self).__init__()
# 共享层
self.shared_layer = nn.Linear(10, 50)
# 任务1输出层(回归任务)
self.task1_head = nn.Linear(50, 1)
# 任务2输出层(满足硬约束的任务)
self.task2_head = nn.Linear(50, 1)
def forward(self, x):
shared_output = torch.relu(self.shared_layer(x))
task1_output = self.task1_head(shared_output)
task2_output = self.task2_head(shared_output)
return task1_output, task2_output
# 自定义优化器实现硬约束
def projection_step(output, constraint_value):
# 将 output 投影到硬约束之上,例如 output 必须大于等于 constraint_value
return torch.clamp(output, min=constraint_value)
# 初始化模型、损失函数和优化器
model = MultiTaskModel()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 示例训练数据
x = torch.randn(32, 10)
y1 = torch.randn(32, 1) # 任务1的标签
y2 = torch.randn(32, 1) # 任务2的标签
# 训练循环
for epoch in range(100):
optimizer.zero_grad()
# 模型前向传播
output1, output2 = model(x)
# 硬约束投影
output2 = projection_step(output2, constraint_value=0.85) # 约束值为0.85
# 计算损失
loss1 = criterion(output1, y1) # 任务1损失
loss2 = criterion(output2, y2) # 任务2损失
# 总损失
loss = loss1 + loss2
# 反向传播和优化
loss.backward()
optimizer.step()
print(f"Epoch {epoch}, Loss: {loss.item()}")
基于软约束的多任务学习
通过添加正则化惩罚项来引导模型尽量满足约束条件,而不是强制要求。
import torch
import torch.nn as nn
import torch.optim as optim
# 多任务学习模型
class MultiTaskModel(nn.Module):
def __init__(self):
super(MultiTaskModel, self).__init__()
# 共享层
self.shared_layer = nn.Linear(10, 50)
# 任务1输出层(回归任务)
self.task1_head = nn.Linear(50, 1)
# 任务2输出层(软约束任务)
self.task2_head = nn.Linear(50, 1)
def forward(self, x):
shared_output = torch.relu(self.shared_layer(x))
task1_output = self.task1_head(shared_output)
task2_output = self.task2_head(shared_output)
return task1_output, task2_output
# 初始化模型、损失函数和优化器
model = MultiTaskModel()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 软约束的惩罚系数
constraint_penalty = 10.0
# 示例训练数据
x = torch.randn(32, 10)
y1 = torch.randn(32, 1) # 任务1的标签
y2 = torch.randn(32, 1) # 任务2的标签
# 训练循环
for epoch in range(100):
optimizer.zero_grad()
# 模型前向传播
output1, output2 = model(x)
# 计算损失
loss1 = criterion(output1, y1) # 任务1损失
loss2 = criterion(output2, y2) # 任务2损失
# 软约束:如果输出违反约束(小于0.85),则施加惩罚
constraint_violation = torch.relu(0.85 - output2)
penalty = constraint_penalty * torch.mean(constraint_violation ** 2)
# 总损失 = 基本损失 + 软约束惩罚
loss = loss1 + loss2 + penalty
# 反向传播和优化
loss.backward()
optimizer.step()
print(f"Epoch {epoch}, Loss: {loss.item()}")
硬约束:通过 projection_step
函数将输出值限制在约束范围内。例如,输出值不能小于 0.85。
软约束:通过对违反约束的情况施加惩罚,使用 relu(0.85 - output)
来计算违反的程度,并将其平方作为惩罚项加入到总损失中。
两者的区别在于:硬约束严格限制模型的输出,而软约束允许模型输出违反约束,但通过损失函数引导其减少违反的程度。