与子类别区分

时间:2016-09-24 15:44:27

标签: machine-learning scikit-learn

这些天我正在处理区分A和B两个类别,我发现当B类包含一些子类别B1,B2,B3 ...

有时,区分结果对于明确标记B1,B2,B3(子类别标签)更好,但有时结果更适合收集子类别并只标记它们。

换句话说,有时候

y=[A, A, A, ..., B1, B1, ..., B2, B2, ... B3, B3, ...]

更好,但有时候,

y=[A, A, A, ..., B, B, B, ...]

更好。

我天真地认为结果会产生两种影响:

  1. 案例1包含更多信息
  2. 案例2算法可以更多地关注A和B的区分
  3. 但我不确定我的假设是对的,有人知道吗?在处理这种情况时,如果有子类别,那么您获得最佳结果的方式是什么?

1 个答案:

答案 0 :(得分:0)

在这种情况下,您可以使用两级分类器,它首先预测顶级类,第二级选择最可能的二级类。这是我使用过的一些代码,

from sklearn.base import BaseEstimator, ClassifierMixin
import pandas as pd
import numpy as np

class TwoLevelClassifier(BaseEstimator, ClassifierMixin):
    """
    A two-level classifier intended to be used with labels taken from a 2-level taxonomy. 
    The labels are pipe-separated class-subclass pairs as "class|subclass".

    >>> from sklearn.linear_model import LogisticRegression()
    >>> X = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]])
    >>> y1 = pd.Series(['A','A','B'])
    >>> y2 = pd.Series(['A1','A2','B1'])
    >>> y = y1 + "|" + y2
    >>> clf = TwoLevelClassifier(LogisticRegression(), LogisticRegression())
    >>> clf.fit(X,y)
    """

    def __init__(self, classifier1, classifier2):
        self.classifier1 = classifier1
        self.classifier2 = classifier2

    def fit(self, X, y):
        y1 = y.str.split('|').str[0]
        y2 = y.str.split('|').str[1]
        self.classifier1.fit(X, y1)
        self.classifier2.fit(X, y)
        self.classes_ = self.classifier2.classes_

    def predict_proba(self, X):
        level1_pred = pd.Series(self.classifier1.predict(X))
        probs = pd.DataFrame(self.classifier2.predict_proba(X), columns = self.classifier2.classes_)
        classes_ = self.classifier2.classes_
        mask = np.array(pd.Series(level1_pred).map(lambda x: [y.split('|')[0] == x for y in classes_]).tolist())
        probs_filtered = probs.where(mask, 0)
        return probs_filtered.values

    def predict(self, X):
        probs = self.predict_proba(X)
        return probs.idxmax(axis=1)