![](/img/trans.png)
[英]GradientBoostingTree training with soft labels in scikit-learn?
[英]scikit-learn classification on soft labels
根据文档,可以为SGDClassifier
指定不同的损失函数。 据我所知,对log loss
是cross-entropy
损失 function 理论上可以处理软标签,即以某些概率 [0,1] 给出的标签。
问题是:是否可以开箱即用SGDClassifier
with log loss
function 来解决软标签的分类问题? 如果不是 - 如何使用 scikit-learn 解决此任务(软标签上的线性分类)?
更新:
target
的标记方式和问题的性质硬标签不会给出好的结果。 但这仍然是一个分类问题(不是回归),我不想保留对prediction
的概率解释,所以回归也不是开箱即用的。 交叉熵损失 function 可以自然地处理target
中的软标签。 似乎scikit-learn中线性分类器的所有损失函数都只能处理硬标签。
所以问题大概是:
例如,如何为SGDClassifier
指定我自己的损失 function。 似乎scikit-learn
并没有坚持这里的模块化方法,需要在它的源代码中的某个地方进行更改
我最近遇到了这个问题,并提出了一个似乎有效的不错的修复方法。
基本上,使用逆 sigmoid 函数将您的目标转换为对数优势比空间。 然后拟合线性回归。 然后,为了进行推理,从线性回归模型中获取预测的 sigmoid。
因此,假设我们有软目标/标签y ∈ (0, 1)
(确保将目标限制为[1e-8, 1 - 1e-8]
以避免在我们记录日志时出现不稳定问题)。
我们采用逆 sigmoid,然后我们拟合线性回归(假设预测变量在矩阵X
):
y = np.clip(y, 1e-8, 1 - 1e-8) # numerical stability
inv_sig_y = np.log(y / (1 - y)) # transform to log-odds-ratio space
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X, inv_sig_y)
然后进行预测:
def sigmoid(x):
ex = np.exp(x)
return ex / (1 + ex)
preds = sigmoid(lr.predict(X_new))
这似乎有效,至少对于我的用例。 我的猜测是,无论如何,LogisticRegression 的幕后发生的事情都不远了。
奖励:这似乎也适用于sklearn
其他回归模型,例如RandomForestRegressor
。
根据文档,
“log”损失给出了逻辑回归,一种概率分类器。
通常,损失函数的形式为Loss( prediction, target )
,其中prediction
是模型的输出, target
是真实值。 在逻辑回归的情况下, prediction
是(0,1)
上的值(即“软标签”),而target
是0
或1
(即“硬标签”)。
因此,在回答您的问题时,这取决于您指的是prediction
还是target
。 一般来说,标签的形式(“硬”或“软”)由为prediction
选择的算法和target
手头数据给出。
如果您的数据具有“硬”标签,并且您希望模型输出“软”标签(可以设置阈值以提供“硬”标签),那么是的,逻辑回归属于这一类。
如果您的数据具有“软”标签,那么在使用典型分类方法(即逻辑回归)之前,您必须选择一个阈值将它们转换为“硬”标签。 否则,您可以使用模型适合的回归方法来预测“软”目标。 在后一种方法中,您的模型可能会给出(0,1)
之外的值,并且必须对此进行处理。
对于那些感兴趣的人,我已经实现了一个自定义的 class,它的行为类似于普通分类器,但在构造函数中采用任何回归器来执行@nlml 建议的转换:
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_array
from scipy.special import softmax
import numpy as np
def _log_odds_ratio_scale(X):
X = np.clip(X, 1e-8, 1 - 1e-8) # numerical stability
X = np.log(X / (1 - X)) # transform to log-odds-ratio space
return X
class FuzzyTargetClassifier(ClassifierMixin, BaseEstimator):
def __init__(self, regressor):
'''
Fits regressor in the log odds ratio space (inverse crossentropy) of target variable.
during transform, rescales back to probability space with softmax function
Parameters
---------
regressor: Sklearn Regressor
base regressor to fit log odds ratio space. Any valid sklearn regressor can be used here.
'''
self.regressor = regressor
return
def fit(self, X, y=None, **kwargs):
#ensure passed y is onehotencoded-like
y = check_array(y, accept_sparse=True, dtype = 'numeric', ensure_min_features=1)
self.regressors_ = [clone(self.regressor) for _ in range(y.shape[1])]
for i in range(y.shape[1]):
self._fit_single_regressor(self.regressors_[i], X, y[:,i], **kwargs)
return self
def _fit_single_regressor(self, regressor, X, ysub, **kwargs):
ysub = _log_odds_ratio_scale(ysub)
regressor.fit(X, ysub, **kwargs)
return regressor
def decision_function(self,X):
all_results = []
for reg in self.regressors_:
results = reg.predict(X)
if results.ndim < 2:
results = results.reshape(-1,1)
all_results.append(results)
results = np.hstack(all_results)
return results
def predict_proba(self, X):
results = self.decision_function(X)
results = softmax(results, axis = 1)
return results
def predict(self, X):
results = self.decision_function(X)
results = results.argmax(1)
return results
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.