Введение

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

В этой статье мы сосредоточимся на кластеризации данных и уменьшении размерности с использованием методов обучения без учителя. Мы будем использовать PCA для уменьшения размерности и различные кластеризации для сравнения результатов. Этот блог просто дает обзор всего процесса, который можно найти на GitHub по этой ссылке;



Описание данных

Мы будем работать с реальным набором данных из репозитория машинного обучения UCI. Доступ к данным можно получить из здесь. Набор данных содержит обзоры туристических направлений в Восточной Азии. Каждый отзыв оценивается по шкале от 0 до 4, где 4 — отлично, а 0 — ужасно. Набор данных содержит 11 атрибутов, включая идентификатор пользователя, написавшего отзыв. Наша цель — сгруппировать обзоры на основе их сходства и уменьшить размерность набора данных для лучшей визуализации.

Предварительная обработка данных

Прежде чем мы начнем с кластеризации и уменьшения размерности, мы предварительно обработаем данные. Мы заметили, что некоторые столбцы имели аномальное распределение и были смещены в одну сторону. Для нормализации данных мы использовали алгоритм MinMaxScaler, который масштабирует данные от 0 до 1. Мы также использовали PCA для уменьшения размерности набора данных.

#read the dataset
df = pd.read_csv("tripadvisor_review.csv")

#normalize the data
mms = MinMaxScaler()
mms.fit(df)
df = mms.transform(df)

#reduce the dimensionality of the dataset
n_components = df.shape[1]
pca = PCA(n_components=n_components, random_state=SEED)
pca.fit(df)
pca_df = pca.transform(df)

Объясняемый коэффициент дисперсии

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

Коэффициент объясненной дисперсии является мерой того, сколько информации (дисперсии) можно отнести к каждому основному компоненту. Мы обнаружили, что большая часть дисперсии данных может быть закодирована в 7 из 10 измерений, а более 72% дисперсии может быть закодировано в 3 измерениях. Поскольку мы можем нормально работать в 3D (но не для этого блога), предполагается, что мы можем ожидать увидеть часть базовой структуры в 3D-визуализации, хотя некоторая информация (менее 25%) будет скрыта. Ниже приведен фрагмент, используемый для получения представления компонентов вместе с окончательным уменьшением размеров.

#determine the explained variance ratio
# get variance/data representability of each of the component
for i in range(n_components):
    first_n = pca.explained_variance_ratio_[0:i+1].sum()*100
    print(f'Percent variance explained by first {i+1} components: {round(first_n , 4)}%')

#reduce the dataset to 2 dimensions using PCA and visualize
pca = PCA(n_components=2, random_state=SEED)
pca.fit(df)
traindf = pca.transform(df)
plt.title("2D plot of the data representation")
sns.scatterplot(traindf[: , 0] , traindf[: , 1])

Ниже приведен снимок экрана, показывающий дисперсию для каждого компонента результатов модели PCA.

Кластеризация данных

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

  1. Метод кривой локтя.

Мы подгоним наш алгоритм кластеризации, используя несколько различных значений k, где k — количество кластеров в диапазоне от 2 до 15. Для каждого значения k мы будем оценивать результаты кластеризации, используя среднюю сумму квадрата показателя расстояния. Мы нанесем результаты на каждое значение k и определим, какое количество кластеров дает наилучшие результаты. Некоторые шаги и фрагменты кода показаны ниже.

  • Инициализировать пустой список для хранения Sum_of_squared_distances для каждого значения k.
  • Для каждого значения k выполните алгоритм кластеризации k-средних для данных и рассчитайте Sum_of_squared_distances.
  • Добавить Sum_of_squared_distances к списку.
  • Постройте график зависимости Sum_of_squared_distances от количества кластеров, k.
  • Определите точку изгиба на графике, которая является оптимальным количеством кластеров.
Sum_of_squared_distances = []
for k in range(1,15):
    km = KMeans(n_clusters=k, init='k-means++')
    km = km.fit(traindf)
    Sum_of_squared_distances.append(km.inertia_)

plt.plot(range(1,15), Sum_of_squared_distances, 'bx-')
plt.xlabel('k')
plt.ylabel('Sum_of_squared_distances')
plt.title('Elbow Method For Optimal k')
plt.show()

2. Использование метода оценки силуэта

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

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

max_k=15

