Kar*_*arl 22 machine-learning neural-network lstm keras tensorflow
前言
我目前正在研究机器学习问题,我们的任务是使用过去的产品销售数据来预测未来的销售量(以便商店可以更好地计划他们的库存).我们基本上有时间序列数据,对于每一个产品,我们知道在哪几天销售了多少单位.我们还提供有关天气如何,是否有公众假期,是否有任何产品销售等信息.
我们已经能够使用具有密集层的MLP取得一些成功,并且仅使用滑动窗口方法来包括周围几天的销售量.但是,我们相信,通过LSTM等时间序列方法,我们将能够获得更好的结果.
数据
我们的数据基本如下:
(编辑:为清楚起见,上图中的"时间"列不正确.我们每天输入一次,而不是每月一次.但结构是相同的!)
所以X数据的形状如下:
(numProducts, numTimesteps, numFeatures) = (50 products, 1096 days, 90 features)
Run Code Online (Sandbox Code Playgroud)
并且Y数据的形状如下:
(numProducts, numTimesteps, numTargets) = (50 products, 1096 days, 3 binary targets)
Run Code Online (Sandbox Code Playgroud)
因此,我们有三年的数据(2014年,2015年,2016年),并希望对此进行培训,以便对2017年进行预测.(当然,这不是100%正确,因为我们实际上有数据截至2017年10月,但我们只是现在忽略它)
问题
我想在Keras建立一个LSTM,允许我做出这些预测.有几个地方我被卡住了.所以我有六个具体问题(我知道应该尝试将Stackoverflow帖子限制为一个问题,但这些问题都是交织在一起的).
首先,我如何为批次切割数据?由于我有三年的时间,所以只需按顺序推进三批,每次大小一年是否合理?或者更小的批次(比如30天)以及使用滑动窗口更有意义吗?也就是说,不是36个批次,每个30天,我使用36*6批次,每个30天,每次滑动5天?或者这不是真的应该使用LSTM的方式吗?(请注意,数据中存在相当多的季节性,我需要捕捉这种长期趋势).
其次,在这里使用 return_sequences=True
是否有意义?换句话说,我保持我的Y数据是(50, 1096, 3)
这样的(据我所知),每个时间步都有一个预测,可以针对目标数据计算损失?或者我会更好return_sequences=False
,因此只有每批的最终价值用于评估损失(即如果使用年度批次,那么在2016年的产品1,我们评估2016年12月的价值(1,1,1)
).
第三,我该如何处理50种不同的产品?它们是不同的,但仍然强相关,我们已经看到其他方法(例如具有简单时间窗的MLP),当所有产品被考虑在同一模型中时,结果更好.目前摆在桌面上的一些想法是:
第四,我如何处理验证数据?通常我会随机选择一个随机选择的样本进行验证,但在这里我们需要保持时间排序.所以我想最好只是暂时搁置几个月?
第五,这是我可能最不清楚的部分 - 我如何使用实际结果来执行预测?假设我使用return_sequences=False
和训练了三年三次(每次都是11月),目标是训练模型以预测下一个值(2014年12月,2015年12月,2016年12月).如果我想在2017年使用这些结果,这实际上是如何工作的?如果我理解正确的话,我在这个例子中唯一可以做的就是为2017年1月到11月的所有数据点提供模型,它会给我回到2017年12月的预测.这是正确的吗?但是,如果我使用return_sequences=True
,然后对截至2016年12月的所有数据进行培训,那么我是否能够通过给出模型在2017年1月观察到的特征来获得2017年1月的预测?或者我需要在2017年1月之前的12个月内给它吗?那么2017年2月,我是否需要在2017年之前再提供11个月的价值?(如果听起来我很困惑,那是因为我!)
最后,根据我应该使用的结构,我如何在Keras中这样做?我现在想到的是以下几点:(虽然这只适用于一种产品,因此不能解决所有产品都在同一型号中):
Keras代码
trainX = trainingDataReshaped #Data for Product 1, Jan 2014 to Dec 2016
trainY = trainingTargetReshaped
validX = validDataReshaped #Data for Product 1, for ??? Maybe for a few months?
validY = validTargetReshaped
numSequences = trainX.shape[0]
numTimeSteps = trainX.shape[1]
numFeatures = trainX.shape[2]
numTargets = trainY.shape[2]
model = Sequential()
model.add(LSTM(100, input_shape=(None, numFeatures), return_sequences=True))
model.add(Dense(numTargets, activation="softmax"))
model.compile(loss=stackEntry.params["loss"],
optimizer="adam",
metrics=['accuracy'])
history = model.fit(trainX, trainY,
batch_size=30,
epochs=20,
verbose=1,
validation_data=(validX, validY))
predictX = predictionDataReshaped #Data for Product 1, Jan 2017 to Dec 2017
prediction=model.predict(predictX)
Run Code Online (Sandbox Code Playgroud)
Mar*_*jko 12
所以:
首先,我如何为批次切割数据?由于我有三年的时间,所以只需按顺序推进三批,每次大小一年是否合理?或者更小的批次(比如30天)以及使用滑动窗口更有意义吗?也就是说,不是36个批次,每个30天,我使用36*6批次,每个30天,每次滑动5天?或者这不是真的应该使用LSTM的方式吗?(请注意,数据中存在相当多的季节性,我需要捕捉这种长期趋势).
老实说 - 建模这样的数据真的很难.首先 - 我不建议你使用LSTM
s,因为它们设计用于捕获一些不同类型的数据(例如NLP或语音,其中模拟长期依赖性非常重要 - 而不是季节性)并且它们需要大量的数据才能被学习.我宁愿建议你使用其中任何一个GRU
或SimpleRNN
哪个更容易学习,并且应该更好地完成你的任务.
当谈到批处理时 - 我肯定会建议你使用固定窗口技术,因为它最终会产生比整年或整整一个月更多的数据点.尝试将天数设置为元参数,这也将通过在训练中使用不同的值并选择最合适的值来进行优化.
谈到季节性 - 当然,这是一个案例,但是:
我建议你做的是:
其次,在这里使用return_sequences = True是否有意义?换句话说,我保持我的Y数据不变(50,1096,3),以便(据我所知),每个时间步都有一个预测,可以针对目标数据计算损失?或者我最好使用return_sequences = False,这样只使用每批次的最终值来评估损失(即如果使用年度批次,那么在2016年对于产品1,我们将评估2016年12月的价值(1) ,1,1)).
使用return_sequences=True
可能很有用,但仅限于以下情况:
LSTM
(或另一个复发层)后面还有另一个复发层.第二点中描述的方式可能是一种有趣的方法,但请记住,它可能有点难以实现,因为您需要重写模型才能获得生产结果.还有一点可能更难的是你需要针对许多类型的时间不稳定性来测试你的模型 - 而这种方法可能会使这完全不可行.
第三,我该如何处理50种不同的产品?它们是不同的,但仍然强相关,我们已经看到其他方法(例如具有简单时间窗的MLP),当所有产品被考虑在同一模型中时,结果更好.目前摆在桌面上的一些想法是:
- 将目标变量更改为不仅仅是3个变量,而是3*50 = 150; 即,对于每个产品,有三个目标,所有目标都是同时训练的.
- 将LSTM层之后的结果分成50个密集网络,将LSTM的输出作为输入,加上每个产品特有的一些功能 - 即我们得到一个具有50个丢失函数的多任务网络,然后我们优化一起.那会疯了吗?
- 将产品视为单一观察,并在LSTM层中包含产品特定功能.仅使用这一层,然后使用大小为3的输出层(对于三个目标).在单独的批次中推送每个产品.
我肯定会选择第一选择,但在提供详细解释之前,我将讨论第二和第三的缺点:
在做出选择之前 - 让我们讨论另一个问题 - 数据集中的冗余.我想你有3种功能:
现在你有大小的表(timesteps, m * n, products)
.我会将其转换为形状表,(timesteps, products * m + n)
因为所有产品的一般功能都相同.这将为您节省大量内存,并且还可以提供给经常性网络(请记住,复制层keras
只有一个要素维度 - 而您有两个 - product
和feature
一个).
那么为什么第一种方法在我看来是最好的呢?因此,它利用了数据中许多有趣的依赖关系.当然 - 这可能会损害培训过程 - 但是有一个简单的方法可以克服这个问题:减少维数.你可以训练PCA
你的150维向量并将它的大小减小到一个小得多 - 这要归功于你的依赖关系建模PCA
,你的输出有一个更可行的大小.
第四,我如何处理验证数据?通常我会随机选择一个随机选择的样本进行验证,但在这里我们需要保持时间排序.所以我想最好只是暂时搁置几个月?
这是一个非常重要的问题.根据我的经验 - 您需要针对许多类型的不稳定性测试您的解决方案,以确保它正常工作.所以你应该记住一些规则:
最后一点可能有点模糊 - 所以为您提供一些例子:
当然 - 你可以再试一次.
第五,这是我可能最不清楚的部分 - 我如何使用实际结果来执行预测?假设我使用了return_sequences = False,我分三批训练了这三年(每次都是11月),目的是训练模型以预测下一个值(2014年12月,2015年12月,2016年12月).如果我想在2017年使用这些结果,这实际上是如何工作的?如果我理解正确的话,我在这个例子中唯一可以做的就是为2017年1月到11月的所有数据点提供模型,它会给我回到2017年12月的预测.这是正确的吗?但是,如果我使用return_sequences = True,然后对截至2016年12月的所有数据进行过培训,那么我是否可以通过给出模型在2017年1月观察到的特征来获得2017年1月的预测?或者我需要在2017年1月之前的12个月内给它吗?那么2017年2月,我是否需要在2017年之前再提供11个月的价值?(如果听起来我很困惑,那是因为我!)
这取决于您如何构建模型:
return_sequences=True
,则需要重写它以获取return_sequence=False
或仅获取输出并仅考虑结果的最后一步,如果您使用了不同的长度 - 您可以提供任何时间步骤来处理您想要的预测期(但我建议您至少提供7个处理日).
最后,根据我应该使用的结构,我如何在Keras中这样做?我现在想到的是以下几点:(虽然这只适用于一种产品,因此不能解决所有产品都在同一型号中)
在这里 - 需要更多关于您选择何种模型的信息.
有几种方法可以解决这个问题。您建议的那个似乎是一个滑动窗口。
但实际上你不需要对时间维度进行切片,你可以一次输入所有3年。您可以对产品维度进行切片,以防您的批次对于内存和速度而言太大。
您可以使用具有形状的单个数组 (products, time, features)
是的,使用return_sequences=True
.
如果我正确理解你的问题,你y
每天都有预测,对吗?
这确实是一个悬而未决的问题。所有方法都有其优点。
但是,如果您考虑将所有产品功能放在一起,作为这些不同性质的功能,您可能应该扩展所有可能的功能,就像考虑所有产品的所有功能有一个大的单热向量一样。
如果每个产品都有仅适用于自身的独立功能,那么为每个产品创建单独模型的想法对我来说似乎并不疯狂。
您还可以将产品 ID 设为单热向量输入,并使用单个模型。
根据您选择的方法,您可以:
可能还有很多方法。
有一些方法可以使用滑动窗口。您可以在固定的时间长度内训练模型。
还有一些方法可以训练整个长度的 LSTM 层。在这种情况下,您首先预测整个已知部分,然后开始预测未知部分。
我的问题:
X
您必须预测的时期的数据是否已知Y
?的X
也是在这个时期不明,所以你也来预测X
?
I recommend you to take a look at this question and its answer: How to deal with multi-step time series forecasting in multivariate LSTM in keras
See also this notebook that manages to demonstrate the idea: https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb
In this notebook, though, I used an approach that puts X and Y as inputs. And we predict future X and Y.
You can try creating a model (if that's the case) only to predict X. Then a second model to predict Y from X.
在另一种情况下(如果您已经拥有所有 X 数据,则无需预测 X),您可以创建一个仅从 X 预测 Y 的模型。(您仍然会遵循笔记本中的部分方法,在那里您首先预测已知 Y 只是为了让您的模型适应它在序列中的位置,然后您预测未知的 Y)——这可以在一个单一的全长 X 输入中完成(其中包含开头的训练 X 和最后测试X)。
知道选择哪种方法和哪种模型可能是赢得比赛的确切答案……因此,这个问题没有最佳答案,每个参赛者都在试图找出这个答案。
归档时间: |
|
查看次数: |
2778 次 |
最近记录: |