分位数回归(quantile regression)简介和代码实现

article/2025/9/21 21:51:37

普通最小二乘法如何处理异常值? 它对待一切事物都是一样的——它将它们平方! 但是对于异常值,平方会显著增加它们对平均值等统计数据的巨大影响。

我们从描述性统计中知道,中位数对异常值的鲁棒性比均值强。 这种理论也可以在预测统计中为我们服务,这正是分位数回归的意义所在——估计中位数(或其他分位数)而不是平均值。 通过选择任何特定的分位数阈值,我们既可以缓和异常值,也可以调整错误的正/负权衡。我们还可以处理需要分位数界限的情况,例如:婴儿的安全出生体重,顶级竞技电子竞技玩家的技能水平,等等。

什么是分位数?

分位数(Quantile),亦称分位点,是指将一个随机变量的概率分布范围分为几个等份的数值点,常用的有中位数(即二分位数)、四分位由3个部分组成(第25、50和75个百分位,常用于箱形图)和百分位数等。

什么是分位数回归?

分位数回归是简单的回归,就像普通的最小二乘法一样,但不是最小化平方误差的总和,而是最小化从所选分位数切点产生的绝对误差之和。 如果 q=0.50(中位数),那么分位数回归会出现一个特殊情况 - 最小绝对误差(因为中位数是中心分位数)。我们可以通过调整超参数 q,选择一个适合平衡特定于需要解决问题的误报和漏报的阈值。

statsmodels中的分位数回归

分位数回归是一种不太常见的模型,但 Python中的StatsModel库提供了他的实现。这个库显然受到了R的启发,并从它借鉴了各种语法和API。

StatsModel使用的范例与scikit-learn稍有不同。但是与scikit-learn一样,对于模型对象来说,需要公开一个.fit()方法来实际训练和预测。但是不同的是scikit-learn模型通常将数据(作为X矩阵和y数组)作为.fit()的参数,而StatsModel是在初始化对象时传入数据,而fit方法只传递一些可以调试的超参数。

下面是来自statsmodel的例子(Engel数据集包含在与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 pltdata = 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)

分位数回归与线性回归

标准最小二乘回归模型仅对响应的条件均值进行建模,并且计算成本较低。 相比之下,分位数回归最常用于对响应的特定条件分位数进行建模。 与最小二乘回归不同,分位数回归不假设响应具有特定的参数分布,也不假设响应具有恒定方差。

下表总结了线性回归和分位数回归之间的一些重要区别:

xgboost的分位数回归

