Як розрізняти британську та американську літературу з допомогою машинного навчання

Одного разу мені стало цікаво, чи відрізняється британська та американська література з точки зору вибору слів, і якщо відрізняється, чи вдасться мені навчити класифікатор, який розрізняв літературні тексти з точки зору частоти використаних слів. Розрізняти тексти, написані на різних мовах, досить легко, потужність перетину безлічі слів невелика відносно множини слів у вибірці. Класифікація тексту за категоріями «наука», «християнство», «комп'ютерна графіка», «атеїзм», — всім відомий hello world серед завдань по роботі з частотністю тексту. Переді мною стояла більш складна задача, так як я порівнювала два діалекти однієї мови, а тексти не мали спільної смислової спрямованості.
image
найдовший етап машинного навчання — це вилучення даних. Для навчальної вибірки я використовувала тексти з Project Gutenberg, їх можна вільно завантажити. Список американських та британських авторів я викачала з вікіпедії. Складність полягала в тому, щоб знайти відповідність імені автора. На сайті проекту реалізовано хороший пошук по іменах, але парсити сайті заборонено, замість цього пропонується використовувати архів з метаданими. Це означало, що мені треба вирішувати нетривіальну задачу збігу імен (Sir Arthur Ignatius Conan Doyle і Doyle, C. — одні і ті ж люди, а Doyle M. E. вже немає) і робити це з дуже високою точністю. Замість цього я, пожертвувавши розміром вибірки на користь точності та економії свого часу, вибрала в якості унікального ідентифікатора посилання на вікіпедію автора, яка була включена в деякі файли метаданих. Так я отримала близько 1600 британських текстів і 2500 американських і почала навчати класифікатор.
При всіх операціях я використовувала пакет sklearn. Перший крок після збору і аналізу даних — це препроцессинг, для якого я взяла CountVectorizer. Він приймає на вхід масив текстових даних і повертає вектор ознак. Далі потрібно представити ознаки в числовому форматі, так як класифікатор працює з числовими даними. Для цього потрібно обчислити tf-idf, term frequency — inverted document frequency, використовуючи TfidfTransformer.
Короткий приклад про те, як це робиться і навіщо:
Візьмемо слово «the» і порахуємо кількість входжень цього слова в тексті А. Нехай у нас буде 100 примірників, а загальна кількість слів у документі 1000,
tf("the") = 100/1000 = 0.1

Далі візьмемо слово «sepal» (чашолисток), яке зустрілося 50 разів,
tf("sepal") = 50/1000 = 0.05

Щоб порахувати inverted document frequency для цих слів, треба взяти логарифм від відношення кількості текстів, у яких є хоч одне входження цього слова, до загальної кількості текстів. Якщо все текстів 10000, і в кожному є слово «the»,
idf("the") = log(10000/10000) = 0

tf-idf("the") = idf("the") * tf("the") = 0 * 0.1 = 0

Слово «sepal» набагато більш рідкісне, і зустрілося тільки в 5 текстах, тому
idf("sepal") = log(10000/5) = 7.6

tf-idf("sepal") = 7.6 * 0.05 = 0.38

Таким чином, часті слова мають мінімальну вагу, і специфічні рідкісні — великий, і за великим входження слова «sepal» в текст можна припустити, що він якось пов'язаний з ботанікою.
Тепер, коли дані представлені як набір ознак, потрібно навчити класифікатор. Я працюю з текстом, який представлений як зріджені дані, тому оптимальним варіантом став лінійний класифікатор, добре справляється з завданнями класифікації з великою кількістю ознак. І CountVectorizer, і TF-IDFTransformer, і SGD я навчала з параметрами за замовчуванням. Можна працювати окремо з кожним етапом, але зручніше використовувати pipeline:
pipeline = Pipeline([
('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', SGDClassifier()),
])

Проаналізувавши графік точності від розміру вибірки, я помітила сильні коливання точності навіть на великих обсягах вибірки, що свідчило про те, що класифікатор дуже сильно залежимо від конкретної вибірки, а значить мало ефективний, і потрібні суттєві поліпшення. Отримавши список ваг класифікатора, я помітила частина проблеми: алгоритм переобучался на частих словах типу «of» і «he», які по суті є шумом. Ця проблема легко вирішується видаленням подібних слів з ознак, і задається параметром CountVectorizer stop_words = 'english' або вашим власним списком слів. Ще трохи поліпшило точність, видалення деяких популярних общеупотребимых слів. Прибравши стоп-слова, я отримала поліпшення точності до 0.85.
Далі я зайнялася налаштуванням параметрів c допомогою GridSearchCV. Цей спосіб виявляє кращу комбінацію параметрів для CountVectorizer, TfidfTransformer і SGDClassifier, тому це дуже довгий процес, у мене він вважався близько доби. У підсумку отримала такий pipeline:
pipeline = Pipeline([
('vect', CountVectorizer(stop_words = modifyStopWords(), ngram_range = (1, 1))),
('tfidf', TfidfTransformer(use_idf = True norm = 'l2', smooth_idf = True)),
('clf', SGDClassifier(alpha=0.001, fit_intercept = True, n_iter = 10, penalty = 'l2', loss = 'epsilon_insensitive')),
])

Підсумкова точність — 0.89.
Тепер найцікавіше для мене: які слова вказують на походження тексту. Ось список слів, відсортований за спаданням модуля ваги в класифікаторі:
Американський текст: dollars, new, york, girl, gray, american, carvel, color, city, ain, long, just, parlor, boston, honor, washington, home, labor, got, finally, maybe, hodder, forever, dorothy, dr
Британський текст: round, sir, lady, london, quite, mr, shall, lord, grey, dear, honour, having, philip, poor, pounds, scrooge, soames, things, sea, man, end, come, colour, illustration, english, learnt
Розважаючись з класифікатором, я отримала «британських» авторів з числа американців і найбільш «американських» британців (витончений спосіб розповісти про те, як сильно може помилятися мій класифікатор):
«британські» американці:
  • Бернетт, Френсіс Еліза (народилася в Англії, у віці 17 років переїхала в США, тому відношу її до американців)
  • Генрі Джеймс (народився в США, у 33 роки емігрував до Великобританії)
  • Уистер, Оуен
  • Мері Робертс Рейнхарт (як бачимо, звана американської Агатою Крісті не без причини)
  • Вільям Мак-Фі (як і Бернетт, переїхав в США в юному віці)
«американські» британці:
  • Ридьярд Кіплінг (прожив кілька років в США, потрапив у список завдяки «American Notes»)
  • Ентоні Троллоп (знову ж винні американські топоніми в його «North America»)
  • Фредерік Марриет (можливо, одного б назви «Narrative of the Travels and Adventures of Monsieur Violet in California, Sonara, and Western Texas» вистачило б, щоб заплутати класифікатор)
  • Арнольд Беннет (спасибі його «Your United States: Impressions of a first visit»)
  • Філліпс Оппенхейм
А також самих «британських» британців і «американських» американців (бо класифікатор все ж таки гарний).
Американці:
  • Франсіс Хопкинсон Сміт
  • Гемлін Гарленд
  • Джордж Ейд
  • Чарльз Дадлі Уорнер
  • Марк Твен
Британці:
  • Джордж Мередіт
  • Семюел Річардсон
  • Джон Голсуорсі
  • Гілберт Кіт Честертон
  • Ентоні Троллоп
На спробу зробити такий класифікатор мене підштовхнув твіт @TragicAllyHere:
I would love to be British. Drinking my leaf water and staring at a huge clock from my red phone booth, adding extra letters to wourds.
Код можна взяти тут, там же доступний вже навчений класифікатор.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.