亚太杯赛题思路发布(中文版)

导读: 本文将继续修炼回归模型算法,并总结了一些常用的除线性回归模型之外的模型,其中包括一些单模型及集成学习器。

保序回归、多项式回归、多输出回归、多输出K近邻回归、决策树回归、多输出决策树回归、AdaBoost回归、梯度提升决策树回归、人工神经网络、随机森林回归、多输出随机森林回归、XGBoost回归。

需要面试或者需要总体了解/复习机器学习回归模型的小伙伴可以通读下本文,理论总结加代码实操,有助于理解模型。

本文所用数据说明:所有模型使用数据为股市数据,与线性回归模型中的数据一样,可以做参考,此处将不重复给出。

保序回归

保序回归或单调回归是一种将自由形式的直线拟合到一系列观测值上的技术,这样拟合的直线在所有地方都是非递减(或非递增)的,并且尽可能靠近观测值。

理论规则是

  • 如果预测输入与训练中的特征值完全匹配,则返回相应标签。如果一个特征值对应多个预测标签值,则返回其中一个,具体是哪一个未指定。

  • 如果预测输入比训练中的特征值都高(或者都低),则相应返回最高特征值或者最低特征值对应标签。如果一个特征值对应多个预测标签值,则相应返回最高值或者最低值。

  • 如果预测输入落入两个特征值之间,则预测将会是一个分段线性函数,其值由两个最近的特征值的预测值计算得到。如果一个特征值对应多个预测标签值,则使用上述两种情况中的处理方式解决。

    n = len(dataset['Adj Close'])

    X = np.array(dataset['Open'].values)

    y = dataset['Adj Close'].values

    from sklearn.isotonic import IsotonicRegression

    ir=IsotonicRegression()

    y_ir=ir.fit_transform(X,y)

将拟合过程可视化

红色散点图是原始数据X-y关系图,绿色线为保序回归拟合后的数据X-y_ir关系图。这里以可视化的形式表现了保序回归的理论规则。

lines=[[[i,y[i]],[i,y_ir[i]]] for i in range(n)]

lc=LineCollection(lines)

plt.figure(figsize=(15,6))

plt.plot(X,y,'r.',markersize=12)

plt.plot(X,y_ir,'g.-',markersize=12)

plt.gca().add_collection(lc)

plt.legend(('Data','Isotonic Fit','Linear Fit'))

plt.title("Isotonic Regression")

plt.show(

多项式回归

多项式回归(PolynomialFeatures)是一种用多项式函数作为自变量的非线性方程的回归方法。

将数据转换为多项式。多项式回归是一般线性回归模型的特殊情况。它对于描述曲线关系很有用。曲线关系可以通过平方或设置预测变量的高阶项来实现。

sklearn中的多项式拟合

X = dataset.iloc[ : , 0:4].values

Y = dataset.iloc[ : ,  4].values



from sklearn.preprocessing import PolynomialFeatures

from sklearn.linear_model import LinearRegression



poly=PolynomialFeatures(degree=3)

poly_x=poly.fit_transform(X)



regressor=LinearRegression()

regressor.fit(poly_x,Y)



plt.scatter(X,Y,color='red')

plt.plot(X,regressor.predict(poly.fit_transform(X)),color='blue')

plt.show()

以原始数据绘制X-Y红色散点图,并绘制蓝色的、经过多项式拟合后再进行线性回归模型拟合的直线图。

一元自变量计算三阶多项式
from scipy import *

f = np.polyfit(X,Y,3)

p = np.poly1d(f)

print(p)

            3            2

-6.228e-05x + 0.0023x + 0.9766x + 0.05357
多元自变量的多项式
from sklearn.preprocessing import PolynomialFeatures

from sklearn import linear_model

X = np.array(dataset[['Open', 'High', 'Low']].values)

Y = np.array(dataset['Adj Close'].values)



Y = Y.reshape(Y.shape[0], -1)

poly = PolynomialFeatures(degree=3)

X_ = poly.fit_transform(X)

predict_ = poly.fit_transform(Y)
Pipeline形式
from sklearn.pipeline import Pipeline

X = np.array(dataset['Open'].values)

Y = np.array(dataset['Adj Close'].values)

X = X.reshape(X.shape[0], -1)

Y = Y.reshape(Y.shape[0], -1)

Input=[('scale',StandardScaler()),('polynomial', PolynomialFeatures(include_bias=False)),('model',LinearRegression())]

pipe = Pipeline(Input)

pipe.fit(X,Y)

yhat = pipe.predict(X)

yhat[0:4]

array([[3.87445269],

       [3.95484371],

       [4.00508501],

       [4.13570206]])

numpy 中的多项式拟合

首先理解nump用于多项式拟合的两个主要方法。

np.poly1d
np.poly1d(c_or_r, 

          r=False, 

          variable=None)

一维多项式类,用于封装多项式上的"自然"操作,以便上述操作可以在代码中采用惯用形式。如何理解呢?看看下面几个例子。

  • c_or_r系数向量

    import numpy as np

    a=np.array([2,1,1])

    f=np.poly1d(a)

    print(f)

    2
    

    2 x + 1 x + 1

  • r=False是否反推

表示把数组中的值作为根,然后反推多项式。

f=np.poly1d([2,3,5],r=True)

#(x - 2)*(x - 3)*(x - 5)  = x^3 - 10x^2 + 31x -30

print(f)

   3      2

1 x - 10 x + 31 x - 30
  • variable=None表示改变未知数的字母

    f=np.poly1d([2,3,5],r=True,variable='z')

    print(f)

     3      2
    

    1 z - 10 z + 31 z - 30

np.polyfit
np.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)

