https://github.com/viktor-shcherb/mch-hackathon
Moscow City Hack fake news detection case solution
https://github.com/viktor-shcherb/mch-hackathon
fake-news fake-news-detection nlp nlp-machine-learning pytorch spacy
Last synced: about 2 months ago
JSON representation
Moscow City Hack fake news detection case solution
- Host: GitHub
- URL: https://github.com/viktor-shcherb/mch-hackathon
- Owner: viktor-shcherb
- Created: 2022-06-11T07:54:15.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-06-13T13:21:06.000Z (over 3 years ago)
- Last Synced: 2025-06-19T19:56:39.392Z (4 months ago)
- Topics: fake-news, fake-news-detection, nlp, nlp-machine-learning, pytorch, spacy
- Language: Python
- Homepage:
- Size: 53.9 MB
- Stars: 5
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Kadmus Fake Detection
Распознавание фейковых новостей.Система способна определять новости, в которых произошло искажение фактов относительно информации в первоисточнике, а также выделять конкретные факты, которые, по мнению системы, были искажены.
ROC AUC качество классификации: 95%.
Демо: https://share.streamlit.io/viktorooreps/mch-hackathon/main/web_app.py
## Принцип работы:
* Форма на предложенной веб-странице принимает текст новости, для которой требуется узнать вероятность того, что новость фейковая.
* Текст предобрабатывается, после чего для этого текста в базе новостей ищется наиболее вероятный кандидат на первоисточник. Если все новости в базе сильно отличаются по тематике от запрошенной, то пользователю выводится сообщение о том, что первоисточник не найден
* В случае, если удалось найти достаточно правдоподобного кандидата на первоисточник, этот кандидат и запрошенный текст разбиваются по предложениям, после чего эти предложения сравниваются между собой - для каждого предложения из первоисточника ищется соответствующее предложение из запрошенного текста. Из предложений извлекаются факты и сравниваются между собой, и, на основе этого сравнения, алгоритм выдает вероятность того, что новость является фейковой.## Технические детали:
Предположения:
* Предполагаем, что новости с портала mos.ru являются достоверными. Предположение корректноработают профессионалы, которые а) максимально быстро публикуют информацию и б) максимально качественно занимаются факт-чеккингом.## Пайплайн
### Обучение:
* Сохраняем банк новостей с mos ru, делим на трейн и тест
* Генерируем и сохраняем по трейну новый датасет - (исходный текст, парафразированный, семантизированный, парафразированный и семантизированный)
* Дополняем этот csv-датасет эмбеддингами каждого из 4 текстов
* Формируем новую трейн-выборку: идем в цикле и добавляем в датасет 4 пары эмбеддингов на каждой итерации: (src, src), (src, par), (src, sem), (src, par_sem)
* Обучаем модель:
* Применяем модель генерации признаков по паре эмбеддингов
* Подаем в классификатор LGBM вместе с меткой фейк/не фейк### Валидация:
* Формируем датасет по test.csv аналогично трейну и считаем метрику
### Тест в реальной жизни:
* Принимаем на вход текст статьи, которую надо проверить на фейковость
* Берем эмбеддинг Берта от всего текста
* Ищем ближайшего соседа по эмбеддингу из банка новостей - говорим, что это кандидат на первоисточник
* Если радиус больше порога - говорим что нет первоисточника, заканчиваем.
* Если радиус меньше порога - идем дальше
* Применяем модель генерации признаков по паре (src, mb_fake) -> вектор признаков
* Применяем LGBM, который дает вероятность того что письмо фейк## Изменения текста
1. Семантически нейтральные
* Backtranslation
* Парафраз
* Удалять предложения/абзацы, тогда полученную новость можно считать достоверной (меньше количество информации по сравнению с первоисточником не считается фейком)2. Меняющие семантику
* Распознавать именованные сущности и замена их на похожие
* С помощью предобученной модели из spacy для русского языка (данный подход позволяет распознавать сущности верно в 98-99% случаях). Заменять в тексте локации, организации и личности с определенной вероятностью. Замена подбирается случайно из списка сущностей того же типа, этот список сформирован из выявленных сущностей новостей с mos.ru
* С помощью предобученной модели из spacy для английского языка: DATE, TIME, PERCENT, CARDINAL
* Применялась дополнительная фильтрация сущностей, проверки на корректность
* Удалять предложения/абзацы, тогда исходную новость можно считать фейковом (содержатся лишние факты, которых нет в первоисточнике)В итоге для каждой исходной статьи из обучающей выборки были сгенерированы 3 измененных: перефразированная, с изменением сущностей, перефразированная с изменением сущность. Таким образом, исходная и перефразированная новости являются достоверными, а остальные две - фейковыми.
### Именнованные сущности:
LOC - локация
ORG - организация
PER - личность
PERCENT - процент
TIME - время
DATE - дата
CARDINAL - числа## Разработка
Все используемые в пайплайне модули сопровождались **комментариями** с кратким описанием работы. В разработке по большей части опирались на принципы **ООП**.
В файлах requirements.txt и init.py описаны все используемые зависимости, в том числе указаны **ссылки на используемые готовые решения**.
semantic_modification.py - модуль для изменения фактов в тексте
paraphraser.py - модуль, составляющий парафразу для абзацев в тексте.
datamodel.py - обертки для данных
augmentation_script.py - скрипт для получения аугментированного датасета для обучения классификатораlgbm_model - модуль LGBM-классификатора
feature_extraction - модуль для извлечения признаков из пары текстов - первоисточника и фейка
fact_extraction - ...
data - обкаченные краулером данные
crawlers - скрипты для краулинга mos.ru
bank_embeddings - модуль для получения эмбеддингов из текстовcrawl_mos.sh - bash-скрипт для запуска краулера новостей с mos.ru
init.sh - модуль для настройки окруженияrequirements.txt - зависимости проекта
web_app.py - код веб-приложения
## Метрики
Качество по ROC AUC для модели LGBM: 95%.
Гиперпараметры:
'''
{
"max_depth": -1,
"min_child_samples": 19,
"min_child_weight": 0.001,
"min_split_gain": 0.0,
"n_estimators": 30,
"n_jobs": -1,
"num_leaves": 176,
"objective": null,
"random_state": null,
"reg_alpha": 0.0,
"reg_lambda": 0.0,
"silent": "warn",
"subsample": 1.0,
"subsample_for_bin": 200000,
"subsample_freq": 0,
"lambda_l1": 0.10760824726959102,
"lambda_l2": 1.220269679867742e-08,
"feature_fraction": 0.6389666241304643,
"bagging_fraction": 0.523470095488254,
"bagging_freq": 6
},
"score": 0.9502150848765432
}
'''Precision: 0.83@0.5
Recall: 0.90@0.5