Вариант Word2Vec для MetaWord2Vec - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь создать систему рекомендаций с помощью модели SkipGram, я создал вариант Word2vec, адаптированный к моим данным (аниме), где я использую список просмотра аниме таких пользователей, как

data =[]
for key, chunk in ratings.groupby('user_id'):
    data.append(chunk.sort_values('user_rating').anime_id.values)

мои рейтинги датафрейм имеет 30 тыс. Уникальных пользователей, 12 тыс. Уникальных аниме, пользовательский рейтинг и некоторые лайки метаданных (anime_tags, год, количество эпизодов, синопсис и т. Д.)

Я пытаюсь найти способ добавить эти метаданные в мою модель "Anime2Vec".

Могу ли я построить другую модель (concat / blend / sum ???) вложения

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

def get_batch(seq, rel_window_size=.2):
    """get a batch of data for a single user sequence.
    data will be chosen randomly from within a anime 
    window relative to the size of the entire sequence. 
    with the initial point chosen at random.
    """
    window = math.floor(len(seq) * rel_window_size) +1
    x = []
    y = []
    i = random.randint(0, len(seq)-1)
    for _ in range(batch_size):
        x.append(seq[i])
        moves = list(range(max(i-window, 0), i)) + list(range(i+1, min((i+window + 1, len(seq)))))
        j = random.choice(moves)
        y.append(seq[j])
        i = j
    return x, y            

def gen_batch(data, batch_size, rel_window_size=.2, shuffle=True):
    """make a generator for data using each 'user' as a document."""
    while True:
        for doc_index, doc in enumerate(data):
            x, y = get_batch(doc, rel_window_size)
            yield np.array(x, 'int32'), np.expand_dims(np.array(y,'int32'), 1)
        if shuffle:
            random.shuffle(data)

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

val_anime = ['Naruto', 
         'Bleach', 
         "Clannad",
         "Air", 
         "Code Geass Hangyaku no Lelouch",
         "Overlord", 
         "Mononoke Hime",
         "Hajime no Ippo",
         "Fullmetal Alchemist"]

val_ids = [reverse_dictionary[s] for s in val_anime]
val_set = np.array(val_ids, 'int32')

Тогда я определяю модель и данные

   # valid_examples = np.array(random.sample(range(1, valid_window+1), valid_size))# valid_e 
vocab_size = len(dictionary)
batch_size = 128
embedding_size = 50  # Dimension of the embedding vector.
val_size =len(val_set)
lr = 1.

model = SkipGramModel(vocab_size, val_set, embedding_dims=embedding_size, 
                      batch_size=batch_size, sample_factor=1., lr=lr, optimizer= tf.train.AdagradOptimizer)

# create the data generator
data_gen = gen_batch(data, batch_size, rel_window_size = .2, shuffle=True)

Параметры для обучения.

steps_per_cycle = (len(data) // batch_size)
n_iter = 300 # number of full cycles through data
num_steps = int(n_iter * steps_per_cycle)
lstep = steps_per_cycle # steps to show average loss
vstep = steps_per_cycle * 20  # steps to show val data

Я определяю функцию для ближайших пунктов

def show_n_similar(item, sim, k=5):                
    item_name = dictionary[item]
    nearest = (-sim).argsort()[1:k + 1]
    log_str = '\nNearest to - {}:\n'.format(item_name)
    for k in range(k):
        log_str += '\t{},\n'.format(dictionary[nearest[k]])
    print(log_str)

losses = []

Наконец я тренирую модель, чтобы найти ближайших соседей в моем ранее определенном списке

with tf.Session() as sess:
    sess.run(model.init_op())
    print('initialized ...')
    # set so we can watch average loss during training

    for step in tqdm(range(num_steps)):
        batch_inputs, batch_labels = next(data_gen)
        feed_dict = {model.x: batch_inputs, 
                     model.y: batch_labels}

        _, loss_ = sess.run([model.optimize, model.loss], feed_dict=feed_dict)
        losses.append(loss_) # for plotting

    sim = model.similarity.eval()

    for i in range(len(val_ids)):
        show_n_similar(model.val_data[i], sim[i], k=5)

    out_embeddings = model.normalized_embeddings.eval()

Я хотел бы получить совет по добавлению метаданных в модель, в первую очередь просто добавьте anime_tags.

Мои anime_tags представлены списком ключевых слов, подобных этому:

anime_id | tags 
8        | action, historical, sci-fi, comedy 
12       | comedy, romance 
...