sil_scores=[]
for i in range(2, max_k+1):
    clusterer = GaussianMixture(n_components=i, random_state=SEED, n_init=5)
    clusterer.fit(traindf)

    #Predict the cluster for each data point
    preds = clusterer.predict(traindf)

    #Find the cluster centers
    centers = clusterer.means_

    #Calculate the mean silhouette coefficient for the number of clusters chosen
    score = silhouette_score(traindf, preds)
    sil_scores.append(score)
    
sil_scores= pd.Series(sil_scores, index= range(2,max_k+1))
max_score= sil_scores.max()
n_clusters= sil_scores.idxmax()
print('Max Silhouette Score: {:.3f}'.format(max_score))
print('Number of clusters: {}\n'.format(max_k))

print('First 3 Silhouette Scores')
print(sil_scores[0:3])

Сравнение результатов методов оценки силуэта и кривой локтя

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

Метод оценки силуэта показывает, что максимальная оценка достигается, когда мы используем 2 (это отправная точка для анализа, поэтому игнорируется) кластеров, которые затем доходят до 4. Таким образом, мы будем соответствовать гауссовой смешанной модели (GMM), используя 4 кластера. Затем мы раскрасим каждый кластер по-разному и снова визуализируем данные в двух измерениях, используя первые два компонента. Это позволит нам увидеть, как интересующее нас свойство распределяется между нашими кластерами.

С другой стороны, метод кривой локтя показывает, что оптимальное количество кластеров может варьироваться от 2 до 4. Поскольку разница между методами оценки силуэта и кривой локтя незначительна, мы будем обобщать от 2 до 5 в качестве наших предпочтительных номеров кластеров. . Исходя из этих результатов, мы будем использовать k как 2, 3 и 4, поскольку они кажутся лучшими.

Сравнение результатов с использованием выбранных кластеров

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

  1. Использование модели GMM
f = plt.figure(figsize=(16 ,10))
plt.title("Comparison of various Cluster points using Gausian Mixture method" , fontsize =24)
f.add_subplot(2, 2, 1)
for i in [2,3,4 , 5]:
    model_i = GaussianMixture(n_components=i, random_state=2021, n_init=5)
    model_i.fit(traindf)
    label_i = model_i.predict(traindf)
    f.add_subplot(2, 2, i-1)
    sns.scatterplot(traindf[:, 0], traindf[:, 1] , c = label_i , label="n_cluster-"+str(i))
    plt.legend()
plt.show()

На рисунке ниже показаны результаты, полученные с помощью модели GMM.

Используя этот метод, наилучшее количество кластеров кажется кластером 3 и кластером 4.

2. Алгоритм SpectralClustering

3. Метод алгоритма агломеративной кластеризации

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

Чтобы определить оптимальное количество кластеров для AgglomerativeClustering, мы создаем дендрограмму, показывающую иерархическую структуру кластеров. Дендрограмма может помочь нам определить соответствующее количество кластеров, визуально проверяя высоту вертикальных линий, которые представляют расстояние между кластерами. Фрагмент кода показан ниже

def dendrogramPlot(model, **kwargs): 
    '''
    IT creates a dendogram plot using Agglomerative Clustering algorithm
    '''
    counts = np.zeros(model.children_.shape[0])

    n_samples = len(model.labels_)
    for i, merge in enumerate(model.children_):
        current_count = 0
        for child_idx in merge:
            if child_idx < n_samples:
                current_count += 1  # leaf node
            else:
                current_count += counts[child_idx - n_samples]
        counts[i] = current_count
    linkage_matrix = np.column_stack([model.children_, model.distances_,counts]).astype(float)
    dendrogram(linkage_matrix, **kwargs)  

ClusteringModel = AgglomerativeClustering(distance_threshold=0, n_clusters=None)
# setting distance_threshold=0 ensures we compute the full tree.

ClusteringModel = ClusteringModel.fit(traindf)

plt.figure(figsize=(25,10))
plt.title('Clustering Dendrogram for 4 levels')
dendrogramPlot(ClusteringModel, p=4, truncate_mode='level')                    
plt.xlabel("Number of points in node")
plt.show()

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

Графики дендрограмм, созданные с использованием алгоритма иерархической агломерационной кластеризации, предполагают, что оптимальное количество кластеров равно 4, поскольку дендрограммы уровня 4 и 5 показывают четкое разделение между кластерами. Мы можем использовать эту информацию для создания модели с 4 кластерами и визуализировать результаты с помощью графика предсказанных меток классов.

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

