1

以下代码

from sklearn import metrics
import numpy as np
y_true = np.array([[0.2,0.8,0],[0.9,0.05,0.05]])
y_predict = np.array([[0.5,0.5,0.0],[0.5,0.4,0.1]])
metrics.log_loss(y_true, y_predict)

产生以下错误:

   ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-32-24beeb19448b> in <module>()
----> 1 metrics.log_loss(y_true, y_predict)

~\AppData\Local\conda\conda\envs\tensorflow\lib\site-packages\sklearn\metrics\classification.py in log_loss(y_true, y_pred, eps, normalize, sample_weight, labels)
   1646         lb.fit(labels)
   1647     else:
-> 1648         lb.fit(y_true)
   1649 
   1650     if len(lb.classes_) == 1:

~\AppData\Local\conda\conda\envs\tensorflow\lib\site-packages\sklearn\preprocessing\label.py in fit(self, y)
    276         self.y_type_ = type_of_target(y)
    277         if 'multioutput' in self.y_type_:
--> 278             raise ValueError("Multioutput target data is not supported with "
    279                              "label binarization")
    280         if _num_samples(y) == 0:

ValueError: Multioutput target data is not supported with label binarization

我很好奇为什么。我正在尝试重新阅读日志丢失的定义,但找不到任何会使计算不正确的东西。

4

2 回答 2

3

源代码表明metrics.log_loss不支持y_true. 它只支持形状的二进制指示符(n_samples, n_classes),例如,[[0,0,1],[1,0,0]]或形状的类标签(n_samples,),例如[2, 0]。在后一种情况下,在计算对数损失之前,类标签将被单热编码以看起来像指标矩阵。

在这个块中:

lb = LabelBinarizer()

if labels is not None:
    lb.fit(labels)
else:
    lb.fit(y_true)

您正在到达,如果不是 all和/或lb.fit(y_true),这将失败。例如:y_true10

>>> import numpy as np
>>> from sklearn import preprocessing

>>> lb = preprocessing.LabelBinarizer()

>>> lb.fit(np.array([[0,1,0],[1,0,0]]))

LabelBinarizer(neg_label=0, pos_label=1, sparse_output=False)

>>> lb.fit(np.array([[0.2,0.8,0],[0.9,0.05,0.05]]))

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/imran/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/sklearn/preprocessing/label.py", line 278, in fit
    raise ValueError("Multioutput target data is not supported with "
ValueError: Multioutput target data is not supported with label binarization

我会定义你自己的自定义日志损失函数:

def logloss(y_true, y_pred, eps=1e-15):
    y_pred = np.clip(y_pred, eps, 1 - eps)
    return -(y_true * np.log(y_pred)).sum(axis=1).mean()

这是您的数据的输出:

>>> logloss(y_true, y_predict)
0.738961717153653
于 2018-01-29T16:48:31.050 回答
2

不,我不是在谈论二进制分类。

除非另有说明,否则上面显示的y_truey_predict您将不被视为分类目标。

首先,因为它们是概率,所以它可以采用任何连续值,因此在 scikit 中被检测为回归。

其次,y_pred 或 y_true 中的每个元素都是一个概率列表。这被检测为多输出。因此出现“多输出目标”的错误。

您需要log_loss为 y_true(基本事实)提供实际标签而不是概率。顺便说一句,为什么你有这种可能性?预测数据可以存在概率,但为什么实际数据存在概率?

为此,您需要首先y_true通过将最高概率视为获胜者类来将概率转换为标签。

这可以通过numpy.argmax使用以下代码来完成:

import numpy as np
y_true = np.argmax(y_true, axis=1)

print(y_true)
Output:-  [0, 1]
# We will not do this the above for y_predict, because probabilities are allowed in it.

# We will use labels param to declare that we have actually 3 classes, 
# as evident from your probabilities.
metrics.log_loss(y_true, y_predict, labels=[0,1,2])

Output:-  0.6931471805599458

y_true正如@Imran 所讨论的,这里有一个值不是 0 或 1的示例。

下面的示例简单地检查是否允许其他值:

y_true = np.array([0, 1, 2])
y_pred = np.array([[0.5,0.5,0.0],[0.5,0.4,0.1], [0.4,0.1,0.5]])
metrics.log_loss(y_true, y_pred)

Output:- 1.3040076684760489   (No error)
于 2018-01-30T17:12:59.570 回答