最小二乘多项式拟合。

拟合多项式。返回一个系数'p'的向量,以最小化平方误差的顺序'deg'``,'deg-1',..."0"

推荐使用 <numpy.polynomial.polynomial.Polynomial.fit> 类方法,因为它在数值上更稳定。

下图是以原始数据绘制的蓝色X-Y散点图,以及红色的X分布图。

X = dataset['Open'].values

y = dataset['Adj Close'].values

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

plt.figure(figsize=(10,6))

plt.plot(X_train, y_train, 'bo')

plt.plot(X_test, np.zeros_like(X_test), 'r+')

plt.show()
numpy与sklearn中的多项式回归对比
# numpy

model_one = np.poly1d(np.polyfit(X_train, y_train,1))

preds_one = model_one(X_test)

print(preds_one[:3])

>>> [11.59609048 10.16018804 25.23716889]

# sklearn

from sklearn.linear_model import LinearRegression

model = LinearRegression()

model.fit(X_train.reshape(-1, 1), y_train)

preds = model.predict(X_test.reshape(-1, 1))

preds[:3]

>>> array([11.59609048, 10.16018804, 25.23716889])

# 预测结果是一样的

print("all close?", np.allclose(preds, preds_one))

>>> 'all close? True

结果表明两者相比预测结果时一致的。

多阶多项式效果对比

比较一阶、二阶及三阶多项式拟合,多线性回归模型的效果影响。由图可看出,三条线基本重合,且RMSE相差不大。

model_one = np.poly1d(np.polyfit(X_train, y_train,1))

model_two = np.poly1d(np.polyfit(X_train, y_train, 2))

model_three = np.poly1d(np.polyfit(X_train, y_train, 3))



fig, axes = plt.subplots(1, 2, figsize=(14, 5),sharey=True)

labels = ['line', 'parabola', 'nonic']

models = [model_one, model_two, model_three]

train = (X_train, y_train)

test = (X_test, y_test)

for ax, (ftr, tgt) in zip(axes, [train, test]):

    ax.plot(ftr, tgt, 'k+')

    num = 0

    for m, lbl in zip(models, labels):

        ftr = sorted(ftr)

        ax.plot(ftr, m(ftr), '-', label=lbl)

        if ax == axes[1]:

            ax.text(2,55-num, f"{lbl}_RMSE: {round(np.sqrt(mse(tgt, m(tgt))),3)}")

            num += 5

axes[1].set_ylim(-10, 60)

axes[0].set_title("Train")

axes[1].set_title("Test");

axes[0].legend(loc='best');
绘制类似学习曲线

因低阶多项式效果相差并不明显,因此增大多项式阶数,并以残差平方和为y轴,看模型拟合效果,由图可以看出,随着多项式阶数越来越高,模型出现严重的过拟合(训练集残差平方和降低,而测试集却在上涨)。

results = []

for complexity in [1, 2, 3, 4, 5, 6,7,8, 9]:

    model = np.poly1d(np.polyfit(X_train, y_train, complexity))

    train_error = np.sqrt(mse(y_train, model(X_train)))

    test_error = np.sqrt(mse(y_test,model(X_test)))

    results.append((complexity, train_error, test_error))

columns = ["Complexity", "Train Error", "Test Error"]

results_df = pd.DataFrame.from_records(results, 

              columns=columns,

              index="Complexity")

results_df

results_df.plot(figsize=(10,6))

多输出回归

多输出回归为每个样本分配一组目标值。这可以认为是预测每一个样本的多个属性,比如说一个具体地点的风的方向和大小。

多输出回归支持 MultiOutputRegressor 可以被添加到任何回归器中。这个策略包括对每个目标拟合一个回归器。因为每一个目标可以被一个回归器精确地表示,通过检查对应的回归器,可以获取关于目标的信息。因为 MultiOutputRegressor 对于每一个目标可以训练出一个回归器,所以它无法利用目标之间的相关度信息。

支持多类 - 多输出分类的分类器 :

sklearn.tree.DecisionTreeClassifier 

sklearn.tree.ExtraTreeClassifier  

sklearn.ensemble.ExtraTreesClassifier  

sklearn.neighbors.KNeighborsClassifier

sklearn.neighbors.RadiusNeighborsClassifier

sklearn.ensemble.RandomForestClassifier

X = dataset.drop(['Adj Close', 'Open'], axis=1)