Анализ модели и результаты

В этом анализе мы будем сравнивать производительность различных алгоритмов кластеризации на двух разных кластерах (кластеры 3 и 4). Чтобы оценить производительность каждого алгоритма, мы будем использовать две метрики: оценку Дэвиса-Булдина и оценку силуэта. Вся структура кода для этого сравнения и визуализации доступна в записной книжке GitHub.

Кластер 3 Результаты

Ниже приведены результаты, полученные для кластера 3:

          RESULTS METRICS COMPARISON FOR USING 3 CLUSTERS.
//=========================[]==============[]==================\\
|| Algorithm               || Davies Score || Silhouette Score ||
|]=========================[]==============[]==================[|
|| MiniBatchKmeans         || 0.883340     || 0.396502         ||
|| Kmeans++                || 0.888266     || 0.396317         ||
|| Gaussian_mixture        || 0.952638     || 0.388971         ||
|| SpectralClustering      || 0.909897     || 0.378901         ||
|| SpectralClusterer       || 0.879011     || 0.377372         ||
|| KMedoids_cosine         || 0.848656     || 0.366039         ||
|| AgglomerativeClustering || 0.938955     || 0.336498         ||
\\=========================[]==============[]==================//

MiniBatchKmeans был наиболее эффективным алгоритмом, когда он основывался на оценке силуэта, за которой следовали Kmeans, а затем смесь Гаусса. Этот кластер, кажется, имеет разные результаты в отношении того, какая модель является лучшей.
Для этой цели MinibatchKmeans и Kmeans++ будут выбраны как лучшая модель, поскольку они были первыми и вторыми соответственно при использовании оценки силуэта и вторыми и третьими соответственно, когда с помощью индекса Дэвиса

Кластер 4 Результаты

Ниже приведены результаты, полученные при использовании 4 кластеров.

            RESULTS METRICS COMPARISON FOR USING 3 CLUSTERS.
//=========================[]==============[]==================\\
|| Algorithm               || Davies Score || Silhouette Score ||
|]=========================[]==============[]==================[|
|| Gaussian_mixture        || 0.776347     || 0.413012         ||
|| MiniBatchKmeans         || 0.813552     || 0.411235         ||
|| Kmeans++                || 0.834765     || 0.409727         ||
|| KMedoids_cosine         || 0.851633     || 0.372040         ||
|| SpectralClustering      || 0.959275     || 0.352476         ||
|| AgglomerativeClustering || 1.031960     || 0.313524         ||
|| SpectralClusterer       || 4.206309     || 0.226269         ||
\\=========================[]==============[]==================//

Из приведенной выше таблицы видно, что смешанная модель Гаусса имеет самый низкий показатель Дэвиса, в то время как MiniBatchKmeans имеет самый высокий показатель силуэта. В целом, используя различные методы кластеризации, мы смогли получить хорошие результаты. Результаты показали точную метрику в каждом алгоритме, и, основываясь на производительности каждого алгоритма, мы можем выбрать MiniBatchKmeans и Kmeans++ в качестве лучших моделей для кластера 3, а гауссовскую смесь и MiniBatchKmeans в качестве лучших моделей для кластера 4.

Заключение

В заключение, этот анализ показывает, что методы обучения без учителя, такие как кластеризация данных, полезны для анализа и кластеризации многомерных данных. Мы изучили различные алгоритмы кластеризации и применили их к реальному набору данных отзывов об отелях. Кластеризуя отзывы, мы можем выявить закономерности и сгруппировать похожие отзывы. Наш анализ показывает, что алгоритмы MiniBatchKmeans и Kmeans++ были наиболее эффективными для кластеров 3 и 4 на основе оценки силуэта и индекса Дэвиса-Булдина.

Мы также заметили, что качество обзоров в Кластере 4 в целом было выше, чем в Кластере 3, с более высокой оценкой силуэта и более низким индексом Дэвиса-Булдина. Ярлыки, присвоенные каждому отзыву, давали полезную информацию об общем качестве отелей: 4 балла означают отличные отзывы, а 0 — ужасные отзывы. Неконтролируемые методы обучения, такие как кластеризация, могут быть мощным инструментом для анализа многомерных данных и извлечения значимой информации.

Код, используемый для блога, можно найти в следующем репозитории.



Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.