Однажды мне стало интересно, отличается ли британская и американская литература с точки зрения выбора слов, и если отличается, удастся ли мне обучить классификатор, который бы различал литературные тексты с точки зрения частоты использованных слов. Различать тексты, написанные на разных языках, довольно легко, мощность пересечения множества слов небольшая относительно множества слов в выборке. Классификация текста по категориям «наука», «христианство», «компьютерная графика», «атеизм», — всем известный hello world среди задач по работе с частотностью текста. Передо мной стояла более сложная задача, так как я сравнивала два диалекта одного языка, а тексты не имели общей смысловой направленности.
Самый долгий этап машинного обучения — это извлечение данных. Для обучающей выборки я использовала тексты с 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
Развлекаясь с классификатором, я получила самых «британских» авторов из числа американцев и самых «американских» британцев (изящный способ рассказать о том, как сильно может ошибаться мой классификатор):
Cамые «британские» американцы:
- Бёрнетт, Фрэнсис Элиза (родилась в Англии, в возрасте 17 лет переехала в США, поэтому отношу ее к американцам)
- Генри Джеймс (родился в США, в 33 года эмигрировал в Великобританию)
- Уистер, Оуэн
- Мэри Робертс Рейнхарт (как видим, называемая американской Агатой Кристи не без причины)
- Уильям Мак-Фи (как и Бёрнетт, переехал в США в юном возрасте)
Cамые «американские» британцы:
- Ридьярд Киплинг (прожил несколько лет в США, попал в список благодаря “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”)
- Филлипс Оппенхейм
А также самых «британских» британцев и «американских» американцев (потому что классификатор все же хорош).
Aмериканцы:
- Франсис Хопкинсон Смит
- Гэмлин Гарленд
- Джордж Эйд
- Чарльз Дадли Уорнер
- Марк Твен
Британцы:
- Джордж Мередит
- Сэмюэл Ричардсон
- Джон Голсуорси
- Гилберт Кит Честертон
- Энтони Троллоп
На попытку сделать такой классификатор меня подтолкнул твит @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.
Код можно взять здесь, там же доступен уже обученный классификатор.
Комментарии (20)
Gurklum
18.01.2017 13:15Были ли попытки исключить топонимы? Как следует из списка ошибок классификатора, они, возможно, все же негативно влияют.
По крайней мере, к ним нет того доверия, что к gray/grey и color/colour.Deosis
19.01.2017 06:51Меня больше заинтересовала пара girl/lady.
pro100olga
19.01.2017 09:16Возможно, американские тексты позже написаны? По топ-5 приведенных авторов тяжело оценить.
agee
18.01.2017 14:37Это интересно.
А была ли мысль просто скормить пары синонимов или просто слов, которые пишутся по-разному из американского и британского английского? Например классические tube и subway, ну или всякие color и colour. Или в процессе выделения признаков эти слова и так всплыли вверх?
omruruch
18.01.2017 16:56+2Мне интересно было узнать, справится ли алгоритм самостоятельно в выделении таких слов. Слова типа color и colour, а также слова, типичные для Америки и Великобритании, действительно получились с большими весами.
Wayfarer15
19.01.2017 01:31А если добавить канадский и австралийский английский? Сможет ли алгоритм выявлять принадлежность текста без подобных слов?
ServPonomarev
18.01.2017 15:06+1По отдельным словам — неплохо, но можно пойти намного дальше:
1. Вернуться к токенам. Не переводить слова в нижний регистр, не отлеплять от них пунктуацию. На выходе получим увеличение словаря, разделение имён собственных (как Нью Йорк) и главное — сможем увидеть, с каких слов обычно англичане и американцы фарзу начинают, а какими — заканчивают. Приятно, что это не потребует изменения самой модели.
2. Учитывать n-граммы. Тоже интересно — идиоматические выражения, обороты речи
3. Учитывать контекст. Взять модели спкипграмм, обученные по английским и американским текстам и посмотреть, какие слова встречаются в сильно отличных контекстах (то есть — имеют разный смысл). Это наиболее интересно, как мне думаетсяomruruch
18.01.2017 17:18+1Топонимы и имена достаточно важны для классификатора, у самых популярных типа London, Washington, America большие веса. Я без проверки не могу быть уверена, что это будет полезно. Если проверю, от добавлю в статью, спасибо. В полезности выбора именно первого и последнего слова в предложении у меня сомнения.
Я обучала с биграммами, это не улучшило качества алгоритма, но заняло гораздо больше времени. Выявление таких оборотов — отдельная задача, в которой нужно учитывать грамматику языка, применять стемминг и так далее.
Вы описали объем работ на хорошую PhD.ServPonomarev
18.01.2017 20:16+2на самом деле тут неделя-две счёта, и пара часов на подготовку. Взять Word2Vec, Glove или аналогичную систему, обучить две модели — одну для американского, другую для британского, и сравнить ассоциированные и взаимозаменяемые слова в обоих вариантах. Можно будет много чего интересного увидеть.
Самая сложная часть работы — подготовка обучающих текстов — уже выполнена.
arandomic
18.01.2017 17:21Такими темпами можно углубиться и до семантики/грамматики языка.
<алаверды>
Видел проект по краудсорсинг-разметке грамматических конструкций английского языка. GameWithWords:Which English
Уже неплохо определяется диалект английского языка, которым вы пользуетесь и родной язык, если вы не носитель.
</алаверды>
mephistopheies
18.01.2017 16:50I 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.
а мне вот этот анекдот напомнило
xenohunter
18.01.2017 17:03+2Небольшое отступление: вы учитесь или стажируетесь в Калифорнии или просто живёте в Штатах?
pro100olga
19.01.2017 09:18Очень интересно, спасибо! Судя по списку авторов, тексты в основном конца 19го-начала 20го века. Интересно, сохранилось ли это различие в современной литературе :)
omruruch
19.01.2017 09:44С современной литературой сложно из-за авторских прав. Возможно, я как-нибудь попробую обучить классификатор на газетных статьях, тем более что есть готовые датасеты.
pro100olga
19.01.2017 09:47Мне кажется, с прессой должно быть проще, ведь в каждой стране пресса больше пишет про внутренние дела, чем про внешние. Хотя про Трампа пишут все :)
omruruch
19.01.2017 09:53Имена и топонимы можно удалять, в ситуации с прессой вреда от них больше, чем пользы.
sdi74
«dollars, new, york, girl» — забавно )