主页 > 钱包imtoken > 使用 LSTM 预测比特币价格

使用 LSTM 预测比特币价格

钱包imtoken 2023-01-17 13:06:19

本文建立在“用于时间序列预测的 LSTM 神经网络”一文的基础上。如果你还没有读过,我强烈推荐你读一读。

考虑到最近关于比特币货币泡沫的讨论,我写这篇文章主要是为了预测比特币价格和张量,使用的方法不仅关注价格,还关注 BTC 数量和货币(在下面的例子中)多维 LSTM 神经网络和创建一个多元顺序机器学习模型。

事不宜迟,让我们进入正题。

时间数据集

我们首先需要数据。幸运的是,Kaggle 上有一个包含 7 个元素的历史比特币数据的数据集,非常完美。

但是,我们需要在将其输入到 LSTM 之前对该数据集进行标准化。具体操作可以参考我之前的文章。我们在数据上取一个大小为 N 的滑动窗口,并从 0 开始重建数据:

.

这是一种多维方法,这意味着我们将在所有维度上进行这种滑动窗口方法。通常,这将是一个痛苦的屁股。但幸运的是,我们能够在 Python 中使用 Pandas 库!我们可以将每个窗口表示为 Pandas 数据框,然后我们可以对整个数据框(即所有列)执行规范化操作。

你需要注意的另一件事是,这个数据集一开始并不是很整洁。各个列中有很多NaN值。我们对这个问题采取了一种偷懒的做法:在创建窗口的时候,我们检查窗口中是否有 NaN 值。如果是这样,我们丢弃这个窗口并移动到下一个窗口。

比特币28结果预测

当我们在这里时,我们将这些函数提供给一个名为 ETL(提取、转换、加载)的自包含类并将其保存为 etl.py,我们可以将完整的数据加载到一个名为的库中。

这是我们 clean_data() 函数的核心代码:

num_rows= len(data)
x_data= []
y_data= []
i= 0
while((i+x_window_size+y_window_size) <= num_rows):
    x_window_data= data[i:(i+x_window_size)]
    y_window_data= data[(i+x_window_size):(i+x_window_size+y_window_size)]
    #Remove any windows that contain NaN
    if(x_window_data.isnull().values.any()or y_window_data.isnull().values.any()):
        i+= 1
        continue
    if(normalise):
        abs_base, x_window_data= self.zero_base_standardise(x_window_data)
        _, y_window_data= self.zero_base_standardise(y_window_data, abs_base=abs_base)
    #Average of the desired predicter y column
    y_average= np.average(y_window_data.values[:, y_col])
    x_data.append(x_window_data.values)
    y_data.append(y_average)
    i+= 1

复制

一旦完成,我们只需要确保我们的 LSTM 模型接受 M 类型的序列,其中 M = 数据的维度,就是这样!

装载存储器损坏

或者你认为它已经完成了,但生活很少如你所愿。我第一次尝试这样做时,我的机器停止了并给了我一个内存错误。你看,问题在于使用的比特币数据集每分钟都有记录,所以数据集非常大。标准化后,大约有 100 万个数据窗口。将所有这 100 万个窗口加载到 Keras 并开始训练需要很长时间。

那么如果你没有 100G 的 RAM,你如何训练这些数据(即使你有那么多 RAM,如果这个数据增长到 100 倍,增加更多的 RAM 显然是不可行的)?这时候我们就需要用到 Keras 的 fit_generator() 函数了!

比特币28结果预测

现在,如果您不了解 Python 生成器,请先去了解它们。

简而言之; 生成器迭代未知(可能无限)长度的数据,每次调用只传递下一个数据。现在,只要你有一半的大脑,我相信你可以看到它是有用的;如果我们可以一次训练模型一组窗口,那么一旦我们完成了那个窗口,我们就可以把它扔掉并使用下一组窗口替代方案。这使得训练具有低内存利用率的模型成为可能。从技术上讲,如果你把窗户做得足够小,你甚至可以在你的物联网烤面包机上训练这个模型!

我们需要做的是创建一个生成器,创建一批窗口,并将其传递给 Keras 的 fit_generator() 函数。简而言之,我们只是扩展 clean_data() 的核心代码来生成(在生成模式下返回)批量窗口:

#Restrict yielding until we have enough in our batch. Then clear x, y data for next batch
if(i% batch_size== 0):
    #Convert from list to 3 dimensional numpy array [windows, window_val, val_dimension]
    x_np_arr= np.array(x_data)
    y_np_arr= np.array(y_data)
    x_data= []
    y_data= []
    yield (x_np_arr, y_np_arr)

复制

烦人的重播

现在我在这里发现的另一个问题是我创建的 clean_data() 生成器平均需要 3-4 秒来为每个“批次”创建窗口。这本身是可以接受的,因为处理一批训练数据大约需要 15-20 分钟。但是如果我想调整模型并再次运行它,重新训练它需要很长时间。

那么我们该怎么办?首先尝试对其进行规范化,然后将其规范化的 numpy 数组保存到文件中,希望它保留结构并快速访问?

比特币28结果预测

HDF5可以帮助你!通过使用 h5py 库,我们可以轻松地将整洁且标准化的数据窗口保存为具有亚秒级 IO 访问的 numpy 数组列表。因此,我们创建了一个名为 create_clean_datafile() 的函数,它就是这样做的:

def create_clean_datafile(self, filename_in, filename_out, batch_size=1000, x_window_size=100, y_window_size=1, y_col=0, filter_cols=None, normalise=True):
    """Incrementally save a datafile of clean data ready for loading straight into model"""
    print('> Creating x & y data files...')
    data_gen= self.clean_data(
        filename_in,
        batch_size= batch_size,
        x_window_size= x_window_size,
        y_window_size= y_window_size,
        y_col= y_col,
        filter_cols= filter_cols,
        normalise= True
    )
    i= 0
    with h5py.File(filename_out,'w') as hf:
        x1, y1= next(data_gen)
        #Initialise hdf5 x, y datasets with first chunk of data
        rcount_x= x1.shape[0]
        dset_x= hf.create_dataset('x', shape=x1.shape, maxshape=(None, x1.shape[1], x1.shape[2]), chunks=True)
        dset_x[:]= x1
        rcount_y= y1.shape[0]
        dset_y= hf.create_dataset('y', shape=y1.shape, maxshape=(None,), chunks=True)
        dset_y[:]= y1
        for x_batch, y_batchin data_gen:
            #Append batches to x, y hdf5 datasets
            print('> Creating x & y data files | Batch:', i, end='\r')
            dset_x.resize(rcount_x+ x_batch.shape[0], axis=0)
            dset_x[rcount_x:]= x_batch
            rcount_x+= x_batch.shape[0]
            dset_y.resize(rcount_y+ y_batch.shape[0], axis=0)
            dset_y[rcount_y:]= y_batch
            rcount_y+= y_batch.shape[0]
            i+= 1

复制

现在我们可以创建一个新的生成器函数 generate_clean_data() 来打开 hdf5 文件并将这些相同的标准化批次输入到 Keras fit_generator() 函数中,速度非常快!

def generate_clean_data(self, filename, batch_size=1000, start_index=0):
    with h5py.File(filename,'r') as hf:
        i= start_index
        while True:
            data_x= hf['x'][i:i+batch_size]
            data_y= hf['y'][i:i+batch_size]
            i+= batch_size
            yield (data_x, data_y)

复制

但是,查看数据,我们不想在某些维度上添加不必要的噪声。我所做的是为 create_clean_datafile() 函数创建一个参数,该函数接受特征(列)的过滤。有了这个,我将数据文件缩减为 4 维时间序列,包括开盘、收盘、交易量(比特币)和交易量(货币)。这样做会减少我花在训练网络上的时间。

然后将数据输入网络,该网络具有:一个输入 LSTM 层,用于接收模型数据 [dimension, sequence_size, training_rows],来自隐藏的第二个 LSTM 层的数据,以及一个带有 tanh 函数的全连接输出层,用于输出下一个预测归一化收益率。

比特币28结果预测

训练是通过根据我们的 epoch 数和我们的配置 JSON 文件中指定的训练或测试拆分计算 steps_per_epoch 来完成的。

我们以类似的方式进行测试,使用相同的生成器和训练并利用 eras predict_generator() 函数。在预测我们的测试集时,我们唯一需要添加的额外内容是迭代生成器并分离出 x 和 y 输出的输出。这是因为 Keras predict_generator() 函数只接受 x 输入,不处理 x 和 y 值的元组。但是,我们仍然想使用 y 值(真实数据),所以我们将它们存储在单独的列表中,因为我们想将它们用于绘图,以防我们想与真实数据进行比较并可视化结果. 然后,我们做同样的事情,而不是逐步预测,我们为第一个预测预先设置一个大小为 50 的窗口,然后沿着新的预测滑动窗口,将它们作为基本事实,所以我们慢慢开始预测这个预言,

最后,我们将测试集预测和测试集真实 y 值保存在 HDF5 文件中,以便我们将来可以轻松访问它们,而无需重新运行所有内容,如果模型有用的话。然后我们将结果绘制在 2 个图表上。一个显示每天前进一步的预测比特币28结果预测,另一个显示前进五十步的预测。

比特币利润

让我们继续预测Bitcon的价格!根据我上一篇文章,我们将尝试做两种类型的预测:

第一种是逐点预测,即预测点t+1,然后移动真实数据的窗口,继续预测下一个点,结果如下:

第二种类型的预测是 t+n 多步前瞻预测,其中我们用来自地面实况窗口的预测填充移动窗口并绘制 N 步。结果如下:

然后,我们可以看到,在逐点预测时,预测是合理的。有时会有些出入,但大体以真实数据为准。然而,这些预测确实比实际数据更不稳定。如果不进行更多测试,则很难确定可能的原因,如果模型重新参数化可以解决问题。

比特币28结果预测

在预测趋势时,该模型的准确性开始下降。这种趋势似乎不是特别准确,有时甚至不一致。然而!有趣的是,预测趋势线的大小似乎与价格波动的大小相关。

综上所述

在本节中,我不是从 AI 帽子的角度,而是从投资经理的角度解释一些关键事实……

人们应该注意的主要事情是预测回报是一项非常无用的活动。我的意思是,预测回报是预测的圣杯,一些顶级对冲基金的观点是通过在事实中找到新的阿尔法指标来做到这一点,这是一件非常困难的事情比特币28结果预测,因为巨大的外部影响会推高资产价格。实际上,它可以等同于尝试预测随机的下一步行动。

然而,我们所做的并不是完全没有意义的。有限的时间序列数据,即使有多个维度,也很难预测回报,我们可以看到,特别是从第二张图表中,有一种方法可以预测波动性。不仅仅是波动,我们还可以通过扩展来预测市场环境,让我们了解我们目前所处的市场环境。

它在哪里有用?许多不同的策略(我不会在这里详细介绍)在不同的市场环境中都能很好地发挥作用。动量策略可能在低迷和强劲的趋势环境中运作良好,套利策略可能在高压环境中更有效以产生高回报。我们可以看到,通过了解我们当前的市场环境,预测未来的市场状况是始终为市场分配正确策略的关键。虽然这更像是传统市场的一般投资方式,但同样适用于比特币市场。

如你所见,目前预测比特币的长期价格相当困难,仅通过时间序列数据技术没有人可以做到,因为有很多因素会影响价格走势。在此类数据集上使用 LSTM 神经网络的另一个问题是,我们将整个时间序列数据集视为一个固定的时间序列。也就是说,时间序列的属性随时间保持不变。然而,这是不可能的,因为影响价格变化的因素也会随着时间的推移而变化,因此假设网络发现的属性或模式今天仍在使用是天真的,而且实际上不必如此。

有一些工作可以帮助解决这个非平稳性问题,目前的前沿研究集中在使用贝叶斯方法和 LSTM 来克服时间序列非平稳性问题。

当然,这超出了这篇短文的范围。

该项目的完整代码:Multidimensional-LSTM-BitCoin-Time-Series。