请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3351360 新帖:47

《机器学习》从零开始学(15) 集成方法之Baggin

交易资深人士发表于:6 月 27 日 00:00回复(1)

《机器学习》从零开始学(15) 集成方法之Bagging算法¶

参考教材:Python机器学习预测分析核心算法-[美]M·鲍尔-沙嬴&李鹏(译)-人民邮电出版社-2017

Machine Learning in Python:Essential Techniques for Predictive Analysis(Python机器学习:预测分析核心算法), Michael Bowles, Wiley, 2015.pdf 

注意:书中的代码很繁杂,我用更精炼的代码重写之。

所谓“从零开始”面向的对象其实仅指我本人。也就是我的学习笔记。

2) 自举集成:Bagging算法¶

Bagging算法是如何工作的¶

自举集成(bootstrap aggregation, 简写Bagging)核心: 首先,从训练集中通过有放回均匀随机抽样获得N组Bootstrap样本集。 然后,每组Bootstrap样本集按预先选定的某个基学习器构建模型,一共构建N个模型。 最后,通过投票取平均来整合这N个模型的预测值,进而获得整个集成模型的预测值。

有放回均匀随机抽样意味着:1) Bootstrap样本集可能有重复样本; 2) 这N组Bootstrap样本集的并集可能会遗漏掉原始数据。 然而,这正是我们所期望的,这为集成模型中各模型带来多样性。

下面的例子,选择二元决策树作为基学习器, 选择取平均来整合各模型的预测结果。

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn import treefrom sklearn.tree import DecisionTreeRegressor'''    产生玩具数据集'''m = 1001# 产生一组含标准正态随机扰动数据集x = 1.0*np.arange(m)/(m-1) - 0.5np.random.seed(1)y = x + np.random.normal(scale=0.1,size=m)'''    采样30%的数据作为测试集'''mSample = int(m * 0.30); idx = range(m); np.random.shuffle(idx)idxTest = idx[:mSample]; idxTest.sort()idxTrain = list(set(idx) - set(idxTest)); idxTrain.sort()xTrain = x[idxTrain].reshape((m-mSample,1)); yTrain = y[idxTrain]xTest = x[idxTest].reshape((mSample,1)); yTest = y[idxTest]'''    在训练集上生成一系列模型'''# 生成的最大模型数numTreesMax = 20# 决策树深度treeDepth = 1# 收集模型及其对应的预测modelList = []predList = []# 用于随机提升(bagging)的样本数 nBagSamples = int(len(xTrain) * 0.5)for iTrees in range(numTreesMax):# 有放回均匀取样idxBag = np.random.choice(m-mSample, nBagSamples)xTrainBag = xTrain[idxBag,:]yTrainBag = yTrain[idxBag]# 训练数据采样集进行二元决策树训练modelList.append(DecisionTreeRegressor(max_depth=treeDepth))modelList[-1].fit(xTrainBag, yTrainBag)# 预测并收集预测值latestPrediction = modelList[-1].predict(xTest)predList.append(list(latestPrediction))'''    给定头n个模型 n=1,...,numTreesMax    依次计算n个模型的平均预测值     依次计算n个模型的均方误差 '''allPredictions = 1.0 * np.cumsum(predList,axis=0) / np.arange(1,numTreesMax+1).reshape(numTreesMax,1)mse = ((yTest - allPredictions)**2).sum(axis=1) / len(yTest)'''    绘制或输出计算结果 '''# 绘制均方误差和模型数之间的关系nModels = [i + 1 for i in range(numTreesMax)]plt.plot(nModels,mse)plt.axis('tight')plt.xlabel(u'所用模型数目')plt.ylabel(u'均方误差')plt.ylim((0.0, max(mse)))plt.show()# 绘制原始数据及3组特定模型产生的预测值plotList = [0, 9, 19]for iPlot in plotList:plt.plot(xTest, allPredictions[iPlot])plt.plot(xTest, yTest, linestyle="")plt.axis('tight')plt.xlabel(u'测试输入x值')plt.ylabel(u'预测值')plt.show()print(u'最小均方误差')print(min(mse))
最小均方误差
0.024820246185

上述代码的二元决策树设置的默认深度是1, 那么1个模型(决策树)生成一个“单一台阶”预测。 10个模型和20个模型则在“单一台阶”附近生成更精细的“台阶”预测。

增加模型数,可以减少模型间的方差,但对深度为1的决策树的偏差是平均不掉的。

而要改善决策树的偏差,需要深度更深的决策树。 通过修改代码中变量treeDepth,可以重新绘制查看深度更深的决策树对预测曲线光滑度的影响。

如何解决多变量问题¶

前面的玩具数据集市单变量问题,下面将以红酒口感数据集来解决多变量问题。

由于我们是调用sklearn.tree.DecisionTreeRegressor进行决策树训练的,所以从代码角度和前面的代码没啥区别。

我们重点关注,下面代码的运行结果(包括调整参数变量treeDepth后的结果)。

1) 基于深度为1的决策树的集成方法,相对单1层决策树而言,均方误差几乎没有啥改变。

2)对多变量问题而言,决策树若要达到一定的性能要求,需要一定的决策树深度。

# 获取红酒数据集target_url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"df = pd.read_csv(target_url, header=0, sep=";")df.columns = ['非挥发性酸','挥发性酸','柠檬酸', '残留糖分', '氯化物', '游离二氧化*','总二氧化*', '密度', 
              'PH值', '亚硝酸盐', '酒精含量', '品质']xData = df.values[:,:-1]; yData = df.values[:,-1] m, n = xData.shape'''    采样30%的数据作为测试集'''mSample = int(m * 0.30);np.random.seed(1)idx = range(m);  np.random.shuffle(idx)idxTest = idx[:mSample]; idxTest.sort()idxTrain = list(set(idx) - set(idxTest)); idxTrain.sort()xTrain = xData[idxTrain,:]; yTrain = yData[idxTrain]xTest = xData[idxTest,:]; yTest = yData[idxTest]'''    在训练集上生成一系列模型'''# 生成的最大模型数numTreesMax = 20# 决策树深度treeDepth = 1# 收集模型及其对应的预测modelList = []predList = []# 用于随机提升(bagging)的样本数 nBagSamples = int(len(xTrain) * 0.5)for iTrees in range(numTreesMax):# 有放回均匀取样idxBag = np.random.choice(m-mSample, nBagSamples)xTrainBag = xTrain[idxBag,:]yTrainBag = yTrain[idxBag]# 训练数据采样集进行二元决策树训练modelList.append(DecisionTreeRegressor(max_depth=treeDepth))modelList[-1].fit(xTrainBag, yTrainBag)# 预测并收集预测值latestPrediction = modelList[-1].predict(xTest)predList.append(list(latestPrediction))'''    给定头n个模型 n=1,...,numTreesMax    依次计算n个模型的平均预测值     依次计算n个模型的均方误差 '''allPredictions = 1.0 * np.cumsum(predList,axis=0) / np.arange(1,numTreesMax+1).reshape(numTreesMax,1)mse = ((yTest - allPredictions)**2).sum(axis=1) / len(yTest)'''    绘制或输出计算结果 '''# 绘制均方误差和模型数之间的关系nModels = [i + 1 for i in range(numTreesMax)]plt.plot(nModels,mse)plt.axis('tight')plt.xlabel(u'所用模型数目')plt.ylabel(u'均方误差')plt.ylim((0.0, max(mse)))plt.show()print(u'最小均方误差')print(min(mse))
最小均方误差
0.483658658747

全部回复

0/140

量化课程

    移动端课程