Продолжая наш анализ покемонов, мы вспоминаем, что когда мы строили матрицу покемонов в части 1, мы закодировали набор движений покемона как битовый вектор. В то время мы оправдывали это как правильное кодирование, поскольку оно соответствовало внутренней структуре ходов. Когда мы выполнили Анализ основных компонентов в части 2, этой кодировки было достаточно для первоначального понимания отношений между покемонами. Настало время проанализировать сами движения покемонов и найти среди них структуру.

Мы сделаем следующее предположение о том, как создаются Moves. Во-первых, что существуют различные «аспекты» Движений, подразумевающие некоторые из их свойств; значение этих аспектов, как и значение Основных Компонентов в последней главе, можно интерпретировать только путем изучения. Мы надеемся, что они будут соответствовать нашим интуитивным классам приемов, например, что Double-Edge и Wood Hammer похожи в отличие от Slam и Solar Beam. Эти аспекты представляют собой распределения вероятностей по функциям, присваивая более высокую вероятностную массу функциям, которые лучше «принадлежат» аспекту (например, имеющие повреждения от отдачи).

Во-вторых, мы предполагаем, что Движение представлено как комбинация этих аспектов, интерпретируемая либо как их взвешенная сумма, либо как распределение вероятностей по аспектам.

Эта установка обычно рассматривается в обработке естественного языка как особый тип тематической модели; ранее упомянутые аспекты Move аналогичны темам в документе. При анализе тематической модели и, в частности, модели скрытого распределения Дирихле (LDA), мы предполагаем, что значение документа может быть выведено из его облака слов — часто называемого в этом контексте набором слов — и что пунктуация и порядок слов можно отбросить. В модели LDA предполагается, что слова в текстовом документе взяты из смеси вероятностных распределений в зависимости от тем, о которых идет речь в документе: для каждого слова сначала выбирается тема, а затем слово из этой темы.

В нашем случае можно было бы ожидать, что будет тема приоритетных ходов, в которой условная вероятность ℙ[ход|тема] для таких ходов, как Акваструя, Быстрая атака и Подкрадывание к тени, велика; или тема Особые приемы с PP 10, силой не менее 90 и точностью 100, в которой выбираются такие приемы, как Удар молнии и Ледяной луч.

Конечно, как неконтролируемый метод, темы, определенные в нашей модели, не будут идеально соответствовать тому, как мы будем группировать Движения вместе, как люди — и это нормально! Мы надеемся, что темы будут достаточно хорошо соответствовать тому, что мы ожидаем, и что они, кроме того, будут полезны для последующих задач, о которых мы поговорим в следующей статье!

Как только мы разработаем нашу модель темы, мы обсудим, как интерпретировать темы, но сначала, чтобы обнаружить эти взаимосвязи, нам нужно будет сделать что-то лучшее, чем кодирование ходов как самих битовых векторов — мы собираемся нужна дополнительная информация.

У каждого движения есть несколько определяющих особенностей, как у покемонов! Для примера возьмем всю описательную информацию о ходу Thunderbolt:

Name: Thunderbolt
Num: 85
Accuracy: 100
Base Power: 90
Category: Special
PP: 15
Priority: 0
Flags: Blocked by Protect, reflected by Mirror Coat
Secondary: 10% chance of paralysis
Target: One target
Type: Electric
Contest type: Cool
Description: Has a 10% chance to paralyze the target
Short description: 10% chance to paralyze the target

Если раньше вам нравилось бит-векторное кодирование, теперь оно вам действительно понравится. Мы можем закодировать ход битовым вектором всех соответствующих полей хода: его точности, базовой мощности, категории, PP, приоритета, флагов, вторичного, цели, типа и описания. Для полей без описания мы кодируем каждую возможную опцию в виде битового вектора: 504 различных механики, которые может иметь Движение, от 5 PP Гидронасоса до способности Тысячи Стрел игнорировать иммунитет Земли.

Описания мы обрабатываем аналогичным образом, используя метод, очень распространенный в обработке естественного языка. Мы кодируем эти описания как мешок слов, обобщение битового вектора, в котором мы считаем каждый раз, когда каждое слово появляется в описании. Этот процесс в решающей степени зависит от определения слова, которое является понятием, которое лингвистически и практически трудно определить — в нашем случае, поскольку мы работаем на английском языке и с текстом, который не слишком плохо себя ведет, слово должно быть последовательностью символов, разделенных пробелом, и с удаленными следующими специальными символами: ',.;:)(. На практике может быть лучше вместо этого установить белый список для символов, но для любого фиксированного набора данных выбор белого списка эквивалентен к принятию решения о черном списке. Подразумеваемый белый список для этого набора данных — это буквы, цифры и специальные символы %-/+*. В соответствии с этим определением имеется 1090 уникальных слов, от "the", встречающегося 1942 раза, до 281 слова. которые появляются только один раз, например, джунгли.

