分位數(shù)回歸模型quantile regeression應(yīng)用詳解及示例教程
普通最小二乘法如何處理異常值? 它對(duì)待一切事物都是一樣的——它將它們平方! 但是對(duì)于異常值,平方會(huì)顯著增加它們對(duì)平均值等統(tǒng)計(jì)數(shù)據(jù)的巨大影響。
我們從描述性統(tǒng)計(jì)中知道,中位數(shù)對(duì)異常值的魯棒性比均值強(qiáng)。 這種理論也可以在預(yù)測(cè)統(tǒng)計(jì)中為我們服務(wù),這正是分位數(shù)回歸的意義所在——估計(jì)中位數(shù)(或其他分位數(shù))而不是平均值。 通過選擇任何特定的分位數(shù)閾值,我們既可以緩和異常值,也可以調(diào)整錯(cuò)誤的正/負(fù)權(quán)衡。我們還可以處理需要分位數(shù)界限的情況,例如:嬰兒的安全出生體重,頂級(jí)競(jìng)技電子競(jìng)技玩家的技能水平,等等。
什么是分位數(shù)?
分位數(shù)(Quantile),亦稱分位點(diǎn),是指將一個(gè)隨機(jī)變量的概率分布范圍分為幾個(gè)等份的數(shù)值點(diǎn),常用的有中位數(shù)(即二分位數(shù))、四分位由3個(gè)部分組成(第25、50和75個(gè)百分位,常用于箱形圖)和百分位數(shù)等。
什么是分位數(shù)回歸?
分位數(shù)回歸是簡(jiǎn)單的回歸,就像普通的最小二乘法一樣,但不是最小化平方誤差的總和,而是最小化從所選分位數(shù)切點(diǎn)產(chǎn)生的絕對(duì)誤差之和。 如果 q=0.50(中位數(shù)),那么分位數(shù)回歸會(huì)出現(xiàn)一個(gè)特殊情況 - 最小絕對(duì)誤差(因?yàn)橹形粩?shù)是中心分位數(shù))。我們可以通過調(diào)整超參數(shù) q,選擇一個(gè)適合平衡特定于需要解決問題的誤報(bào)和漏報(bào)的閾值。
statsmodels中的分位數(shù)回歸
分位數(shù)回歸是一種不太常見的模型,但 Python中的StatsModel庫(kù)提供了他的實(shí)現(xiàn)。這個(gè)庫(kù)顯然受到了R的啟發(fā),并從它借鑒了各種語(yǔ)法和API。
StatsModel使用的范例與scikit-learn稍有不同。但是與scikit-learn一樣,對(duì)于模型對(duì)象來(lái)說,需要公開一個(gè).fit()方法來(lái)實(shí)際訓(xùn)練和預(yù)測(cè)。但是不同的是scikit-learn模型通常將數(shù)據(jù)(作為X矩陣和y數(shù)組)作為.fit()的參數(shù),而StatsModel是在初始化對(duì)象時(shí)傳入數(shù)據(jù),而fit方法只傳遞一些可以調(diào)試的超參數(shù)。
下面是來(lái)自statsmodel的例子(Engel數(shù)據(jù)集包含在與statmodels中)
%matplotlib inline import numpy as np import pandas as pd import statsmodels.api as sm import statsmodels.formula.api as smf import matplotlib.pyplot as plt data = sm.datasets.engel.load_pandas().data mod = smf.quantreg("foodexp ~ income", data) res = mod.fit(q=0.5) print(res.summary())
我們可以看看quantile regression model fit的幫助文檔:
help(quant_mod.fit)
分位數(shù)回歸與線性回歸
標(biāo)準(zhǔn)最小二乘回歸模型僅對(duì)響應(yīng)的條件均值進(jìn)行建模,并且計(jì)算成本較低。 相比之下,分位數(shù)回歸最常用于對(duì)響應(yīng)的特定條件分位數(shù)進(jìn)行建模。 與最小二乘回歸不同,分位數(shù)回歸不假設(shè)響應(yīng)具有特定的參數(shù)分布,也不假設(shè)響應(yīng)具有恒定方差。
下表總結(jié)了線性回歸和分位數(shù)回歸之間的一些重要區(qū)別:
xgboost的分位數(shù)回歸
最后如果想使用xgboost,又想試試分位數(shù)回歸,那么可以參考以下代碼
class XGBQuantile(XGBRegressor): def __init__(self,quant_alpha=0.95,quant_delta = 1.0,quant_thres=1.0,quant_var =1.0,base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0,max_depth=3, min_child_weight=1, missing=None, n_estimators=100, n_jobs=1, nthread=None, objective='reg:linear', random_state=0,reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,silent=True, subsample=1): self.quant_alpha = quant_alpha self.quant_delta = quant_delta self.quant_thres = quant_thres self.quant_var = quant_var super().__init__(base_score=base_score, booster=booster, colsample_bylevel=colsample_bylevel, colsample_bytree=colsample_bytree, gamma=gamma, learning_rate=learning_rate, max_delta_step=max_delta_step, max_depth=max_depth, min_child_weight=min_child_weight, missing=missing, n_estimators=n_estimators, n_jobs= n_jobs, nthread=nthread, objective=objective, random_state=random_state, reg_alpha=reg_alpha, reg_lambda=reg_lambda, scale_pos_weight=scale_pos_weight, seed=seed, silent=silent, subsample=subsample) self.test = None def fit(self, X, y): super().set_params(objective=partial(XGBQuantile.quantile_loss,alpha = self.quant_alpha,delta = self.quant_delta,threshold = self.quant_thres,var = self.quant_var) ) super().fit(X,y) return self def predict(self,X): return super().predict(X) def score(self, X, y): y_pred = super().predict(X) score = XGBQuantile.quantile_score(y, y_pred, self.quant_alpha) score = 1./score return score @staticmethod def quantile_loss(y_true,y_pred,alpha,delta,threshold,var): x = y_true - y_pred grad = (x<(alpha-1.0)*delta)*(1.0-alpha)- ((x>=(alpha-1.0)*delta)& (x<alpha*delta) )*x/delta-alpha*(x>alpha*delta) hess = ((x>=(alpha-1.0)*delta)& (x<alpha*delta) )/delta grad = (np.abs(x)<threshold )*grad - (np.abs(x)>=threshold )*(2*np.random.randint(2, size=len(y_true)) -1.0)*var hess = (np.abs(x)<threshold )*hess + (np.abs(x)>=threshold ) return grad, hess @staticmethod def original_quantile_loss(y_true,y_pred,alpha,delta): x = y_true - y_pred grad = (x<(alpha-1.0)*delta)*(1.0-alpha)-((x>=(alpha-1.0)*delta)& (x<alpha*delta) )*x/delta-alpha*(x>alpha*delta) hess = ((x>=(alpha-1.0)*delta)& (x<alpha*delta) )/delta return grad,hess @staticmethod def quantile_score(y_true, y_pred, alpha): score = XGBQuantile.quantile_cost(x=y_true-y_pred,alpha=alpha) score = np.sum(score) return score @staticmethod def quantile_cost(x, alpha): return (alpha-1.0)*x*(x<0)+alpha*x*(x>=0) @staticmethod def get_split_gain(gradient,hessian,l=1): split_gain = list() for i in range(gradient.shape[0]): split_gain.append(np.sum(gradient[:i])/(np.sum(hessian[:i])+l)+np.sum(gradient[i:])/(np.sum(hessian[i:])+l)-np.sum(gradient)/(np.sum(hessian)+l) ) return np.array(split_gain)
https://gist.github.com/benoitdescamps/af5a8e42d5cfc7981e960e4d559dad19#file-xgboostquantile-py
對(duì)于LightGBM這里有一篇詳細(xì)的實(shí)現(xiàn)文章:
http://jmarkhou.com/lgbqr/
以上就是分位數(shù)回歸quantile regeression詳解及示例教程的詳細(xì)內(nèi)容,更多關(guān)于分位數(shù)回歸quantile regeression的資料請(qǐng)關(guān)注本站其它相關(guān)文章!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。