负置信度损失函数:“是什么”与“不是什么”的讨论
引言
在传统的深度学习分类任务中,我们通常使用Softmax+CrossEntropy的组合,让模型学会"这是什么"。但这里我做一个有意思的尝试:让模型同时学会"这是什么"和"这不是什么"。
通过引入负置信度(Negative Confidence)的概念,我们设计了一种全新的损失函数,让模型能够输出负值来表示对某类别的强烈否定。以此期待既能提高了分类准确率,还可以为模型提供了更丰富的认知表达。
任务与创新点
传统方法 vs 负置信度方法
方法 | 输出范围 | 学习目标 | 预测逻辑 |
---|---|---|---|
传统Softmax | [0,1] | 学习"是什么" | argmax |
负置信度 | [-1,1] | 学习"是什么"+“不是什么” | 阈值判断 |
核心创新
负置信度损失函数设计:让模型输出负值来表示对某类别的强烈否定,实现双重学习机制。
方法概览
组件 | 设计 |
---|---|
主干网络 | 自定义CNN(Tanh激活,输出范围[-1,1]) |
损失函数 | 负置信度损失(MSE-based) |
数据增强 | 随机噪声(±50) |
优化器 | Adam(LR 1e-4) |
训练轮数 | 20 epochs |
批次大小 | 32 |
关键实现解析
负置信度损失函数
class NegativeConfidenceLoss(nn.Module):
def __init__(self):
super().__init__()
self.mse = nn.MSELoss()
def forward(self, outputs, labels):
targets = torch.zeros_like(outputs)
# 蓝色样本 (label=0): 目标为 [-1, 0]
# 红色样本 (label=1): 目标为 [0, 1]
blue_indices = labels == 0
red_indices = labels == 1
targets[blue_indices, 0] = -1 # 蓝色样本的蓝色通道为-1(负置信度)
targets[blue_indices, 1] = 0 # 蓝色样本的红色通道为0
targets[red_indices, 0] = 0 # 红色样本的蓝色通道为0
targets[red_indices, 1] = 1 # 红色样本的红色通道为1
return self.mse(outputs, targets)
设计动机:
- Loss端:通过负值目标让模型学会"排除"
- 输出端:Tanh激活确保输出范围[-1,1]
- 预测端:阈值判断而非相对比较
模型架构
class NegativeConfidenceCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 16, 3, padding=1),
nn.BatchNorm2d(16),
nn.Tanh(), # 使用Tanh激活函数,输出范围[-1, 1]
nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1),
nn.BatchNorm2d(32),
nn.Tanh(),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, 3, padding=1),
nn.BatchNorm2d(64),
nn.Tanh(),
nn.MaxPool2d(2),
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(64 * 28 * 28, 128),
nn.Tanh(),
nn.Linear(128, 2) # 输出2个值:[蓝色置信度, 红色置信度]
)
def forward(self, x):
x = self.features(x)
return self.classifier(x)
预测逻辑修复
问题发现:初始预测逻辑 red_conf > blue_conf
导致蓝色样本被错误预测。
解决方案:修改为绝对阈值判断
# 修复前
preds = (outputs[:, 1] > outputs[:, 0]).long()
# 修复后
preds = (outputs[:, 1] > 0.5).long()
实验结果
训练过程
Epoch [1/20] | Train Loss: 3.3468 | Val Loss: 1.6524 | Val Acc: 0.5000
Epoch [2/20] | Train Loss: 0.8732 | Val Loss: 0.3372 | Val Acc: 0.5000
Epoch [3/20] | Train Loss: 0.2017 | Val Loss: 0.1293 | Val Acc: 1.0000
...
Epoch [20/20] | Train Loss: 0.0083 | Val Loss: 0.0079 | Val Acc: 1.0000
最终性能
- 测试准确率: 100%
- 分类报告:
precision recall f1-score support Blue 1.00 1.00 1.00 46 Red 1.00 1.00 1.00 54
置信度分布分析
蓝色样本 (46个)
- 蓝色置信度: -0.8881 ± 0.0000 (100%负置信度)
- 红色置信度: -0.0138 ± 0.0000 (100%负置信度)
- 预测逻辑: 红色置信度 < 0.5 → 预测为蓝色 ✓
红色样本 (54个)
- 蓝色置信度: 0.1389 ± 0.0000 (正值)
- 红色置信度: 0.9828 ± 0.0000 (强正值)
- 预测逻辑: 红色置信度 > 0.5 → 预测为红色 ✓
完整代码示例
数据集生成
def generate_imbalanced_color_dataset(output_dir="color_dataset",
blue_samples=200, red_samples=300,
img_size=224, noise_range=50):
"""
生成不平衡颜色分类数据集
- blue_samples: 蓝色类别的样本数量
- red_samples: 红色类别的样本数量
"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 生成蓝色样本
for i in range(blue_samples):
base_color = np.array([0, 0, 200], dtype=np.uint8) # 深蓝色
noise = np.random.randint(-noise_range, noise_range,
(img_size, img_size, 3), dtype=np.int16)
img_array = np.clip(base_color + noise, 0, 255).astype(np.uint8)
img = Image.fromarray(img_array, 'RGB')
img.save(os.path.join(output_dir, f"image_{i:04d}.png"))
# 生成红色样本
for i in range(blue_samples, blue_samples + red_samples):
base_color = np.array([200, 0, 0], dtype=np.uint8) # 深红色
noise = np.random.randint(-noise_range, noise_range,
(img_size, img_size, 3), dtype=np.int16)
img_array = np.clip(base_color + noise, 0, 255).astype(np.uint8)
img = Image.fromarray(img_array, 'RGB')
img.save(os.path.join(output_dir, f"image_{i:04d}.png"))
训练脚本
def train_model(model, train_loader, val_loader, criterion, optimizer, device, num_epochs=20):
train_losses, val_losses, val_accs = [], [], []
for epoch in range(num_epochs):
# 训练阶段
model.train()
train_loss = 0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
train_loss += loss.item()
train_loss /= len(train_loader)
# 验证阶段
model.eval()
val_loss, val_correct, val_total = 0, 0, 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
val_loss += loss.item()
# 修复后的预测逻辑
preds = (outputs[:, 1] > 0.5).long()
val_correct += (preds == labels).sum().item()
val_total += labels.size(0)
val_loss /= len(val_loader)
val_acc = val_correct / val_total
print(f"Epoch [{epoch+1}/{num_epochs}] | "
f"Train Loss: {train_loss:.4f} | "
f"Val Loss: {val_loss:.4f} | "
f"Val Acc: {val_acc:.4f}")
return train_losses, val_losses, val_accs
关键发现与问题解决
初始问题
最初的预测逻辑 red_conf > blue_conf
导致:
- 蓝色样本(蓝色置信度=-0.99, 红色置信度=0.004)被错误预测为红色
- 测试准确率仅为54%
问题根源
预测逻辑与损失函数设计不匹配:
- 损失函数期望蓝色样本输出[-1, 0]
- 但预测时仍用相对比较
red_conf > blue_conf
解决方案
修改预测逻辑为绝对阈值判断:
# 修复前
preds = (outputs[:, 1] > outputs[:, 0]).long()
# 修复后
preds = (outputs[:, 1] > 0.5).long()
负置信度的价值
1. 双重否定机制
蓝色样本的两个置信度都是负值,但通过阈值判断正确分类:
- 蓝色置信度: -0.89 (确信不是蓝色)
- 红色置信度: -0.01 (确信不是红色)
- 结果: 红色置信度 < 0.5 → 预测为蓝色
2. 更强的判别能力
模型不仅学习正面特征,还学习负面特征:
- 传统方法: 只学习"是什么"
- 负置信度: 同时学习"是什么"和"不是什么"
3. 更好的不确定性建模
负值可以表示模型对某类别的强烈否定,提供额外的排除信息。
运行指南
环境要求
pip install torch torchvision numpy matplotlib pandas pillow scikit-learn seaborn
运行步骤
-
生成数据集
python dataset.py
-
训练模型
python train.py
-
测试模型
python test_model.py
-
检查置信度输出
python check_confidence.py
-
调试预测逻辑
python debug_prediction.py
应用前景
负置信度方法可应用于:
- 医学诊断: 不仅诊断疾病,还要排除其他疾病
- 安全系统: 不仅识别威胁,还要排除误报
- 推荐系统: 不仅推荐相关项目,还要排除不相关项目
- 异常检测: 通过负置信度识别异常样本
下一步计划:三元置信度
研究动机
当前的负置信度设计虽然成功,但缺乏对不确定性的显式建模。我们计划引入三元置信度系统,更精确地表达模型的认知状态。
三元置信度设计
置信度向量结构
[x, y, z]
├── x: 是什么 (What it is) - 正向置信度
├── y: 不知道是什么 (Unknown) - 不确定性
└── z: 不是什么 (What it is not) - 负向置信度
设计原则
- 归一化约束: x + y + z = 1
- 语义解释:
- x > 0.5: 模型确信样本属于该类
- y > 0.5: 模型不确定样本的类别
- z > 0.5: 模型确信样本不属于该类
实验结论
- 负置信度设计可行: 模型成功学会了输出负值
- 预测逻辑关键: 必须与损失函数设计匹配
- 性能提升显著: 修复后达到100%准确率
- 概念验证成功: 证明了"学习排除"的价值
总结
负置信度方法为深度学习分类任务提供了一种全新的思路。通过让模型同时学习"是什么"和"不是什么",目前来看提高了分类准确率,还为模型提供了更丰富的认知表达,但是其核心部分代码可能存在错误欢迎指正。
这种方法的核心价值在于:
- 更强的判别能力: 双重学习机制
- 更好的不确定性建模: 负值表示强烈否定
- 更丰富的语义表达: 不仅知道答案,还知道为什么不是其他答案
后续我们将继续探索三元置信度系统,进一步推进深度学习中的不确定性建模研究。
参考资料:
作者简介:文科院校ai算法工程师,专注于深度学习创新算法研究,致力于推动AI技术的边界。
如果这篇文章对您有帮助,请点赞、收藏、关注!您的支持是我继续创作的动力!
有任何问题或建议,欢迎在评论区留言讨论!