我的问题总结:我有一个检测(二进制分类,不平衡问题)。我使用 sigmoid 对样本进行分类。报告的 f 分数、精度和召回率似乎考虑了这两个类别,例如,真阳性似乎是正确分类的样本总数,而不是属于正确分类的“1”类的样本总数。
更长的解释:在我的实验中,我有关于人的人口统计数据,我必须预测他们是否购买了产品。我使用 PCA 将初始特征减少到只有 4 个特征,并且数据存储在 csv 文件中(第一列有类标签,“0”和“1”)。请注意,大多数人没有购买,然后这两个班级非常不平衡。我使用CSVDataset类来读取它:
dataset: &train !obj:pylearn2.datasets.csv_dataset.CSVDataset {
path: 'input.csv',
task: 'classification'
}
我想从一个简单的分类模型开始,我使用 f-score 作为性能衡量标准。因此,我的第一个想法是使用具有单个 sigmoid 层的 MLP 模型(默认监视器“检测”提供召回、精度、f-score):
model: !obj:pylearn2.models.mlp.MLP {
layers: [
!obj:pylearn2.models.mlp.Sigmoid {
layer_name: 'y',
dim: 2,
irange: .005
}
],
nvis: 4,
}
我最初的想法是将dim设置为1(决策规则是:如果输出> 0.5选择类'1',如果< 0.5选择类'0')。但是,我得到了错误ValueError: Can't convert to VectorSpace of dim 1. Expected either dim=2 (merged one-hots) or 2 (concatenated one-hots)然后我决定将 dim 设置为 2 (决策规则将是:如果 out1 > out0 选择 '1',如果 out1
在我的train.yaml中,我或多或少地遵循了文档中提供的 softmax 示例笔记本。例如,我使用 BGD 算法并将 batch_size 设置为训练集中的示例总数(74164 个示例,一个小数据集!)只是为了避免在手动检查性能时产生混淆。
该模型使用提供的train.py脚本进行训练,一切似乎都很好,直到我查看了结果。如前所述,这是一个检测问题,其中要检测的类('1')很少发生。因此,我很惊讶地看到报告的 train_y_f1 的高值(最好的结果是大约 94%,在一个 epoch 之后)。
为了检查这一点,我使用提供的脚本 predict_csv.py 手动计算了 f 分数,然后加载了预测。我看到实际上只有未命中(所有“1”都归类为“0”),所以精确率、召回率和 f-score 应该都为零。为什么检测监视器报告更高的值?
经过一番调查,我发现 MLP 对每个类都有一个输出,并且我验证(手动计算并得到相同的数字)在 get_detection_channels_from_state() 中定义的真阳性和假阳性实际上指的是两个类,“1”和'0',例如真阳性是属于分类为'1'的'1'的向量的数量与属于分类为'0'的'0'的向量的数量之和。因此 MLP 将所有内容分类为“0”,并且由于几乎所有向量都属于“0”,因此性能很好。这是不平衡检测问题的一个已知问题,其中正确分类率不是合适的度量,这也是我们使用 f-score 或 AUC 等度量的原因。然而,
我可以想象这是 Sigmoid 类的设计者知道的,所以我只能假设我做错了什么。希望有人可以给我一个提示:)
注意:我已将此问题提交到 pylearn2 用户邮件列表。如果我得到答案,我会在这里复制它......