K-Means - это простой для понимания и часто используемый алгоритм кластеризации. Этот метод обучения без учителя начинается со случайного определения k центроидов или k средних. Затем он генерирует кластеры, итеративно выполняя следующие две задачи:

  • Каждая точка данных назначается кластеру таким образом, что она находится ближе к своему собственному центру кластера, чем любой другой центр кластера. Другими словами, евклидово расстояние каждой точки данных с центроидами минимально для ее собственного кластера.
  • Для каждого кластера рассчитывается новый «центр кластера», который представляет собой среднее арифметическое всех точек, принадлежащих кластеру.

Эти две задачи повторяются до тех пор, пока не произойдет одно из следующего:

  • Сумма квадратов евклидовых расстояний для всех точек данных сведена к минимуму.
  • Итерации достигают предопределенного предела

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

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

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

Вот пошаговое руководство по созданию взвешенных кластеров K-средних с использованием Python 3.

Шаг 1. Импортируйте все библиотеки и сгенерируйте случайные образцы для упражнения. В этом случае я создаю капли для доли расходов за год в двух категориях и асимметричное распределение для общих годовых расходов клиента.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()  # for plot styling
from sklearn.cluster import KMeans
from pandas import DataFrame
import random
from sklearn.datasets.samples_generator import make_blobs
from scipy.stats import skewnorm
X, y = make_blobs(n_samples=5000, centers=4, n_features=2, random_state=25)
df = DataFrame(dict(Pct_Spend_in_Organic=(X[:,0])+10, Pct_Spend_in_Local=(X[:,1])+10))
df['Total_Spend']=(skewnorm.rvs(1000,size=5000)*5000)+100
ax=df.reset_index().plot(x='index',y="Total_Spend",kind="hist")

Шаг 2. Визуализируйте входные данные в виде диаграммы рассеяния.

plt.style.use('default')
x=np.array(df['Pct_Spend_in_Local'])
y=np.array(df['Pct_Spend_in_Organic'])
plt.figure(figsize=(15, 10))
plt.scatter(x, y, s=5, cmap='viridis',c='orange',label='Spend in Organic Products')
plt.title('Pct Spend in Local vs Organic Products',fontsize=18, fontweight='bold')
plt.xlabel('Pct Spend in Local',fontsize=15)
plt.ylabel('Pct Spend in Organic',fontsize=15)

Шаг 3:

  • Определите K-средние с максимумом 1000 итераций
  • Определите массив «X» с входными переменными.
  • Определите массив «Y» со столбцом «Total_Spend» в качестве наблюдательных весов.
kmeans = KMeans(n_clusters=5, random_state=0, max_iter=1000)
X = np.array(df.drop(['Total_Spend'], 1).astype(float))
Y = np.array(df['Total_Spend'].astype(float))

Шаг 4: Запустите взвешенную кластеризацию k-средних и введите массив «X» в качестве входных данных и массив «Y» в качестве весов выборки. Сгенерируйте уровни кластера для всех точек данных

wt_kmeansclus = kmeans.fit(X,sample_weight = Y)
predicted_kmeans = kmeans.predict(X, sample_weight = Y)

Шаг 5. Визуализируйте кластеры и центроиды на диаграмме рассеяния.

plt.style.use('default')
plt.figure(figsize=(15, 10))
plt.scatter(X[:,0], X[:,1], c=wt_kmeansclus.labels_.astype(float),s=10,cmap='tab20b',marker='x')
plt.title('Customer Spend Local vs Organic - Weighted K-Means',fontsize=18, fontweight='bold')
plt.xlabel('Pct_Spend_in_Local',fontsize=15)
plt.ylabel('Pct_Spend_in_Organic',fontsize=15)
centers = wt_kmeansclus.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='black', s=500, alpha=0.5);

Шаг 6. Соедините метки кластера и центроиды с фреймом данных.

df['ClusterID_wt'] = predicted_kmeans
centersdf=pd.DataFrame(centers)
centersdf['ClusterID_wt'] = centersdf.index
centersdf=centersdf.rename(columns = {0:'Wt Centroid: Spend in Local',1:'Wt Centroid: Spend in Organic'})
df=df.merge(centersdf,on='ClusterID_wt',how='left')
df.head()

Сравнение: кластеризация K-средних с наблюдательными весами и без них.

Запустите упражнение по кластеризации без весов наблюдения и соедините метки кластера и центроиды с фреймом данных.

kmeans = KMeans(n_clusters=5, random_state=0,max_iter=1000)
kmeansclus_nw = kmeans.fit(X)
predicted_kmeans_nw = kmeans.predict(X)
centers_nw = kmeansclus_nw.cluster_centers_
df['ClusterID_unwt'] = predicted_kmeans_nw
centersdf_nw=pd.DataFrame(centers_nw)
centersdf_nw['ClusterID_unwt'] = centersdf_nw.index
centersdf_nw=centersdf_nw.rename(columns = {0:'Unwt Centroid: Spend in Local',1:'Unwt Centroid: Spend in Organic'})
df_nw=df.merge(centersdf_nw,on='ClusterID_unwt',how='left')
df_nw.head()

Создайте диаграмму рассеяния для невзвешенных кластеров:

plt.figure(figsize=(15, 10))
plt.scatter(X[:, 0], X[:, 1], c=predicted_kmeans_nw, s=10, cmap='tab20',marker ='x')
plt.scatter(centers_nw[:, 0], centers_nw[:, 1], c='black', s=500, alpha=0.5);
plt.title('Customer Spend - Local vs Organic - Unweighted K-Means',fontsize=18, fontweight='bold')
plt.xlabel('Spend_in_Local',fontsize=15)
plt.ylabel('Spend_in_Organic',fontsize=15)

Кластеры выглядят иначе!

Сгенерируйте графики, чтобы увидеть, как значения центроидов выглядят в обоих случаях:

ax = df_nw.plot(x="Total_Spend", y="Pct_Spend_in_Local", kind="scatter",title="Centroid Comparison - Weighted vs Unweighted",
              figsize=(10,6),color='plum',s=2)
df_nw.plot(x="Total_Spend", y="Wt Centroid: Pct Spend in Local", kind="scatter", ax=ax, color="blue", s=2,
              label="Wt Centroid: Pct Spend in Local")
df_nw.plot(x="Total_Spend", y="Unwt Centroid: Pct Spend in Local", kind="scatter", ax=ax, color="red", s=1,
             label="Unwt Centroid: Pct Spend in Local")

ax = df_nw.plot(x="Total_Spend", y="Pct_Spend_in_Organic", kind="scatter",title="Centroid Comparison - Weighted vs Unweighted",
              figsize=(10,6),color='plum',s=2)
df_nw.plot(x="Total_Spend", y="Wt Centroid: Pct Spend in Organic", kind="scatter", ax=ax, color="red", s=4,
              label="Wt Centroid: Pct Spend in Organic")
df_nw.plot(x="Total_Spend", y="Unwt Centroid: Pct Spend in Organic", kind="scatter", ax=ax, color="orange", s=1,
             label="Unwt Centroid: Pct Spend in Organic")

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

Когда вы работаете над методом обучения без учителя, тщательно обдумайте вариант использования и примите решение о том, должны ли все точки данных иметь равные веса или нет. Взвешенные K-средние - это легко реализуемый метод с использованием библиотеки python scikit-learn, и это было бы очень удобным дополнением к вашему набору инструментов для науки о данных - ключ в том, чтобы применить метод в надлежащем случае использования.