二元分类器只做一个预测

数据挖掘 分类 深度学习 张量流
2021-09-17 14:41:37

tl;博士我正在构建一个二进制分类器,它总是最终在一定数量的时期后预测所有“0”或所有“1”,我正在寻找可能的原因/如何继续。

以下是有关我的方法和想法的更多详细信息:

我在做什么:我正在构建一个二进制分类基本前馈神经网络,用于使用 tensorflow 进行信号处理。

我通过将数据分成长度为 window_size 点(比如 50)的“窗口”来预处理我的数据,并且该窗口/示例可以被认为是“1”(正)或“0”(负)。官方手动标注的标签位于特定点(例如 403、875、1450 等),并且间隔相对均匀。如果窗口包含标签,我决定我的示例/窗口为正,否则为负。通过将窗口移动一些 stride_length(例如 1、2 或 10 个点等)生成多个示例,直到我的移动窗口到达信号的末尾。

对于训练数据,由于我的大多数示例都是负数,因此我尝试将 neg 与 pos 示例的比率标准化,使其接近 1:1。我通过删除负样本的计算比率来做到这一点。对于测试数据,我跳过了最后一步,但其他一切都是一样的。

我通过 3 层 NN 运行它,RELU 在隐藏层上,sigmoid 在唯一输出上,<0.5 预测负数,>0.5 预测正数。成本是(标签 - 预测)^2 的总和,使用默认 LR (0.001) 的 AdamOptimizer。

我的问题: 无论我调整什么参数,我的 NN 似乎在一定数量的时期后(有时甚至在第一个时期立即)预测所有内容为负或正。也蛮随意的。我会多次运行同一件事,每次都会得到不同的结果,大约一半的预测都是正面的,另一半都是负面的。

我尝试过/想过的事情:

  • 在训练我的模型之前,我对训练示例进行了洗牌,没有太大的改进。
  • 如上所述,我减少了负面示例,因为在减少之前我遇到了这个问题(基本上立即预测所有负面示例)。但现在我有接近 1:1 的 pos/neg 示例,它在预测所有负数和所有正数之间翻转,所以它对这个比率非常敏感。
  • 我最初有一个带有 one-hot 编码的 softmax_cross_entropy_with_logits 成本函数,所以 0 1 是正数,而 1 0 是负数。(我想也许成本函数会奖励极端预测,所以我改用平方和,它更苛刻)
  • 我正在考虑尝试批量标准化和辍学,但我不希望这些能解决我的问题。
  • 我认为问题可能在于我如何预处理数据。我的思考过程是这样的:如果 pos/neg 示例的比率如此重要,以至于它使我的模型预测所有正面或全部负面,那么我的数据中可能没有真正的趋势(这是错误的,因为任何有眼睛的人都可以看到不同)。我的想法是,因为我有一个移动窗口,所以有时标签靠近移动窗口的左边缘,有时靠近右边缘,这意味着实际感兴趣的区域每次都输入到不同的神经元中,这会使神经元感到困惑,所以感觉没有真正的趋势。
  • 但是,我查看了权重和偏差,它们似乎在几个时期后趋于稳定。如果数据真的没有趋势,他们不应该还在疯狂地跳来跳去吗?也许那是错误的。
  • 我正在考虑通过不同的神经网络运行左倾标签示例和右倾标签示例来测试我的假设,看看我是否能得到更好的结果,但也许不值得付出努力。

我已经尝试了一段时间,似乎想不出一个好的解释或方法。我非常感谢我能得到的任何帮助,我很乐意提供更多信息。谢谢!

2个回答

我怀疑有几个问题:

  1. 成本函数对于分类来说是不寻常的。您通常会使用您提到的交叉熵之类的东西。确保在输入交叉熵损失时不要对输出设置阈值。此外,我不会将 L2 损失描述为更“苛刻”。如果您对特定数据点的预测概率为 0,但其标签为 1,则 L2 损失将为 1。但对于交叉熵,损失将非常大。
  2. 它预测验证集上的所有一个类还是任何特定批次?
    • 如果它只是一个特定的批次,那么您对数据的批处理方式可能是关闭的,并且一个类的所有内容都在该批次中。查看准确性和损失等指标。
    • 如果是验证集,我会调查训练损失是否持续下降。也许学习率太高了。您使用的是基于动量的 Adam,因此它不一定需要像标准 SGD 那样高的学习率。
  3. 如果权重稳定,则意味着网络已饱和或您的损失为 0,并且您的优化问题已解决(可能不是后者)。如果网络饱和太快,批量标准化肯定会有所帮助。

与其对负值进行抽样以达到 1:1 的比例,不如尝试对类进行加权。您可以简单地使用您已经计算的现有正:负比率并将其传递给 skflow 中的 class_weights 参数(假设您使用的是 skflow,如果没有,在任何 ML 包/语言中几乎总是有等效的方法)。

例子:

class_weight = tf.constant([0.9, 0.1]))

skflow.models.logistic_regression(X, y, class_weight=class_weight)

我建议这样做的原因是您的随机所有正面或所有负面输出可能取决于您对负面示例进行下采样的方式。如果您随机执行此操作,您可能会删除数据集中的一些关键示例,分类器将使用这些示例来学习区分类别(例如:股票数据,其中两根蜡烛显示下降,但一个显示更多的下降)。通过加权,您可以对所有数据进行训练并消除这个潜在问题,同时仍然平等地“学习”两个类。