Инженерный тур. 3 этап
Участникам предстоит разработать алгоритм оценки популярности публикаций в социальной сети.
Социальные сети ежедневно генерируют огромные объемы контента, но определить, какие публикации становятся популярными и почему — сложная аналитическая задача. Для ее решения команды должны создать алгоритм оценки популярности публикаций, анализируя их взаимодействие с пользователями и выявляя ключевые факторы, влияющие на распространение информации.
При просмотре публикаций разные пользователи по-разному взаимодействуют с ними: кто-то активно делится, кто-то комментирует, кто-то просто ставит реакцию. Предпочитаемые взаимодействия могут изменяться в зависимости от того, какое устройство у пользователя и в какое время он просматривает публикацию. Поэтому требуется предсказывать сразу несколько характеристик взаимодействия пользователей с публикациями.
Число участников в команде: 3 человека.
Компетенции, которыми должны обладать члены команды:
- Аналитик придумывает идеи решения.
- Программист реализует идеи в виде программы.
- Тестировщик тестирует программы и настраивает гиперпараметры.
| Наименование | Описание |
|---|---|
| All Cups https://cups.online/ | Платформа для проведения соревнований по машинному обучению. |
| Yandex DataSphere https://datasphere.yandex.cloud/ | Сервис для ML-разработки. Используется для анализа данных и обучения моделей. |
| Docker | ПО для виртуализации. Используется для отправки решения в тестирующую систему. |
При просмотре публикаций разные пользователи по-разному взаимодействуют с ними: кто-то активно делится, кто-то комментирует, кто-то просто ставит реакцию. Предпочитаемые взаимодействия могут изменяться в зависимости от того, какое устройство у пользователя и в какое время он просматривает публикацию. Поэтому требуется предсказывать сразу несколько характеристик взаимодействия пользователей с публикациями.
Каждая строка в наборе данных кодирует какую-то одну публикацию. Набор данных состоит из следующих столбцов:
view— число просмотров публикации;like— число отметок «мне нравится»;comment— число комментариев;hide— число скрытий публикации;expand— число раскрытий публикации;open_photo— число открытий фотографии;open— число открытий публикации;share_to_message— число пересылок публикации;text— текст публикации;photo— прикрепленная к публикации фотография в кодировкеbase64.
Пример содержит способ преобразования изображения.
Тренировочный набор данных, который находится в файле train.csv, включает все эти характеристики.
При запуске решения в контейнере тестовый набор данных будет доступен в файловой системе по пути /tmp/data/test.csv. Тестовый набор данных состоит из колонок: view, text и photo. Файл sample_test.csv содержит пример тестового набора данных с идентичной структурой.
В результате работы в контейнере решение должно создать CSV-файл result в папке /var/log/. Он должен содержать колонки: like, comment, hide, expand, open_photo, open и share_to_message с оценками соответствующих характеристик.
Максимальный балл — 100.
Для оценки решения используется умноженный на 100 коэффициент детерминации, усредненный по всем предсказанным характеристикам. Во время соревнования доступна оценка решения только на 30% тестового набора данных, а после — на оставшихся 70%. Для тестирования на заключительном этапе участникам следует выбрать три решения.
При запуске решения в контейнере тестовый набор данных будет доступен в файловой системе по пути /tmp/data/test.csv. Обратите внимание, что в примере он сначала копируется в рабочую папку, перед запуском решения.
Тестовый набор данных состоит из колонок: view, text и photo. Файл sample_test.csv содержит пример тестового набора данных с идентичной структурой.
В результате работы в контейнере решение должно создать CSV-файл result в папке /var/log/. Он должен содержать колонки: like, comment, hide, expand, open_photo, open и share_to_message с оценками соответствующих характеристик.
Для решения необходимо выделить признаки из текста и изображений. Для выделения признаков из текста можно воспользоваться CountVectorizer, а для изображений — посчитать различные статистики по пикселям, либо воспользоваться какой-нибудь предобученной сверхточной сетью.
После извлечения признаков следует определить для каждой целевой характеристики, какой алгоритм восстановления регрессии будет лучше ее предсказывать. Для некоторых характеристик эффективнее всего работает наивный алгоритм регрессии.
Ниже приведен пример авторского решения.
Файл для fit.py обучения модели.
import pandas as pd
import numpy as np
import base64
from io import BytesIO
from PIL import Image
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.dummy import DummyRegressor
from sklearn.ensemble import GradientBoostingRegressor
import pickle
text_vectorizer = CountVectorizer(max_features=777)
def img_vectorizer(photo_base64):
img = np.array(Image.open(BytesIO(base64.b64decode(photo_base64))))
s = img.shape
if (len(s) == 2):
img = np.repeat(img, 3)
h, w = s[0], s[1]
img.resize((h * w, 3))
stats = []
stats.append(np.array([h,w]))
stats.append(img.min(axis=0))
stats.append(img.max(axis=0))
stats.append(img.mean(axis=0))
stats.append(img.std(axis=0))
stats.append(np.median(img, axis=0))
cm = np.corrcoef(img.T)
stats.append(cm[np.triu_indices(len(cm), k = 1)])
return np.concatenate(stats)
train = pd.read_csv("train.csv")
X_train_img = np.vstack(train['photo'].map(img_vectorizer))
X_train_text = text_vectorizer.fit_transform(train["text"].fillna("")).toarray()
X_train = np.hstack([X_train_img, X_train_text])
model = {
'like': GradientBoostingRegressor(n_estimators=77),
'comment': DummyRegressor(),
'hide': DummyRegressor(),
'expand': GradientBoostingRegressor(n_estimators=77),
'open_photo': GradientBoostingRegressor(n_estimators=77),
'open': GradientBoostingRegressor(n_estimators=77),
'share_to_message': GradientBoostingRegressor(n_estimators=77)
}
for target, reg in model.items():
y_train = train[target] / train['view']
reg.fit(X_train, y_train)
with open('model.pickle', 'wb') as f
pickle.dump(text_vectorizer, f)
pickle.dump(model, f)
Файл predict.py для вывода модели.
with open('text_vectorizer.pickle', 'rb') as f:
text_vectorizer = pickle.load(f)
model = pickle.load(f)
test = pd.read_csv("test.csv")
X_test_img = np.vstack(test['photo'].map(img_vectorizer))
X_test_text = text_vectorizer.fit_transform(test["text"].fillna("")).toarray()
X_test = np.hstack([X_test_img, X_test_text])
prediction = pd.DataFrame()
for target, reg in model.items():
prediction[target] = reg.predict(X_test) * test['view']
prediction.to_csv("submission.csv", index=False)
Файл requirements.txt с используемыми версиями библиотек.
pandas==2.2.3
scikit-learn==1.6.1
pillow==10.4.0
Dockerfile:
FROM python:3
WORKDIR /bdml
COPY run.sh .
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY model.pickle .
COPY predict.py .
CMD ["bash", "run.sh"]
Материалы доступны по ссылке: https://disk.yandex.ru/d/ng3EGZLMueC79Q.
- Учебник по машинному обучению: https://education.yandex.ru/handbook/ml.
- Документация к Python библиотеке для машинного обучения: https://scikit-learn.ru/.
- Документация к Python библиотеке для анализа данных: http://pandas.geekwriter.ru/.
