文章目录

  • 1. 什么是回归?
  • 2. 回归模型
  • 2.1 线性回归
  • 2.1.1 普通线性回归
  • 2.1.2 岭回归
  • 2.2 决策树回归
  • 2.3 SVM回归
  • 参考


1. 什么是回归?

分类的目标变量是标称型数据,而回归是对连续型数据的预测。回归分析是一种预测建模技术,研究因变量和自变量之间的关系,如销售量预测或制造缺陷预测等,下图中的红线表示的就是回归曲线。

xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn

回归不同于分类和聚类,他们的区别可以用下图形象的表达出来。

xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_02

2. 回归模型

这里使用sklearn进行代码实现,如果想手动实现的话,可以看《机器学习实战》,那本书有部分的算法实现,下面介绍的算法统一使用的函数如下

  • 加载数据 数据文件
def load_data(file_path):
    num_feat = len(open(file_path).readline().split("\t")) - 1
    data_mat = list()
    lable_mat = list()
    fr = open(file_path)
    for line in fr.readlines():
        line_arr = list()
        cur_line = line.strip().split("\t")
        for i in range(num_feat):
            line_arr.append(float(cur_line[i]))
        data_mat.append(line_arr)
        lable_mat.append(float(cur_line[-1]))
    return data_mat, lable_mat
  • 绘制回归结果
def plot_regression(model, x_data, y_data):
    x_data = np.mat(x_data)
    y_data = np.mat(y_data).T
    x_train, y_train = x_data[:150,1:], y_data[:150,:]
    x_test, y_test = x_data[150:,1:], y_data[150:,:]
    model.fit(x_train, y_train)
    score = model.score(x_test, y_test)
    result = model.predict(x_train)
    plt.figure()
    srt_idx = x_train.argsort(0)
    plt.plot(x_train[srt_idx].reshape(-1,1), y_train[srt_idx].reshape(-1,1), 'go', label = "true value")
    plt.plot(x_train[srt_idx].reshape(-1,1), result[srt_idx].reshape(-1,1), 'ro-', label = "predict value")
    plt.title("score:%f" % score)
    plt.legend()
    plt.show()

2.1 线性回归

2.1.1 普通线性回归

提到回归,首先想到的肯定是线性回归(linear regression),因为它是最容易理解,最简单的回归方法。设待拟合的数据对象为xgboost 回归 实战 得到回归模型 回归模型介绍_数据_03,其对应的真实值为xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_04,线性模型可以写为
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_05
其中,xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_06回归系数,我们用平方误差来衡量拟合的误差
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_07
上式对xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_06求导等于0可以得到
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_09
可以得到
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_10
上述方式容易对训练数据欠拟合,一种好的解决方式是局部加权线性回归,为每个误差增加一个权重xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_11(这里的xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_06并不是上面的xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_13),此时误差函数可以写成
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_14
其中,xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_15是一个对角矩阵,也叫做核,核的类型可以自由选择,最常见的就是高斯核,高斯核对应的权重如下
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_16
注意:这里的xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_17是指的单个数据,每个数据对应的权重矩阵都不同。
同样的,对新的误差函数xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_18求导可以得到此时回归系数为
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_19
这里的xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_15其实是xgboost 回归 实战 得到回归模型 回归模型介绍_数据_21,但是使用xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_15代替具有同样的意义并且简便。

sklearn调用代码:

x_data, y_data = load_data("ex0.txt")
from sklearn import linear_model
# 线性回归
model_linear_regression = linear_model.LinearRegression()
plot_regression(model_linear_regression, x_data, y_data)

绘制出的回归曲线如下图所示

xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_23

2.1.2 岭回归

我们看线性回归中的输入集xgboost 回归 实战 得到回归模型 回归模型介绍_数据_03,假设其维度为xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_25,当xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_26的时候,xgboost 回归 实战 得到回归模型 回归模型介绍_数据_27不是满秩矩阵,无法求解逆矩阵,这时候就需要用到**岭回归(ridge regression)**了,在矩阵xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_28上加上一个xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_29让其成为满秩矩阵,那么这个时候的回归系数为
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_30

sklearn调用代码:

x_data, y_data = load_data("ex0.txt")
from sklearn import linear_model
# Ridge回归
model_ridge = linear_model.Ridge(alpha = 0.01)
plot_regression(model_ridge, x_data, y_data)

绘制出的回归曲线如下图所示

xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_31

2.2 决策树回归

决策树学习常用的算法有ID3、C4.5、CART(classification and regression tree),这介绍用于回归的决策树CART,具体的方法理论参考李航的《统计学习方法》。

