我目前正在尝试预测客户在下一个时间段内可能购买的下一个商品序列。以下示例用于说明目的(我的实际数据集有大约 600 万个客户 ID 和 5000 种不同的产品)
我当前的数据如下所示:
date customer_nbr products_bought
201701 123 ["product_1","product_5","product_15"]
201704 123 ["product_4","product_10","product_11"]
201721 123 ["product_1","product_6"]
201713 456 ["product_7","sproduct_11","product_12","product_15"]
201714 456 ["product_1","product_3"]
201721 456 ["product_4","product_9","product_10","product_13","product_15"]
其中数据的频率是按周。因此 customer_id 123 在 2017 年的第一周购买了商品“product_1”、“product_5”和“product_15”(因此给定年份最多有 52 周)。在获得输入变量滞后后,我的最终数据帧如下所示:
date customer_nbr products_bought_last_period products_bought
201704 123 ["product_1","product_5","product_15"] ["product_4","product_10","product_11"]
201721 123 ["product_4","product_10","product_11"] ["product_1","product_6"]
201714 456 ["product_7","sproduct_11","product_12","product_15"] ["product_1","product_3"]
201721 456 ["product_1","product_3"]
["product_4","product_9","product_10","product_13","product_15"]
因此,对于我的 seq2seq 模型,我想使用
products_bought_last_period
预测客户在日期 201721 购买的产品序列,因此 products_bought_last_period
是我的输入,products_bought
现在是我的目标变量。然后我编码了我的产品 ID,并在我的数据帧中填充了我的
products_bought_last_period
和 products_bought
数组(基于具有最多产品的数组)。之后,我转换了 np.arrays 中的所有内容。最后,我的实际数据集中的产品总数是 5000,所以我设置了 total_nbr_of_products = 5000
并尝试执行以下操作:train = df[df['date'] < 201721].set_index('date')
test = df[df['date'] >= 201721].set_index('date')
X = train["products_bought_last_period"].copy()
X_test = test["products_bought_last_period"].copy()
y = train['products_bought'].copy()
y_test = test['products_bought'].copy()
X = np.array(X)
X_test = np.array(X_test)
y = np.array(y)
y_test = np.array(y_test)
# Encoder model
total_nbr_of_products = 5000
encoder_input = Input(shape=(None,total_nbr_of_products))
encoder_LSTM = LSTM(256,return_state = True)
encoder_outputs, encoder_h, encoder_c = encoder_LSTM (encoder_input)
encoder_states = [encoder_h, encoder_c]
# Decoder model
decoder_input = Input(shape=(None,total_nbr_of_products))
decoder_LSTM = LSTM(256,return_sequences=True, return_state = True)
decoder_out, _ , _ = decoder_LSTM(decoder_input, initial_state=encoder_states)
decoder_dense = Dense(total_nbr_of_products,activation='softmax')
decoder_out = decoder_dense (decoder_out)
model = Model(inputs=[encoder_input, decoder_input],outputs=[decoder_out])
model = Model(inputs=[encoder_input, decoder_input],outputs=[decoder_out])
model.compile(optimizer='adam', loss='categorical_crossentropy')
model.fit(X,y,
validation_data=(X_test, y_test),
batch_size=64,
epochs=5)
但是,当我尝试这样做时,出现以下错误:
ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 2 array(s), but instead got the following list of 1 arrays: [array([[array([1209, 2280, 1066, 3308, 3057, 4277, 3000, 4090, 0, 0, 0,
我不确定两件主要事情:
1.) 就匹配我的尺寸而言,我可能做错了什么
2.) 以及我的 seq2seq 方法是否正确
理想情况下,我希望预测客户(大约 600 万客户)可能购买的下一批商品。我将不胜感激任何帮助
最佳答案
查看您的模型是如何定义的。
model = Model(inputs=[encoder_input, decoder_input], outputs=[decoder_out])
您需要两个输入([
encoder_input
、 decoder_input
] 和 decoder_out
)来拟合您的数据。您的 model.fit()
应该如下所示,model.fit([train_encoder_input, train_decoder_input], train_decoder_output)
对我来说,这似乎是 seq2seq 的非常规用法,但很好。您必须查看滞后 1 是否是最佳选择,并且必须对您购买的产品列表进行单热编码。
编辑 :在下面添加了一个简单的例子。
如果您查看以下链接,可以解释几个很好的示例。有关使用 keras 的 seq2seq 的进一步查询,请参阅这些。
https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html
https://github.com/philipperemy/keras-seq2seq-example
为了说明的目的,我写了一个小例子。让我们考虑将字符串转换为字符串的情况。比如说,我们正在引入一个新的邮政编码系统。
import numpy as np
from keras.layers import Input, LSTM, Dense
from keras.models import Model
df = {'old': ['ABCDBA', 'EFFEBA', 'CDDCAA', 'BBBBAA', 'FFDDCD', 'DCFEEF',
'AAFFBA'],
'new': ['XYX', 'ZZX', 'YYX', 'XXX', 'ZYY', 'YZZ', 'XZX']}
为方便起见,我已将标记数和序列长度设置为固定。我们为馈入解码器的数据设置开始(
'M'
)和结束字符( 'N'
)。encoder_texts = [[char for char in word] for word in df['old']]
decoder_texts = [[char for char in word] for word in df['new']]
old_char = ['A', 'B', 'C', 'D', 'E', 'F']
new_char = ['M', 'N', 'X', 'Y', 'Z']
encoder_seq_length = 6
decoder_seq_length = 4
num_encoder_tokens = len(old_char)
num_decoder_tokens = len(new_char)
old_token_index = dict((c, i) for i, c in enumerate(old_char))
new_token_index = dict((c, i) for i, c in enumerate(new_char))
以
'XYZ'
为例.作为解码器的输入,它是 'MXYZ'
并且作为解码器的输出,它是' XYZN'
.最终我们无论如何都必须对这个字符序列进行单热编码,所以我完全按照如下方式进行,encoder_input_data = np.zeros((7, encoder_seq_length, num_encoder_tokens), dtype='float32')
decoder_input_data = np.zeros((7, decoder_seq_length, num_decoder_tokens), dtype='float32')
decoder_output_data = np.zeros((7, decoder_seq_length, num_decoder_tokens), dtype='float32')
for i, (encoder_text, decoder_text) in enumerate(zip(encoder_texts, decoder_texts)):
for t, char in enumerate(encoder_text):
encoder_input_data[i, t, old_token_index[char]] = 1
for t, char in enumerate(decoder_text):
decoder_input_data[i, t+1, new_token_index[char]] = 1
if t > 0:
decoder_output_data[i, t-1, new_token_index[char]] = 1
decoder_input_data[i, 0, new_token_index['M']] = 1
decoder_output_data[i, 3, new_token_index['N']] = 1
然后,您可以继续您的代码。
encoder_input = Input(shape=(None, num_encoder_tokens))
encoder_LSTM = LSTM(units=128, return_state = True)
encoder_output, encoder_h, encoder_c = encoder_LSTM(encoder_input)
encoder_states = [encoder_h, encoder_c]
decoder_input = Input(shape=(None, num_decoder_tokens))
decoder_LSTM = LSTM(128, return_sequences=True, return_state=True)
decoder_output, _, _ = decoder_LSTM(decoder_input, initial_state=encoder_states)
decoder_dense = Dense(num_decoder_tokens, activation='softmax')
decoder_output = decoder_dense(decoder_output)
model = Model(inputs=[encoder_input, decoder_input], outputs=[decoder_output])
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit([encoder_input_data, decoder_input_data], decoder_output_data)
为了回答您的第二个问题,您可以使用您购买的用于解码器输入和输出的滞后系列产品。我没有这方面的理论基础,但是通过 seq2seq 方案共享一个状态的两个结果序列似乎没问题。(至少试一试)
关于python - seq2seq 预测下一个时间步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58665482/