Приложение метода k-средних. Нахождение кластеров связанных слов

Здравствуйте и вновь добро пожаловать на занятия по теме «Кластерный анализ и машинное обучение без учителя на языке Python».

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

Прежде всего мы преобразуем данные в терм-документную матрицу, в которой каждая строка представляет собой слово, а каждый столбец – документ. Можно рассматривать каждое слово в качестве примера, а количество его появлений в конкретном документе – в качестве признака. Тогда у нас получится матрица размерностью NxD, где N – размер словаря, а D – количество документов.

Следующий этап – мы преобразуем терм-документную матрицу в матрицу TF-IDF. TF (term frequency) – это частота слов, а IDF (inverse document frequency) – обратная частота документа. Причина, по которой мы должны произвести эту операцию, состоит в том, что простой подсчёт слов часто не даёт истинной картины. К примеру, вы можете предположить, что часто встречающееся слово является важным. Например, вновь и вновь встречая в документе слово «нейтрон», можно предположить, что документ посвящён физике. Но ведь и слова вроде «в» и «на» также являются очень распространёнными словами! Они встречаются множество раз и во множестве различных не взаимосвязанных документов. Потому TF-IDF и используется – частота упоминаемости слова показывает, насколько оно важно, но при этом необходимо учитывать и показатель обратной частоты документа, поскольку если слово встречается во многих различных документах, то, вероятно, оно не имеет особого значения.

Далее мы должны преобразовать данные в двухмерный вид, используя метод уменьшения размерности, который называется t-SNE – методом нелинейного снижения размерности и визуализации многомерных переменных. Преобразование данных в двухмерный вид позволяет наглядно отобразить их, используя диаграмму рассеяния. О методе t-SNE и других методах визуализации данных вы узнаете в продолжении этого курса, которое называется «Глубокое обучение без учителя на языке Python».

Выполнив эти два предварительных этапа, мы переходим к процедуре использования метода k-средних – я скопировал её из предыдущего кода. В этом курсе K выбрано равным размеру словаря, поделённому на 10. Это не было продиктовано какой-то конкретной причины, просто я навскидку предположил, что каждый кластер должен иметь в среднем около десятка слов.

В самой функции k-mean сделано два изменения. Во-первых, это сохранение графика. Поскольку у нас большой массив данных, то и график будет огромным, и нам необходимо изменить масштаб графика, чтобы увидеть что-либо значимое. Кроме того, сам файл также будет очень большим – примерно 10 мегабайт, так что перемещение по графику будет происходить крайне медленно. Именно поэтому мы сохраняем график, вместо того, чтобы просто вывести его на экран.

Далее, я написал специальную функцию annotate1 для отображения подписи к каждому слову. Поскольку слов будет много – около 2 000 – то мы должны удостовериться, что на графике подписи не будут накладываться одна на другую – иначе мы ничего не разберём. По этой причине положения слов будут случайным образом немного смещаться, чтобы избежать наложения подписей.

random_colors = np.random.random((K, 3))

colors = R.dot(random_colors)

plt.figure(figsize=(80.0, 80.0))

plt.scatter(X[:,0], X[:,1], s=300, alpha=0.9, c=colors)

annotate1(X, index_word_map)

# plt.show()

plt.savefig(“test.png”)

И последнее сделанное мною изменение состоит в том, чтобы просто распечатать слова в каждом кластере. Думаю, так будет проще увидеть, какие, по результату работы метода k-средних, считаются взаимосвязанными, нежели пытаться рассмотреть это на графике.

Для этого мы должны вначале указать «жёсткие» идентификаторы кластеров. Не забывайте, что вначале мы использовали более общую форму, именуемую «мягким» методом k-средних. Сделать это можно, использовав функцию argmax по отношению к матрице соответствий вдоль каждой строки. После этого необходимо создать словарь, указывающий на принадлежность к кластеру всех слов, относящихся к этому кластеру. Собрав все эти слова, мы можем пропустить их через словарь и вывести на экран один за другим все списки слов, хранящиеся теперь в словаре в качестве значений.

    # print out the clusters

    hard_responsibilities = np.argmax(R, axis=1) # is an N-size array of cluster identities

    # let’s “reverse” the order so it’s cluster identity -> word index

    cluster2word = {}

    for i in xrange(len(hard_responsibilities)):

      word = index_word_map[i]

      cluster = hard_responsibilities[i]

      if cluster not in cluster2word:

        cluster2word[cluster] = []

      cluster2word[cluster].append(word)

    # print out the words grouped by cluster

    for cluster, wordlist in cluster2word.items():

      print(“cluster”, cluster, “->”, wordlist)

Теперь посмотрим, что получится. Соответствующий файл в репозитарии называется book.py.

Итак, видим диаграмму, на которой можем изучить получившиеся кластеры, некоторые из которых вполне осмысленны. Например, слова «самопоклонение», «суеверие» и «антибиблейский» находятся в одном кластере. Слова «последовательность», «древо» и «строка» также находятся в одном кластере. Есть и компьютерная терминология – слова «контрмера», «угроза», «уязвимость», «анализ» относятся к сфере кибербезопасности и также состоят в одном кластере. Далее мы видим ещё один компьютерный кластер со словами «многозадачность», «кора головного мозга», «встроенный», «ветвь», «масштабируемый», «DSP», «ядро». Ещё один любопытный кластер – со словами «брак», «жена», «муж», «домашняя работа», «обязательство». Есть и что-то вроде кластера, посвящённого физике, который имеет слова «релятивистский» и «рамочный».

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

Теперь давайте посмотрим на действительные принадлежности слов к кластерам. Мы видим, что каждое слово принадлежит к какому-то из кластеров. Любопытен, к примеру, кластер 1 со словами «операция», «сеть», «микропроцессор», «эффективность» – все эти слова взаимосвязаны. Кластер 2 имеет слова «вычисление», «продвинутый», «нейронный», «нечёткий», «интеллект» и относится к сфере машинного обучения. Интересен и кластер 7, который, похоже, имеет религиозную направленность и слова «иудаизм», «христианство», «вера», но далеко не все слова из него имеют смысл, поскольку там же встречаются и слова «численный» и «алгебраический». А вот кластер 8 кажется состоит из вполне взаимосвязанных слов вроде «гостеприимство», «туризм» и «танец».

Определённо, стоит рассмотреть содержимое всех кластеров. Их там много – около двух сотен – и вы сможете убедиться, что большинство из них имеют смысл, хотя некоторые – нет.

Андрей Никитенко
Андрей Никитенко
Задать вопрос эксперту
Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Share via
Copy link