naive bayes classifier

Предсказание популярности статьи еще до ее написания

Всем привет! Захотелось мне запилить приложение, которое бы предсказывало популярность статьи на Либератуме еще до ее написания. Ведь было бы круто не писать статьи, которые в будущем не станут популярными и не привлекут читателя. И писать статьи, которые привлекут читателя? Как вам такой план?

Web-приложение, классификатор текстов на Либератуме

Гугление вопроса показало, что хипстеры и прочие наркоманы используют для этих целей нейронные сети. Тогда как есть простой и чертовски эффективный, дедовский способ классификации текстов — наивный байесовский классификатор.

Действует НБК просто: на вход подается текст (в данном случае заголовок статьи) и класс документа (в данном случае shit или cool). «Обучая» классификатор, мы строим таблицу вероятностей встречи ключевого слова с учетом того, к какому классу относится документ. После того, как таблица будет построена, на вход классификатора мы будем подавать произвольные заголовки (и вы сами сможете в этом поучаствовать), а на выходе получим класс документа: shit или cool.

Единственный серьезный вопрос: на каких данных обучать классификатор? Для этого я экспортировал заголовки статей с Либератума за 10 лет. Около 11 тыс. штук.

Экспорт CSV данных

Сами заголовки, понятное дело, ценности не представляют, нужно каждый соотнести с одним из классов популярности. Для этого я экспортировал и число просмотров каждой статьи.

Число просмотров и комментариев каждой статьи на Либератуме

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

Вот общий график популярности постов:

Популярность постов

Красная линия — медиана, синяя — среднее арифметическое.

А вот гистограмма:

Гистограмма популярности статей на сайте, Либератум

Что считать границей популярных постов и лажовых? Я даже пытался вводить больше классов и использовать классификатор K-Means. Вот такое разбиение было предложено:

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 = '<tr><td>' + t + '</td><td>' + c + '</td></tr>' + results.innerHTML;
      }
    })
  }).catch((err) => {
    console.log('Axios error: ' + err)
  })
})

В фоне подгружается probabilities.json, подключается к классификатору, всё это дело вешается на окно ввода. Готово. Можно пользоваться.

Web-приложение, классификатор текстов на Либератуме

Ссылка на рабочее web-приложение: https://nobleman.xyz/tools/editor/wanga/

Наивный байесовский классификатор

НБК удобно использовать для фильтрации спама, определения тональности высказываний, много для чего. Из Википедии:

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

Достоинством наивного байесовского классификатора является малое количество данных необходимых для обучения, оценки параметров и классификации.

Подробности: How to predict article popularity using Naive Bayes Classifier and NodeJS

Ваша оценка: Нет Средняя оценка: 4.3 (6 votes)
11
pomodor

Предсказание популярности статьи еще до ее написания — shit

Помогите переформулировать заголовок, чтобы стало cool. :)

Ваша оценка: Нет Средняя оценка: 5 (3 votes)
2
auguste

и ремесло поставил я подножием искусству;
Я сделался ремесленник перстам
Придал послушную, сухую беглость
И верность уху, звуки умертвив
Я музыку разъял, как труп >
Поверив алгеброй гармонию

Смысл: проверить разумом, точным расчётом то, что выражено чувствами. Говорится обычно иронически или критически по отношению к человеку, который пытается проверить точными расчётами то, что относится к области чувств

спасибо классикам )

Ваша оценка: Нет Средняя оценка: 3.8 (4 votes)
3

администрация сайта: будьте прокляты!

Ваша оценка: Нет Средняя оценка: 1 (1 vote)
9
comrade

Вы со знаками препинания в проклятиях поаккуратнее! Поставили двоеточие вместо запятой, и проклятие не в ту сторону пошло...
(-;

Ваша оценка: Нет Средняя оценка: 4.5 (6 votes)
11
pomodor

Ваш камент — говно.

TitleAssessment
администрация сайта: будьте прокляты!shit

Ваша оценка: Нет Средняя оценка: 3.3 (4 votes)
4
Agafron

чак норрис досчитал до бесконечности, дважды - cool

а программе уже привито чувство страха))

Ваша оценка: Нет Средняя оценка: 4 (2 votes)
4
Agafron

Помогите переформулировать заголовок, чтобы стало cool. :)

предсказываем оригинальность заголовка статьи - cool

Ваша оценка: Нет Средняя оценка: 4 (2 votes)
4
Agafron

Если это выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это утка (какая разница, что это на самом деле) - cool
If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck (who cares what it really is) - shit

она понимает аглицкий?

Ваша оценка: Нет Средняя оценка: 4 (2 votes)
11
pomodor

Только те иностранные слова, которые уже включались в заголовки. Ubuntu "поймет", а, например, tits нет.

Ваша оценка: Нет Средняя оценка: 3.8 (4 votes)
11
pomodor

Приделал к читалке новостей. Теперь непрочитанные новости сортируются по классу интересности на основе предыдущих решений (просматривал или нет).

Ваша оценка: Нет Средняя оценка: 5 (1 vote)
a

сентябрь на дворе, допилен ли ваш "Локал Гугл"?
"чертовски эффективный" post-popularity-prediction?

Ваша оценка: Нет Средняя оценка: 3.3 (3 votes)
Отправить комментарий
КАПЧА
Вы человек? Подсказка: зарегистрируйтесь, чтобы этот вопрос больше никогда не возникал. Кстати, анонимные ссылки запрещены.
CAPTCHA на основе изображений
Enter the characters shown in the image.
Linux I класса
Linux II класса
Linux III класса
Счетчики
  • Самый популярный сайт о Linux и Windows 10
О Либератуме

Liberatum — это новости мира дистрибутивов Linux, обзоры, сборки, блоги, а также лучший сайт об Ubuntu*.