数据挖掘实训:基于CEEMDAN与多种机器学习模型股票预测与时间序列建模

股票市场的预测是金融领域中的一个重要研究方向,尤其是如何通过历史数据预测未来股价。这篇博客将带你走进如何通过多种方法,如CEEMDAN(Complete Ensemble Empirical Mode Decomposition with Adaptive Noise)分解技术与机器学习模型(如SVM、XGBoost、LSTM等)结合,来实现股票价格预测。我们将使用苹果公司(AAPL)股票的历史数据进行详细分析,并逐步展示如何通过不同的技术和模型对股票市场进行预测。

1. 数据预处理与模态分解

股票市场数据通常呈现出非常复杂的非线性和非平稳性特征。为了更好地进行预测,我们首先需要对数据进行适当的处理,去除噪声并提取更有用的信息。

部分数据如下所示:

1.1 数据读取与清洗

我们从苹果公司(AAPL)股票的历史数据入手,加载CSV文件,并去除缺失值。然后,我们将数据中的"Date"列删除,保留价格信息。

复制代码
df_apple = pd.read_csv("AAPL.csv")
df_apple = df_apple.dropna()
del df_apple["Date"]
df_apple.head()

1.2 数据统计分析

对数据进行初步的统计分析,计算最大值、最小值、平均值、标准差等基本统计量,并进行偏度、峰度、JB检验等高级统计检验,以了解数据的分布特征。

复制代码
def num_jy(df111):
    print("最大值", max(df111))
    print("最小值", min(df111))
    print("平均值", np.mean(df111))
    print("标准差:", np.std(df111))
    print("偏度:", pd.Series(df111).skew())
    print("峰度:", pd.Series(df111).kurt())
    # 计算JB检验量
    skew = pd.Series(df111).skew()
    krut = stats.kurtosis(df111) + 3
    JB = len(df111) * (skew ** 2 / 6 + (krut - 3) ** 2 / 24)
    print("JB检验:", JB)
    p_value = 1 - stats.chi2.cdf(JB, df=2)
    print('p_value:', p_value)
num_jy(df_apple["Close"])

1.3 CEEMDAN分解

为了从原始股价数据中提取潜在的模式,我们使用CEEMDAN(Complete Ensemble Empirical Mode Decomposition with Adaptive Noise)技术对数据进行模态分解。这一技术可以将复杂的时间序列分解为多个本征模态函数(IMFs),有助于去除数据中的噪声并提取出有效的信号。

复制代码
ceemdan = CEEMDAN()
ceemdan.ceemdan(df_apple["Close"].to_numpy())
imfs, res = ceemdan.get_imfs_and_residue()

1.4 分解结果可视化

通过可视化分解后的IMFs(本征模态函数)和残差,可以直观地了解股价的不同时间尺度上的变化趋势。

复制代码
plt.figure(figsize=(10,8))
plt.subplot(imfs.shape[0] + 2, 1, 1)
plt.plot(df_apple["Close"], 'r')
plt.ylabel("Original", rotation=60, fontsize=10)
for i in range(imfs.shape[0]):
    plt.subplot(imfs.shape[0] + 2, 1, i + 2)
    plt.plot(imfs[i], 'g')
    plt.ylabel(f"imf{i+1}", rotation=60, fontsize=10)
plt.subplot(imfs.shape[0] + 2, 1, imfs.shape[0] + 2)
plt.plot(res, 'g')
plt.ylabel("res", rotation=60, fontsize=10)
plt.show()

2. 特征选择与数据集划分

在对数据进行模态分解后,我们选择有意义的特征(如IMFs和残差),并将其作为输入特征来训练我们的模型。同时,划分数据集为训练集和测试集,通常选择80%的数据用于训练,剩余20%的数据用于测试。

复制代码
def data_make(df):
    arr1 = ['imf'+str(i+1) for i in range(imfs.shape[0])] + ['res']
    arr2 = 'target'
    data_set_train1 = df[:int(df.shape[0] * 0.8)]
    data_set_test1 = df[int(df.shape[0] * 0.8):]
    train_X = data_set_train1[arr1]
    train_y = data_set_train1[arr2].to_numpy()
    test_X = data_set_test1[arr1]
    test_y = data_set_test1[arr2].to_numpy()
    return train_X, train_y, test_X, test_y

3. 模型构建与训练

3.1 支持向量机(SVM)

支持向量机(SVM)是一种常用的回归与分类算法,适用于非线性问题。我们首先使用标准的SVM模型进行训练,并用交叉验证评估其性能。

复制代码
model = svm.LinearSVR()
model.fit(train1_X_apple, train1_y_apple)
y_pred_apple_ceemdan_svm = model.predict(test1_X_apple)

3.2 贝叶斯优化(Bayesian Optimization)

为了进一步提高模型的性能,我们使用贝叶斯优化技术来调整SVM的超参数。贝叶斯优化是一种全局优化算法,特别适合于调参问题。

