随机森林原理及代码

一、简介

机器学习中有一种大类叫集成学习(Ensemble Learning),集成学习的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。集成算法大致可以分为:Bagging,Boosting 和 Stacking 三大类型。
机器学习中有两种任务,回归和分类,而随机森林可以同时胜任这两种任务。其中分类任务是对离散值进行预测(比如将一景图像中的植被,建筑,水体等地物类型分类);回归任务是对连续值进行预测(比如根据已有的数据预测明天的气温是多少度,预测明天某基金的价格)。

随机森林(Random Forest)是一种经典的Bagging模型,其弱学习器为决策树模型。 如下图所示,随机森林模型会在原始数据集中随机抽样,构成n个不同的样本数据集,然后根据这些数据集搭建n个不同的决策树模型,最后根据这些决策树模型的平均值(针对回归模型)或者投票情况(针对分类模型)来获取最终结果。
在这里插入图片描述
为了保证模型的泛化能力(或者说通用能力),随机森林模型在建立每棵树时,往往会遵循“数据随机”和“特征随机”这两个基本原则。

  1. 数据随机:从所有数据当中有放回地随机抽取数据作为其中一个决策树模型的训练数据。例如,有1000个原始数据,有放回地抽取1000次,构成一组新的数据,用于训练某一个决策树模型。
  2. 特征随机:如果每个样本的特征维度为M,指定一个常数k<M,随机地从M个特征中选取k个特征。

二、思路

前面已经提到过,随机森林是属于集成学习,其核心思想就是集成多个弱分类器以达到三个臭皮匠赛过诸葛亮的效果。随机森林采用Bagging的思想,所谓的Bagging就是:
(1)每次有放回地从训练集中取出 n 个训练样本,组成新的训练集;
(2)利用新的训练集,训练得到M个子模型;
(3)对于分类问题,采用投票的方法,得票最多子模型的分类类别为最终的类别;对于回归问题,采用简单的平均方法得到预测值。
随机森林以决策树为基本单元,通过集成大量的决策树,就构成了随机森林。其构造过程如下:
(1)构建单棵决策树。
随机森林是多棵决策树的集成,决策树结构如下。
在这里插入图片描述
树的构建包括两个部分:样本和特征。
样本:对于一个总体训练集T,T中共有N个样本,每次有放回地随机选择N(因为有放回,所以虽然是N但是不可能遍历所有样本)个样本。这样选择好了的N个样本用来训练一个决策树。
特征:假设训练集的特征个数为d,每次仅选择k(k<d)个构建决策树。
下面开始构建决策树。
第一步:T中共有N个样本,有放回的随机选择N个样本。这选择好了的N个样本用来训练一个决策树,作为决策树根节点处的样本。
第二步:当每个样本有M个属性时,在决策树的每个节点需要分裂时,随机从这M个属性中选取出m个属性,满足条件m << M。然后从这m个属性中采用某种策略(比如说信息增益)来选择1个属性作为该节点的分裂属性。
第三步:决策树形成过程中每个节点都要按照步骤2来分裂,一直到不能够再分裂为止。注意整个决策树形成过程中没有进行剪枝。
第四步:按照步骤1~3建立大量的决策树,这样就构成了随机森林了。
(2)产生最终结果。
众多决策树构成了随机森林,每棵决策树都会有一个投票结果,最终投票结果最多的类别,就是最终的模型预测结果。
在这里插入图片描述

三、代码

# 导入相关库
import tushare as ts
import numpy as np
import pandas as pd
import talib
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# 1.股票基本数据获取
import tushare as ts
df = ts.get_k_data('000002',start='2015-01-01',end='2019-12-31')
df = df.set_index('date')

# 2.简单衍生变量数据构造
df['close-open'] = (df['close'] - df['open']) / df['open']
df['high-low'] = (df['high'] - df['low']) / df['low']
df['pre_close'] = df['close'].shift(1)
df['price_change'] = df['close'] - df['pre_close']
df['p_change'] = (df['close'] - df['pre_close']) / df['pre_close'] * 100

# 3.移动平均线相关数据构造
df['MA5'] = df['close'].rolling(5).mean()
df['MA10'] = df['close'].rolling(10).mean()
df.dropna(inplace=True)

# 4.通过TA-Lib库构造衍生变量数据
df['RSI'] = talib.RSI(df['close'],timeperiod=12)
df['MOM'] = talib.MOM(df['close'],timeperiod=5)
df['EMA12'] = talib.EMA(df['close'],timeperiod=12) #12日指移动平均值数
df['EMA26'] = talib.EMA(df['close'],timeperiod=26) #26日指移动平均值数
df['MACD'],df['MACDsignal'],df['MACDhist'] = talib.MACD(df['close'],fastperiod=6,slowperiod=12,signalperiod=9)
df.dropna(inplace=True)

# 提取特征变量和目标变量
X = df[['close','volume','close-open','MA5','MA10','high-low','RSI','MOM','EMA12','MACD','MACDsignal','MACDhist']]
y = np.where(df['price_change'].shift(-1) > 0,1,-1)

# 划分训练集和测试集
X_length = X.shape[0]
split = int(X_length * 0.9)
X_train,X_test = X[:split],X[split:]
y_train,y_test = y[:split],y[split:]

# 模型训练
model = RandomForestClassifier(max_depth=3,n_estimators=10,min_samples_leaf=10,random_state=123)
model.fit(X_train,y_train)

# 预测明天股价
y_pred = model.predict(X_test)
result = pd.DataFrame()
result['预测值'] = list(y_pred)
result['实际值'] = list(y_test)
result.head()

# 预测概率
y_pred_proba = model.predict_proba(X_test)
result_proba = pd.DataFrame(y_pred_proba, columns=['分类为-1的概率','分类为1的概率'])
result_proba.head()

# 模型准确度评估
accuracy = accuracy_score(y_pred, y_test)
print(accuracy)

model.score(X_test, y_test)

# 分析特征变量的重要性
importances = model.feature_importances_
result_im = pd.DataFrame()
result_im['特征'] = X.columns
result_im['特征重要性'] = importances
result_im = result_im.sort_values('特征重要性', ascending=False)
result_im 

# 参数调优
from sklearn.model_selection import GridSearchCV
parameters={'n_estimators':[5,10,20],'max_depth':[2,3,4,5,6],'min_samples_leaf':[5,10,20,30]}
new_model = RandomForestClassifier(random_state=123)
grid_search = GridSearchCV(new_model,parameters,cv=6,scoring='accuracy')
grid_search.fit(X_train,y_train)
grid_search.best_params_

# 输出
# {'max_depth': 5, 'min_samples_leaf': 20, 'n_estimators': 5}

# 收益回测曲线绘制
# 在测试数据上添加一列,预测收益
X_test['prediction'] = model.predict(X_test)

# 计算每天的股价变化率
X_test['p_change'] = (X_test['close'] - X_test['close'].shift(1)) / X_test['close'].shift(1)

# 计算累积收益率
# 例如,初始股价是1,2天内的价格变化率为10%
# 那么用cumprod()函数可以求得2天后的股价为1×(1+10%)×(1+10%)=1.21
# 此结果也表明2天的收益率为21%。
X_test['origin'] = (X_test['p_change'] + 1).cumprod()

# 计算利用模型预测后的收益率
X_test['strategy'] = (X_test['prediction'].shift(1) * X_test['p_change'] + 1).cumprod()

X_test[['strategy','origin']].dropna().plot()
# 设置自动倾斜
plt.gcf().autofmt_xdate()
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值