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

Блокнот jupyter со всем кодом доступен здесь, а набор данных доступен по этой ссылке.

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

Неконтролируемое машинное обучение

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

Эти алгоритмы демонстрируют самоорганизацию и фиксируют закономерности в виде плотности вероятности. Они интерпретируют необработанные входные данные и делят объекты данных на группы на основе сходства и различия между ними. Такие алгоритмы находят свое применение в кластеризации и обнаружении аномалий.

Аспекты текстовой кластеризации

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

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

Повседневным применением кластеризации текста является поисковая система Google. При поиске слова/фразы Google с помощью алгоритма разбивает неструктурированные данные с веб-страниц и помечает их ключевыми словами из результатов поиска.

Перед реализацией текстовой кластеризации в нашем корпусе (наборе данных) рассмотрим основное различие между кластеризацией и классификацией.

Классификация. Подход к обучению под наблюдением для сопоставления входных данных с выходными на основе некоторых пар входных и выходных данных. Здесь заранее известны такие классы, как положительные или отрицательные предложения. Он классифицирует прогнозируемые значения.

Кластеризация: обучение без учителя, позволяющее разбить корпус на группы (кластеры). Здесь цель состоит в том, чтобы разделить данные таким образом, чтобы похожие точки были вместе в одном кластере, а точки, не похожие на первый кластер, лежали в другом кластере. Определяет группировку неразмеченных данных.

Теперь давайте подробнее остановимся на теоретических аспектах алгоритма, представленного в шорт-листе для указанной задачи.

Алгоритм K-средних

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

Алгоритм принимает немаркированный корпус в качестве входных данных, делит его на k кластеров (значение для k должно быть задано заранее) и продолжает итеративно до тех пор, пока позиция или группы не перестанут показывать движение.

Реализация:

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

  1. Предварительная обработка текста: определение помех и извлечение набора слов, описывающих тему(дескрипторы)
  2. Извлечение признаков: вычисление частоты дескрипторов с использованием TF-IDF
  3. Кластеризация: применение алгоритма к сгенерированным объектам

Предварительная обработка текста:

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

Каждому резюме присваивается «оценка», которая будет использоваться для присвоения меток (положительных или отрицательных) корпусу, и можно наблюдать элементы шума (теги HTML), соответствующие идентификатору 150529.

Шаги, связанные с предварительной обработкой корпуса, включают:

  1. Удаление стоп-слова: некоторые слова, такие как the, any, in, не очень разборчивы и, как правило, безвредны для задач классификации, кластеризации текста и поиска информации.
  2. Стемминг: в лингвистических терминах это определяется как процесс приведения слов к их корневой форме, т. е. [‘есть’, ‘ест’] -> ест. Для этой цели будет использоваться класс PorterStemmer из Natural Language Toolkit.
  3. Удаление шумов и знаков препинания: удаление тегов HTML и знаков препинания, таких как .,?, определенных на английском языке.

Для выполнения упомянутых шагов используйте функции, указанные ниже:

def clean_html(text):
 
 """
 function to clean text from html tags
 :param string text: the text with html tags
 
 return: text without html tags
 """
 
 cleantext = re.compile('<.*?>') # html tag
 cleantext = re.sub(cleantext,' ', text)
 
 return cleantext

def clean_punc(text):
 """
 function to clean text from punctuation marks or special characters
 :param string text: text containing punctuation marks
 
 return: text without punctuations
 """
 cleantext = re.sub(r'[\|/|")|(|#]', r'', text) # special_char
 cleantext = re.sub(r'[.|,|?|!]', r' ', cleantext) # punctuations
 return cleantext

Функции выставления оценок указаны в блокноте jupyter, после выставления оценок и очистки корпус должен напоминать-

Извлечение признаков:

Алгоритмы машинного обучения имеют дело с числовыми данными, в то время как естественный язык в основном представляет собой текст, поэтому стало важно отображать текстовые данные в реальные векторы, такой процесс был назван «Извлечение признаков». Цель этого шага — показать, насколько важно данное слово для набора документов, чтобы закодированные данные могли использоваться алгоритмом.

TF-IDF (термин частотно-обратная частота документа) – это статистическая мера для оценки релевантности слов корпусу. Этот процесс работает путем увеличения веса слова, когда оно часто встречается в документе, и снижения веса, когда оно встречается во многих документах.

Если слово очень распространено и встречается во многих документах, ему будет присвоена оценка, приближающаяся к 0, в противном случае оценка приближается к 1. Оценка TF-IDF может быть рассчитана с использованием приведенной ниже формулы:

Как только слова преобразуются в числа, оценка передается алгоритму. Более глубокое понимание используемых терминов можно найти здесь. Давайте отложим в сторону тяжелое математическое понимание и реализуем эту меру в Python, используя библиотеку sklearn, в два приятных шага.

