0

我的问题总结:我有一个检测(二进制分类,不平衡问题)。我使用 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 用户邮件列表。如果我得到答案,我会在这里复制它......

4

1 回答 1

0

pylearn 监视器计算每个批次的 f1 分数、错误分类百分比等,而不是整个 epoch。当它生成报告时,f1 分数是epoch 中所有批次的 f1 的平均值。当您查看诸如错误分类之类的数量时,报告所有批次的平均值就可以了:

misclass[n] 是第 n 批的分数
misclass_epoch = mean(misclass[0] + misclass[1] +.. misclass[n])

但是,您不能为 f1 分数构造相同的语句:
f1_epoch != mean(f1[0] + f1[1] +.. f1[n])
where f1[n] = 2*precision[n]*召回[n]/(精度[n] + 召回[n])

出于演示目的,尝试将批量大小设置为数据集的大小(您可以在 mnist 示例中摆脱这一点)。f1 分数将是正确的。

因此,最好的建议是密切关注监视器中的数量,例如 misclass,其中批次的平均值与 epoch 的值相同。训练好 nn 后,您就可以对整个验证集进行预测并计算此时的 f1 分数。

于 2015-04-24T04:59:08.633 回答