我们考虑输入的训练数据xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_32,一个回归树对应着输入空间(即特征空间)的一个划分以及在划分的单元上的输出值,假设已将输入空间划分为xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_33个单元xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_34,并且在每一个单元上都有一个固定的输出值xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_35,那么回归树模型可以表示为
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_36
其中,函数xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_37对应着0-1函数。当输入空间的划分确定时,可以用平方误差xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_38来表示回归树对于训练数据的预测误差,用平方误差最小的准则求解每个单元上的最优输出值,那么单元xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_39上的最优值xgboost 回归 实战 得到回归模型 回归模型介绍_数据_40xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_39上的所有输入实例xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_17对应的输出xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_43的均值,即
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_44
上面是整个树的输出形式,关键的问题来了,怎么对输入空间进行划分?这里采用启发式的算法,选择第xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_45个变量和它取的值xgboost 回归 实战 得到回归模型 回归模型介绍_数据_46作为切分变量(spliting variable)和切分点(spliting point),并定义两个区域
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_47
然后寻找最优切分变量和最优切分点,即
xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_48
简单的理解,就是在要求切分点xgboost 回归 实战 得到回归模型 回归模型介绍_数据_46两边的区域的均方差都尽量小的同时,保证两个区域的最小均方差和是最小的。

对每一对xgboost 回归 实战 得到回归模型 回归模型介绍_数据_50,均值表示为
xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_51
遍历所有输入变量,找到最优的对xgboost 回归 实战 得到回归模型 回归模型介绍_数据_50,从而将输入空间切分为两个区域,接着对切分的两个区域重复上述划分过程,直到满足停止条件为止,这样一个回归树的生成就完成了。

举个🌰,输入数据xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_53如下表所示。

xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_54

1

2

3

4

5

6

xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_55

5.56

5.70

5.91

6.40

6.90

7.95

对上述连续型变量,只有一个切分变量,那么考虑切分点为1.5, 2.5, 3.5, 4.5, 5.5。对切分点依次求解xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_56,例如当切分点为2.5时,xgboost 回归 实战 得到回归模型 回归模型介绍_数据_57,其他的计算如下
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_58
第一次切分时,对象为全体输入,计算出来的xgboost 回归 实战 得到回归模型 回归模型介绍_数据_59值如下表所示。

切分点

1.5

2.5

3.5

4.5

5.5

xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_60

3.23468

2.294

1.31373333

0.956725

1.21752

可以看到,当xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_61时,取得最小的xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_62值,此时的回归估计值为全体输入的均值6.403,递归求解左子树和右子树的回归估计值,最终求解的回归方程为
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_63

这个过程可以使用graphviz模块显示出来。


xgboost 回归 实战 得到回归模型 回归模型介绍_数据_64

使用本文一开始提到的数据,决策树回归的代码如下

# 决策树回归
from sklearn import tree
model_decisiontree_regression = tree.DecisionTreeRegress(min_weight_fraction_leaf=0.01)
plot_regression(model_decisiontree_regression, x_data, y_data)

xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_65

2.3 SVM回归

先回顾一下在基本线性可分情况下的SVM模型:
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_66
分类SVM模型中要让训练集中的每个样本尽可能远离自己类别一侧的支持向量,回归模型也一样,沿用的是最大建哥分类器的思想。

对于回归模型,优化的目标函数和分类模型保持一致,依然是xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_67,但是约束条件不一样,回归模型的目标是让训练集中的每个样本点xgboost 回归 实战 得到回归模型 回归模型介绍_数据_68尽量拟合到一个线性模型xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_69上,对于一般的回归模型使用均方误差MSE作为损失函数的,但是SVM回归不是这样定义的。

SVM需要我们定义一个常量xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_70,对于某一个点xgboost 回归 实战 得到回归模型 回归模型介绍_数据_68,如果xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_72,则完全没有损失,如果xgboost 回归 实战 得到回归模型 回归模型介绍_数据_73,则对应的损失为xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_74,这个和均方差损失不同,对于均方差,只要xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_75就会有损失。

如下图所示,在蓝色条带里面的点是没有损失的,但是在外面的点是有损失的,损失大小为红色线的长度。

xgboost 回归 实战 得到回归模型 回归模型介绍_回归模型_76

总结下,我们的SVM回归模型的损失函数度量为
xgboost 回归 实战 得到回归模型 回归模型介绍_sklearn_77
有了损失函数之后,我们就可以定义SVM回归的目标函数为
xgboost 回归 实战 得到回归模型 回归模型介绍_线性回归_78
这个模型的最优解求解过程这里不再赘述,有兴趣的可以看参考[2]或者[3]中的论述。

使用本文一开始提到的数据,SVM回归的代码如下

# SVM回归
from sklearn import svm
model_svr = svm.SVR()
plot_regression(model_svr, x_data, y_data)

xgboost 回归 实战 得到回归模型 回归模型介绍_机器学习_79

参考

[1] 李航. 统计学习方法, 清华大学出版社