Y = dataset[['Adj Close', 'Open']]



from sklearn.multioutput import MultiOutputRegressor

from sklearn.svm import LinearSVR



model = LinearSVR()

wrapper = MultiOutputRegressor(model)

wrapper.fit(X, Y)



data_in = [[23.98, 22.91, 7.00, 7.00, 

            1.62, 1.62, 4.27, 4.25]]

yhat = wrapper.predict(data_in)

print(yhat[0])

>>> [16.72625136 16.72625136]

wrapper.score(X, Y)

多输出K近邻回归

多输出K近邻回归可以不使用MultiOutputRegressor作为外包装器,直接使用KNeighborsRegressor便可以实现多输出回归。

X = dataset.drop(['Adj Close', 'Open'], axis=1)

Y = dataset[['Adj Close', 'Open']]

from sklearn.neighbors import KNeighborsRegressor

model = KNeighborsRegressor()

model.fit(X, Y)

data_in = [[23.98, 22.91, 7.00, 7.00, 

            1.62, 1.62, 4.27, 4.25]]

yhat = model.predict(data_in)

print(yhat[0])

>>> [2.34400001 2.352     ]

model.score(X, Y)

>>> 0.7053689393640217

决策树回归

决策树是一种树状结构,她的每一个叶子结点对应着一个分类,非叶子结点对应着在某个属性上的划分,根据样本在该属性上的不同取值降气划分成若干个子集。

基本原理

数模型通过递归切割的方法来寻找最佳分类标准,进而最终形成规则。CATA树,对回归树用平方误差最小化准则,进行特征选择,生成二叉树。

CATA回归树的生成

在训练数据集所在的空间中,递归地将每个空间区域划分为两个子区域,并决定每个子区域上的输出值,生产二叉树。

选择最优切分变量 和最优切分点 ,求解

遍历 ,对固定的切分变量 扫描切分点 ,使得上式达到最小值的对 ,不断循环直至满足条件停止。

X = dataset.drop(['Adj Close', 'Close'], axis=1)  

y = dataset['Adj Close'] 

# 划分训练集和测试集略 

# 模型实例化

from sklearn.tree import DecisionTreeRegressor  

regressor = DecisionTreeRegressor()  

# 训练模型

regressor.fit(X_train, y_train)

# 回归预测

y_pred = regressor.predict(X_test)

df = pd.DataFrame({'Actual':y_test, 'Predicted':y_pred})  

print(df.head(2))

            Actual  Predicted

Date                         

2017-08-09   12.83      12.63

2017-11-14   11.12      11.20

模型评价

from sklearn import metrics 

# 平均绝对误差

print(metrics.mean_absolute_error(

    y_test, y_pred))  

# 均方差

print(metrics.mean_squared_error(

    y_test, y_pred))

# 均方根误差

print(np.sqrt(

    metrics.mean_squared_error(

      y_test, y_pred)))

0.0924680893617

0.0226966010212

0.1506539114039

交叉验证

from sklearn.model_selection import cross_val_score

dt_fit = regressor.fit(X_train, y_train)

dt_scores = cross_val_score(

    dt_fit, X_train, y_train, cv = 5)



print("Mean cross validation score: {}".format(np.mean(dt_scores)))

print("Score without cv: {}".format(dt_fit.score(X_train, y_train)))

Mean cross validation score: 0.99824909037

Score without cv: 1.0

R2

from sklearn.metrics import r2_score



print('r2 score:', r2_score(y_test, dt_fit.predict(X_test)))

print('Accuracy Score:', dt_fit.score(X_test, y_test))

r2 score: 0.9989593390532074

Accuracy Score: 0.9989593390532074

亚太杯赛题思路发布(中文版)https://mbd.pub/o/bread/ZpeZm5dp

相关推荐
浊酒南街7 小时前
Statsmodels之OLS回归
人工智能·数据挖掘·回归
subject625Ruben1 天前
随机森林(Random Forest, RF)筛选回归数据(处理异常值)
算法·随机森林·数学建模·回归
杰哥技术分享2 天前
百度飞浆:paddle 线性回归模型
百度·线性回归·paddle
机器学习之心2 天前
POD-Transformer多变量回归预测(Matlab)
matlab·回归·transformer·pod-transformer
baijin_cha3 天前
机器学习基础07_sklearn梯度下降&岭回归&拉索回归&逻辑回归
笔记·机器学习·回归·sklearn
Hh27674741443 天前
对数几率回归
人工智能·数据挖掘·回归
Seeklike3 天前
11.19 机器学习-岭回归+拉索回归+逻辑回归
机器学习·回归·逻辑回归
谢眠3 天前
机器学习day7-线性回归3、逻辑回归、聚类、SVC
机器学习·逻辑回归·线性回归
卡卡_R-Python3 天前
训练误差or测试误差与特征个数之间的关系--基于R语言实现
开发语言·回归·r语言
行码棋3 天前
【机器学习】回归模型(线性回归+逻辑回归)原理详解
人工智能·机器学习·线性回归