Предсказание популярности статьи еще до ее написания
Всем привет! Захотелось мне запилить приложение, которое бы предсказывало популярность статьи на Либератуме еще до ее написания. Ведь было бы круто не писать статьи, которые в будущем не станут популярными и не привлекут читателя. И писать статьи, которые привлекут читателя? Как вам такой план?
Гугление вопроса показало, что хипстеры и прочие наркоманы используют для этих целей нейронные сети. Тогда как есть простой и чертовски эффективный, дедовский способ классификации текстов — наивный байесовский классификатор.
Действует НБК просто: на вход подается текст (в данном случае заголовок статьи) и класс документа (в данном случае shit или cool). «Обучая» классификатор, мы строим таблицу вероятностей встречи ключевого слова с учетом того, к какому классу относится документ. После того, как таблица будет построена, на вход классификатора мы будем подавать произвольные заголовки (и вы сами сможете в этом поучаствовать), а на выходе получим класс документа: shit или cool.
Единственный серьезный вопрос: на каких данных обучать классификатор? Для этого я экспортировал заголовки статей с Либератума за 10 лет. Около 11 тыс. штук.
Сами заголовки, понятное дело, ценности не представляют, нужно каждый соотнести с одним из классов популярности. Для этого я экспортировал и число просмотров каждой статьи.
Трудным вопросом стало выяснение того, что считать популярным, а что нет. Я долго чесал яйца затылок, разглядывая гистограмму постов, накладывал на нее медиану и среднее, боролся с выбросами с помощью логарифмов и т.п.
Вот общий график популярности постов:
Красная линия — медиана, синяя — среднее арифметическое.
А вот гистограмма:
Что считать границей популярных постов и лажовых? Я даже пытался вводить больше классов и использовать классификатор K-Means. Вот такое разбиение было предложено:
И такое деление на классы (норм, огонь, бестселлер, кал) показало очень плохие результаты. Позже я понял почему, но долго объяснять вам, не знающим нюансы байесовского классификатора.
А лучший результат показало деление по среднему арифметическому.
2550 просмотров на статью. Ниже этого значения — shit, больше или равно — cool.
Теперь обучим классификатор. НБК имеет очень простую формулу и запилить классификатор можно самому. Делать этого я конечно же не стану. Возьму готовый.
Обучение:
const fs = require('fs')
const papa = require('papaparse')
const bayes = require('bayes')
const _ = require('lodash')
var classifier = bayes()
var train = (resolve, reject) => {
let f = fs.readFileSync('../data/liberpop.csv', 'utf8')
papa.parse(f, {
delimiter: ',',
complete: (result) => {
_.each(result.data, (i) => {
if (i[2] != null) {
classifier.learn(i[2].toLowerCase(), i[4])
}
})
}
})
resolve(1)
}
(new Promise(train)).then(() => {
fs.writeFile('../data/probabilities.json', classifier.toJson(), () => {
console.log('Results saved to probabilities.json')
})
})
Библиотека PapaParse помогла распарсить CSV, а библиотека Bayes предоставила байесовский наивный классификатор. Результат обучения (JSON, ~800 Kb) сохранен в probabilities.json. Вуаля! Теперь можно подгружать probabilities.json в браузер к клиенту и юзер сможет вычислять популярность статей еще до их написания. Последний штрих (client side):
var bayes = require('bayes')
var axios = require('axios')
const PROBABILITIES_FILE = 'https://nobleman.xyz/tools/editor/wanga/js/probabilities.json'
var classifier
document.addEventListener('DOMContentLoaded', () => {
axios.get(PROBABILITIES_FILE).then((res) => {
classifier = bayes.fromJson(JSON.stringify(res.data))
var title = document.getElementById('title')
var results = document.getElementById('results')
title.addEventListener('keydown', (e) => {
if (e.keyCode == 13) {
var t = title.value
let c = classifier.categorize(t.toLowerCase())
title.value = ''
results.innerHTML = '' + t + '' + c + '' + results.innerHTML;
}
})
}).catch((err) => {
console.log('Axios error: ' + err)
})
})
В фоне подгружается probabilities.json, подключается к классификатору, всё это дело вешается на окно ввода. Готово. Можно пользоваться.
Ссылка на рабочее web-приложение: https://nobleman.xyz/tools/editor/wanga/
Наивный байесовский классификатор
НБК удобно использовать для фильтрации спама, определения тональности высказываний, много для чего. Из Википедии:
Несмотря на наивный вид и, несомненно, очень упрощенные условия, наивные байесовские классификаторы часто работают намного лучше во многих сложных жизненных ситуациях.
Достоинством наивного байесовского классификатора является малое количество данных необходимых для обучения, оценки параметров и классификации.
Подробности: How to predict article popularity using Naive Bayes Classifier and NodeJS
Комментарии
pomodor
13 февраля, 2019 - 17:09
Помогите переформулировать заголовок, чтобы стало cool. :)
auguste
13 февраля, 2019 - 21:38
и ремесло поставил я подножием искусству;
Я сделался ремесленник перстам
Придал послушную, сухую беглость
И верность уху, звуки умертвив
Я музыку разъял, как труп >
Поверив алгеброй гармонию
Смысл: проверить разумом, точным расчётом то, что выражено чувствами. Говорится обычно иронически или критически по отношению к человеку, который пытается проверить точными расчётами то, что относится к области чувств
спасибо классикам )
Местный дурачок
13 февраля, 2019 - 23:28
администрация сайта: будьте прокляты!
comrade
13 февраля, 2019 - 23:47
Вы со знаками препинания в проклятиях поаккуратнее! Поставили двоеточие вместо запятой, и проклятие не в ту сторону пошло...
(-;
pomodor
14 февраля, 2019 - 10:22
Ваш камент — говно.
[table Title | Assessment
администрация сайта: будьте прокляты! | shit]
Agafron
14 февраля, 2019 - 01:17
а программе уже привито чувство страха))
Agafron
14 февраля, 2019 - 01:16
предсказываем оригинальность заголовка статьи - cool
Agafron
14 февраля, 2019 - 01:01
она понимает аглицкий?
pomodor
14 февраля, 2019 - 10:21
Только те иностранные слова, которые уже включались в заголовки. Ubuntu "поймет", а, например, tits нет.
pomodor
14 февраля, 2019 - 12:15
Приделал к читалке новостей. Теперь непрочитанные новости сортируются по классу интересности на основе предыдущих решений (просматривал или нет).
Чингачгук
23 сентября, 2019 - 16:06
сентябрь на дворе, допилен ли ваш "Локал Гугл"?
"чертовски эффективный" post-popularity-prediction?
Діма
12 октября, 2020 - 16:50
Не приложение, а программа. И JavaScript это позор.
Комментировать