随机森林 预测股价
以下只是一个例子,源码为python。本文所有的内容仅供参考和学习研究之用,没有任何实战意义,禁止用于商业投资策略,作者不承担任何的商业投资风险和责任。
这个是利用随机森林模型预测出来的股价,准确率超过95%,以下为python源码。
源码如下:
#author:bf88bb77@126.com
#www.fruit78.com
import pandas as pd
import numpy as np # 导入numpy模块,用于数值计算
from sklearn.preprocessing import MinMaxScaler # 导入sklearn中的MinMaxScaler,用于特征缩放
import xgboost as xgb
from prettytable import PrettyTable # 可以优美的打印表格结果
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score # 导入额外的评估指标
from math import sqrt # 从math模块导入sqrt函数,用于计算平方根
from matplotlib import rcParams
import matplotlib.pyplot as plt # 导入matplotlib.pyplot模块,用于绘图
from sklearn.ensemble import RandomForestRegressor
dataset = pd.read_csv(‘train_dataset.csv’)
values = dataset.values[:,2:] #只取第2列数据,要写成1:2;只取第3列数据,要写成2:3,取第2列之后(包含第二列)的所有数据
values = pd.read_csv(‘train_dataset.csv’).values
把数据集分为训练集和测试集
values = np.array(values)
将前面处理好的DataFrame(data)转换成numpy数组,方便后续的数据操作。
num_samples = values.shape[0]
n_train_number = per[:int(num_samples * 0.99)] # 选择99%作为训练集
n_test_number = per[int(num_samples * 0.99):] # 选择除过99%之外的作为测试集
计算训练集的大小。
设置99%作为训练集
int(…) 确保得到的训练集大小是一个整数。
先划分数据集,在进行归一化,这才是正确的做法!
Xtrain = values[n_train_number, :-1] # 取特征列
Ytrain = values[n_train_number, -1] # 取最后一列为目标列
Ytrain = Ytrain.reshape(-1, 1)
Xtest = values[n_test_number, :-1]
Ytest = values[n_test_number, -1]
Ytest = Ytest.reshape(-1, 1)
对训练集和测试集进行归一化
m_in = MinMaxScaler()
vp_train = m_in.fit_transform(Xtrain) # 注意fit_transform() 和 transform()的区别
vp_test = m_in.transform(Xtest) # 注意fit_transform() 和 transform()的区别
m_out = MinMaxScaler()
vt_train = m_out.fit_transform(Ytrain) # 注意fit_transform() 和 transform()的区别
vt_test = m_out.transform(Ytest) # 注意fit_transform() 和 transform()的区别
使用模型对测试集的输入特征(vp_test)进行预测。
yhat是模型预测的输出值。
yhat = yhat.reshape(-1, 1)
将预测值yhat重塑为二维数组,以便进行后续操作。
predicted_data = m_out.inverse_transform(yhat) # 反归一化
def mape(y_true, y_pred):
定义一个计算平均绝对百分比误差(MAPE)的函数。
record = []
for index in range(len(y_true)):
遍历实际值和预测值。
temp_mape = np.abs((y_pred[index] - y_true[index]) / y_true[index])
计算单个预测的MAPE。
record.append(temp_mape)
将MAPE添加到记录列表中。
return np.mean(record)
返回所有记录的平均值,乘以100得到百分比。
def evaluate_forecasts(Ytest, predicted_data, n_out):
定义一个函数来评估预测的性能。
mse_dic = []
rmse_dic = []
mae_dic = []
mape_dic = []
r2_dic = []
初始化存储各个评估指标的字典。
table = PrettyTable([‘测试集指标’, ‘MSE’, ‘RMSE’, ‘MAE’, ‘MAPE’, ‘R2’])
for i in range(n_out):
遍历每一个预测步长。每一列代表一步预测,现在是在求每步预测的指标
actual = [float(row[i]) for row in Ytest] # 一列列提取
从测试集中提取实际值。
predicted = [float(row[i]) for row in predicted_data]
从预测结果中提取预测值。
mse = mean_squared_error(actual, predicted)
计算均方误差(MSE)。
mse_dic.append(mse)
rmse = sqrt(mean_squared_error(actual, predicted))
计算均方根误差(RMSE)。
rmse_dic.append(rmse)
mae = mean_absolute_error(actual, predicted)
计算平均绝对误差(MAE)。
mae_dic.append(mae)
MApe = mape(actual, predicted)
计算平均绝对百分比误差(MAPE)。
mape_dic.append(MApe)
r2 = r2_score(actual, predicted)
计算R平方值(R2)。
r2_dic.append(r2)
if n_out == 1:
strr = ‘预测结果指标:’
else:
strr = ‘第’ + str(i + 1) + ‘步预测结果指标:’
table.add_row([strr, mse, rmse, mae, str(MApe) + ‘%’, str(r2 * 100) + ‘%’])
print(“对price进行预测得出的值:”)
print(predicted)
print(“price实际的值:”)
print(actual)
return mse_dic, rmse_dic, mae_dic, mape_dic, r2_dic, table
返回包含所有评估指标的字典。
mse_dic, rmse_dic, mae_dic, mape_dic, r2_dic, table = evaluate_forecasts(Ytest, predicted_data, 1)
print(table) # 显示预测指标数值
config = {
“font.family”: ‘serif’,
“font.size”: 6,
“mathtext.fontset”: ‘stix’, # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
“font.serif”: [‘Times New Roman’], # Times New Roman
‘axes.unicode_minus’: False # 处理负号,即-号
}
rcParams.update(config) # 设置想要的格式
plt.ion()
plt.rcParams[‘axes.unicode_minus’] = False
设置matplotlib的配置,用来正常显示负号。
使用赛博朋克风样式
plt.style.use(‘cyberpunk’)
创建一个图形对象,并设置大小为10x2英寸,分辨率为300dpi。
plt.figure(figsize=(4, 2), dpi=300)
x = range(1, len(predicted_data) + 1)
创建x轴的值,从1到实际值列表的长度。
plt.xticks(x[::int((len(predicted_data)+1))])
设置x轴的刻度,每几个点显示一个刻度。
plt.tick_params(labelsize=5) # 改变刻度字体大小
设置刻度标签的字体大小。
plt.plot(x, predicted_data, linestyle=“–”, linewidth=0.8, label=‘predict’, marker=“o”, markersize=2)
绘制预测值的折线图,线型为虚线,线宽为0.5,标签为’predict’。
plt.plot(x, Ytest, linestyle=“-”, linewidth=0.5, label=‘Real’, marker=“x”, markersize=2)
绘制实际值的折线图,线型为直线,线宽为0.5,标签为’Real’。
plt.rcParams.update({‘font.size’: 5}) # 改变图例里面的字体大小
更新图例的字体大小。
plt.legend(loc=‘upper right’, frameon=False)
显示图例,位置在图形的右上角,没有边框。
plt.xlabel(“Sample points”, fontsize=5)
设置x轴标签为"样本点",字体大小为5。
plt.ylabel(“value”, fontsize=5)
设置y轴标签为"值",字体大小为5。
plt.title(f"The prediction result:\nMAPE: {mape(Ytest, predicted_data)} %", fontsize=5)
plt.xlim(xmin=600, xmax=700) # 显示600-1000的值 局部放大有利于观察
如果需要,可以取消注释这行代码,以局部放大显示600到700之间的值。
plt.savefig(‘figure/预测结果图.png’)
如果需要,可以取消注释这行代码,以将图形保存为PNG文件。
plt.ioff() # 关闭交互模式
plt.show()
以下为截至2025年3月8日的数据:
以下为结果:
