簡體   English   中英

sklearn 如何模擬訓練集中不存在的標簽的零概率預測?

[英]sklearn how to mock prediction of zero probabilities of the labels that were not present in the training set?

我希望我的標題正確。

我運行多類分類(3 個類)。 並用 ROC AUC 對其進行評分。

make_scorer(roc_auc_score, needs_proba=True, average="macro", multi_class='ovo', labels=[-1, 0, 1])

我用時間序列分割器分割了訓練/測試數據,不能重新調整數據的順序(沒有分層參數)。

其中一個拆分不包含訓練數據中的“0”label。 所以.fit function 只能看到 2 個標簽,因此 predict_proba function 只有 2 列 output。

當我運行多類 ROC AUC 評分時,我得到這個 ValueError Number of given labels, 3, not equal to the number of columns in 'y_score', 2

我認為我可以接受 function 預測“0”class 的概率為零。所以我想添加一個模擬概率預測。 有沒有辦法在標准庫中做到這一點?

還有其他建議嗎? 我想到了 1) 包裝 predict_proba,添加缺失的概率列 2) 更改時間序列拆分,以便如果訓練數據僅包含 2 個類 - 獲取更多訓練數據。

我將發布我最終所做的事情。 我做了一個包裝器 function,它返回帶有增強預測概率和增強擬合 function 的估計器(例如 LogisticRegression)的子項 class。擬合 function 保存它在 y_train 中看到的標簽。 predict_proba function 用零填充與 y_train 中不存在但存在於標簽中的標簽對應的列。

def predict_proba_wrapper(method: classmethod, labels: list):
    """Add zeros to the predict_proba columns if labels not present in y_true."""

    @wraps(method)
    def wrapper(self, *args, **kwargs ):
        # find labels indices not in y_train
        indices_to_fill = []
        for i, label in enumerate(labels):
            if label not in self.labels_seen:
                indices_to_fill.append(i)
        # call method
        y_pred = method(self, *args, **kwargs)
        # fill zeros
        if not isinstance(y_pred, np.ndarray):
            y_pred_np = np.array(y_pred)
        else:
            y_pred_np = y_pred

        for i in indices_to_fill:
            y_pred_np = np.insert(y_pred_np, i, 0., axis=1)

        if isinstance(y_pred, np.ndarray):
            return y_pred_np
        elif isinstance(y_pred, pd.DataFrame):
            return pd.DataFrame(y_pred_np, index=y_pred.index)
        elif isinstance(y_pred, pd.Series):
            return pd.Series(y_pred_np, index=y_pred.index)
        elif isinstance(y_pred, list):
            return y_pred_np.tolist()
        else:
            raise ValueError(f"y_pred type {type(y_pred)} not supported")

    return wrapper

def fit_wrapper(method: classmethod, labels: list):
    """Add labels seen to the class."""

    @wraps(method)
    def wrapper(self, *args, **kwargs ):
        res = method(self, *args, **kwargs)
        if len(args) >= 2:
            y = args[1]
        else:
            y = kwargs["y"]
        if isinstance(y, np.ndarray):
            self.labels_seen = list(np.unique(y))
        elif isinstance(y, pd.DataFrame):
            self.labels_seen = list(y.iloc[:, 0].unique())
        elif isinstance(y, pd.Series):
            self.labels_seen = list(y.unique())
        elif isinstance(y, list):
            self.labels_seen = list(set(y))
        else:
            raise ValueError(f"y type {type(y)} not supported")
        if hasattr(self, "classes_"):
            if isinstance(self.classes_, np.ndarray):
                self.classes_ = np.array(labels)
            elif isinstance(self.classes_, pd.DataFrame):
                self.classes_ = pd.DataFrame(labels)
            elif isinstance(self.classes_, pd.Series):
                self.classes_ = pd.Series(labels)
            elif isinstance(self.classes_, list):
                self.classes_ = labels
            else:
                raise ValueError(f"y type {type(y)} not supported")

        return res

    return wrapper


def class_child_with_wrapped_methods(class_: Type, method_names: List[str], wrappers: List[callable]):
    """Return a new class with a method wrapped by method wrapper."""
    new_class = type(class_.__name__ + "Wrapped", (class_,), {})
    for i, method_name in enumerate(method_names):
        setattr(new_class, method_name, wrappers[i](getattr(new_class, method_name)))
    return new_class


def wrap_fit_predict_proba(class_: Type, labels: list):
    """Return a new class with predict_proba wrapped by predict_proba_wrapper."""
    return class_child_with_wrapped_methods(
        class_,
        ["predict_proba", "fit"],
        [
            lambda x: predict_proba_wrapper(x, labels),
            lambda x: fit_wrapper(x, labels)
        ]
    )
    
CLASSIFIERS = [
    wrap_fit_predict_proba(LogisticRegression, labels[-1,0,1]),
    wrap_fit_predict_proba(ExtraTreesClassifier, labels=[-1,0,1]),
]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM