(二)预处理时间序列数据用于AI预测和异常检测

目录

介绍

检查、重新格式化和清理比特币数据集

拆分比特币数据集

扩展比特币数据集

生成序列并创建数据集

下一步


介绍

本系列文章将指导您完成使用AI开发功能齐全的时间序列预测器和异常检测器应用程序所需的步骤。我们的预测器/检测器将处理加密货币数据,特别是比特币。但是,在学习完本系列之后,您将能够将学到的概念和方法应用于任何性质相似的数据类型。

要从本系列中充分受益,您应该具备一些Python、机器学习和Keras技能。整个项目都可以在我的“GitHub 存储库中找到。您还可以在此处此处查看完全交互式的notebooks。

在本系列的前一篇文章中,我们讨论了时间序列数据的性质和重要性。在本教程中,您将学习如何将数据转换为可用于训练神经网络预测模型以及异常检测器的形式。

我们大部分时间都会处理比特币价格。我在Kaggle找到了一个完整的数据集。为了澄清一些概念和想法,我们将使用我从NOAA网站获得的天气数据集。继续下载这些数据集以进行后续操作。在这个项目中,我将使用Kaggle Notebooks——但你可以使用任何其他云笔记本,甚至你的本地机器。

检查、重新格式化和清理比特币数据集

在深入检查之前,让我们导入我们将在这个项目中使用的所有库。如果您的notebooks 无法导入其中任何一个,请记住您可以从终端使用pip命令安装它们。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import plotly.graph_objects as go
from sklearn.preprocessing import MinMaxScaler
import gc
import joblib
from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.models import load_model
from sklearn.ensemble import IsolationForest
from sklearn.cluster import KMeans
import json
import urllib
from datetime import datetime, timedelta,timezone
import requests

现在让我们加载包含从2011年12月到2020年12月的比特币历史记录的.csv文件(每分钟间隔——大约400万个样本)并且显示第一行。文件路径为/kaggle/input/bitcoin-historical-data/bitstampUSD_1-min_data_2012-01-01_to_2020-1

btc = pd.read_csv('/kaggle/input/bitcoin-historical-data/bitstampUSD_1-min_data_2012-01-01_to_2020-12-31.csv')
btc.head()

您现在可以先看看:

(二)预处理时间序列数据用于AI预测和异常检测

请注意,应表示为日期格式的“时间戳”列当前表示为Unix格式。要将其切换到正确的,让我们这样做:

btc['Timestamp'] = pd.to_datetime(btc.Timestamp, unit='s')
btc.head()

这会将列格式更改为正确的格式:

(二)预处理时间序列数据用于AI预测和异常检测

您可能会在大多数列中看到大量NaN值(空字段)。让我们选择“Weighted_Price”来专注于单变量方法,以保持简单。我们将重新采样观察结果并获得平均间隔1小时而不是1分钟的点,因为您不会期望在短时间内注意到大的变化时间段,因此您将拥有大量冗余数据。

btc = btc[['Timestamp','Weighted_Price']]
btc = btc.resample('H', on='Timestamp')[['Weighted_Price']].mean()

现在让我们看一下整个图片,以直观地了解必须删除集合的哪些部分以检测数据不连续性并摆脱无意义的数据:

pano = btc.copy() #We're going to use this later
fig = go.Figure()
fig.add_trace(go.Scatter(x=pano.index, y=pano['Weighted_Price'],name='Full history BTC price'))
fig.update_layout(showlegend=True,title="BTC price history",xaxis_title="Time",yaxis_title="Prices",font=dict(family="Courier New, monospace"))
fig.show()

(二)预处理时间序列数据用于AI预测和异常检测

在上图中,您会注意到从2012年到2013年年中的一些不连续性。此外,直到2017年年中的数据趋势是无用的,因为比特币价格不太可能回到接近于零的值。您不想为未来的模型提供不相关的数据,因此让我们截断我们的数据集并仅包含有意义的值,并将空值替换为它们的下一个非空邻居:

btc = btc.iloc[51000:]
btc.fillna(method ='bfill', inplace = True)
print('NaN values: ',btc.isna().sum())

现在您有一个不包含任何空值的数据集。数据点从2017-10-25 07:00:00开始,您的新集合有27906个值。如果你再次绘制你的数据集,你必须得到这样的东西:

(二)预处理时间序列数据用于AI预测和异常检测

拆分比特币数据集

您可能知道,采用数据集的一部分来训练模型并使用另一部分来测试它是一种常见的做法。在这种特殊情况下,我们需要采用连续的部分,这就是为什么我将前20%的值作为测试集,最后80%作为训练集。为此,请发出以下命令:

data_for_us = btc.copy() #To be used later on Unsupervised Learning
training_start = int(len(btc) * 0.2)
train = btc.iloc[training_start:]
test = btc.iloc[:training_start]

