Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在多标签分类中使用样本权重_Python_Scikit Learn_Classification - Fatal编程技术网

Python 在多标签分类中使用样本权重

Python 在多标签分类中使用样本权重,python,scikit-learn,classification,Python,Scikit Learn,Classification,当我使用线性SVM在scikit learn中处理分类问题时,我可以对每个训练样本应用自定义权重,如下所示: from sklearn.linear_model import SGDClassifier X = [[0.0, 0.0], [1.0, 1.0]] y = [0, 1] sample_weight = [1.0, 0.5] clf = SGDClassifier(loss="hinge") clf.fit(X, y, sample_weight=sample_weight) 现在

当我使用线性SVM在scikit learn中处理分类问题时,我可以对每个训练样本应用自定义权重,如下所示:

from sklearn.linear_model import SGDClassifier

X = [[0.0, 0.0], [1.0, 1.0]]
y = [0, 1]
sample_weight = [1.0, 0.5]
clf = SGDClassifier(loss="hinge")
clf.fit(X, y, sample_weight=sample_weight)
现在,当我有一个多标签分类任务时,我需要转换标签,
sgdclassizer
必须包装在一个元估计器中,如
OneVsRestClassifier

from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import SGDClassifier

X = [[0.0, 0.0], [1.0, 1.0], [1.0, 0.0]]
y = [[0], [1], [0, 1]]
y_mlb = MultiLabelBinarizer().fit_transform(y)
sample_weight = [1.0, 0.5, 0.8]
clf = OneVsRestClassifier(SGDClassifier(loss="hinge"))
clf.fit(X, y_mlb)   # unable to pass `sample_weight`

但是,除了
X
y
之外,
OneVsRestClassifier
不允许我向
fit
方法传递任何参数,因此我无法像以前那样应用样本权重。在这种情况下,我如何应用自己的样本权重?

相反,请尝试将OneVsRestClassifier子类化,以更改fit方法以允许传递样本权重。 您需要更改其中使用的fit()和_fit_binary()方法

请尝试编辑以下内容:

import warnings
import numpy as np
from sklearn.externals.joblib import Parallel, delayed
from sklearn.base import clone
from sklearn.multiclass import _ConstantPredictor, OneVsRestClassifier
from sklearn.preprocessing import LabelBinarizer, MultiLabelBinarizer
from sklearn.linear_model import SGDClassifier

def _fit_binary_new(estimator, X, y, sample_weight, classes=None):
    unique_y = np.unique(y)
    if len(unique_y) == 1:
        if classes is not None:
            if y[0] == -1:
                c = 0
            else:
                c = y[0]
            warnings.warn("Label %s is present in all training examples." %
                          str(classes[c]))
        estimator = _ConstantPredictor().fit(X, unique_y)
    else:
        estimator = clone(estimator)

        # Only this changed
        estimator.fit(X, y, sample_weight=sample_weight)
    return estimator

class OneVsRestClassifierNew(OneVsRestClassifier):

    def fit(self, X, y, sample_weight=None):
        self.label_binarizer_ = LabelBinarizer(sparse_output=True)
        Y = self.label_binarizer_.fit_transform(y)
        Y = Y.tocsc()
        self.classes_ = self.label_binarizer_.classes_
        columns = (col.toarray().ravel() for col in Y.T)
        self.estimators_ = Parallel(n_jobs=self.n_jobs)(delayed(_fit_binary_new)(
            self.estimator, X, column, sample_weight, classes=[
                "not %s" % self.label_binarizer_.classes_[i],
                self.label_binarizer_.classes_[i]])
            for i, column in enumerate(columns))

        return self


X = [[0.0, 0.0], [1.0, 1.0], [1.0, 0.0]]
y = [[0], [1], [0, 1]]
y_mlb = MultiLabelBinarizer().fit_transform(y)
sample_weight = [1.0, 0.5, 0.8]
clf = OneVsRestClassifierNew(SGDClassifier(loss="hinge"))
clf.fit(X, y_mlb, sample_weight=sample_weight)

clf.predict(X)
# Output: array([[1, 0],
#                [0, 1],
#                [1, 1]])

注意:这只适用于那些在fit()方法中定义了sample\u weight的分类器,因为我不检查
\u fit\u binary\u new()中是否存在

我试图用一个技巧解决这个问题:用一个自定义实现替换
sgdclassizer
实例的
fit
方法,该实现获取对我的样本权重列表的引用,但是:结果是
OneVsRestClassifier
克隆了估计器。当然,不是使用标准的python工具,而是使用从
get_params
方法检索的参数实例化同一类的新估计器。因此,猴子补丁没有被保留,我又回到了原点……因此现在我可以将
sgdclassizer
子类化,添加样本权重作为实例参数,修补
get_params
方法,修补
fit
方法以使用类中存储的样本权重。。。这是可怕的,这似乎工作,但我可以看到它将如何爆炸,一旦sklearn开发人员决定触摸其中一个功能。也许我应该为此提交一份bug报告(或功能请求)。无论如何,谢谢你的回答。@Klamann可能是因为OneVsRestClassifier设计用于所有不适合样本权重的估计器()。无论如何,我试图搜索此请求的现有问题,但找不到。请随意补充。另外,请接受答案,如果它的工作和帮助。我已经为此提交了一份报告。我知道OneVsRestClassifier应该能够与其他估计器一起工作,因此显而易见的解决方案是将任意Kwarg传递给底层估计器。我会把这件事留一段时间,也许有人会想出一个不那么麻烦的解决办法。