PyTorch中自定义正则化逻辑回归(Module类)报错求解
问题分析与解决方案
错误直接原因
你遇到的Boolean value of Tensor with more than one value is ambiguous错误,是因为错误调用了nn.BCELoss类:nn.BCELoss(projected, actual)是把张量直接传给类的构造函数,而不是先实例化类再调用。BCELoss的构造函数会做参数合法性检查,触发了张量布尔值判断的歧义报错。正确做法是先实例化BCELoss(比如bce = nn.BCELoss()),再用bce(projected, actual)计算损失,或者用函数式的F.binary_cross_entropy。
隐藏的其他问题
除了直接报错的问题,你的代码还有几个破坏正则化逻辑的问题:
- 把权重转成numpy(
p.data.numpy())会断开PyTorch的计算图,导致正则化项无法参与反向传播,权重永远不会被正则化约束。 - 惩罚项只在
regularized_loss调用时计算一次,后续权重更新后不会重新计算,完全失去正则化效果。 - 正则化项符号错误:应该加惩罚项(最小化总损失=分类损失+正则化惩罚),你写成减会鼓励权重变大,反而加剧过拟合。
修正方案(符合Module练习需求)
推荐把正则化逻辑整合到RegularizedLogistic模块中,这更符合PyTorch的设计范式,也能满足你练习Module类的目标:
import torch import torch.nn as nn import torch.nn.functional as F class RegularizedLogistic(nn.Module): def __init__(self, num_features, lambda_=0.1): super().__init__() self.num_features = num_features self.lambda_ = lambda_ self.linear = nn.Linear(num_features, 1) def forward(self, x): return torch.sigmoid(self.linear(x)) def compute_loss(self, y_pred, y_true): # 计算二元交叉熵损失 bce_loss = F.binary_cross_entropy(y_pred, y_true) # 计算L2正则化惩罚项(仅针对权重,不含偏置) l2_penalty = (self.lambda_ / self.num_features) * torch.sum(self.linear.weight ** 2) # 总损失=分类损失+正则化惩罚 return bce_loss + l2_penalty # 用法示例 model = RegularizedLogistic(num_features=10, lambda_=0.1) # 替换成你的特征数 optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练步骤 y_predicted = model(x_train) loss = model.compute_loss(y_predicted, y_train) loss.backward() optimizer.step() optimizer.zero_grad()
另一种修正:保留原Module结构,修复损失函数
如果你不想修改Module类,也可以修正regularized_loss函数的写法,确保计算图完整且动态更新惩罚项:
def regularized_loss(lambda_, model): bce_criterion = nn.BCELoss() # 先实例化BCELoss类 def compute_loss(projected, actual): # 直接使用模型的权重张量计算,避免转numpy w = model.linear.weight # 注意权重形状是(1, num_features),所以用shape[1]获取特征数 punishment = (lambda_ / w.shape[1]) * torch.sum(w ** 2) return bce_criterion(projected, actual) + punishment return compute_loss # 用法示例 model = RegularizedLogistic(num_features=10) criterion = regularized_loss(0.1, model) optimizer = torch.optim.SGD(model.parameters(), lr=0.01) y_predicted = model(x_train) loss = criterion(y_predicted, y_train) loss.backward() optimizer.step() optimizer.zero_grad()
总结
这个问题完全可以解决,和使用Module类无关,只是你的损失函数写法存在错误。把正则化逻辑整合到Module中是更优雅的实现方式,也完全符合你练习PyTorch Module类的需求。
内容的提问来源于stack exchange,提问作者Terence C
相关产品推荐
相关产品推荐

