【Intel校企实践】基于LSTM与CNN-GRU的比特币价格预测

第1章 背景与意义

1.1 问题描述

比特币价格预测器是一项极具前瞻性和实用性的项目。在这个数字化时代,区块链技术的不断发展推动着加密货币市场的蓬勃发展。随着越来越多的数字货币涌现,并且市场波动性增加,对比特币价格的准确预测变得至关重要。

1.2 预期解决方案

通过参考英特尔的类似实现方案,预测比特币价格趋势的可靠性和准确性,以及预测模型的推理速度,可以为全球数字货币市场的安全性和可持续性提供有力支持。这里,我们将分类准确度和推理时间作为评估比特币价格预测器的主要依据

1.3 需求

需要使用英特尔®oneAPI AI分析工具包中数据分析和机器学习相关的优化库,基于参考资料的方案,进行比特币价格预测的实现。

第2章 项目介绍

 2.1项目方案选择

2.1.1项目方案介绍

本文主要探索了预测比特币价格的几种模型以及优化方法,并对他们的结果进行总结。本文试图预测时间序列数据,因此选用循环神经网络RNN进行探讨研究,由于LSTM(长短时记忆)与GRU(门控循环单元)都是循环神经网络的变种,用来解决RNN在处理长序列时遇到的梯度消失或梯度爆炸问题,本文先后对两者都进行了模型训练。

★LSTM——长短时记忆网络

LSTM是一种特殊的循环神经网络(RNN),LSTM单元包含三个门:输入门(input gate)、遗忘门(forget gate)和输出门(output gate),这些门用于控制信息的流入和流出。

★GRU——门控循环单元

GRU是一种特殊的循环神经网络(RNN)单元,GRU的结构相对简单,它只有两个门:重置门(reset gate)和更新门(update gate)。这两个门都是用来控制信息的流入和流出。

GRU相对于LSTM更为简单,计算效率更高,因此在某些情况下,GRU可以作为LSTM的一个有效替代方案。

2.1.2项目方案优化

网格搜索

网格搜索(Grid Search)是一种常用的调参手段,用于在机器学习中找到最优的超参数组合。它属于穷举法的一种,通过手动给定一个模型中想要改动的所有参数,然后让程序使用穷举法把所有参数组合运行一遍,以选出最好的参数组合。网格搜索通常与交叉验证搭配使用,以使评分更加严谨。

结合卷积神经网络CNN

结合GRU(门控循环单元)与CNN(卷积神经网络)是一种有效的策略,特别适用于处理同时具有时间依赖性和局部空间相关性的序列数据。这种组合可以充分利用CNN捕捉局部空间特征的能力以及GRU处理序列中时间依赖性的能力。CNN通过卷积操作能够从输入数据中提取出局部的空间特征。通过卷积和池化操作,CNN可以有效地减少数据的维度,从而简化后续层的处理。

特征工程

特征工程是一项重要的工程活动,其本质是将原始数据转变为能更好地代表预测模型的潜在问题的特征,从而提高对未知数据的预测准确性。在机器学习中,特征工程直接决定了模型预测的结果好坏。

本文中特征工程主要有:

7天和21天移动平均线 (MA7, MA21):技术分析中常用的指标,用于平滑价格数据并识别趋势。

平滑异同移动平均线(MACD):根据移动平均线原理发展出来的MACD,一方面去除了移动平均线频繁发出假信号的缺陷,另一方面保留了移动平均线的效果。因此,MACD指标具有均线趋势性、稳重性、安定性等特点,是用来研判买卖股票的时机、预测股票价格涨跌的技术分析指标。

布林带 (upper_band, lower_band):布林带的主要作用是识别股票是否处于超买超卖状态,帮助投资者决策入场和离场时机。当价格在布林带通道内波动时,说明价格处于相对稳定的状态;当价格突破上下限时,说明价格可能发生趋势性的变化。

指数移动平均线 (EMA):指数移动平均线是一种技术分析工具,用于平滑价格数据并识别趋势。

对数动量 (logmomentum):对数动量是一个技术分析指标,用于衡量价格变动的速率和方向。它通过对价格序列进行对数差分计算得到,因此能够捕捉到价格变动的百分比变化,而不是绝对变化。

傅里叶变换:随着每日收盘价,我们创建了傅里叶变换来提取比特币的长期和短期趋势。傅里叶变换采用一个函数并产生一系列正弦波;结合后,这些正弦波近似于原始函数,帮助GRU网络更准确地选择其预测趋势。

第3章 模型详解

3.1 数据探索

3.1.1数据读取

Modin是一个Python第三方库,可以通过并行来处理大数据集。其中语法与pandas相近,拥有出色的性能弥补了pandas处理大型数据集的缺陷。

而Dask 是一个用于分析计算的灵活的并行计算库,实现大型多维数据集分析的更快执行以及加速和扩展数据科学制作流程或工作流程的强大工具。

本文使用pandas库来读取和处理CSV文件,为了后续方便调用,这里将两组数据都读取出来,并进行了堆叠,按照时间索引,并对其进行了排序。

图3-1 data数据集展示

相关代码如下:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math
import time
from collections import deque
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras import optimizers
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from keras.layers import Input  

data = pd.read_csv('./bitcoin_price_Training - Training.csv', index_col="Date", parse_dates=True)
data_test = pd.read_csv('./bitcoin_price_1week_Test - Test.csv', index_col="Date", parse_dates=True)

# 使用concat沿行堆叠  
data = pd.concat([data_test, data])
# 排序
data.sort_index(inplace = True)

print(data)

3.1.2数据预处理

首先通过  查看数据的缺失值情况。

图3-2 data缺失值展示

由于"Market Cap"与"Volume"数字较大,采用的是xxx,xxx,xxx形式,存在符号",",且部分存在有符号"-",这里通过replace进行替换,"-"替换为0,","置空。

图3-3 处理后的data

相关代码如下:

print(Final_data.isnull().sum())
# 交易量去除“,” 转换浮点数
data.Volume = data.Volume.astype(str)
data["Volume"] = data["Volume"].str.replace('-', '0')
data["Volume"] = data["Volume"].str.replace(',', '').astype(float)

# 市场价格去除“,” 转换浮点数
data["Market Cap"] = data["Market Cap"].astype(str)
data["Market Cap"] = data["Market Cap"].str.replace(',', '').astype(float)
print(data)

3.1.3绘制价格趋势图

为了更直观的看出比特币价格趋势走向,这里将收盘价,即"Close"列数据进行可视化。

图3-4 Close可视化

相关代码如下:

# 创建比特币价格的图表
fig, ax = plt.subplots(figsize=(10,3))
ax.plot(data.index, data['Close'], label='BiT price')
ax.set(xlabel="Date",
       ylabel="USD",
       title="BiT Price")
# 设置x轴的日期格式
date_form = DateFormatter("%Y")
ax.xaxis.set_major_formatter(date_form)
plt.show()

3.1.4构建数据集

为了预测n天后的价格,这里本文首先定义了pre_days,将"Close"数据整体移动了pre_days天数,并用"label"进行存储,通过fit_transform进行标准化处理,其返回的是NumPy数组。

然后通过队列,将返回的NumPy数组按照men_his_days进行划分,men_his_days指的是记忆天数,具体数值需要后续调整。

至此,我们将得到数据集进行划分为训练集与测试集,其中训练集:测试集为0.9:0.1。

相关代码如下:

# pre_days =7
data['label']=data['Close'].shift(-pre_days)
scaler=StandardScaler()
Sc_X=scaler.fit_transform(data.iloc[:,:pre_days])
eq = deque(maxlen = men_his_days)
X = []
for i in Sc_X:
deq.append(i)
if len(deq) == men_his_days:
X.append(list(deq))



# 划分训练集、测试集  
test_size = 0.1  
train_size = 1 - test_size  
# 计算测试集和训练集的样本数量  
num_test = int(test_size * len(X))  
num_train = int(train_size * len(X))  


X_train = X[:num_train]
X_test = X[num_train:]
Y_train = Y[:num_train]
Y_test = Y[num_train:]

3.2 LSTM模型

3.2.1 LSTM模型构建

首先,初始化了一个顺序模型,定义模型的输入层,输入层的形状由输入数据X的特征数量决定,通过X.shape[1:]获取,即除去样本数之外的所有维度。

然后LSTM层作为模型的主要组成部分,添加一个带有ReLU激活函数的LSTM层,并设置了return_sequences=True,以便在输出中返回每个时间步的输出,然后,添加了一个Dropout层,通过随机丢弃一部分神经元的输出来减少过拟合。

后续添加相同配置的LSTM层和Dropout层,每次循环都增加模型对序列数据的处理能力,视情况而定。

在所有LSTM层之后,我们添加了一个不返回序列的LSTM层,以便将序列的最终输出汇总为一个固定大小的向量。

最后,我们添加了输出层,这是一个没有激活函数的Dense层,其单元数设置为1,因为我们正在预测一个单一连续值。

相关代码如下:

# 构建模型  
model = Sequential()
# 添加输入层,形状由数据特征决定
model.add(Input(shape=X.shape[1:]))  
# 添加GRU层和Dropout层  
model.add(GRU(the_units, activation='relu', return_sequences=True))  
model.add(Dropout(0.1))  


model.add(GRU(the_units, activation='relu', return_sequences=True))  
model.add(Dropout(0.1))  


model.add(GRU(the_units, activation='relu'))  
model.add(Dropout(0.1))  
# 添加全连接层和Dropout层
model.add(Dense(the_units, activation='relu'))  
model.add(Dropout(0.1))  
# 添加输出层
model.add(Dense(1))  

3.2.2网格搜索优化参数

为了使网格搜索更加方便,本文定义了一个名为BiT_Price_GRU_DataPrecessing的函数,用来处理时间序列数据,其相关内容已在上文阐述。

模型的网格搜索中,主要探索了men_days(移动平均的天数),gru_layers(GRU层的数量),dense_layers(全连接层的数量),units(GRU层和全连接层的单元数),同时设置一个回调函数,当验证集上的mape(平均绝对百分比误差)最小化时,保存当前最佳模型。保存路径名字包含了相关信息,以便后续能通过文件名快速找出最佳超参数。

在找到最佳模型的超参数后,将参数固定进行训练,在多个训练结果中,找到最佳模型,即平均误差最小的模型,通过load_model进行读取。

值得注意的是,在网格搜索时可以将save_weights_only 置为True,只保存模型权重。

相关代码如下:

# 构建数据集

def BiT_Price_LSTM_DataPrecessing(data, men_his_days, pre_days):
    data.dropna(inplace = True)
    # 排序
    data.sort_index(inplace = True)

    # 移动七天
    # pre_days = 7
    data['label']=data['Close'].shift(-pre_days)

    scaler=StandardScaler()
    Sc_X=scaler.fit_transform(data.iloc[:,:pre_days])

    # 设置输入值
    # 记忆10天
    # men_his_days = 10

    deq = deque(maxlen = men_his_days)

    X = []
    for i in Sc_X:
        deq.append(i)
        if len(deq) == men_his_days:
            X.append(list(deq))

    # len(X_LSTM)
    # 记录最后7天
    X_lately = X[-pre_days:]

    # 删除
    X = X[:-pre_days]

    Y = data['label'].values[men_his_days-1:-pre_days]

    X = np.array(X)
    Y = np.array(Y)
    
    return X,Y,X_lately

# 设置要尝试的参数组合
# men_days = [5, 10, 20]    # 移动平均的天数
# lstm_layers = [1, 2, 3]   # LSTM层的数量
# dense_layers = [1, 2, 3]  # 全连接层的数量
# units = [16, 32]          # LSTM层和全连接层的单元数
# 3.51_20_men_10_lstm_3_dense_2_units_32.index

pre_days = 7       # 预测前多少天的数据
men_days = [10]    # 移动平均的天数
lstm_layers = [3]  # LSTM层的数量
dense_layers = [2] # 全连接层的数量
units = [128]       # LSTM层和全连接层的单元数

from keras.callbacks import ModelCheckpoint


# 网格搜索循环
for the_men_days in men_days:
    for the_lstm_layers in lstm_layers:
        for the_dense_layers in dense_layers:
            for the_units in units:
                # 构建模型保存路径
                # filepath = './models/{val_mape:.2f}_{epoch:02d}_'+f'men_{the_men_days}_lstm_{the_lstm_layers}_dense_{the_dense_layers}_units_{the_units}'
                filepath = './models_best/{val_mape:.2f}_'+f'men_{the_men_days}_lstm_{the_lstm_layers}_dense_{the_dense_layers}_units_{the_units}'
                
                # 设置ModelCheckpoint回调,用于保存最佳模型
                checkpoint = ModelCheckpoint(
                    filepath = filepath,
                    save_weights_only = False,
                    monitor = 'val_mape',
                    mode = 'min',
                    save_best_only = True)
                
                # 数据预处理,这里调用了一个名为BiT_Price_LSTM_DataPrecessing的函数,用来处理时间序列数据
                X, Y, X_lately = BiT_Price_LSTM_DataPrecessing(data, the_men_days, pre_days)

                # 划分训练集、测试集  
                # X_train, X_test, Y_train, Y_test = train_test_split(X, Y, shuffle = False, test_size=0.1)
                test_size = 0.1  
                train_size = 1 - test_size  
                
                # 计算测试集和训练集的样本数量  
                num_test = int(test_size * len(X))  
                num_train = int(train_size * len(X))  

                # 如果不需要打乱顺序,则直接分割  
                X_train = X[:num_train]
                X_test = X[num_train:]
                Y_train = Y[:num_train]
                Y_test = Y[num_train:]
                
                # 构建模型  
                model = Sequential()  
                
                # 添加输入层,形状由数据特征决定
                model.add(Input(shape=X.shape[1:]))  

                # 添加LSTM层和Dropout层
                # 第一个LSTM层
                model.add(LSTM(the_units, activation='relu', return_sequences=True))  
                # 添加Dropout层以减少过拟合
                model.add(Dropout(0.1))  
                
                # 根据参数添加更多的LSTM层
                for i in range(the_lstm_layers):
                    model.add(LSTM(the_units, activation='relu', return_sequences=True))  
                    model.add(Dropout(0.1))  
                
                # 添加最后一个LSTM层
                model.add(LSTM(the_units, activation='relu'))  
                model.add(Dropout(0.1))  
                
                # 添加全连接层和Dropout层
                for i in range(the_dense_layers):
                    model.add(Dense(the_units, activation='relu'))  
                    model.add(Dropout(0.1))  
                
                # 添加输出层
                model.add(Dense(1))  


3.2.3模型训练

 Adam优化器,Adam优化器来更新模型的权重。Adam是一种自适应学习率的优化算法,通常比传统的随机梯度下降(SGD)具有更好的性能。它结合了AdaGrad和RMSProp的优点,通过计算梯度的一阶矩估计(均值)和二阶矩估计(未中心化的方差)来调整每个参数的学习率。

loss='mse',均方误差(Mean Squared Error,MSE)作为损失函数。MSE是衡量模型预测值与实际值之间差异的一种常见方法,它计算每个样本预测误差的平方和的平均值。在回归问题中,MSE是一个常用的损失函数。

metrics=['mape'],平均绝对百分比误差(Mean Absolute Percentage Error,MAPE)作为评估指标。MAPE是另一种衡量预测误差的方法,它计算每个样本预测误差的绝对值与其实际值的百分比,然后取平均值。

本文对最佳模型训练轮次设置为300,validation_data在模型的训练过程中用来评估模型的性能。

相关代码如下:

# 编译模型

model.compile(optimizer='adam',  # 使用Adam优化器
                         loss='mse',        # 使用均方误差作为损失函数
                         metrics=['mape'])  # 使用平均绝对百分比误差作为评估指标


                # 训练模型
model.fit(X_train,Y_train,batch_size = 32,epochs = 300,validation_data = (X_test,Y_test),callbacks = [checkpoint])

3.3 GRU模型

在构建GRU模型时,要将模型中的LSTM层替换为GRU层,只需要将LSTM替换为GRU,并保留其他参数不变。GRU层在结构上比LSTM层简单,因为它没有LSTM中的门控机制,但通常在某些任务中表现相似或更好

相关代码参考上述LSTM模型构建。

第4章 模型测试

4.1 LSTM模型测试

4.1.1 test集上的推理时间

首先加载保存好的模型,这里需要自己去文件中找到平均误差最小的文件名进行加载。

推理时间为:0.09873509407043457

预测结果如图所示

图4-1 LSTM预测结果图

图4-2 LSTM预测结果图

相关代码如下:

from keras.models import load_model

best_model = load_model('./models_best/9.82_men_10_lstm_3_dense_2_units_32')

best_model.summary()

best_model.evaluate(X_test, Y_test)

data_time = data.index[-len(Y_test):]

print(Y_test)

pre = best_model.predict(X_test)

plt.title('BiT Price Prediction')
plt.xlabel('Time')
plt.ylabel('BiT Price')

plt.plot(data_time, Y_test,color = 'red', label = 'price')
plt.plot(data_time, pre, color = 'green', label = 'predict')
plt.show()

# 预测时间
pre_time = 7

