引言
时间序列数据指的是在一系列特定时间间隔内的数据。如果我们想要在机器学习中建立序列预测,那么就必须处理与时间和序列相关的数据。序列数据是时间序列数据的一种抽象。数据的顺序是序列数据的一个重要特性。
序列分析或时间序列分析的基本概念
序列分析或时间序列分析是根据之前观察到的数据来预测给定输入序列中的下一个元素。预测可以是任何可能出现的事物:一个符号、一个数字、第二天的天气、语音中的下一个词语等等。序列分析在诸如股票市场分析、天气预报、产品推荐等应用中非常有用。
示例
考虑以下示例来理解序列预测。这里 A, B, C, D 是已知的值,你需要使用序列预测模型来预测值 E。
安装有用的软件包
对于使用 Python 进行的时间序列数据分析,我们需要安装以下软件包:
Pandas
Pandas 是一个开源的 BSD 许可库,提供了高性能的数据结构以及用于 Python 的数据分析工具。你可以使用以下命令来安装 Pandas:
pip install pandas
如果你使用的是 Anaconda 并希望通过 conda 包管理器安装,你可以使用以下命令:
conda install -c anaconda pandas
hmmlearn
这是一个开源的 BSD 许可库,包含了用于学习隐马尔科夫模型(HMM)的简单算法和模型。你可以使用以下命令来安装 hmmlearn:
pip install hmmlearn
如果你使用的是 Anaconda 并希望通过 conda 包管理器安装,你可以使用以下命令:
conda install -c omnia hmmlearn
PyStruct
这是一个结构化学习和预测库。PyStruct 中实现的学习算法包括条件随机场(CRF)、最大边际马尔科夫网络(M3N)或结构化的支持向量机。你可以使用以下命令来安装 PyStruct:
pip install pystruct
CVXOPT
这是一个基于 Python 编程语言用于凸优化的软件包。它也是一个免费的软件包。你可以使用以下命令来安装 CVXOPT:
pip install cvxopt
如果你使用的是 Anaconda 并希望通过 conda 包管理器安装,你可以使用以下命令:
conda install -c anaconda cvxopt
使用 Pandas 处理、切片和提取时间序列数据的统计数据
如果你需要处理时间序列数据,Pandas 是一个非常有用的工具。使用 Pandas,你可以执行以下操作:
示例
以下示例展示了如何使用 Pandas 处理和切片时间序列数据。注意这里我们使用的数据是从 monthly.ao.index.b50.current.ascii 下载的月度北极振荡数据,并且已经转换为文本格式供我们使用。
处理时间序列数据
处理时间序列数据,你需要执行以下步骤:
第一步是导入以下包:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
接下来,定义一个函数,该函数将从输入文件读取数据,如下所示:
def read_data(input_file):
input_data = np.loadtxt(input_file, delimiter=None)
现在,将此数据转换为时间序列。为此,创建我们时间序列的日期范围。在此示例中,我们将一个月作为数据的频率。我们的文件包含从 1950 年 1 月开始的数据。
dates = pd.date_range('1950-01', periods=input_data.shape[0], freq='M')
在这一步骤中,我们将使用 Pandas Series 创建时间序列数据,如下所示:
output = pd.Series(input_data[:, index], index=dates)
return output
在主程序块中:
if __name__ == '__main__':
input_file = "/Users/admin/AO.txt"
timeseries = read_data(input_file)
最后,绘制并可视化数据:
plt.figure()
timeseries.plot()
plt.show()
你会看到类似下图所示的图表:
切片时间序列数据
切片涉及检索时间序列数据的一部分。作为示例的一部分,我们只从 1980 年到 1990 年切片数据。观察以下执行此任务的代码:
timeseries['1980':'1990'].plot()
plt.show()
当你运行切片时间序列数据的代码时,你可以看到类似下图所示的图表:
请注意,由于缺少具体的数据文件和索引信息,在上述示例代码中 input_data[:, index]
部分可能需要调整以适应实际的数据集情况。
时间序列数据的切片与统计提取
切片时间序列数据
切片是指仅检索时间序列数据的一部分。作为示例的一部分,我们仅从 1980 年到 1990 年切片数据。观察以下执行此任务的代码:
timeseries['1980':'1990'].plot()
plt.show()
当你运行切片时间序列数据的代码时,你可以看到类似下图所示的图表:
提取时间序列数据的统计信息
在某些情况下,你需要从给定数据中提取一些统计信息以得出重要的结论。均值、方差、相关性、最大值和最小值就是这样的统计信息。如果你想从给定的时间序列数据中提取此类统计信息,可以使用以下代码:
均值
你可以使用 mean()
函数来找出均值,如下面所示:
timeseries.mean()
然后你会观察到以下输出:
-0.11143128165238671
最大值
你可以使用 max()
函数来找出最大值,如下面所示:
timeseries.max()
然后你会观察到以下输出:
3.4952999999999999
最小值
你可以使用 min()
函数来找出最小值,如下面所示:
timeseries.min()
然后你会观察到以下输出:
-4.2656999999999998
同时获取所有统计信息
如果你想同时计算所有统计信息,可以使用 describe()
函数,如下面所示:
timeseries.describe()
然后你会观察到以下输出:
count 817.000000
mean -0.111431
std 1.003151
min -4.265700
25% -0.649430
50% -0.042744
75% 0.475720
max 3.495300
dtype: float64
重采样
你可以将数据重新采样到不同的时间频率。进行重采样的两个参数是:
使用均值方法进行重采样
你可以使用以下代码用 mean()
方法对数据进行重采样,默认方法是 mean()
:
timeseries_mm = timeseries.resample("A").mean()
timeseries_mm.plot(style = 'g--')
plt.show()
然后,你可以观察到以下图形作为使用 mean()
方法进行重采样的输出:
使用中位数方法进行重采样
你可以使用以下代码用 median()
方法对数据进行重采样:
timeseries_mm = timeseries.resample("A").median()
timeseries_mm.plot()
plt.show()
然后,你可以观察到以下图形作为使用 median()
方法进行重采样的输出:
移动平均
你可以使用以下代码来计算移动平均:
timeseries.rolling(window = 12, center = False).mean().plot(style = '-g')
plt.show()
然后,你可以观察到以下图形作为移动平均的输出:
使用隐马尔科夫模型 (HMM) 分析序列数据
隐马尔科夫模型 (HMM) 是一种统计模型,广泛应用于具有连续性和扩展性的数据,例如时间序列股票市场分析、健康检查和语音识别。这部分详细介绍了如何使用 HMM 分析序列数据。
隐马尔科夫模型 (HMM)
HMM 是一种基于马尔科夫链的概念而建立的随机模型,假设未来状态的概率仅取决于当前状态而不是任何先前的状态。例如,在掷硬币时,我们不能说第五次抛投的结果将是正面,因为硬币没有记忆,下一个结果不依赖于前一个结果。
数学上,HMM 包括以下变量:
-
状态 (S):HMM 中的一组隐藏或潜伏状态。记作 S。
-
输出符号 (O):HMM 中的一组可能的输出符号。记作 O。
-
状态转移概率矩阵 (A):从一个状态转移到其他每个状态的概率。记作 A。
-
观测发射概率矩阵 (B):在特定状态下发射/观察符号的概率。记作 B。
-
初始概率矩阵 (Π):从系统的各种状态开始处于特定状态的概率。记作 Π。
因此,一个 HMM 可定义为 λ = (S, O, A, B, Π),其中:
-
S = {s1, s2, ..., sN} 是一个由 N 个可能状态组成的集合,
-
O = {o1, o2, ..., oM} 是一个由 M 个可能观测符号组成的集合,
-
A 是一个 N×N 的状态转移概率矩阵 (TPM),
-
B 是一个 N×M 的观测或发射概率矩阵 (EPM),
-
示例:股票市场数据分析
在这个例子中,我们将逐步分析股票市场的数据,以便了解 HMM 如何处理序列或时间序列数据。请注意,我们在 Python 中实现这个例子。
导入必要的包,如下所示:
import datetime
import warnings
现在,使用 matpotlib.finance
包中的股票市场数据,如下所示:
import numpy as np
from matplotlib import cm, pyplot as plt
from matplotlib.dates import YearLocator, MonthLocator
try:
from matplotlib.finance import quotes_historical_yahoo_och1
except ImportError:
from matplotlib.finance import (
quotes_historical_yahoo as quotes_historical_yahoo_och1)
from hmmlearn.hmm import GaussianHMM
加载从开始日期到结束日期的数据,即在两个特定日期之间的数据,如下所示:
start_date = datetime.date(1995, 10, 10)
end_date = datetime.date(2015, 4, 25)
quotes = quotes_historical_yahoo_och1('INTC', start_date, end_date)
在这一阶段,我们将提取每日收盘报价。为此,使用以下命令:
closing_quotes = np.array([quote[2] for quote in quotes])
现在,我们将提取每日交易的股票数量。为此,使用以下命令:
volumes = np.array([quote[5] for quote in quotes])[1:]
在这里,我们采用收盘股价的百分比差异,使用以下代码:
diff_percentages = 100.0 * np.diff(closing_quotes) / closing_quotes[:-1]
dates = np.array([quote[0] for quote in quotes], dtype = np.int)[1:]
training_data = np.column_stack([diff_percentages, volumes])
在这个阶段,创建并训练高斯 HMM。为此,使用以下代码:
hmm = GaussianHMM(n_components = 7, covariance_type = 'diag', n_iter = 1000)
with warnings.catch_warnings():
warnings.simplefilter('ignore')
hmm.fit(training_data)
现在,使用 HMM 模型生成数据,使用以下命令:
num_samples = 300
samples, _ = hmm.sample(num_samples)
最后,在这个阶段,我们将差异百分比和交易股票数量以图形形式输出。
使用以下代码绘制和可视化差异百分比:
plt.figure()
plt.title('Difference percentages')
plt.plot(np.arange(num_samples), samples[:, 0], c = 'black')
使用以下代码绘制和可视化交易的股票数量:
plt.figure()
plt.title('Volume of shares')
plt.plot(np.arange(num_samples), samples[:, 1], c = 'black')
plt.ylim(ymin = 0)
plt.show()