复制代码
def SVM_mse_cv(params):
    random_state = 10
    cv = 5
    params = {
        'epsilon': params['epsilon'],
        'C': int(params['C']),
        'intercept_scaling': params['intercept_scaling']
    }
    
    model = svm.LinearSVR(random_state=random_state, **params)
    
    score = -cross_val_score(model, train1_X_apple, train1_y_apple, 
                             cv=cv, scoring='neg_mean_squared_error',
                             n_jobs=1).mean()
    return {'loss': score, 'status': 'ok'}

def BO_SVM_pri(train_X, train_y, test_X):
    random_state = 10
    
    space = {
        'epsilon': hp.loguniform('epsilon', -2, 1),
        'C': hp.quniform('C', 1, 300, 1),
        'intercept_scaling': hp.loguniform('intercept_scaling', -2, 0)
    }
    trials = Trials()
    print("==========================贝叶斯参数优化==============================")
    
    best = fmin(fn=SVM_mse_cv,
                space=space,
                algo=tpe.suggest,
                max_evals=200,
                trials=trials)
    
    if best is None:
        raise ValueError("贝叶斯优化未能找到有效解")
    
    model = svm.LinearSVR(random_state=random_state, 
                          epsilon=best['epsilon'], 
                          C=int(best['C']), 
                          intercept_scaling=best['intercept_scaling'])
    
    model.fit(train_X, train_y)
    y_pred = model.predict(test_X)
    
    return y_pred

3.3 XGBoost与LightGBM

XGBoost和LightGBM是目前应用广泛的树模型,常用于回归与分类任务。它们通过提升树的性能,在许多竞赛中表现出色。我们使用Optuna进行超参数优化,并使用训练好的模型进行预测。

复制代码
def objective(trial):
    params = {
        'objective': 'reg:squarederror',
        'learning_rate': trial.suggest_loguniform('learning_rate', 1e-3, 1),
        'max_depth': trial.suggest_int('max_depth', 3, 15),
        'n_estimators': trial.suggest_int('n_estimators', 50, 300),
        'subsample': trial.suggest_float('subsample', 0.5, 1.0),
        'colsample_bytree': trial.suggest_float('colsample_bytree', 0.5, 1.0),
        'reg_alpha': trial.suggest_float('reg_alpha', 0, 10),
        'reg_lambda': trial.suggest_float('reg_lambda', 0, 10),
    }
    model = XGBRegressor(**params)
    model.fit(train2_X_apple, train2_y_apple)
    y_pred = model.predict(test2_X_apple)
    mse = mean_squared_error(test2_y_apple, y_pred)
    return mse

3.4 LSTM与GRU

长短时记忆(LSTM)和门控循环单元(GRU)是两种常用的循环神经网络(RNN)结构,适用于时间序列数据。通过这些网络结构,可以捕捉股价的长期依赖关系,提高预测准确性。

复制代码
def LSTM_model(x_train, y_train, x_test, epochs, batch_size):
    model = Sequential()
    model.add(LSTM(units=32, return_sequences=True, input_shape=(x_train.shape[1], 1)))
    model.add(Dropout(0.2))
    model.add(LSTM(units=16))
    model.add(Dropout(0.2))
    model.add(Dense(units=1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    model.fit(np.array(x_train), np.array(y_train), epochs=epochs, batch_size=batch_size)
    prediction = model.predict(x_test)
    return prediction

4. 模型评估与性能比较

通过计算RMSE(均方根误差)、MAE(平均绝对误差)、MAPE(平均绝对百分比误差)等指标,我们可以评

估每个模型的表现并比较其优劣。下面是一个基于RMSE和MAPE评估模型的代码示例:

复制代码
def evaluate_predictions(y_true, y_pred):
    rmse = np.sqrt(mean_squared_error(y_true, y_pred))
    mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
    print(f"RMSE: {rmse:.4f}, MAPE: {mape:.4f}%")

5. 结果可视化与总结

最后,我们通过可视化预测结果与实际值的对比,直观地展示每个模型的效果。通过图形,可以清楚地看到哪些模型在股票价格预测中表现得更好。

复制代码
plt.plot(test_y_apple, color='blue', label='Real AAPL Price')
plt.plot(y_pred_apple_svm, color='red', label='Predicted AAPL Price')
plt.title('AAPL Price Prediction using SVM')
plt.xlabel('Time')
plt.ylabel('Price')
plt.legend()
plt.show()

总结

通过结合CEEMDAN和多种机器学习模型(如SVM、XGBoost、LSTM等),我们能够更准确地预测股票价格。每种模型在不同数据集上的表现有所不同,通过评估指标的比较,我们可以选择最佳的模型进行未来的预测。通过这种方法,不仅能提升股票预测的准确性,还能为金融分析师和投资者提供更有力的数据支持。

由于篇幅有限,需要完整代码请私信我!

相关推荐
databook11 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar12 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805112 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_13 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机19 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机20 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机20 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机20 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i20 小时前
drf初步梳理
python·django
每日AI新事件20 小时前
python的异步函数
python