Методы машинного обучения для оценки возраста пользователей на сайтах Facebook, которые им нравятся

25

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

Есть три важных характеристики моей базы данных:

  • распределение по возрасту в моем обучающем наборе (в сумме 12 тыс. пользователей) перекошено в сторону более молодых пользователей (т.е. у меня 1157 пользователей в возрасте 27 лет и 23 пользователя в возрасте 65 лет);

  • у многих сайтов не более 5 пользователей (я отфильтровал сайты FB с менее чем 5 пользователями).

  • есть намного больше возможностей, чем образцов.

Итак, мои вопросы: какую стратегию вы бы предложили для подготовки данных для дальнейшего анализа? Должен ли я выполнить какое-то уменьшение размерности? Какой метод ML будет наиболее подходящим для использования в этом случае?

Я в основном использую Python, так что советы, специфичные для Python, будут высоко оценены.

Войцех Валчак
источник
1
Когда вы говорите «намного больше функций, чем образцов», я предполагаю, что вы имеете в виду, что уникальное количество понравившихся сайтов составляет >> num пользователей. Это также относится и к корневому домену сайтов? т. е. это несколько URL-адресов youtube.com или cnn.com на сайтах или они уже связаны с доменом? Я склоняюсь к уменьшению размерности, сворачивая URL к корням домена, а не к конкретным страницам, если это возможно.
cwharland
Спасибо за ответ. Количество функций (уникальных понравившихся сайтов) составляет 32 КБ, а количество образцов (пользователей) - 12 КБ. Функциями являются страницы Facebook, поэтому нет необходимости останавливать URL-адреса. Пользователь может либо понравиться facebook.com/cnn или нет. Мне нравится идея пытаться оценить возраст пользователей на основе ссылок, которыми они делятся, хотя :)
Войцех Валчак
Аааа, я неправильно прочитал описание понравившихся сайтов. Благодарю за разъяснение.
cwharland

Ответы:

16

Одна вещь, с которой нужно начать, была бы k-NN. Идея заключается в том, что у вас есть матрица пользователей / предметов, а для некоторых пользователей вы сообщаете возраст. Возраст человека в матрице элементов пользователя может быть хорошо определен чем-то вроде среднего или среднего возраста некоторых ближайших соседей в пространстве элементов.

Таким образом, каждый пользователь выражается в виде вектора в пространстве элементов, находите k ближайших соседей и присваивает рассматриваемому вектору некоторую сводную статистику по возрастам ближайших соседей. Вы можете выбрать k на отрезке расстояния или более реалистично, итеративно назначая возрасты для удержания поезда и выбирая k, который минимизирует ошибку в этом назначении.

Если размерность является проблемой, вы можете легко выполнить сокращение в этой настройке путем разложения по одному значению, выбрав m векторов, которые улавливают наибольшую дисперсию в группе.

Во всех случаях, поскольку каждая особенность является двоичной, кажется, что косинусное сходство будет вашим показателем расстояния.

Мне нужно немного больше подумать о других подходах (регрессия, ВЧ и т. Д.), Учитывая узкую направленность вашего пространства функций (все варианты одного и того же действия, нравится). Я думаю, что подход пользователь / элемент может быть лучшим.

Одно замечание: если вы сами указали возраст, в котором вы тренируетесь, вам, возможно, придется исправить некоторые из них. Люди на Facebook, как правило, сообщают о возрасте за десятилетие, в котором они родились. Составьте гистограмму дат рождения (по возрастам) и посмотрите, есть ли у вас всплески в десятилетия, как 70-е, 80-е, 90-е

