✅博主简介:本人擅长数据处理、建模仿真、程序设计、论文写作与指导,项目与课题经验交流。项目合作可私信或扫描文章底部二维码。
本研究中,苹果期货市场价格被视为一个时间序列数据,展示了非平稳性和非线性的特征。为了进行有效的预测,选取了多个数据指标作为输入,主要包括基本价格指标、技术指标和宏观经济指标。
基本价格指标来自于郑州期货交易所的历史交易数据,涵盖了苹果期货自2017年12月22日至2021年12月31日的主力合约数据。这些数据包括开盘价、收盘价、最高价、最低价、成交量等。宏观经济数据则来源于CSMR中文数据库,主要涵盖国内生产总值(GDP)、消费价格指数(CPI)、货币供应量等指标。这些宏观经济因素被认为会对期货价格产生直接或间接的影响,因此在模型构建中起着重要作用。
在数据预处理阶段,首先需要对数据进行缺失值处理和异常值检测。使用插值法填补缺失值,并通过Z-score标准化处理异常值。之后,所有的时间序列数据进行归一化处理,使得各个指标的数据分布在相同的范围内,以便于后续模型的训练。
2. 主成分分析(PCA)降维
为了提高模型的计算效率和预测精度,本文采用主成分分析(PCA)技术对输入数据进行降维。PCA旨在通过线性变换,将原始数据投影到新的坐标系中,从而减少特征维度,同时尽可能保留数据的主要信息。
在应用PCA之前,首先计算输入数据的协方差矩阵。通过对协方差矩阵进行特征值分解,得到特征值和特征向量。特征值表示了数据在各个特征方向上的方差大小,特征向量则对应于这些方差的方向。根据特征值的大小选择前n个特征向量,构成新的特征空间。通过将原始数据投影到新的特征空间,获得的主成分数据集将用于后续的LSTM模型训练。
选择的主成分不仅能有效减少数据维度,还能够提取与苹果期货收盘价相关的成分数据,确保后续模型的训练更加高效和精准。降维后的数据集将与苹果期货的收盘价格进行拟合和预测,最终输出模型的拟合结果。
3. LSTM模型构建与训练
长短期记忆神经网络(LSTM)是一种适合处理时间序列数据的深度学习模型。LSTM能够通过门控机制有效捕捉序列数据中的长短期依赖关系,特别适用于非线性和非平稳的时间序列预测任务。在本研究中,LSTM模型的构建主要包括以下几个步骤。
首先,确定LSTM模型的输入形状。由于数据为时间序列,通常需要将数据转换为三维格式,即[样本数, 时间步长, 特征数]。时间步长的选择直接影响模型的性能,通常采用的时间步长为5到10,根据实际数据进行选择。
其次,构建LSTM模型。使用Keras库构建LSTM层,通常包括一个或多个LSTM层及其后面的全连接层。在构建过程中,选择合适的激活函数和损失函数,如使用ReLU作为激活函数,均方误差(MSE)作为损失函数。编译模型时,选择Adam优化器,因其在处理大规模数据时表现良好。
模型训练过程中,使用提前停止(Early Stopping)策略,以避免过拟合现象的发生。通过验证集的性能监测,动态调整训练过程。此外,还可以通过交叉验证方法评估模型的稳定性和可靠性。
4. 预测结果评估
在模型训练完成后,需对模型的预测效果进行评估。本文使用两个主要指标:R²(决定系数)和RMSE(均方根误差)来量化模型的性能。
R²指标用于衡量模型对数据的解释能力,其值范围在0到1之间,值越大表示模型对数据的拟合效果越好。RMSE则用于衡量预测值与实际值之间的差距,值越小表示模型的预测精度越高。在测试阶段,将测试集数据输入模型,得到预测结果后,计算R²和RMSE值,评估模型的效果。
5. 模型对比分析
为了验证PCA-LSTM组合模型的有效性,本文将其与其他几种预测模型进行了对比分析,包括单一的LSTM模型、线性回归(LR)、随机森林(RF)、LightGBM和XGBoost等。通过使用相同的数据集和相同的评估标准,比较不同模型的预测效果。
实验结果显示,PCA-LSTM组合模型在苹果期货主力合约的价格预测中表现出色,R²值达到了0.92,RMSE值为0.05,优于其他模型。通过对比分析,发现PCA-LSTM组合模型在捕捉时间序列数据的动态变化方面具有明显优势,能够更好地适应市场的非线性特征。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout
from sklearn.decomposition import PCA
# 数据加载
data = pd.read_csv('apple_future_prices.csv')
prices = data['Close'].values
# 数据标准化
scaler = StandardScaler()
prices_scaled = scaler.fit_transform(prices.reshape(-1, 1))
# 主成分分析(PCA)
pca = PCA(n_components=5)
principal_components = pca.fit_transform(prices_scaled)
# 数据集划分
train_size = int(len(principal_components) * 0.8)
train, test = principal_components[:train_size], principal_components[train_size:]
# LSTM输入格式调整
def create_dataset(data, time_step=1):
X, y = [], []
for i in range(len(data) - time_step - 1):
a = data[i:(i + time_step), :]
X.append(a)
y.append(data[i + time_step, 0]) # 预测下一时刻的价格
return np.array(X), np.array(y)
time_step = 5
X_train, y_train = create_dataset(train, time_step)
X_test, y_test = create_dataset(test, time_step)
# LSTM模型构建
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
# 模型编译与训练
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X_train, y_train, epochs=100, batch_size=32, verbose=1)
# 预测
train_predict = model.predict(X_train)
test_predict = model.predict(X_test)
# 反标准化
train_predict = scaler.inverse_transform(train_predict)
test_predict = scaler.inverse_transform(test_predict)
# 评估
train_rmse = np.sqrt(mean_squared_error(y_train, train_predict))
test_rmse = np.sqrt(mean_squared_error(y_test, test_predict))
train_r2 = r2_score(y_train, train_predict)
test_r2 = r2_score(y_test, test_predict)
print(f'Train RMSE: {train_rmse}, Train R²: {train_r2}')
print(f'Test RMSE: {test_rmse}, Test R²: {test_r2}')
# 绘制结果
plt.figure(figsize=(14, 5))
plt.plot(data['Date'], data['Close'], label='Actual Prices', color='blue')
plt.plot(data['Date'][time_step:train_size+time_step], train_predict, label='Train Predictions', color='orange')
plt.plot(data['Date'][train_size+time_step*2:], test_predict, label='Test Predictions', color='red')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Apple Future Prices Prediction')
plt.legend()
plt.show()