from sklearn.feature_extraction import TfidfVectorizer
tfidf_vect = TfidfVectorizer()
tfidf = tfidf_vect.fit_transform(df['CleanedText'].values)

Кластеризация:

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

from sklearn.cluster import KMeans
wcss = []
for i in range(1,10):
  kmeans = KMeans(n_clusters=i, init='k-means++', random_state=0)
  kmeans.fit_predict(tfidf)
  wcss.append(kmeans.inertia_)

plt.plot([1, 2, 3, 4, 5, 6, 7, 8, 9], wcss)
plt.xlabel('No of clusters')
plt.ylabel('Values')
plt.show()

В соответствии с кривой 7 было выбрано в качестве значения k (функция критерия) для построения модели, которая передает оценки TF-IDF и определить метки, как описано ниже-

model = KMeans(n_clusters = 7, init = 'k-means++', random_state = 0)
labels = model.fit_predict(tfidf)
print(labels)

Обнаружено, что метки представляют собой список нулей и единиц, которые присвоены корпусу.

df['Cluster_Label'] = labels # assigning labels to text
df.head()

Присвоив метки, давайте посмотрим на несколько обзоров, присвоенных каждому кластеру. Код для этого шага можно найти в блокноте jupyter.

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

Чтобы сделать точный вывод, наблюдают за верхними словами в каждом кластере (дескрипторы).

print("Top terms per cluster:")
order_centroids = kmeans.cluster_centers_.argsort()[:, ::-1]
for i in range(7):
   print("Cluster %d:" % i, end='')
   for ind in order_centroids[i, :7]:
      print(' %s' % tfidf_vect.get_feature_names()[ind], end='')
      print()

Как и ожидалось, кластеры перекрываются. Рассмотрим кластер 2 и кластер 5 в качестве примера, они пересекаются из-за присутствия слова «хорошо». Одни и те же слова, описывающие корм для собак и кошек, встречаются в кластерах 3 и 6.

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

Оценка кластера

Алгоритмы кластеризации оцениваются статистически с помощью оценки силуэта или индекса Данна. Выбранный корпус оценивался по баллам силуэта.

Показатель силуэта. Этот показатель находится в диапазоне от -1 до 1 и показывает, насколько хорошо образцы сгруппированы по отношению к другим образцам. Оценка, приближающаяся к 1, указывает на плотные кластеры, а оценка, приближающаяся к 0, указывает на перекрывающиеся кластеры.

Математически для среднего расстояния внутри кластера (a) и среднего расстояния до ближайшего кластера (b) оценка рассчитывается как:

             silhouette_score = (b-a)/max(a, b)

Код для вычисления оценки силуэта с использованием библиотеки sklearn с использованием евклидова расстояния в качестве метрики расстояния приведен ниже.

from sklearn import metrics
from sklearn.metrics import silhouette_score
s_score = silhouette_score(tfidf, labels, metric='euclidean')

Бинго! Оценка приближается к 0, что статистически завершает перекрывающиеся кластеры. Диаграмма рассеяния (показана ниже) следовала общей тенденции и представляла собой прямую линию, параллельную оси Y.

import matplotlib.pyplot as plt
list_00 = tfidf[labels == 0][:, 0].toarray()[:, 0]
list_01 = tfidf[labels == 0][:, 1].toarray()[:, 0]
list_10 = tfidf[labels == 1][:, 0].toarray()[:, 0]
list_11 = tfidf[labels == 1][:, 1].toarray()[:, 0]
plt.scatter(list_00, list_01, s = 5, c = 'red', label = '0')
plt.scatter(list_10, list_11, s = 5, c = 'blue', label = '1')
plt.xlim([-0.1, 0.1])
plt.legend()
plt.show()

Выводы:

  1. Кластеризация текста — это подход к обучению без учителя, при котором сходные точки объединяются в одну группу.
  2. Для кластеризации документов с контекстуальным сходством; евклидово расстояние служило метрикой расстояния, k - критериальной функцией, а KMeans - жадным, неконтролируемым и основанным на центроиде алгоритмом.
  3. Оптимальное значение k=7 было определено с помощью кривой локтя.
  4. Оценка силуэта приближалась к 0, а график рассеяния представлял собой прямую линию, параллельную оси Y. Из чего делается вывод, что кластеры перекрываются

Ссылки:

Алгоритмы кластеризации на основе Centroid: https://ijcsit.com/docs/Volume%205/vol5issue06/ijcsit2014050688.pdf

Понимание TF-IDF для машинного обучения: https://www.capitalone.com/tech/machine-learning/understanding-tf-idf/

Метод локтя: https://www.oreilly.com/library/view/statistics-for-machine/9781788295758/c71ea970-0f3c-4973-8d3a-b09a7a6553c1.xhtml

Индекс Данна для оценки кластеризации K-средних: https://python-bloggers.com/2022/03/dunn-index-for-k-means-clustering-evaluation/

Весь код доступен из этого репозитория Github.