【问题标题】:Spark : setNumClasses() for a subset of labels for Multiclass LogisticRegressionModelSpark:setNumClasses() 用于 Multiclass LogisticRegressionModel 的标签子集
【发布时间】:2016-06-24 15:21:58
【问题描述】:

我有一个 id(标签)范围从 1 到 1040 的数据库。我正在使用多类 Logistic 回归来预测 id。现在,如果我只想训练标签的一个子集,比如说从 800 到 810。当我为 11 个类设置 setNumClasses(11) 时出现错误。我必须始终将此方法设置为类的最大值,即 1040。这样训练模型将针对从 0 到 1040 的所有标签进行训练,这非常昂贵并且使用大量资源。

我理解的对吗?如何通过给定 setNumClasses(count_of_classes) 仅针对标签子集训练我的模型。

final LogisticRegressionModel model = new LogisticRegressionWithLBFGS()
            .setNumClasses(811).run(train.rdd());

【问题讨论】:

    标签: apache-spark logistic-regression apache-spark-mllib


    【解决方案1】:

    根据预览答案的 cmets,我发现最后第二条评论是主要查询。如果设置 setNumClasses(23) 意味着:在训练集中所有的类都应该在(0 到 22)的范围内。检查 (docs)。写成:

    :: Experimental :: 设置多项 Logistic 回归中 k 类分类问题的可能结果数。默认情况下,它是二元逻辑回归,因此 k 将设置为 2。

    这意味着,对于二元逻辑回归,二元值/类是(0 和 1),因此 setNumClasses(2) 是默认值。

    在训练集中,如果您有 2、3、4 等其他类,则对于二进制分类,它将不起作用。

    建议的解决方案:如果您的训练集或子集包含 790 - 801 和 900 - 910 个类,则将您的数据标准化或转换为(0 到 22)并将 23 作为 setNumClasses(23)。

    【讨论】:

    • 标准化是什么意思?更改现有标签不是一个好主意,因为它已经被贴上了这样的标签。如果通过规范化您的意思是“只获取带有这些标签的记录进行训练”,那么这就是我的答案所建议的......而且你不必将它们规范化到一个范围(0,k),一个范围(n,n+k) 也可以工作.. .
    • 在您的上一条评论中,您说:“如果在过滤器之后 rdd 的所有行中,您将只有 21 个类(介于 790 和 801 之间以及介于 900 和 910 之间),那么您应该设置班数为 21"。根据这个你说你可以将21设置为numClasses。即使您在 790 和 801 以及 900 到 910 之间的火车集中有标签,这种方法是否适用于 21?我想你会再次得到那个错误。我说的对吗?
    • 所以,我的意思是归一化或转换,为了消除该错误,您必须如何将训练集的子集从 0 标记到 K-1。但你必须确保在预测后取回原始标签。
    • 你能解释一下这是怎么可能的吗?我可以在此处的文档中向您推荐:github.com/kaysar07cuet/spark/blob/master/mllib/src/main/scala/…。如果您检查,您会发现这样的 cmets: * 为二元 Logistic 回归训练分类模型 * 注意:Logistic 回归中使用的标签应为 {0, 1, ..., k - 1} * 对于 k 类多标签分类问题。 * 建议使用 [[LogisticRegressionWithLBFGS]]。 */"
    • 很好,你是对的!我一定检查过其他一些源代码。
    【解决方案2】:

    你不能这样做,你提供了一组训练数据,它可能在 Spark 的梯度下降方法中的某个地方失败(不确定,因为你没有提供错误消息)。

    Spark 应该如何确定它应该针对哪些 800 个标签来训练模型?

    您应该做的是仅过滤掉 RDD 中带有您想要训练模型的标签的行。例如,假设您的标签是 0 到 1040 之间的值,而您只想训练 0 到 800 的标签,您可以这样做:

    val actualTrainingRDD = train.filter( _.label < 801 )
    final LogisticRegressionModel model = new LogisticRegressionWithLBFGS()
            .setNumClasses(801).run(train.rdd());
    

    @Edit:是的,当然可以选择一组不同的标签,这只是一个例子,只需将过滤方法更改为:

    train.filter( row => (row.label >= 790 && row.label < 801) )
    

    这是 Scala,Java 闭包使用 -&gt;,对吗?

    【讨论】:

    • 这是我将 MAX 作为 386 传递时的错误。错误 DataValidators:分类标签应在 {0 到 385} 中。找到 676 个无效标签。我想过滤每个用户的 id。假设我有许多具有相同名称和不同 ID 的用户。对我来说没有意义,我必须训练“一千行如果行”以预测位于 900 - 910 范围内的类(id)。
    • 以你为例:我不想从 0 到 800 训练,而是从 790 到 800 训练。这可能吗?
    • @Sparkan 是的,但是 Spark(或更准确地说是底层算法)如何知道您只想将该模型用于标签 900-910,您是否将 11 作为类数传递?是的,只需更改过滤器关闭...
    • 是的,我希望能够从 DB 中提取这些类,以便我可以用它们训练算法并将 setNumClasses() 设置为 11。我希望我可以通过过滤器闭包来解决它。感谢@Mateusz 提供这个可能的解决方案,我会在这篇文章中更新我的进度。
    • 你好@Mateusz,如果同一个用户的 id 在两个范围之间怎么办? 790 - 801 和 900 - 910 之类的?过滤器也可以吗?
    猜你喜欢
    • 2010-12-15
    • 2019-08-13
    • 2019-05-16
    • 2022-01-08
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多