Таким образом, особенностями Move являются его определяющие эффекты и механика, такие как битовый вектор и набор слов, которые появляются в его описании, что дает матрицу 666 на 1490 для обучения тематической модели. В оставшейся части этой статьи я буду говорить «слово» для обозначения столбца в этой матрице; с этого момента нам не нужно будет различать имена функций и слова в описании, и это будет более точно соответствовать обычному описанию тематической модели.

Одним из недостатков тематической модели является то, что вам необходимо заранее указать количество тем. Это можно сделать только в специальной исследовательской манере: давайте пока возьмем 20 тем. Если нам не нравятся выходные данные этой модели, изменение количества тем будет первой ручкой, с которой мы возимся.

Выходными данными тематической модели являются в основном две матрицы: матрица слов темы (20 × 1490), представляющая ℙ [тема | слово], и матрица тем документа (666 × 20), представляющая ℙ [тема | документ]; первый помогает определить, что означают темы, а второй сообщает, какие темы представлены в каждом документе.

Очень часто в ссылках на тематические модели темы описываются словами в порядке убывания ℙ[тема|слово] — это неверно как с философской, так и с практической точки зрения. Если мы хотим знать, из чего состоит тема, мы задаем себе вопрос: «Если я прочитаю что-то в этой теме, что я должен ожидать увидеть?» Это высказывание ℙ[слово|тема].

На практике возникает проблема так называемых «стоп-слов»; слова, которые имеют мало семантического значения (например, «тот», «из», «или»). Это проблематично для тематической модели: во-первых, эти слова имеют порождающую структуру, которая отличается от более содержательных слов, поскольку они почти ближе к пунктуации по смыслу. Во-вторых, поскольку они очень распространены, ℙ[тема|стоп-слово] обычно заметна для большинства тем. Если тема такова, что есть слова, которые сильно ее подразумевают, то это не проблема, но вполне возможно, что ℙ[тема|слово] будет меньше 1/20 для каждого слова и позволит преобладать стоп-словам. .

В самом деле, давайте рассмотрим одну тему из нашей модели, учитывая 10 слов и движений, которые максимизируют ℙ[тема|слово] и ℙ[тема|ход]:

Topic  2
Words: 
	 the :  0.08832
	 turn :  0.04595
	 move :  0.04128
	 on :  0.03569
	 and :  0.03432
	 this :  0.03338
	 is :  0.03051
	 if :  0.0286
	 user :  0.02693
	 a :  0.02279
Moves: 
	 fly :  0.9875
	 dive :  0.98603
	 dig :  0.98603
	 frenzyplant :  0.97121
	 rockwrecker :  0.97121
	 gigaimpact :  0.97121
	 blastburn :  0.97031
	 hydrocannon :  0.97031
	 hyperbeam :  0.97031
	 prismaticlaser :  0.97031

Глядя только на слова, вообще не понятно, что эта тема пытается описать! Тем не менее, глядя на ходы, мы можем сказать, что эта тема имеет смысл: она четко описывает двухходовые движения, которые требуют либо хода зарядки (Fly, Dig), либо хода перезарядки (Frenzy Plant, Hyper Beam). Если вместо этого мы ранжируем термины по ℙ[слово|тема], мы получаем гораздо лучшее описание:

Topic  2
Words:
	 charges: 0.940620
	 executes: 0.940620
	 herb: 0.940620
	 completes: 0.940620
	 flags: charge; 1: 0.940620
	 self: volatileStatus; mustrecharge: 0.913640
	 following: 0.913640
	 must: 0.913640
	 flags: recharge; 1: 0.913640
	 recharge: 0.837500
Moves: 
	 fly :  0.9875
	 dive :  0.98603
	 dig :  0.98603
	 frenzyplant :  0.97121
	 rockwrecker :  0.97121
	 gigaimpact :  0.97121
	 blastburn :  0.97031
	 hydrocannon :  0.97031
	 hyperbeam :  0.97031
	 prismaticlaser :  0.97031

Однако в целом у этого подхода есть свои недостатки. Текстовые документы нередко содержат редкие слова или слова с ошибками, тесно связанные с определенной темой. Есть несколько способов справиться с этим: можно исключить все слова, которые не встречаются определенное количество раз (либо из этих списков слов, либо из анализа в целом), или можно смягчить вычисление ℙ[слово|тема] с помощью включая доверительный интервал.

