我们首先需要理解LSTM模型对输入数据的要求。LSTM通常用于处理序列数据,对于股票预测,我们通常将一段时间内的数据作为一个序列,然后预测下一个时间点的涨跌。
假设我们有100只股票,每只股票500天,每天14个特征。我们想要预测未来一天是涨还是跌(二分类问题).
一种常见的方法是:对于每只股票,我们使用过去N天的数据来预测下一天的涨跌。因此,我们需要将数据重构为样本,每个样本是一个序列(长度为N,包含N天的数据,每天有14个特征),对应的标签是下一天的涨跌(例如,如果收盘价上涨则为1,否则为0)。
步骤:
- 确定序列长度N(例如,选择过去20天作为输入序列)。
- 对于每只股票,我们从第N天开始,到第499天(因为最后一天没有下一天的数据,所以到倒数第二天)结束,每个样本是连续N天的数据,标签是下一天的涨跌。
- 注意:由于每只股票是独立的,我们不能将不同股票的数据混在一个序列中,即每个序列只包含一只股票的数据。
具体处理:
假设原始数据是一个二维数组,形状为(100*500,14),其中前500行是第一只股票,接着500行是第二只股票,接着500行是第三只股票...但更常见的是,我们有一个三维数组,形状为(100, 500, 14),即(股票数量,时间步长,特征数)。
但是,如果原始数据是每行一只股票一天的数据,并且按股票顺序排列(即前500行是股票1,接着500行是股票2,接着500行是股票3...),那么我们可以先reshape成(100, 500, 14)。
然后,对于每只股票,我们生成一系列长度为N的序列,以及对应的标签。
例如,对于一只股票,我们有500天数据,使用过去N天,那么我们可以生成500-N个样本(也就是500-N个序列).
因此,总样本(及:总序列数)数为:100 * (500 - N)
注意:在生成样本时,我们需要确保每个样本的标签是下一天的涨跌。这里涨跌可以根据收盘价(假设收盘价是其中一个特征)来定义,比如如果下一天的收盘价高于当前收盘价,则标签为1,否则为0。
假设收盘价是第3个特征(索引为2),那么我们可以这样计算标签。
具体步骤:
- 将原始数据reshape为(100, 500, 14)
- 确定序列长度N
- 初始化两个空列表,一个用于存储
样本(序列),一个用于存储标签。 - 对于每只股票,从索引N开始到索引499(最后一天)结束,取每个位置i的前N天数据作为样本,然后取i+1天的收盘价与i天的收盘价比较,设置标签。
- 注意:我们只能到499,因为i+1不能超过499(因为我们只有500天,索引从0到499,所以i最大为498,但我们是从N开始,所以i最大为498,实际上我们取样本的时候,最后一个样本是第498天(索引498)的前N天,然后预测第499天。所以标签是用第499天和第498天的收盘价比较。
但是注意:我们共有500天,所以对于每只股票,我们可以生成500-N个样本。例如,N=20,那么每只股票有480个样本(也就是序列)。
将所有样本(序列)组合成一个三维数组,形状为(总样本(序列)数,N,14),标签是一个一维数组,长度为总样本数。
另外,注意:在训练LSTM时,我们通常需要对特征进行归一化。这里我们可以对每只股票的特征分别归一化,因为不同股票的价格范围可能不同,通常建议对每只股票单独归一化, 不要所有股票的数据放在一起进行归一化.
-
归一化:对于每只股票,我们使用其自身的均值和标准差对每个特征进行归一化。注意:在归一化时,我们不应该使用未来的数据,所以我们应该用
每个样本序列内的数据来计算均值和标准差,或者更常用的,使用训练集的统计量来归一化训练集和测试集。但这里我们只是生成样本,可以在后续划分训练集和测试集后再归一化。 -
但是,如果我们使用每只股票的全部数据(比如500天的数据)来归一化,可能会存在
数据泄露。所以更好的做法是:先划分训练集和测试集(按股票划分或按时间划分),然后使用训练集的统计量来归一化训练集和测试集。 -
由于我们是用过去N天预测下一天,所以我们可以按时间划分
训练集和测试集。例如,前80%的时间步(也就是序列)作为训练集,后20%作为测试集。但是注意,我们不能打乱顺序,因为时间序列是有顺序的。 -
另一种划分是按股票划分,比如80%的股票作为训练集,20%作为测试集。
这里,我们假设按股票划分训练集和测试集。那么我们可以先划分股票,然后对训练集和测试集分别归一化(使用训练集的均值和标准差归一化训练集和测试集,注意测试集使用训练集的统计量)。
步骤:
- 将数据reshape为(100, 500, 14)
- 划分训练集和测试集:例如,选择80只股票作为训练集,20只股票作为测试集。
- 对训练集,计算每个特征的均值和标准差(形状为(14,)),然后对训练集和测试集进行归一化。
- 然后从归一化后的数据中生成样本和标签。
但是,注意:归一化时,我们是在每个特征上进行的,即对每个特征,我们使用训练集中所有样本(所有股票的所有时间步)的均值和标准差。但是,如果我们按股票划分,我们可以这样计算训练集的均值和标准差:
训练集数据形状为(80, 500, 14),我们可以将其reshape为(80*500, 14)然后计算每个特征的均值和标准差。
- 生成样本:对于归一化后的数据,我们按照上述方法生成样本和标签。
代码步骤:
假设原始数据已经按股票顺序排列,每只股票500天,我们可以这样处理:
注意:我们假设原始数据是一个二维数组,形状为(100*500, 14),我们首先将其reshape为(100, 500, 14)
步骤:
- 读取数据,reshape为(100, 500, 14)
- 划分训练集和测试集(按股票索引)
- 计算训练集的均值和标准差(用于归一化)
- 对训练集和测试集进行归一化
- 生成序列样本和标签