# 获取最后7天的索引
data_time = data.index[-pre_time:]

# 记录开始时间
start_time = time.time()

# 模型预测
predicted = best_model.predict(X_test)

# 记录结束时间
end_time = time.time()

print(f"推理时间为:",end_time - start_time)

# 画图
plt.title('BiT Price Prediction')
plt.xlabel('Time')
plt.ylabel('BiT Price')
plt.plot(data_time, Y_test[-pre_time:],color = 'red', label = 'price')
plt.plot(data_time, pre[-pre_time:], color = 'green', label = 'predict')
plt.show()

from sklearn.metrics import r2_score, mean_absolute_percentage_error  

# 计算R²分数  
r2 = r2_score(Y_test, predicted)  
print(f'R² Score: {r2}')  
            

4.1.2模型指标

这里对R²、Mape进行了统计,其中R²分数衡量模型对数据的拟合程度。其值介于0到1之间,数值越接近1表示模型的拟合效果越好;Mape越小模型越好。

图4-3 统计

图4-4 模型参数统计

图4-5 Mape统计

4.2 GRU模型测试

4.2.1 test集上的推理时间

首先加载保存好的模型,这里需要自己去文件中找到平均误差最小的文件名进行加载。

推理时间为:0.09873509407043457

预测结果如图所示

图4-6 GRU预测结果图

图4-7 GRU预测结果图

4.2.2模型指标

这里对R²、Mape进行了统计,其中R²分数衡量模型对数据的拟合程度。其值介于0到1之间,数值越接近1表示模型的拟合效果越好;Mape越小模型越好。

图4-8 统计

图4-9 模型参数统计

图4-10 Mape统计

第5章 模型优化

5.1 将GRU与CNN结合

CNN与GRU模型结合,利用了CNN在空间特征提取方面的优势和GRU在处理序列数据和捕捉长期依赖关系方面的能力。

本文添加一维卷积层,用于提取时间序列数据的特征。设置了64个过滤器(filters),卷积核大小为3(kernel_size),激活函数为ReLU,并且使用'SAME'填充方式以保持输出尺寸不变(padding='same')。

添加一维最大池化层,用于降低特征的空间维度,减少计算量。

最后添加批量归一化层,用于加速训练过程并提高模型稳定性。

后续GRU模型构建不变。

相关代码如下:

# 添加CNN层  
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', padding='same',input_shape=X.shape[1:]))  
model.add(MaxPooling1D(pool_size=2))  
model.add(BatchNormalization())  

5.1.1模型评估

和上文一样,通过网格搜索最佳参数,寻找最佳模型进行训练。

这里是优化模型后的预测结果、推理时间、R²与Mape。

图5-1 模型预测统计

图5-2 模型预测

图5-3 统计

图5-4 模型参数统计

图5-5 Mape统计

5.2 特征工程

在优化模型构建与超参数后,接下来将对数据特征进一步处理。

5.2.1移动平均线

本文计算了7天和21天移动平均线,并对其进行可视化。

相关代码如下:

# 计算7天和21天移动平均线
data_temp['MA7'] = data_temp.iloc[:,4].rolling(window=7).mean()
data_temp['MA21'] = data_temp.iloc[:,4].rolling(window=21).mean()

5.2.2 MACD

计算MACD,移动平均收敛发散指标,并对其进行可视化。

相关代码如下:

# 计算MACD,移动平均收敛发散指标
data_temp['MACD'] = data_temp.iloc[:,4].ewm(span=26).mean() - data_temp.iloc[:,1].ewm(span=12,adjust=False).mean()

5.2.3布林带

计算布林带,由三条轨道线组成,其中上下两条线分别可以看成是价格的压力线和支撑线,而中间的一条线则是价格平均线。

可视化如下:

图5-6 布林带统计

相关代码如下:

# 计算布林带
data_temp['20SD'] = data_temp.iloc[:, 4].rolling(20).std()
data_temp['upper_band'] = data_temp['MA21'] + (data_temp['20SD'] * 2)
data_temp['lower_band'] = data_temp['MA21'] - (data_temp['20SD'] * 2)

5.2.4指数移动平均线与对数动量

两种在技术分析中常用的指标,它们可以帮助交易者识别趋势和潜在的交易机会。

相关代码如下:

# 计算指数移动平均线
data_temp['EMA'] = data_temp.iloc[:,4].ewm(com=0.5).mean()
# 计算对数动量
data_temp['logmomentum'] = np.log(data_temp.iloc[:,4] - 1)

5.2.5傅里叶变换

从数据集中提取特定列('Date' 和 'Close'),然后计算收盘价('Close')的傅里叶变换(FFT),并基于这些变换结果生成一些特征,主要目的是提取收盘价序列的不同频率成分的特征。

可视化如下:

图5-7 傅里叶变换

相关代码如下:

# 获取傅里叶变换特征的函数
def get_fourier_transfer(dataset):
    # 获取用于傅里叶变换的列
    data_FT = dataset[['Date', 'Close']]
    # 对收盘价进行傅里叶变换
    close_fft = np.fft.fft(np.asarray(data_FT['Close'].tolist()))
    # 创建一个新的DataFrame来存储傅里叶变换的结果
    fft_df = pd.DataFrame({'fft': close_fft})
    fft_df['absolute'] = fft_df['fft'].apply(lambda x: np.abs(x))
    fft_df['angle'] = fft_df['fft'].apply(lambda x: np.angle(x))
    # 对傅里叶变换的结果进行处理,以获取不同成分的傅里叶变换
    fft_list = np.asarray(fft_df['fft'].tolist())
    fft_com_df = pd.DataFrame()
    for num_ in [3, 6, 9]:
        # 创建一个新列表,将中间的num_个成分置零
        fft_list_m10 = np.copy(fft_list);
        fft_list_m10[num_:-num_] = 0
        # 对修改后的傅里叶变换列表进行逆傅里叶变换
        fft_ = np.fft.ifft(fft_list_m10)
        fft_com = pd.DataFrame({'fft': fft_})
        # 计算逆傅里叶变换的绝对值和角度
        fft_com['absolute of ' + str(num_) + ' comp'] = fft_com['fft'].apply(lambda x: np.abs(x))
        fft_com['angle of ' + str(num_) + ' comp'] = fft_com['fft'].apply(lambda x: np.angle(x))
        fft_com = fft_com.drop(columns='fft')
        # 将新计算的列添加到fft_com_df中
        fft_com_df = pd.concat([fft_com_df, fft_com], axis=1)
    return fft_com_df

完成上述处理后,本文还检查了其自相关性。

图5-8 自相关性检验

5.2.6模型评估

和上文一样,通过网格搜索最佳参数,寻找最佳模型进行训练。

这里是优化模型后的预测结果、推理时间、R²与Mape。

图5-9 模型预测

图5-10 模型预测

图5-11 统计

图5-12 模型参数统计

图5-13 Mape统计

第6章 项目总结

以下是对test集不同版本的推理时间与预测结果:

网格搜索的LSTM(上)和GRU(下):

 

CNN与GRU结合:

特征工程后,CNN与GRU结合:

在上述不同版本中,LSTM表现最差,预测曲线与实际曲线相差甚远,而GRU模型本身表现就比较好,在结合CNN后,有一定的提升。

最后通过特征工程后的版本表现最好。

各版本数据统计

版本

推理时间(ms)

Mape

LSTM

0.0967409610748291

0.8174559681025202

9.824846267700195

GRU

0.0857701301574707

0.9364221296739852

5.722115993499756

CNN-GRU

0.08017826080322266

0.9759744825402124

3.573458433151245

Technology-CNN-GRU

0.10770988464355469

0.996093234399166

1.3454499244689941

通过上表可以知道,CNN-GRU推理时间最短,Technology-CNN-GRU的R²分数最高,用于衡量模型对数据的拟合程度,R²越接近1表示模型对数据的拟合效果越好,Technology-CNN-GRU的Mape也是最低的,MAPE的值越小,说明模型的预测结果与实际观测结果之间的误差越小,预测模型的准确度越高。

通过本次比特币价格预测,我学习了如何利用先进的英特尔® ONEAPI AI分析工具包来应对加密货币市场的高波动性和预测挑战。在本项目中,不仅学习了LSTM与GRU原理的区别,同时也明白了两个模型面对相同数据表现的差异,其次,通过卷积神经网络与GRU相结合,可以提高模型的精度。通过项目也学习到了特征工程处理时序的布林带、傅里叶变换等,虽然模型最后的R²达到了0.996,但是预测结果不尽人意。这也让我明白了市场的价格难以模拟与预测,同时也意识到数据的分析与处理在市场中的重要地位。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值