Критерий Стьюдента является стандартным способом получения доверительного интервала. Требуется оценка среднего значения (вычисленное ℙ[слово|тема]), дисперсии (поскольку ℙ[слово|тема] распределено Дирихле, дисперсия составляет приблизительно ℙ[слово|тема](1-ℙ[слово|тема ])) и количество наблюдений (общее количество раз, когда функция появляется во всех ходах). С их вычислением можно вместо этого сортировать слова на основе нижнего предела доверительного интервала для ℙ[слово|тема].

В реальных наборах данных стоп-слова обычно обрабатываются путем строгого удаления через списки стоп-слов. Я нахожу это крайне неудовлетворительным с философской точки зрения. Во-первых, язык — это постоянно развивающийся инструмент, поэтому списки стоп-слов всегда будут неверными — dis редко встречается в списке стоп-слов, а this — почти всегда. Во-вторых, что является стоп-словом, а что нет, сильно зависит от набора данных и проблемы; вы часто считается стоп-словом, но я обнаружил, что оно очень полезно для анализа тематических моделей, обученных в Википедии, где оно идентифицирует страницы о песнях. В-третьих, стоп-слова по своей природе зависят от языка, и поэтому их создание требует больших затрат; если ваши методы требуют удаления стоп-слов, и вы работаете на языке (или диалекте) без легкодоступного списка стоп-слов, вам не повезло.

Оказывается, улучшение между ранжированием ℙ[слово|тема] и ℙ[тема|слово] иногда можно использовать для создания управляемого данными (но все же специального!) описания стоп-слов. В частности, стоп-слова резко меняются в рейтинге между этими двумя системами, поэтому список стоп-слов может быть создан путем анализа изменений в рейтинге.

В любом случае 20 тем нашей модели кажутся довольно тесными. Такие приемы, как Aura Sphere, Bullet Punch и Slam, сгруппированы в теме 1, а такие приемы, как Trick и Water Shuriken, сгруппированы в теме 9. Скорее всего, просто недостаточно тем для описания всех различных классов приемов. которые существуют. Мы завершим эту статью, увеличив количество тем до 60, удалив стоп-слова, определенные этой моделью, а затем изучим темы в новой модели, запущенной на очищенных данных.

Вот описания каждой десятой темы, определенной нашей новой моделью (загляните в блокнот Jupyter, чтобы изучить полную модель и попробовать сами!):

Topic  0
Words: 
	 raise :  0.73941
	 heal: 1 :  0.70799
	 heal: 2 :  0.65454
	 secondary: self; boosts; spe; 1 :  0.57579
	 secondary: self; boosts; spa; 1 :  0.44497
Moves: 
	 chargebeam :  0.61229
	 fierydance :  0.40577
	 flatter :  0.38524
	 meteormash :  0.29398
	 doubleteam :  0.27497

Topic  10
Words: 
	 basePower: 70 :  0.75706
	 secondary: volatileStatus; confusion :  0.74688
	 confuse :  0.47798
	 basePower: 75 :  0.35326
	 doubles :  0.15786
Moves: 
	 dizzypunch :  0.94825
	 boltbeak :  0.91806
	 fishiousrend :  0.73784
	 diamondstorm :  0.67699
	 boltstrike :  0.64442

Topic  20
Words: 
	 more :  0.5081
	 result :  0.44497
	 120 :  0.36646
	 weight :  0.28042
	 60 :  0.19581
Moves: 
	 quash :  0.6746
	 heatcrash :  0.66714
	 electroball :  0.66439
	 heavyslam :  0.64363
	 gyroball :  0.29317

Topic  30
Words: 
	 typeless :  0.70799
	 types :  0.32481
	 type :  0.26893
	 copied :  0.181
	 include :  0.14959
Moves: 
	 reflecttype :  0.98388
	 soak :  0.36077
	 magicpowder :  0.35143
	 conversion :  0.24423
	 electrify :  0.22328

Topic  40
Words: 
	 recoil :  0.8188
	 recoil: 100 :  0.65454
	 recoil: 33 :  0.65454
	 33% :  0.51437
	 less :  0.45537
Moves: 
	 doubleedge :  0.96927
	 woodhammer :  0.96927
	 headcharge :  0.86724
	 submission :  0.85934
	 bravebird :  0.85476

Topic  50
Words: 
	 boosts: def; 1 :  0.8188
	 boosts: spd; 1 :  0.77652
	 2 :  0.73822
	 stages :  0.72812
	 defense :  0.70986
Moves: 
	 cosmicpower :  0.94825
	 amnesia :  0.94216
	 cottonguard :  0.93854
	 defendorder :  0.8102
	 calmmind :  0.75486

Что вы думаете? В следующей части этой серии мы будем использовать эти темы для измерения расстояний между покемонами и выявления кластеров.