最后如果想使用xgboost,又想试试分位数回归,那么可以参考以下代码

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_alphaself.quant_delta = quant_deltaself.quant_thres = quant_thresself.quant_var = quant_varsuper().__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 = Nonedef 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 selfdef 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./scorereturn score@staticmethoddef quantile_loss(y_true,y_pred,alpha,delta,threshold,var):x = y_true - y_predgrad = (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)*varhess = (np.abs(x)<threshold )*hess + (np.abs(x)>=threshold )return grad, hess@staticmethoddef original_quantile_loss(y_true,y_pred,alpha,delta):x = y_true - y_predgrad = (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@staticmethoddef quantile_score(y_true, y_pred, alpha):score = XGBQuantile.quantile_cost(x=y_true-y_pred,alpha=alpha)score = np.sum(score)return score@staticmethoddef quantile_cost(x, alpha):return (alpha-1.0)*x*(x<0)+alpha*x*(x>=0)@staticmethoddef 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

对于LightGBM这里有一篇详细的实现文章:

http://jmarkhou.com/lgbqr/


http://chatgpt.dhexx.cn/article/hDRwqcSp.shtml

相关文章

分位数回归(Quantile Regression)

在介绍分位数回归之前&#xff0c;先重新说一下回归分析&#xff0c;我们之前介绍了线性回归、多项式回归等等&#xff0c;基本上&#xff0c;都是假定一个函数&#xff0c;然后让函数尽可能拟合训练数据&#xff0c;确定函数的未知参数。尽可能拟合训练数据&#xff0c;一般是…

C语言最全函数大全

以下图片以字母顺序排列&#xff0c;语法着色版本。 每个函数包含函数名&#xff0c;功能&#xff0c;用法&#xff0c;举例...

C语言函数大全-- s 开头的函数(2)

s 开头的函数&#xff08;2&#xff09; 1. setlinestyle1.1 函数说明1.2 演示示例1.3 运行结果 2. setmem2.1 函数说明2.2 演示示例 3. setmode3.1 函数说明3.2 演示示例3.3 运行结果 4. setpalette4.1 函数说明4.2 演示示例4.3 运行结果 5. setrgbpalette5.1 函数说明5.2 演示…

C语言函数大全-- i 开头的函数

i 开头的函数 1. imagesize1.1 函数说明1.2 演示示例1.3 运行结果 2. initgraph2.1 函数说明2.2 演示示例2.3 运行结果 3. inport3.1 函数说明3.2 演示示例 4. insline4.1 函数说明4.2 演示示例 5. installuserdriver5.1 函数说明5.2 演示示例 6. installuserfont6.1 函数说明6…

函数 C语言】

函数的声明和定义 函数间调用关系是&#xff0c;由于函数调用其他函数&#xff0c;替他函数也可以互相调用&#xff0c;同一个函数可以被一个或多个函数调用任意次。 先声明&#xff0c;后调用。 #include <stdio.h> //去标准库下找文件 #include "stdio.h"…

【C语言】函数详解

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️小林爱敲代码       &#x1f6f0;️专栏&#xff1a;✈️C语言快速入门       &#x1f6f0;️欢迎关注&#xff1a;&#x1f44d;点…

C语言函数大全-- s 开头的函数(1)

s 开头的函数&#xff08;1&#xff09; 1. sbrk1.1 函数说明1.2 演示示例 2. scalb&#xff0c;scalbf&#xff0c;scalbl2.1 函数说明2.2 演示示例 3. scalbln&#xff0c;scalblnf&#xff0c;scalblnl3.1 函数说明3.2 演示示例3.3 运行结果 4. scalbn&#xff0c;scalbnf&a…

【详解C语言】函数

文章目录 1. 函数是什么&#xff1f;2. C语言中函数的分类&#xff1a;1. 库函数&#xff1a;2. 自定义函数 3. 函数的参数3.1 实际参数&#xff08;实参&#xff09;3.2 形式参数&#xff08;形参&#xff09; 4. 函数的调用&#xff1a;4.1 传值调用4.2 传址调用4.3 练习 5. …

C语言函数介绍

1.字母的大小写转换-->islower() 2.快速排序函数-->qsort() 下面正式给大家介绍这两个函数 &#xff08;1&#xff09;islower() islower() 函数用来检测一个字符是否是小写字母。 在默认情况下&#xff0c;小写字母包括&#xff1a; a,b,c,d,e,f,g,h,i,j,k,l,m,n,o…

C语言标准库函数大全(ctype、time 、stdio、stdlib、math、string)

文章目录 C语言函数库:一. <ctype.h>二. <math.h>三. <stdio.h>四. <stdlib.h>五. <time.h>六. <string.h> 文档资料 C语言函数库: C语言的常用的标准头文件有 &#xff1a; <ctype.h>   <time.h>   <stdio.h> <…

【C语言进阶】最常用的库函数大全——从入门到精通

目录 前言&#xff1a; 一.字符串函数 1.strlen——求字符串长度 strlen 2.长度不受限制的字符串函数 a.strcpy——字符串拷贝 strcpy b.strcat——追加字符串 strcat c.strcmp——字符串比较 strcmp 3.长度受限制的字符串函数——strncpy,strncat,strncmp 为什么会…

C语言一些常用的函数

目录 sizeof()运算符strlen()函数abort()函数exit()函数Sleep()函数atof()将字符串转换成浮点数atoi()将字符串转换成整型数的函数atol()将字符串转换成长整型数的函数strlwr()函数strupr()函数 sizeof()运算符 sizeof()运算符: 编译器自带的,不用到任何包都能用。用法&…

C语言常用函数详解

函数详解&#xff1a; strlen(字符串长度)sizeof(字节大小)strcmp(字符串比较)strcpy(字符串拷贝)strcat(字符串追加)strncpy(字符串按字节拷贝)strncmp(字符串按字节比较)strncat(字符串按字节追加)strstr(查找字符串)strtok(查找符号)memcpy(按字节拷贝数据&#xff08;任意类…

C语言的中常用的函数

一、main函数 一个C程序就是由若干头文件和函数组成&#xff0c;有且只有一个主函数&#xff0c;即main函数。 #include <stdio.h>int main(){printf("c语言主函数");return 0; } C程序就是执行主函数里的代码&#xff0c;C语言中的唯一入口。 main前面的int…

C语言中常用的函数

C语言中常用的函数 1、putchar()函数2、getchar()函数3、pow( a , b )函数4、sqrt( a )函数5、fabs(a)函数6、puts(字符数组)函数——输出字符串的函数7、gets(字符数组)——输入字符串的函数8、strcat(a , b)函数——字符串连接函数9、strcpy函数——字符串复制函数10、strncp…

C语言中的函数(详解)

目录 1.函数是什么 2.c语言中函数的分类&#xff1a; 2.1. 库函数 2. 自定义函数 3. 函数的参数 3.1 实际参数&#xff08;实参&#xff09; 3.2 形式参数&#xff08;形参&#xff09; 4. 函数的调用&#xff1a; 4.1 传值调用 4.2 传址调用 5. 函数的嵌套调用和链…

linux Ubuntu将默认bash修改为csh

Ubuntu将默认bash修改为csh 前言Linux系统中的shell版本问题修改方法bash切换csh方法 前言 为什么要将默认bash修改为csh&#xff0c;有时候安装的软件命令是基于csh写的&#xff0c;如果用bash使用软件就会报错&#xff0c;如&#xff1a;“No command ‘setenv’ found”&…

配置你的 csh/tcsh

配置你的 csh/tcsh 选择 csh/tcsh 和许多刚从 Linux 转到 BSD 的人不同&#xff0c;我并没有装完 BSD 就顺手安装 bash&#xff0c;因为之前除了打命令&#xff0c;我没有用到额外的功能&#xff0c;bash 也好&#xff0c;csh 也罢&#xff0c;在我眼里都是当做 shell 来用。但…

bash 和 tcsh(csh)的不同,带例子

我使用bash和tcsh(csh)过程中总结出的一些异同&#xff0c;附我的彩色的提示行配置 效果&#xff1a; 自做的彩色提示符 bash PS1 命令提示符 ## PS1\[\033[01;33m\][\D{%y-%m-%d} \t]\[\033[00m\]\[\033[01;32m\][\!]\[\033[00m\]${debian_chroot:($debian_chroot)}\[\03…

Bash与Csh的区别

zz &#xff1a;http://dangdanding.blog.163.com/blog/static/27992981201262595221896/ 一、csh的while循环控制结构及if then: #!/bin/csh -f while ($#argv > 1) if ("$1" "-s") then shift if ($#argv > 1) then set source …