Рекомендательный двигатель с дополнительными переменными - PullRequest
0 голосов
/ 27 апреля 2019

Общий подход к выработке рекомендаций заключается в моделировании матрицы полезности (взаимодействия пользователя с элементом), вот один хороший пример того, как это делается.

Я бы хотел повторить этот пример с двумя изменениями:

  • вместо того, чтобы иметь рейтинг 1-5, я бы хотел, чтобы мои оценки или лайки были бинарными
  • Я хотел бы построить модель на служебной матрице + некоторые дополнительные функции

Вот моя попытка:

# imports
import pandas as pd
from sklearn.model_selection import train_test_split
from tensorflow.keras.layers import Input, Embedding, Flatten, Dot, Dense, Multiply
from tensorflow.keras.models import Model
from tensorflow.keras.utils import plot_model

# data
dummy_data = pd.DataFrame.from_dict({
    'user_id': [1,1,1,2,2,2,3,3,3],
    'book_id': [1,2,4,2,3,4,1,2,3],
    'status':  [1,0,0,0,0,0,1,0,1],
    'feature': [1,1,0,0,0,0,1,0,0]
})

n_users = len(dummy_data.user_id.unique())
n_items = len(dummy_data.item_id.unique())

train, test = train_test_split(dummy_data, test_size=0.2, random_state=42)

# model definition

# items
item_input = Input(shape=[1], name='Item-Input')
item_embeddings = Embedding(n_items+1, 5, name='Item-Embeddings')(item_input)
item_vector = Flatten(name='Item-Vector')(item_embeddings)

# features
feature_input = Input(shape=[1], name='Item-Features')
feature_dense_layer = Dense(5, name='Item-Features-Dense')(feature_input)
feature_dense_flat = Flatten(name='Item-Features-Flat')(feature_dense_layer)

# users
user_input = Input(shape=[1], name='User-Input')
user_embeddings = Embedding(n_users+1, 5, name='User-Embeddings')(user_input)
user_vector = Flatten(name='User-Vector')(user_embeddings)

# cross
item_user_product = Dot(name='Item-User-Dot-Prod', axes=1)([item_vector, user_vector])
feature_aggregate = Multiply(name='feature_aggregation')([item_user_product, feature_dense_flat])
dense_out = Dense(1, name='output')(feature_aggregate)
model = Model([user_input, item_input, feature_input], dense_out)
model.compile('adam', 'binary_crossentropy')
plot_model(model)

Оператор plot создает следующее изображение:

enter image description here

Тогда, если я запускаю следующую команду, все работает нормально:

history = model.fit([train.user_id, train.item_id, train.feature], train.status, epochs=5, verbose=1)

Однако, когда я пытаюсь запустить точно такой же код для большего набора данных, а именно Набор данных Goodbooks 10k , я получаю ошибку:

# load data
current_path = os.path.dirname(os.path.abspath(os.getcwd()))

ratings_df = pd.read_csv(current_path + '/data/ratings.csv')

# convert to binary
ratings_df['rating'] = ratings_df['rating'].apply(lambda x: 0 if x < 4 else 1)

# book attributes
books_df = pd.read_csv(current_path + '/data/books.csv')
books_df = books_df[['book_id','original_publication_year']].set_index('book_id')
ratings_df = ratings_df.join(books_df, on='book_id', how='inner')
ratings_df['book_age'] = MinMaxScaler().fit_transform(ratings_df[['original_publication_year']])
ratings_df.drop('original_publication_year', axis=1, inplace=True)

# split
train, test = train_test_split(ratings_df, test_size=0.2, random_state=42)
n_users = len(ratings_df.user_id.unique())
n_items = len(ratings_df.book_id.unique())

# items
item_input = Input(shape=[1], name='Item-Input')
item_embeddings = Embedding(n_items+1, 5, name='Item-Embeddings')(item_input)
item_vector = Flatten(name='Item-Vector')(item_embeddings)

# features
feature_input = Input(shape=[1], name='Item-Features')
feature_dense_layer = Dense(5, name='Item-Features-Dense')(feature_input)
feature_dense_flat = Flatten(name='Item-Features-Flat')(feature_dense_layer)

# users
user_input = Input(shape=[1], name='User-Input')
user_embeddings = Embedding(n_users+1, 5, name='User-Embeddings')(user_input)
user_vector = Flatten(name='User-Vector')(user_embeddings)

# cross
item_user_product = Dot(name='Item-User-Dot-Prod', axes=1)([item_vector, user_vector])
feature_aggregate = Multiply(name='feature_aggregation')([item_user_product, feature_dense_flat])
dense_out = Dense(1, name='output')(feature_aggregate)
model = Model([user_input, item_input, feature_input], dense_out)
model.compile('adam', 'binary_crossentropy')

history = model.fit([train.user_id, train.book_id, train.book_age], train.rating, epochs=1, verbose=1)

# ERROR
# InvalidArgumentError: indices[0,0] = 7670 is not in [0, 813)
#    [[{{node Item-Embeddings_4/embedding_lookup}}]] [Op:__inference_keras_scratch_graph_5389]

Итак, мои вопросы:

  1. Основной вопрос: что вызывает эту ошибку и как ее исправить?
  2. Вторичный вопрос: это надежная NN-архитектура для проблемы с рекомендациями? Что было бы лучшим способом сделать это? Причина, по которой я спрашиваю, состоит в том, что я не видел много примеров, когда матрица утилит смешивалась с поддерживающими функциями

Большое спасибо и простите за длинный пост

...