长短期记忆(LSTM)是一种特殊类型的循环神经网络(RNN),它可以使用记忆细胞随时间保留重要信息。 LSTM的这一特性使其成为学习相互依赖的序列的绝佳算法,可以帮助构建语言翻译、销售时间序列、聊天机器人、自动更正、下一个单词建议等解决方案。 在这个案例研究中,我将展示如何使用LSTM来学习股票价格的模式。使用此模板,您将能够根据过去10天的价格预测明天的股票价格。拉取历史股价数据 要提取任何股票的数据,我们可以使用名为nsepy的库 如果您想对任何其他股票执行此操作,只需使用该公司的股票市场代码,就像我在这里为Infosys使用INFY一样。importpandasaspdimportnumpyasnp从numpy数组中删除科学记数法np。setprintoptions(suppressTrue)安装nsepy库以获取股票价格!pipinstallnsepy使用nsepy库获取Stock数据fromnsepyimportgethistoryfromdatetimeimportdatetimestartDatedatetime(2019,1,1)endDatedatetime(2020,10,5)获取数据StockDatagethistory(symbolINFY,startstartDate,endendDate)print(StockData。shape)StockData。head() 可视化股价走势创建一个日期列StockData〔TradeDate〕StockData。index绘制股票价格matplotlibinlineStockData。plot(xTradeDate,yClose,kindline,figsize(20,6),rot20) 准备数据 LSTM模型需要以XVsy的形式输入数据。其中X代表最近10天的价格,y代表第11天的价格。 通过查看过去2年的大量此类示例,LSTM将能够了解价格的变动。因此,当我们通过价格的最后10天时,它将能够预测明天的股票收盘价。 由于LSTM是一种基于神经网络的算法,因此必须对数据进行标准化或规范化,以实现快速和更准确的拟合。提取每天的收盘价FullDataStockData〔〔Close〕〕。valuesprint(FullData〔0:5〕)用于神经网络快速训练的特征缩放fromsklearn。preprocessingimportStandardScaler,MinMaxScaler在标准化或规范化之间进行选择scStandardScaler()scMinMaxScaler()DataScalersc。fit(FullData)XDataScaler。transform(FullData)XFullDataprint(AfterNormalization)X〔0:5〕 为LSTM准备数据splitintosamplesXsampleslist()ysampleslist()NumerOfRowslen(X)TimeSteps10第二天的价格预测是基于过去多少天的价格遍历值以创建组合foriinrange(TimeSteps,NumerOfRows,1):xsampleX〔iTimeSteps:i〕ysampleX〔i〕Xsamples。append(xsample)ysamples。append(ysample)将输入重塑为3D(样本数、时间步长、特征)Xdatanp。array(Xsamples)XdataXdata。reshape(Xdata。shape〔0〕,Xdata。shape〔1〕,1)print(InputDatashape)print(Xdata。shape)我们不会将y重塑为3D数据,因为它应该只是一列ydatanp。array(ysamples)ydataydata。reshape(ydata。shape〔0〕,1)print(OutputDatashape)print(ydata。shape) 将数据拆分为训练和测试 保留最后几天的数据以测试模型的学习情况,并休息以训练模型。 这里我选择最近5天作为测试。选择测试数据记录的数量TestingRecords5将数据拆分为训练和测试XtrainXdata〔:TestingRecords〕XtestXdata〔TestingRecords:〕ytrainydata〔:TestingRecords〕ytestydata〔TestingRecords:〕打印训练和测试的形状print(TrainingDatashape)print(Xtrain。shape)print(ytrain。shape)print(TestingDatashape)print(Xtest。shape)print(ytest。shape) 可视化LSTM的输入和输出数据 打印一些示例输入和输出值,以帮助您直观地了解LSTM模型将如何学习价格。 您可以看到输入是最近10个价格的3D数组,输出是下一个价格的1D数组。可视化发送到LSTM模型的输入和输出forinp,outinzip(Xtrain〔0:2〕,ytrain〔0:2〕):print(inp,,out) 创建深度学习LSTM模型 查看使用LSTM函数而不是Dense来定义隐藏层。输出层有一个神经元,因为我们预测的是第二天的价格,如果你想预测多天,那么改变输入数据和神经元等于预测的天数。为LSTM定义输入形状TimeStepsXtrain。shape〔1〕TotalFeaturesXtrain。shape〔2〕print(NumberofTimeSteps:,TimeSteps)print(NumberofFeatures:,TotalFeatures) 在下面的代码片段中,我使用了三个隐藏的LSTM层和一个输出层。如果您的数据不准确,您可以选择更多层。同样,您可以增加或减少隐藏层中的神经元数量。 请记住,您使用的神经元和层越多,模型变得越慢。因为有更多的计算要做。 每层都有一些需要调整的超参数。 下面看看LSTM的一些重要超参数units10:这意味着我们正在创建一个包含十个神经元的层。这五个神经元中的每一个都将接收输入值。inputshape(步长,总特征):LSTM期望的输入是3D格式。我们的训练数据的形状为(420,10,1),形式为(样本数、时间步长、特征数)。这意味着我们在训练数据中有420个示例要学习,每个示例回顾10步的时间,比如昨天、前天的股价是多少,直到最近10天。这称为时间步长。最后一个数字1代表特征的数量。这里我们只使用一列收盘价,因此它等于1kernelinitializer’uniform’:当神经元开始计算时,一些算法必须确定每个权重的值。这个参数指定的就是它。您可以为其选择不同的值,例如normal或glorotuniform。activation’relu’:这指定了每个神经元内部计算的激活函数。您可以选择relu、tanh、sigmoid等值。returnsequencesTrue:LSTM通过时间反向传播,因此它们将每个时间步的输出值返回到下一个隐藏层。这会将下一个隐藏层的预期输入保持为3D格式。对于最后一个隐藏层,此参数为False,因为现在它不必将3D输出返回到最终的Dense层。optimizer’adam’:该参数有助于找到神经网络中每个权重的最佳值。adam是最有用的优化器之一,另一个是rmspropbatchsize10:这指定了一次将多少行传递给网络,之后SSE计算将开始,神经网络将开始根据错误调整其权重。 当所有行都按此参数中指定的每批10行传递时,我们称其为1epoch。或者一个完整的数据周期。这也称为小批量梯度下降。batchsize的小值会使LSTM缓慢地查看数据,例如一次2行或一次4行,这可能会导致过度拟合,与一次20或50行这样的大值相比,这将使LSTM快速查看数据,这可能会导致欠拟合。因此,必须使用超参数调整来选择合适的值。Epochs10:相同的调整权重活动持续10次,如该参数所指定的。简单来说,LSTM会查看完整的训练数据10次并调整其权重。导入Keras库和包fromkeras。modelsimportSequentialfromkeras。layersimportDensefromkeras。layersimportLSTM初始化RNNregressorSequential()添加第一个输入隐藏层和LSTM层returnsequencesTrue,表示每个时间步的输出要与隐藏的下一层共享regressor。add(LSTM(units10,activationrelu,inputshape(TimeSteps,TotalFeatures),returnsequencesTrue))添加SecondSecond隐藏层和LSTM层regressor。add(LSTM(units5,activationrelu,inputshape(TimeSteps,TotalFeatures),returnsequencesTrue))添加SecondThird隐藏层和LSTM层regressor。add(LSTM(units5,activationrelu,returnsequencesFalse))添加输出层regressor。add(Dense(units1))编译RNNregressor。compile(optimizeradam,lossmeansquarederror)importtime测量模型训练所花费的时间StartTimetime。time()将RNN拟合到训练集regressor。fit(Xtrain,ytrain,batchsize5,epochs100)EndTimetime。time()print(TotalTimeTaken:,round((EndTimeStartTime)60),Minutes) 测量模型在测试数据上的准确性 现在使用经过训练的模型,我们正在检查最近5天的预测价格是否接近实际价格。 注意预测的逆变换。由于我们在模型训练之前对数据进行了归一化,因此对测试数据的预测也将被归一化,因此逆变换会将值恢复到原始规模。那么只有我们必须计算百分比准确度。对测试数据进行预测predictedPriceregressor。predict(Xtest)predictedPriceDataScaler。inversetransform(predictedPrice)获取测试数据的原始价格值origytestorigDataScaler。inversetransform(ytest)预测的准确性print(Accuracy:,100(100(abs(origpredictedPrice)orig))。mean())可视化结果importmatplotlib。pyplotaspltplt。plot(predictedPrice,colorblue,labelPredictedVolume)plt。plot(orig,colorlightblue,labelOriginalVolume)plt。title(StockPricePredictions)plt。xlabel(TradingDate)plt。xticks(range(TestingRecords),StockData。tail(TestingRecords)〔TradeDate〕)plt。ylabel(StockPrice)plt。legend()figplt。gcf()fig。setfigwidth(20)fig。setfigheight(6)plt。show() 可视化完整数据的预测 绘制训练和测试数据以查看LSTM模型的拟合效果。对完整数据生成预测TrainPredictionsDataScaler。inversetransform(regressor。predict(Xtrain))TestPredictionsDataScaler。inversetransform(regressor。predict(Xtest))FullDataPredictionsnp。append(TrainPredictions,TestPredictions)FullDataOrigFullData〔TimeSteps:〕绘制完整数据plt。plot(FullDataPredictions,colorblue,labelPredictedPrice)plt。plot(FullDataOrig,colorlightblue,labelOriginalPrice)plt。title(StockPricePredictions)plt。xlabel(TradingDate)plt。ylabel(StockPrice)plt。legend()figplt。gcf()fig。setfigwidth(20)fig。setfigheight(8)plt。show() 如何预测明天的股价 如果你想预测明天的价格,你所要做的就是将过去10天的价格以3D格式传递给训练中使用的模型。 下面的代码片段向您展示了如何手动获取最后10个价格并对下一个价格进行单一预测。最近10天的价格Last10Daysnp。array(〔1002。15,1009。9,1007。5,1019。75,975。4,1011。45,1010。4,1009,1008。25,1017。65〕)就像我们训练模型一样归一化数据Last10DaysDataScaler。transform(Last10Days。reshape(1,1))将数据的形状更改为3D选择TimeSteps为10,因为我们已经将其用于训练NumSamples1TimeSteps10NumFeatures1Last10DaysLast10Days。reshape(NumSamples,TimeSteps,NumFeatures)对数据进行预测predictedPriceregressor。predict(Last10Days)predictedPriceDataScaler。inversetransform(predictedPrice)predictedPrice 在上面的代码片段中,我使用了截至上周五的股市实际价格! 因此,我们看到该模型预测(2020年10月5日)Infosys的下一个收盘价为1023!我查了一下,发现当天的收盘价是1048卢比!这么小的努力还不错!如果我想预测未来5天的价格怎么办? 我们在上面建立的模型使用最近10天的价格并预测第二天的价格,因为我们已经用许多过去的相同粒度的示例训练了我们的模型,如下所示 最近10天的价格第11天的价格 现在,如果我们想要预测接下来5天或接下来20天的价格,那么我们需要使用过去的类似示例来训练模型,如下所示 最近10天价格未来5天价格 这也称为多步时间序列预测,我们在其中预测多个时间步长。 为此,需要对数据准备步骤和LSTM模型进行小幅修改。 但是,请记住,您预测得越远,您可能就越不准确,因为股票价格波动很大,没有人知道10天后会发生什么!会传来什么样的消息?这可能会影响这只股票的价格! 因此,建议预测尽可能少的时间步长,例如最多接下来2天或接下来5天。多步LSTM的数据准备 我正在展示如何准备用于预测未来5天的数据。同样的代码也可以轻松修改以预测接下来的10天或20天。再次考虑我们上面提取的完整数据打印最后10个值print(OriginalPrices)print(FullData〔10:〕)print()打印我们在上面为最后一个模型创建的缩放数据的最后10个值在这里,我将数据的形状更改为一维数组,因为对于多步数据准备,我们需要以这种方式进行X输入XX。reshape(X。shape〔0〕,)print(ScaledPrices)print(X〔10:〕) 我修改了上一个模型的数据拆分逻辑,通过定义FutureTimeSteps5来生成输入输出对。这决定了我们要根据过去10天预测未来5天的价格。多步骤数据准备拆分样本Xsampleslist()ysampleslist()NumerOfRowslen(X)TimeSteps10未来几天的价格预测是基于过去多少天的价格FutureTimeSteps5您想预测未来多少天的价格遍历值以创建组合foriinrange(TimeSteps,NumerOfRowsFutureTimeSteps,1):xsampleX〔iTimeSteps:i〕ysampleX〔i:iFutureTimeSteps〕Xsamples。append(xsample)ysamples。append(ysample)将输入重塑为3D(样本、时间步长、特征)Xdatanp。array(Xsamples)XdataXdata。reshape(Xdata。shape〔0〕,Xdata。shape〔1〕,1)print(InputDataShape)print(Xdata。shape)我们不会将y重塑为3D数据,因为它应该只是一列ydatanp。array(ysamples)print(OutputDataShape)print(ydata。shape) 将数据拆分为训练和测试选择测试数据记录的数量TestingRecords5将数据拆分为训练和测试XtrainXdata〔:TestingRecords〕XtestXdata〔TestingRecords:〕ytrainydata〔:TestingRecords〕ytestydata〔TestingRecords:〕打印训练和测试的形状print(TrainingDatashape)print(Xtrain。shape)print(ytrain。shape)print(TestingDatashape)print(Xtest。shape)print(ytest。shape) 可视化发送到LSTM多步模型的输入输出 打印一些输入和输出记录总是有助于理解LSTM模型中的过程。 您可以在此处看到输入是过去10天价格的3D数组,输出是接下来5天价格的数组。可视化发送到LSTM模型的输入和输出根据过去10天的价格,我们正在了解未来5天的价格forinp,outinzip(Xtrain〔0:2〕,ytrain〔0:2〕):print(inp)print()print(out)print(20) 创建深度学习多步LSTM模型 我使用的配置与上一个模型中使用的配置相同。更改是在Dense层完成的。现在密集层输出等于FutureTimeSteps的值的数量。在本例中为5,因为我们要预测接下来的5天。 如果您想要预测更多天数,您可以将其更改为10到20,但您需要在运行此代码之前以相同的方式准备数据。DefiningInputshapesforLSTMTimeStepsXtrain。shape〔1〕TotalFeaturesXtrain。shape〔2〕print(NumberofTimeSteps:,TimeSteps)print(NumberofFeatures:,TotalFeatures) 导入Keras库和包fromkeras。modelsimportSequentialfromkeras。layersimportDensefromkeras。layersimportLSTM初始化RNNregressorSequential()添加第一个输入隐藏层和LSTM层returnsequencesTrue,表示每个时间步的输出要与隐藏的下一层共享regressor。add(LSTM(units10,activationrelu,inputshape(TimeSteps,TotalFeatures),returnsequencesTrue))添加第二个隐藏层和LSTM层regressor。add(LSTM(units5,activationrelu,inputshape(TimeSteps,TotalFeatures),returnsequencesTrue))添加第三个隐藏层和LSTM层regressor。add(LSTM(units5,activationrelu,returnsequencesFalse))添加输出层注意密集层中的神经元数量现在是未来时间步数基于我们要预测的未来天数regressor。add(Dense(unitsFutureTimeSteps))编译RNNregressor。compile(optimizeradam,lossmeansquarederror)importtime测量模型训练所花费的时间StartTimetime。time()将RNN拟合到训练集regressor。fit(Xtrain,ytrain,batchsize5,epochs100)EndTimetime。time()print(TotalTimeTaken:,round((EndTimeStartTime)60),Minutes) 测量模型在测试数据上的准确性 因为这是训练有素的多步模型来预测接下来的5天。每个预测将生成5天的价格,我们可以将其与原始价格相匹配。 我们将一次比较它们一行。对测试数据进行预测predictedPriceregressor。predict(Xtest)predictedPriceDataScaler。inversetransform(predictedPrice)print(PredictedPrices)print(predictedPrice)获取测试数据的原始价格值origytestorigDataScaler。inversetransform(ytest)print(OriginalPrices)print(orig) 每行代表原始价格和预测价格。 我们将一次比较一行。使用简单的for循环,将每行原始值与预测值进行比较importmatplotlib。pyplotaspltforiinrange(len(orig)):PredictionpredictedPrice〔i〕Originalorig〔i〕可视化结果plt。plot(Prediction,colorblue,labelPredictedVolume)plt。plot(Original,colorlightblue,labelOriginalVolume)plt。title(Accuracyofthepredictions:str(100(100(abs(OriginalPrediction)Original))。mean()。round(2)))plt。xlabel(TradingDate)startDateIndex(FutureTimeStepsTestingRecords)FutureTimeSteps(i1)endDateIndex(FutureTimeStepsTestingRecords)FutureTimeSteps(i1)FutureTimeStepsTotalRowsStockData。shape〔0〕plt。xticks(range(FutureTimeSteps),StockData。iloc〔TotalRowsendDateIndex:TotalRows(startDateIndex),:〕〔TradeDate〕)plt。ylabel(StockPrice)plt。legend()figplt。gcf()fig。setfigwidth(20)fig。setfigheight(3)plt。show() 预测未来5天 如果你想预测未来5天的价格,你所要做的就是将过去10天的价格以3D格式传递给训练中使用的模型。 下面的代码片段向您展示了如何手动传递最后10个值以获得未来5天的价格预测。对测试数据进行预测Last10DaysPricesarray(〔1376。2,1371。75,1387。15,1370。5,1344。95,1312。05,1316。65,1339。45,1339。7,1340。85〕)将数据重塑为(1,1)因为它是单个条目Last10DaysPricesLast10DaysPrices。reshape(1,1)在训练模型的同一级别上缩放数据XtestDataScaler。transform(Last10DaysPrices)NumberofSamples1TimeStepsXtest。shape〔0〕NumberofFeaturesXtest。shape〔1〕将数据重塑为3D输入XtestXtest。reshape(NumberofSamples,TimeSteps,NumberofFeatures)生成未来5天的预测Next5DaysPriceregressor。predict(Xtest)以原始比例生成价格Next5DaysPriceDataScaler。inversetransform(Next5DaysPrice)Next5DaysPrice 总结 这种预测只是短期的。当您尝试预测多天(例如接下来的30天或60天)时,这会惨遭失败。不是因为我们的LSTM模型不好,而是因为股市波动很大。所以,不要仅仅把钱押在这个模型上!做一些研究,然后使用这个模型作为分析的补充工具! 我希望您喜欢阅读这篇文章,它可以帮助您消除对LSTM模型的一些疑虑。考虑与您的朋友分享这篇文章以帮助传播知识