Оптимизировать работу с памятью

Используя известный датасет MovieLens, пытаюсь построить рекомендательную систему. Для этого необходимо спрогнозировать, какую оценку пользователь поставит фильму (целевая переменная - rating), используя информацию: оценки фильмов со стороны юсера и теги, которые он им подписывает. Применяю следующую логику. 1.1. фильмам каких жанров человек ставит оценки (отфильтровать по пользователю, выделить фильмы, которым он поставил оценки, узнать жанры этих фильмов) 1.2. какие оценки ставит пользователь данным жанрам 1.3. как он размечает фильмы тегами 1.4. расставим веса жанров и тегов методом tfidf

  1. соединяю таблицы фильмов и рейтингов, чтобы понимать, какому фильм какая оценка поставлена (для тестовой выборки)
  2. сформирую модель линейной регрессии и сделаю прогноз
  3. найду ошибку RMSE

Вопрос: в датасете описаний фильмов свыше 4 млн. 600 тыс. Когда пытаюсь описать вектором картины через модель CountVectorizer() (из библиотеки sklearn.feature_extraction.text), применив жанры, все норм (уникальных значений жанров не так много) - см. код. Но если делаю то же самое для тегов (коих значений более полутора тысяч), не хватает памяти. Что можно предпринять?

def change_string(s):
    """
    Функция принимает строку и возвращает список слов, разденных в столбце символом '|', 
    которые склеивает (.join()) через пробел
    """
    return ' '.join(s.replace(' ', '').replace('-', '').split('|'))

# прогоним через функцию строки столбца жанров 
movie_genres = [change_string(g) for g in movies_tags_ratings.genres.values]

# обучим модель для понимания, каким жанром принадлежит каждый их фильмов 
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(movie_genres)
X_train_counts.toarray()

# обучим модель, чтобы придать жанрам различные веса 
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)

# реализовав метод, видим, что вес фильмов изменился в зависимости от его жанров (чем реже жанр, тем выше вес)
X_train_tfidf.toarray()

# уникальных значений в столбце тегов слишком много
movies_tags_ratings.tag.nunique()

def change_string_tag(s):
    """
    Функция принимает строку и возвращает список слов, разденных в столбце пробелом, 
    которые склеивает (.join()) через пробел
    """
    return ' '.join(s.replace(' ', '').replace('-', '').split(' '))

# прогоним через функцию строки столбца жанров 
movie_tags = [change_string_tag(g) for g in movies_tags_ratings.tag.values]

# обучим модель для понимания, какими тегами описывается каждый их фильмов: здесь выкидывается ошибка
# X_train_tags = count_vect.fit_transform(movie_tags)
# X_train_tags.toarray()

Ответы (1 шт):

Автор решения: CrazyElf

А зачем вы делаете везде toarray(), вам это точно нужно? Те трансформеры, которые вы применяете, делают разреженные матрицы, они занимают немного места. Но если превращать их в обычные массивы - никакого места не хватит. Можно параметрами ограничить число фич, создаваемых этими трансформерами, но сильно их лучше не уменьшать. Хотите экономить место - работайте с разреженными матрицами, не превращайте их в обычные. В sklearn есть модели, которые умеют с ними работать, например Naive Bayes. Ну и другие, сейчас навскидку не вспомню, поиском тут должно находиться что-то, такие вопросы уже отвечались тут. Ещё можно предварительно понизить размерность через TruncatedSVD, он тоже понимает разреженные матрицы.

→ Ссылка