seq2seq预测下一步骤

时间:2019-11-01 20:24:41

标签: python keras time-series lstm seq2seq

我目前正在尝试预测客户可能在下一个时间段内购买的下一个商品序列。以下示例仅用于说明目的(我的实际数据集中有大约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_periodproducts_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万客户)可能购买的下一篮子商品。非常感谢您的帮助

1 个答案:

答案 0 :(得分:0)

  1. 就我的尺寸而言,我可能做错了什么?

查看如何定义模型。

model = Model(inputs=[encoder_input, decoder_input], outputs=[decoder_out])

您需要两个输入([[encoder_inputdecoder_input]和decoder_out)以适合您的数据。您的model.fit()如下所示,

model.fit([train_encoder_input, train_decoder_input], train_decoder_output)
  1. seq2seq在这里正确吗?

对我来说,这似乎是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方案共享状态的两个结果序列似乎还可以。(至少可以尝试一下)