cwharland
источник
Привет, ваш ответ очень похож на мою настоящую стратегию. Я использовал sklearn.neighbors.KNeighborsRegressorкосинусную метрику в пространстве с уменьшенным SVD (после применения SVD средняя ошибка оценки снизилась с ~ 6 лет до ~ 4). Пользователи в моей базе данных имеют возраст 18-65 лет (пожилые пользователи были отфильтрованы), поэтому существует 48 возможных классов. Интересно, не слишком ли много классов для kNN, и следует ли мне рассматривать это как регрессию или проблему классификации (я думаю, что применимы оба).
Войцех Вальчак
Я могу сказать, анекдотично, что я использовал для каждого класса случайных лесов, чтобы подгонять несколько классов по отдельности, а затем комбинировать результаты каждой из этих моделей различными способами. В этом случае вы можете даже подумать о назначении предыдущих вероятностей для возраста каждого пользователя с помощью kNN, а затем просмотреть каждую модель на основе классов, использовать эти оценки для обновления предыдущих вероятностей для каждого класса и выбрать наиболее вероятный класс из этих последующих. Похоже, что это немного усложняет, но в худшем случае у вас будет точность kNN.
cwharland
7

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

  1. Прочитайте в обучающем наборе (n = N), перебирая строки, разделенные запятыми, как записи, построчно и используйте счетчик для определения наиболее популярных страниц.
  2. Для каждой из K самых популярных страниц (я использовал около 5000, но вы можете поиграть с разными значениями), используйте pandas.DataFrame.isin, чтобы проверить, нравится ли каждому человеку в обучающем наборе каждую страницу, затем создайте N x K фрейм данных результатов (я назову это xdata_train)
  3. Создайте серию (я назову ее ydata_train), содержащую все переменные результата (в моем случае, в вашем возрасте) с тем же индексом, что и xdata_train
  4. Настройте случайный лесной классификатор с помощью scikit-learn для прогнозирования ydata_train на основе xdata_train
  5. Используйте тест перекрестной проверки scikit-learn для настройки параметров и повышения точности (настройка количества популярных страниц, количества деревьев, минимального размера листа и т. Д.)
  6. Вывести классификатор случайного леса и список самых популярных страниц с помощью pickle (или сохранить в памяти, если вы делаете все сразу)
  7. Загрузите оставшиеся данные, загрузите список популярных страниц (при необходимости) и повторите шаг 2, чтобы создать xdata_new.
  8. Загрузите классификатор случайных лесов (при необходимости) и используйте его для прогнозирования значений для данных xdata_new
  9. Вывести прогнозируемые оценки в новый CSV или другой формат вывода по вашему выбору

В вашем случае вам нужно поменять местами классификатор для регрессора (так что смотрите здесь: http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html ), но в остальном тот же процесс должно работать без особых проблем.

Кроме того, вы должны знать о самой удивительной особенности случайных лесов в Python: мгновенное распараллеливание! Те из нас, кто начал делать это в R, а затем перешел, всегда удивляются, особенно когда вы работаете на машине с несколькими десятками ядер (см. Здесь: http://blog.yhathq.com/posts/comparing- random-forest-in-python-and-r.html ).

Наконец, обратите внимание, что это было бы идеальным приложением для анализа сети, если у вас есть данные о друзьях, а также о самих людях. Если вы можете проанализировать возраст друзей пользователя, возраст пользователя почти наверняка будет в пределах года или двух от медианы среди его или ее друзей, особенно если пользователи достаточно молоды, чтобы построить свои сети друзей, пока они находятся в школа (так как большинство будет одноклассниками). Этот прогноз, вероятно, превзойдет все, что вы получите от моделирования - это пример из учебника, где правильные данные> правильная модель каждый раз.

Удачи!

Therriault
источник
2
Одним из интересных аспектов использования топ-5000 сайтов является тот факт, что они не могут быть хорошими в сегментации пользователей по возрасту. Лучшие сайты, по построению, являются теми, которые посещают все. Поэтому они не очень хороши в сегментации ваших пользователей, поскольку все возможные классификации (возрасты) задействованы на этих сайтах. Это понятие похоже на часть idf в tf-idf. idf помогает отфильтровать шум "у всех есть эта особенность". Как наиболее посещаемые сайты оцениваются как функции в ваших графиках переменной важности с вашим RF?
cwharland
1
Хорошая точка зрения. Простым решением этой проблемы было бы разделить тренировочный набор данных на возрастные группы J (например, 13-16, 17-20, 21-24 и т. Д.) И взять верхние (K / J) страницы для каждой группы. Это обеспечит вам значительную представленность для каждой группы. Несомненно, между группами будет некоторое совпадение, поэтому, если вы действительно требовательны, вы можете выбрать лучшие (K / J) уникальные страницы для каждой группы, но я думаю, что это может быть излишним.
Therriault
5

Еще одно предложение - проверить логистическую регрессию . В качестве дополнительного бонуса, веса (коэффициенты) модели дадут вам представление о том, какие сайты являются возрастными.

Sklearn предлагает пакет sklearn.linear_model.LogisticRegression , который также предназначен для обработки разреженных данных.

Как упоминалось в комментариях, в данном случае с большим количеством входных переменных, чем сэмплов, вам необходимо упорядочить модель (с помощью аргумента sklearn.linear_model.LogisticRegressionpenalty='l1' ).

damienfrancois
источник
1
Я думаю, что с LR вам придется делать несколько моделей для возрастных корзин. Как бы сравнить две модели для разных возрастных групп, которые предсказывают одинаковую вероятность включения для пользователя?
cwharland
1
Обратите внимание, что LR дает сбой, когда имеется больше переменных, чем наблюдений, и работает плохо, если предположения модели не выполняются. Чтобы использовать его, уменьшение размерности должно быть первым шагом.
Кристофер Лоуден
1
@cwharland, вы не должны рассматривать переменную ответа как категориальную, так как она непрерывна по своей природе и дискретизирована определением проблемы. Полагать, что это категорично, означало бы сказать алгоритму, что прогнозирование 16-летнего возраста, когда ему фактически 17 лет, является такой же серьезной ошибкой, как и прогнозирование 30-летнего возраста, когда ему фактически 17 лет. Считать его непрерывным гарантирует, что небольшие ошибки (16 против 17) считаются малыми и большими ошибками 30 против 17) считаются большими. В этом случае логистическая регрессия используется для прогнозирования непрерывного значения, а не для оценки апостериорных вероятностей.
Дамьенфрансуа
@ChristopherLouden Вы правы, что ванильная версия логистической регрессии не подходит для случая «большой p маленький n», я должен был упомянуть, что регуляризация важна в данном случае. Я обновляю свой ответ. Но L1-регуляризованный LR - это своего рода выбор функций, поэтому я не считаю необходимым предварительный шаг FS.
Дамьенфрансуа
@damienfrancois: Я определенно согласен. Я просто немного обеспокоен тем, что в этом случае LR будет слишком строго штрафовать промежуточные значения. Похоже, что нет никакой мотивации отображать сигмоидальную кривую, если учесть, что вы не особенно заинтересованы в экстремальных возрастных значениях. Возможно, я неправильно истолковываю использование.
cwharland
4

