Как мне оптимизировать гиперпараметры LightFM?

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

Плохие результаты после нескольких эпох

NUM_THREADS = 4
NUM_COMPONENTS = 30
NUM_EPOCHS = 5
ITEM_ALPHA = 1e-6
LEARNING_RATE = 0.005
LEARNING_SCHEDULE = 'adagrad'
RANDOM_SEED = 29031994    

warp_model = LightFM(loss='warp',
                    learning_rate=LEARNING_RATE,
                    learning_schedule=LEARNING_SCHEDULE,
                    item_alpha=ITEM_ALPHA,
                    no_components=NUM_COMPONENTS,
                    random_state=RANDOM_SEED)

bpr_model = LightFM(loss='bpr',
                    learning_rate=LEARNING_RATE,
                    learning_schedule=LEARNING_SCHEDULE,
                    item_alpha=ITEM_ALPHA,
                    no_components=NUM_COMPONENTS,
                    random_state=RANDOM_SEED)

Формы моих черт следующие:

Фигуры элементов и пользовательских функций

Как я могу оптимизировать свои гиперпараметры, чтобы улучшить показатели площади под кривой (AUC)?


person Tim Visser    schedule 18.04.2018    source источник


Ответы (1)


Хорошее общее руководство по оптимизации гиперпараметров можно найти в документации sklearn.

Одним из простых, но эффективных способов оптимизации модели LightFM является случайный поиск. Грубо говоря, он состоит из следующих шагов:

  1. Разделите данные на обучающий набор, проверочный набор и тестовый набор.
  2. Определите распределение для каждого гиперпараметра, который вы хотите оптимизировать. Например, если вы оптимизируете скорость обучения, вы можете использовать экспоненциальное распределение со средним значением 0,05; если вы оптимизируете функцию потерь, вы можете выбрать однородную выборку из ['warp', 'bpr', 'warp-kos'].
  3. В каждой итерации оптимизации отбирайте все свои гиперпараметры и используйте их, чтобы подогнать модель к обучающим данным. Оцените производительность модели на проверочном наборе.
  4. После выполнения ряда шагов оптимизации выберите тот, который обеспечивает наилучшую производительность проверки.

Чтобы оценить производительность окончательной модели, вы должны использовать тестовый набор: просто оцените лучшую модель проверки в тестовом наборе.

Следующий сценарий иллюстрирует это:

import itertools

import numpy as np

from lightfm import LightFM
from lightfm.evaluation import auc_score


def sample_hyperparameters():
    """
    Yield possible hyperparameter choices.
    """

    while True:
        yield {
            "no_components": np.random.randint(16, 64),
            "learning_schedule": np.random.choice(["adagrad", "adadelta"]),
            "loss": np.random.choice(["bpr", "warp", "warp-kos"]),
            "learning_rate": np.random.exponential(0.05),
            "item_alpha": np.random.exponential(1e-8),
            "user_alpha": np.random.exponential(1e-8),
            "max_sampled": np.random.randint(5, 15),
            "num_epochs": np.random.randint(5, 50),
        }


def random_search(train, test, num_samples=10, num_threads=1):
    """
    Sample random hyperparameters, fit a LightFM model, and evaluate it
    on the test set.

    Parameters
    ----------

    train: np.float32 coo_matrix of shape [n_users, n_items]
        Training data.
    test: np.float32 coo_matrix of shape [n_users, n_items]
        Test data.
    num_samples: int, optional
        Number of hyperparameter choices to evaluate.


    Returns
    -------

    generator of (auc_score, hyperparameter dict, fitted model)

    """

    for hyperparams in itertools.islice(sample_hyperparameters(), num_samples):
        num_epochs = hyperparams.pop("num_epochs")

        model = LightFM(**hyperparams)
        model.fit(train, epochs=num_epochs, num_threads=num_threads)

        score = auc_score(model, test, train_interactions=train, num_threads=num_threads).mean()

        hyperparams["num_epochs"] = num_epochs

        yield (score, hyperparams, model)


if __name__ == "__main__":
    from lightfm.datasets import fetch_movielens

    data = fetch_movielens()
    train = data["train"]
    test = data["test"]

    (score, hyperparams, model) = max(random_search(train, test, num_threads=2), key=lambda x: x[0])

    print("Best score {} at {}".format(score, hyperparams))
person Maciej Kula    schedule 23.04.2018
comment
Я заметил, что если не передавать train_interactions=train в метрике (auc/precision_at_k/recall_at_k), соответствующие значения становятся довольно низкими. Правильный ли способ вычислить их, чтобы всегда передавать взаимодействие с поездом? - person D_K; 12.03.2019
comment
@D_K Я тоже хочу знать то же самое. - person Ashok Rayal; 22.05.2019
comment
До применения вашей методики оптимизации я получал Precision: train 0.36, test 0.13. Recall: train 0.49, test 0.39. AUC: train 0.97, test 0.93. после Precision: train 0.02, test 0.01. Recall: train 0.02, test 0.02. AUC: train 0.60, test 0.60. - person Ashok Rayal; 22.05.2019
comment
@AshokRayal да, это сбивает с толку необходимость пройти обучение по вычислению показателей при тестировании. Это не то, как можно было бы сделать это по книге. - person D_K; 22.05.2019
comment
@Maciej Kula, как мы можем использовать здесь настройку гиперпараметров байесовской оптимизации? - person Kshitij Yadav; 19.02.2020