损失函数为几个点的最小值,自定义损失函数和梯度

时间:2016-09-26 14:11:10

标签: python machine-learning scikit-learn gradient-descent

我试图预测金属线圈的质量。我的金属线圈宽10米,长1至6公里。作为训练数据,每10米测量约600个参数,最终质量控制标记 - 好/坏(整个线圈)。坏意味着至少有一个地方有线圈坏,没有数据在哪里。我有大约10000个线圈的数据。

让我们想象一下,我们希望训练这些数据的逻辑回归(有两个因素)。

X = [[0, 0],
      ...
     [0, 0],
     [1, 1], # coil is actually broken here, but we don't know it yet.
     [0, 0],
      ...
     [0, 0]]

Y = ?????

我不能把所有"坏"在Y和运行分类器,因为我会混淆分类器。我不能把所有"好的"和一个"坏"因为我不知道坏的位置在哪里。

我想到的解决方案如下,我可以将损失函数定义为总和((Y-min(F(x1,x2)))^ 2)(由所有F计算的最小值)属于一个线圈)不和((YF(x1,x2))^ 2)。在这种情况下,我可能正确地训练了F指向不好的地方。我需要渐变,它不可能在所有点上计算它,min在所有地方都不是可微分的,但我可以使用弱渐变(使用在每个地方线圈最小的函数值)。

我或多或少知道如何自己实现它,问题是使用scikit-learn在python中执行它的最简单方法是什么。理想情况下,它应该是相同的(或容易适应)几种学习方法(许多基于损失函数和梯度的方法),是否有可能为这种方式的学习方法做一些包装?

更新:查看gradient_boosting.py - 内部抽象类LossFunction能够计算损失和渐变,看起来是透视。看起来没有共同的解决方案。

1 个答案:

答案 0 :(得分:3)

您在此处考虑的内容在机器学习社区中被称为超集学习,这意味着,您可以以{(x_i,y_i)}的形式设置训练集,而不是典型的监督设置拥有{({x_1,...,x_N},y_1)},以便您知道集合中至少有一个元素具有属性y_1。这不是一个非常常见的设置,但现有的,有一些研究可用,google域中的论文。

就你自己的损失功能而言 - scikit-learn是不行的。 Scikit-learn是关于简单性的,它为您提供了一小组即用型工具,而且灵活性很小。它不是一个研究工具,你的问题是研究性的。你可以用什么代替?我建议你选择任何符号微分解决方案,例如autograd,它使你能够通过python代码区分,只需在它上面应用scipy.optimize.minimize就可以了!任何自定义丢失功能都可以正常工作。

作为旁注 - 最小运算符不可微分,因此模型可能很难弄清楚发生了什么。你可以尝试做sum((Y - prod_x F(x_1, x_2) )^2),因为乘法很容易区分,你仍然会得到类似的效果 - 如果至少有一个元素被预测为0,它将删除任何" 1"从其余的回答。您甚至可以更进一步使其在数值上更稳定,并且:

if Y==0 then loss = sum_x log(F(x_1, x_2 ) )
if Y==1 then loss = sum_x log(1-F(x_1, x_2))

转换为

Y * sum_x log(1-F(x_1, x_2)) + (1-Y) * sum_x log( F(x_1, x_2) )

您可以注意到与交叉熵成本的相似性,这非常有意义,因为您的问题确实是分类。而现在你有完美的概率损失 - 你正在附加每个细分的概率为“坏”"或"好"所以整个物体坏的概率要么高(如果Y == 0),要么低(如果Y == 1)。