Некоторые исследования D. Nguyen et al. попытаться предсказать возраст пользователя Твиттера на основе их твитов. Может быть, вы найдете их полезными. Они используют логистическую и линейную регрессию.

lgylym
источник
3

Помимо более изощренных методов, вы можете попробовать формулу Байеса

P (I | p1 ... pn) = P (p1 ... pn | I) P (I) / sum_i (P (p1 ... pn | i) P (i))

P (I | p1 ... pn) - вероятность того, что пользователь относится к возрастной группе I, если ему понравились p1, .., pn

P (i) - вероятность того, что пользователь относится к возрастной группе i

P (p1 .. pn | i) - вероятность того, что пользователю понравились p1, .., pn, если он принадлежит к возрастной группе i.

  • У вас уже есть оценки для P (i) из ваших данных: это только доля пользователей в возрастной группе I.
  • Чтобы оценить P (p1 ... pn | i), для каждой возрастной группы я оцениваю вероятность (частоту) p_ij как страницу j. Чтобы p_ij было ненулевым для всех j, вы можете смешать частоту для всего населения с небольшим весом.

  • Тогда log P (p1 ... pn | i) = sum (log p_ij, i = p1, .., pn), сумма по всем страницам, которые нравятся новому пользователю. Эта формула была бы приблизительно верной, предполагая, что пользователь любит страницы в своей возрастной группе независимо.

  • Теоретически, вы также должны добавить log (1-p_ij) для всех i, которые ему не нравятся, но на практике вы должны обнаружить, что сумма log (1-p_ij) будет неуместно мала, поэтому вам не понадобится много памяти.

Если вы или кто-то еще пытался это сделать, пожалуйста, прокомментируйте результат.

Valentas
источник
2

Это очень интересная проблема.

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

  • Вместо того, чтобы связывать данные с возрастами (15 лет, 27 лет, ...), я создал различные группы возрастов: менее 18, от 18 до 30 и более 30 (это связано с конкретной проблемой, с которой мы были лицом, но вы можете выбрать любые интервалы, которые вы хотите). Это разделение очень помогает решить проблему.
  • После этого я создал иерархическую кластеризацию (делительную или агрегированную). Затем я выбираю те ветви, в которых у меня были пользователи с известным возрастом (или возрастом группы), а затем для этой ветви я продлил тот же возраст для этой группы.

Этот подход - обучение под наблюдением, и я рекомендую его, если у вас есть только некоторые данные, помеченные.

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

adesantos
источник