现在,您的训练集和测试集形状分别为 (22325, 1)和 (5581, 1)。

扩展比特币数据集

在实现任何机器学习/深度学习模型 (ML/DL)之前,此步骤至关重要。没有它,模型收敛速度会很低;可能,模型在训练后甚至永远不会达到一个好的结果。通常,发生这种情况是因为需要适应异构值的参数调整非常消耗资源。我们可以将这一步定义为在小值之间调整数据,使任何ML/DL模型更容易收敛。

让我们首先通过发出以下命令来拟合定标器:

scaler = MinMaxScaler().fit(train[['Weighted_Price']])

请注意,我们使用的是Scikit-Learn中MinMaxScaler方法。我将从官方文档网站上获取它的描述:“这个评估器单独缩放和翻译每个特征,使其在训练集的给定范围内,例如介于01之间。 ”人们在使用缩放器时经常犯的错误在整个可用数据上拟合它。这不是一个合适的方法;您必须仅在训练集上安装缩放器。要保存缩放器以备将来使用并缩放训练和测试集,请发出以下命令:

joblib.dump(scaler, 'scaler.gz')
scaler = joblib.load('scaler.gz')
 
def scale_samples(data,column_name,scaler):
    data[column_name] = scaler.transform(data[[column_name]])
return data
 
train = scale_samples(train.copy(),train.columns[0],scaler)
test = scale_samples(test,test.columns[0],scaler)

现在,如果您检查表格,您会注意到所有值都在0和1之间。这就是我们想要的,对吧?

生成序列并创建数据集

正如我在上一篇文章中提到的,我们希望检测当前和未来比特币价格的异常情况。让我们澄清一下。首先,我们需要使用过去和当前的数据来预测未来的价格值,然后确定整个数据图中的异常情况。让我用图形进一步澄清这一点。

这是您通常在序列数据集中拥有的内容:

(二)预处理时间序列数据用于AI预测和异常检测

假设t = n是当前日期和时间。我们想要的是预测价格值,例如,给定从t = 0t = n的数据,t = n+1,并检测整个窗口(t=0 t=n+1)中的异常。像这样:

(二)预处理时间序列数据用于AI预测和异常检测

为此,您需要将整个数据集分割成可以传递给模型的小块序列。在这种情况下,我们希望将比特币价格的最后24小时传递给我们的模型,并预测下一小时的价格。为此,让我们将回顾定义为过去窗口的步骤,将展望定义为未来窗口的步骤:

(二)预处理时间序列数据用于AI预测和异常检测

在代码中,函数将是:

def shift_samples(data,column_name,lookback=24):
    data_x = []
    data_y = []
    for i in range(len(data) - int(lookback)):
        x_floats = np.array(data.iloc[i:i+lookback])
        y_floats = np.array(data.iloc[i+lookback])
        data_x.append(x_floats)
        data_y.append(y_floats)
    return np.array(data_x), np.array(data_y)

这将返回两个NumPy数组,第一个用于回顾块,第二个用于展望块。现在调用这个函数并通过测试和训练集来创建我们要使用的数据集:

X_train, y_train = shift_samples(train[['Weighted_Price']],train.columns[0])
X_test, y_test = shift_samples(test[['Weighted_Price']], test.columns[0])

最后,要了解集合的最终形状,请发出以下命令:

print("Final datasets' shapes:")
print('X_train: '+str(X_train.shape)+', y_train: '+str(y_train.shape))
print('X_test: '+str(X_test.shape)+', y_train: '+str(y_test.shape))

这将返回:

Final datasets' shapes:
X_train: (22301, 24, 1), y_train: (22301, 1)
X_test: (5557, 24, 1), y_train: (5557, 1)

如果要增加前瞻步骤,则需要稍微修改函数:

def shift_samples(data,column_name,lookback=30,lookforward=2):
    data_x = []
    data_y = []
    for i in range(len(data) - int(lookback)-int(lookforward)):
        x_floats = np.array(data.iloc[i:i+lookback])
        y_floats = np.array(data.iloc[i+lookback:i+lookback+lookforward])
        data_x.append(x_floats)
        data_y.append(y_floats)
    return np.array(data_x), np.array(data_y)

请记住,如果您修改shift_sample函数并增加前瞻步骤,您还需要修改传入模型。我创建了一个notebook,我在其中开发了这种方法。要获得完整的notebook交互性,请查看Kaggle上可用的交互性。

下一步

接下来的文章中,我们将进入更深的时间序列数据异常检测,看看如何构建一个可以执行此任务的模型。

https://www.codeproject.com/Articles/5295162/Preprocessing-Time-Series-Data-for-AI-Forecasting

上一篇:验证实验 Blum’s Book: Sample programs in Chapter 04, 05 (MovingData)


下一篇:BTC:简单易懂比特币之比特币的神奇——区块链技术的体现