Сегментация клиентов — это мощный инструмент для компаний, стремящихся оптимизировать свои усилия в области маркетинга и продаж. Разделяя клиентов на более мелкие группы на основе общих характеристик или поведения, компании могут адаптировать свои кампании к конкретным сегментам, потенциально повышая их эффективность. Одним из распространенных подходов к сегментации клиентов является использование алгоритмов кластеризации. Алгоритмы кластеризации группируют точки данных в кластеры на основе сходства между точками. Существует несколько популярных алгоритмов кластеризации, в том числе K-Means, иерархическая кластеризация и DBSCAN.
K-Means — это итеративный алгоритм, который делит набор данных на определенное количество кластеров в зависимости от расстояния от центра тяжести каждого кластера. Чтобы использовать K-Means для сегментации клиентов, предприятия могут вводить данные о клиентах в алгоритм и указывать количество кластеров, которые они хотят создать. Затем алгоритм сгруппирует клиентов в кластеры на основе общих характеристик.
Иерархическая кластеризация — это метод группировки данных в древовидную структуру на основе сходства между точками. Чтобы использовать иерархическую кластеризацию для сегментации клиентов, предприятия могут вводить данные о клиентах в алгоритм и указывать уровень детализации, который они хотят для кластеров. Затем алгоритм сгруппирует клиентов в кластеры на основе общих характеристик.
DBSCAN (Пространственная кластеризация приложений с шумом на основе плотности) — это алгоритм, который группирует точки, которые плотно упакованы вместе, и помечает точки, которые изолированы как шум. Чтобы использовать DBSCAN для сегментации клиентов, предприятия могут вводить данные о клиентах в алгоритм и указывать минимальное количество точек, необходимых для формирования кластера, и максимальное расстояние между точками в кластере. Затем алгоритм сгруппирует клиентов в кластеры на основе общих характеристик.
Использование K-Means, иерархической кластеризации и DBSCAN для сегментации клиентов может помочь компаниям понять свою клиентскую базу и соответствующим образом адаптировать свои усилия в области маркетинга и продаж. Группируя клиентов в значимые сегменты, компании могут повысить эффективность своих кампаний и, в конечном итоге, улучшить свои финансовые результаты.
А теперь попрактикуемся в Python.
Бизнес-задача: сегментация клиентского портфеля
FLO хочет сегментировать своих клиентов и определять маркетинговые стратегии в соответствии с этими сегментами. С этой целью будет определено поведение клиентов и сформированы группы в соответствии с кластерами этого поведения.
История набора данных: покупательское поведение клиентов FLO
Набор данных включает последние покупки Flo в OmniChannel (как онлайн, так и офлайн) в 2020–2021 годах. 12 переменных 19 945 наблюдений 2,7 МБ
- master_id: уникальный номер клиента
- order_channel: какой канал торговой платформы используется (Android, ios, Desktop, Mobile)
- last_order_channel: канал, на котором была сделана последняя покупка
- first_order_date: Дата первой покупки, сделанной покупателем.
- last_order_date: дата последней покупки клиента.
- last_order_date_online: дата последней покупки, сделанной клиентом на онлайн-платформе.
- last_order_date_offline: дата последней покупки, сделанной клиентом на офлайн-платформе.
- order_num_total_ever_online: общее количество покупок, сделанных клиентом на онлайн-платформе.
- order_num_total_ever_offline: Общее количество покупок, совершенных клиентом в автономном режиме.
- customer_value_total_ever_offline: общая сумма, уплаченная клиентом за офлайн-покупки.
- customer_value_total_ever_online: общая сумма, уплаченная покупателем за покупки в Интернете.
- интересуемый_in_categories_12: Список категорий, в которых покупатель совершил покупку за последние 12 месяцев.
1. Загрузка необходимых библиотек и данных
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from sklearn.cluster import KMeans # K-Means from sklearn.preprocessing import MinMaxScaler from yellowbrick.cluster import KElbowVisualizer # Elbow method from scipy.cluster.hierarchy import linkage, dendrogram # hierarchical clustering from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import LabelEncoder from sklearn.cluster import AgglomerativeClustering # hierarchical clustering pd.set_option('display.max_columns', None) pd.set_option('display.width', 500) import warnings warnings.simplefilter(action='ignore', category=Warning) import os for dirname, _, filenames in os.walk('/kaggle/input'): for filename in filenames: print(os.path.join(dirname, filename)) df = pd.read_csv('/kaggle/input/flodata/flo_data_20k.csv') df['tenure'] = (pd.to_datetime('today') - pd.to_datetime(df['first_order_date'])).dt.days df['recency'] = (pd.to_datetime('today') - pd.to_datetime(df['last_order_date'])).dt.days df['frequency'] = df['order_num_total_ever_online'] + df['order_num_total_ever_offline'] df['monetary'] = df['customer_value_total_ever_online'] + df['customer_value_total_ever_offline'] df["order_num_total"] = df["order_num_total_ever_online"] + df["order_num_total_ever_offline"] df["customer_value_total"] = df["customer_value_total_ever_offline"] + df["customer_value_total_ever_online"]
2. Исследовательский анализ данных
def check_df(dataframe, head=5): print("##################### Shape #####################") print(dataframe.shape) print("##################### Types #####################") print(dataframe.dtypes) print("##################### Head #####################") print(dataframe.head(head)) print("##################### Tail #####################") print(dataframe.tail(head)) print("##################### NA #####################") print(dataframe.isnull().sum()) print("##################### Quantiles #####################") print(dataframe.quantile([0, 0.05, 0.50, 0.95, 0.99, 1]).T) check_df(df) ##################### Shape ##################### (19945, 18) ##################### Types ##################### master_id object order_channel object last_order_channel object first_order_date object last_order_date object last_order_date_online object last_order_date_offline object order_num_total_ever_online float64 order_num_total_ever_offline float64 customer_value_total_ever_offline float64 customer_value_total_ever_online float64 interested_in_categories_12 object tenure int64 recency int64 frequency float64 monetary float64 order_num_total float64 customer_value_total float64 dtype: object ##################### Head ##################### master_id order_channel last_order_channel first_order_date last_order_date last_order_date_online last_order_date_offline order_num_total_ever_online order_num_total_ever_offline customer_value_total_ever_offline customer_value_total_ever_online interested_in_categories_12 tenure recency frequency monetary order_num_total customer_value_total 0 cc294636-19f0-11eb-8d74-000d3a38a36f Android App Offline 2020-10-30 2021-02-26 2021-02-21 2021-02-26 4.0 1.0 139.99 799.38 [KADIN] 784 665 5.0 939.37 5.0 939.37 1 f431bd5a-ab7b-11e9-a2fc-000d3a38a36f Android App Mobile 2017-02-08 2021-02-16 2021-02-16 2020-01-10 19.0 2.0 159.97 1853.58 [ERKEK, COCUK, KADIN, AKTIFSPOR] 2144 675 21.0 2013.55 21.0 2013.55 2 69b69676-1a40-11ea-941b-000d3a38a36f Android App Android App 2019-11-27 2020-11-27 2020-11-27 2019-12-01 3.0 2.0 189.97 395.35 [ERKEK, KADIN] 1122 756 5.0 585.32 5.0 585.32 3 1854e56c-491f-11eb-806e-000d3a38a36f Android App Android App 2021-01-06 2021-01-17 2021-01-17 2021-01-06 1.0 1.0 39.99 81.98 [AKTIFCOCUK, COCUK] 716 705 2.0 121.97 2.0 121.97 4 d6ea1074-f1f5-11e9-9346-000d3a38a36f Desktop Desktop 2019-08-03 2021-03-07 2021-03-07 2019-08-03 1.0 1.0 49.99 159.99 [AKTIFSPOR] 1238 656 2.0 209.98 2.0 209.98 ##################### Tail ##################### master_id order_channel last_order_channel first_order_date last_order_date last_order_date_online last_order_date_offline order_num_total_ever_online order_num_total_ever_offline customer_value_total_ever_offline customer_value_total_ever_online interested_in_categories_12 tenure recency frequency monetary order_num_total customer_value_total 19940 727e2b6e-ddd4-11e9-a848-000d3a38a36f Android App Offline 2019-09-21 2020-07-05 2020-06-05 2020-07-05 1.0 2.0 289.98 111.98 [ERKEK, AKTIFSPOR] 1189 901 3.0 401.96 3.0 401.96 19941 25cd53d4-61bf-11ea-8dd8-000d3a38a36f Desktop Desktop 2020-03-01 2020-12-22 2020-12-22 2020-03-01 1.0 1.0 150.48 239.99 [AKTIFSPOR] 1027 731 2.0 390.47 2.0 390.47 19942 8aea4c2a-d6fc-11e9-93bc-000d3a38a36f Ios App Ios App 2019-09-11 2021-05-24 2021-05-24 2019-09-11 2.0 1.0 139.98 492.96 [AKTIFSPOR] 1199 578 3.0 632.94 3.0 632.94 19943 e50bb46c-ff30-11e9-a5e8-000d3a38a36f Android App Android App 2019-03-27 2021-02-13 2021-02-13 2021-01-08 1.0 5.0 711.79 297.98 [ERKEK, AKTIFSPOR] 1367 678 6.0 1009.77 6.0 1009.77 19944 740998d2-b1f7-11e9-89fa-000d3a38a36f Android App Android App 2019-09-03 2020-06-06 2020-06-06 2019-09-03 1.0 1.0 39.99 221.98 [KADIN, AKTIFSPOR] 1207 930 2.0 261.97 2.0 261.97 ##################### NA ##################### master_id 0 order_channel 0 last_order_channel 0 first_order_date 0 last_order_date 0 last_order_date_online 0 last_order_date_offline 0 order_num_total_ever_online 0 order_num_total_ever_offline 0 customer_value_total_ever_offline 0 customer_value_total_ever_online 0 interested_in_categories_12 0 tenure 0 recency 0 frequency 0 monetary 0 order_num_total 0 customer_value_total 0 dtype: int64 ##################### Quantiles ##################### 0.00 0.05 0.50 0.95 0.99 1.00 order_num_total_ever_online 1.00 1.00 2.00 10.000 20.0000 200.00 order_num_total_ever_offline 1.00 1.00 1.00 4.000 7.0000 109.00 customer_value_total_ever_offline 10.00 39.99 179.98 694.222 1219.9468 18119.14 customer_value_total_ever_online 12.99 63.99 286.46 1556.726 3143.8104 45220.13 tenure 575.00 779.20 1221.00 2644.000 3175.0000 3630.00 recency 572.00 579.00 681.00 905.000 930.0000 937.00 frequency 2.00 2.00 4.00 12.000 22.0000 202.00 monetary 44.98 175.48 545.27 1921.924 3606.3556 45905.10 order_num_total 2.00 2.00 4.00 12.000 22.0000 202.00 customer_value_total 44.98 175.48 545.27 1921.924 3606.3556 45905.10 def cat_summary(dataframe, col_name, plot=False): print(pd.DataFrame({col_name: dataframe[col_name].value_counts(), "Ratio": 100 * dataframe[col_name].value_counts() / len(dataframe)})) print("##########################################") if plot: sns.countplot(x=dataframe[col_name], data=dataframe) plt.show(block=True) def num_summary(dataframe, numerical_col, plot=False): quantiles = [0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.95, 0.99] print(dataframe[numerical_col].describe(quantiles).T) if plot: dataframe[numerical_col].hist(bins=20) plt.xlabel(numerical_col) plt.title(numerical_col) plt.show(block=True) def target_summary_with_num(dataframe, target, numerical_col): print(dataframe.groupby(target).agg({numerical_col: "mean"}), end="\n\n\n") def target_summary_with_cat(dataframe, target, categorical_col): print(pd.DataFrame({"TARGET_MEAN": dataframe.groupby(categorical_col)[target].mean()}), end="\n\n\n") def correlation_matrix(df, cols): fig = plt.gcf() fig.set_size_inches(10, 8) plt.xticks(fontsize=10) plt.yticks(fontsize=10) fig = sns.heatmap(df[cols].corr(), annot=True, linewidths=0.5, annot_kws={'size': 12}, linecolor='w', cmap='RdBu') plt.show(block=True)
df
: это кадр данных, содержащий столбцы, для которых вы хотите рассчитать корреляции.cols
: это список имен столбцов, которые вы хотите включить в матрицу корреляции.fig
: Эта переменная хранит ссылку на текущий объект фигуры. Объект фигуры представляет общее окно или страницу, на которой будет отображаться график.fig.set_size_inches
: Этот метод устанавливает размер объекта фигуры в дюймах.plt.xticks
иplt.yticks
: эти функции управляют внешним видом меток осей x и y.sns.heatmap
: Эта функция из библиотеки Seaborn создает тепловую карту, визуализирующую корреляции между столбцами в фрейме данных. Параметрannot
указывает, следует ли аннотировать ячейки корреляциями, а параметрannot_kws
управляет внешним видом аннотаций. Параметрlinewidths
управляет шириной линий между ячейками, а параметрlinecolor
задает цвет линий. Параметрcmap
указывает цветовую карту, используемую для тепловой карты.plt.show
: Эта функция отображает график. Параметрblock
указывает, следует ли блокировать сценарий, пока окно графика не будет закрыто.
def grab_col_names(dataframe, cat_th=10, car_th=20): """ It gives the names of categorical, numerical and categorical but cardinal variables in the data set. Note: Categorical variables with numerical appearance are also included in categorical variables. parameters ------ dataframe: dataframe The dataframe from which variable names are to be retrieved cat_th: int, optional class threshold for numeric but categorical variables car_th: int, optinal class threshold for categorical but cardinal variables Returns ------ cat_cols: list Categorical variable list num_cols: list Numeric variable list cat_but_car: list Categorical view cardinal variable list Examples ------ import seaborn as sns df = sns.load_dataset("iris") print(grab_col_names(df)) notes ------ cat_cols + num_cols + cat_but_car = total number of variables num_but_cat is inside cat_cols. The sum of the 3 returned lists equals the total number of variables: cat_cols + num_cols + cat_but_car = number of variables """ # cat_cols, cat_but_car cat_cols = [col for col in dataframe.columns if dataframe[col].dtypes == "O"] num_but_cat = [col for col in dataframe.columns if dataframe[col].nunique() < cat_th and dataframe[col].dtypes != "O"] cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th and dataframe[col].dtypes == "O"] cat_cols = cat_cols + num_but_cat cat_cols = [col for col in cat_cols if col not in cat_but_car] # num_cols num_cols = [col for col in dataframe.columns if dataframe[col].dtypes != "O"] num_cols = [col for col in num_cols if col not in num_but_cat] # print(f"Observations: {dataframe.shape[0]}") # print(f"Variables: {dataframe.shape[1]}") # print(f'cat_cols: {len(cat_cols)}') # print(f'num_cols: {len(num_cols)}') # print(f'cat_but_car: {len(cat_but_car)}') # print(f'num_but_cat: {len(num_but_cat)}') return cat_cols, num_cols, cat_but_car cat_cols, num_cols, cat_but_car = grab_col_names(df, cat_th=5, car_th=20) print(cat_cols) print(num_cols) print(cat_but_car)
- Сначала функция создает список
cat_cols
столбцов, которые являются категориальными переменными (т. е. их тип данных — «O» для «объекта»). - Затем он создает список
num_but_cat
столбцов, которые являются числовыми, но категориальными (т. е. имеют менееcat_th
уникальных значений). - Затем он создает список
cat_but_car
столбцов, которые являются категориальными, но количественными (т. е. имеют болееcar_th
уникальных значений). - Он добавляет список
num_but_cat
в списокcat_cols
и удаляет все имена столбцов, которые также находятся в спискеcat_but_car
. - Он создает список
num_cols
числовых переменных, которых нет в спискеnum_but_cat
.
Функция также имеет необязательные параметры cat_th
и car_th
, которые управляют пороговыми значениями для определения того, какие столбцы считаются числовыми, но категоричными или категориальными, но количественными.
cat_cols ['order_channel', 'last_order_channel'] num_cols ['order_num_total_ever_online', 'order_num_total_ever_offline', 'customer_value_total_ever_offline', 'customer_value_total_ever_online', 'tenure', 'recency', 'frequency', 'monetary', 'order_num_total', 'customer_value_total'] # Correlation of numerical variables with each other correlation_matrix(df, num_cols)
3. Предварительная обработка данных и разработка функций
def outlier_thresholds(dataframe, col_name, q1=0.25, q3=0.75): quartile1 = dataframe[col_name].quantile(q1) quartile3 = dataframe[col_name].quantile(q3) interquantile_range = quartile3 - quartile1 up_limit = quartile3 + 1.5 * interquantile_range low_limit = quartile1 - 1.5 * interquantile_range return low_limit, up_limit def replace_with_thresholds(dataframe, variable): low_limit, up_limit = outlier_thresholds(dataframe, variable) dataframe.loc[(dataframe[variable] < low_limit), variable] = low_limit dataframe.loc[(dataframe[variable] > up_limit), variable] = up_limit def check_outlier(dataframe, col_name, q1=0.25, q3=0.75): low_limit, up_limit = outlier_thresholds(dataframe, col_name, q1, q3) if dataframe[(dataframe[col_name] > up_limit) | (dataframe[col_name] < low_limit)].any(axis=None): return True else: return False def one_hot_encoder(dataframe, categorical_cols, drop_first=False): dataframe = pd.get_dummies(dataframe, columns=categorical_cols, drop_first=drop_first) return dataframe def label_encoder(dataframe, binary_col): labelencoder = LabelEncoder() dataframe[binary_col] = labelencoder.fit_transform(dataframe[binary_col]) return dataframe binary_cols = [col for col in df.columns if df[col].dtype not in [int, float] and df[col].nunique() == 2] for col in binary_cols: df = label_encoder(df, col) def one_hot_encoder(dataframe, categorical_cols, drop_first=True): dataframe = pd.get_dummies(dataframe, columns=categorical_cols, drop_first=drop_first) return dataframe ohe_cols = [col for col in df.columns if 25 >= df[col].nunique() > 2] df = one_hot_encoder(df, ohe_cols) cat_cols, num_cols, cat_but_car = grab_col_names(df)
outlier_thresholds
: эта функция принимает фрейм данных, имя столбца и необязательные параметрыq1
иq3
(значения по умолчанию — 0,25 и 0,75 соответственно). Он вычисляет межквартильный диапазон (IQR) столбца и возвращает верхний и нижний пределы для обнаружения выбросов на основе IQR. Выброс определяется как значение, которое более чем в 1,5 раза превышает IQR выше верхнего квартиля или ниже нижнего квартиля.replace_with_thresholds
: эта функция принимает фрейм данных и имя столбца. Он вызывает функциюoutlier_thresholds
, чтобы получить верхний и нижний пределы для обнаружения выбросов в столбце. Затем он заменяет все значения в столбце, которые выше верхнего предела или ниже нижнего предела, на соответствующий предел.check_outlier
: эта функция принимает фрейм данных, имя столбца и необязательные параметрыq1
иq3
(значения по умолчанию — 0,25 и 0,75 соответственно). Он вызывает функциюoutlier_thresholds
, чтобы получить верхний и нижний пределы для обнаружения выбросов в столбце. Затем он проверяет, есть ли в столбце какие-либо значения выше верхнего предела или ниже нижнего предела, и возвращаетTrue
, если они найдены, илиFalse
, если ничего не найдено.one_hot_encoder
: эта функция принимает кадр данных, список имен столбцов и необязательный параметрdrop_first
(значение по умолчанию —True
). Он преобразует категориальные переменные в указанных столбцах в фиктивные переменные, используя функциюpd.get_dummies
из библиотеки pandas. Параметрdrop_first
указывает, следует ли отбрасывать первую фиктивную переменную в каждом столбце, чтобы избежать ловушки фиктивной переменной.label_encoder
: эта функция принимает фрейм данных и имя столбца. Он преобразует значения в указанном столбце в числовые значения, используя классLabelEncoder
из библиотекиsklearn
.binary_cols
: Эта строка кода создает список имен столбцов для двоичных переменных (т. е. переменных только с двумя уникальными значениями) в фрейме данных.label_encoder
: Эта строка кода вызывает функциюlabel_encoder
для каждого столбца в спискеbinary_cols
, преобразуя значения в этих столбцах в числовые значения.one_hot_encoder
: эта строка кода вызывает функциюone_hot_encoder
для фрейма данных, используя список имен столбцов для категориальных переменных с относительно небольшим количеством уникальных значений.grab_col_names
: эта строка кода вызывает функциюgrab_col_names
в кадре данных, возвращая списки имен столбцов для категориальных переменных, числовых переменных и категориальных переменных, которые также являются кардинальными (имеют большое количество уникальных значений).
df.shape (19945, 23)
4. Сегментация клиентов с помощью K-Means
K-Means — это алгоритм кластеризации, используемый для разделения набора данных на кластеры. Этот алгоритм создает кластеры, используя координаты точек в наборе данных. Следовательно, алгоритм K-средних можно применять только для числовых переменных. Алгоритм K-средних определяет центральную точку, чтобы разделить набор данных на его кластеры. Эти центральные точки представляют собой среднее значение координат точек в наборе данных. Алгоритм K-средних присваивает каждой точке ближайший центр.
sc = StandardScaler() X = sc.fit_transform(df[num_cols]) X = pd.DataFrame(X, columns=num_cols) X.head()
Для работы алгоритма K-средних необходимо определить оптимальные кластеры. Для этого можно использовать метод локтя. Для метода локтя необходимо рассчитать значения WCSS кластеров. Значения WCSS уменьшаются с увеличением количества кластеров. Глядя на график этих значений, снижение замедляется после точки. После этого момента увеличить количество кластеров уже не получится. Эта точка называется точкой локтя.
wcss = [] # We created a list to hold WCSS values. for k in range(1, 15): # We looped the numbers from 1 to 15. kmeans = KMeans(n_clusters=k).fit(X) # We ran the K-Means algorithm. wcss.append(kmeans.inertia_) # We added the WCSS values to the wcss list. plt.plot(range(1, 15), wcss, 'bx-') # We plotted the WCSS values. plt.xlabel('k values') plt.ylabel('WCSS') plt.title('The Elbow Method') plt.show()
kmeans = KMeans() elbow = KElbowVisualizer(kmeans, k=(2, 20)) elbow.fit(X) elbow.show(block=True) elbow.elbow_value_
kmeans = KMeans(n_clusters=elbow.elbow_value_, init='k-means++').fit(X) kmeans.cluster_centers_ # Indicates the centers of clusters. kmeans.n_clusters # Indicates the number of clusters. 8 kmeans.labels_ array([6, 4, 2, ..., 6, 7, 2], dtype=int32) kmeans.inertia_ # Displays the WCSS value. 65766.97770803791 kmeans.get_params() # With get_params() we can see the parameters of the kmeans model. {'algorithm': 'auto', 'copy_x': True, 'init': 'k-means++', 'max_iter': 300, 'n_clusters': 8, 'n_init': 10, 'random_state': None, 'tol': 0.0001, 'verbose': 0}
Создайте свою модель и сегментируйте своих клиентов
clusters_kmeans = kmeans.labels_ # Indicates which observation the clusters belong to. X["cluster"] = clusters_kmeans # We added a variable named cluster_no to X. X.head()
X.groupby('cluster').agg(['mean', 'median', 'count', 'std']).T
X['cluster'] = X['cluster'] + 1 X.head()
X["cluster"].value_counts() # It shows the number of observations belonging to each cluster. X["cluster"].value_counts() / len(X) * 100 7 43.474555 3 27.480572 4 9.917272 8 8.578591 1 8.373026 5 2.070694 6 0.070193 2 0.035097 Name: cluster, dtype: float64 sns.countplot(x='cluster', data=X) plt.show()
5. Сегментация клиентов с помощью иерархической кластеризации
Метод иерархической кластеризации (HC) – это метод кластеризации, используемый для разделения точек данных на группы со схожими характеристиками. Этот метод используется для группировки точек данных друг о друге. Каждая из этих групп называется кластером.
Метод HC также называют методом матрицы ссылок. Этот метод используется для группировки точек данных в соответствии со степенью их связи друг с другом. Этот метод создает матрицу связности для измерения степени взаимосвязи между точками данных. Эта матрица показывает степени связности между точками данных и группирует точки данных в соответствии с этими степенями.
linkage_matrix = linkage(X, method='ward') # Create the dendrogram dend = dendrogram(linkage_matrix) # Show the dendrogram plt.show()
В этом фрагменте создается матрица ссылок, которая измеряет степень сходства точек данных с помощью функции linkage() библиотеки scipy. Затем, используя эту матрицу ссылок, создается дендограмма методом HC с использованием функции dendrogram() библиотеки scipy. Эта дендограмма отображается с помощью функции show() библиотеки matplotlib. В этом фрагменте параметр метода указан как «ward», поэтому в качестве метода HC используется метод hc_ward. Значение этого параметра может принимать различные значения, такие как «одиночное», «полное» или «среднее», и в соответствии с этими значениями можно получить дендограмму, применяя метод HC различными методами.
hc_average = linkage(X, "average") # We created a connection matrix with the average method. hc_ward = linkage(X, "ward") # We created a connection matrix with the ward method. hc_complete = linkage(X, "complete") # We created a connection matrix with the complete method. hc_single = linkage(X, "single") # We created a connection matrix with the single method. hc_centroid = linkage(X, "centroid") # We created a connection matrix with the centroid method. plt.figure(figsize=(7, 5)) plt.title("Hierarchical Clustering Dendrogram") plt.xlabel("Observation Units") plt.ylabel("Distances") dendrogram(hc_average, truncate_mode="lastp", p=10, show_contracted=True, leaf_font_size=10) plt.show()
Мы используем класс AgglomerativeClustering из scikit-learn для выполнения иерархической кластеризации набора данных X. Мы устанавливаем количество кластеров равным 3 и используем евклидово расстояние и метод связывания Уорда для кластеризации.
Метод fit_predict подбирает модель к данным и возвращает метки кластеров для каждой выборки в наборе данных. Метки кластера хранятся в массиве clusters_hc.
После запуска этого кода мы можем использовать массив clusters_hc, чтобы увидеть метки кластеров для каждой выборки в наборе данных. Например, если первая выборка имеет метку кластера 0, она принадлежит первому кластеру. Если второй образец имеет метку кластера 1, он принадлежит второму кластеру и так далее.
hc = AgglomerativeClustering(n_clusters=3, affinity='euclidean', linkage='ward') clusters_hc = hc.fit_predict(X) clusters_hc X.groupby('cluster_hc').agg(['mean', 'median', 'count', 'std']).T
X["cluster_hc"].value_counts() # It shows the number of observations belonging to each cluster. X["cluster_hc"].value_counts() / len(X) * 100 2 52.053146 3 35.853597 1 12.093256 Name: cluster_hc, dtype: float64 sns.countplot(x='cluster_hc', data=X) plt.show()
6. Сегментация клиентов с помощью DBSCAN
DBSCAN (Пространственная кластеризация приложений с шумом на основе плотности) — это алгоритм кластеризации, основанный на плотности точек данных. Его можно использовать для сегментации клиентов путем поиска групп похожих клиентов на основе их характеристик или атрибутов.
from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.8, min_samples=15) clusters = dbscan.fit_predict(X) print(clusters) df['dbscan_cluster'] = clusters df.head()
Используйте класс DBSCAN из scikit-learn, чтобы подогнать модель под ваши данные. Вам нужно указать два важных параметра: eps и min_samples. eps — максимальное расстояние между двумя точками в одном кластере, а min_samples — минимальное количество точек, необходимое для формирования кластера.
X["cluster_dbscan"].value_counts() 1 8662 2 5451 0 2215 5 1289 3 1170 4 1148 6 10 Name: cluster_dbscan, dtype: int64 sns.countplot(x='cluster_dbscan', data=X) plt.show()
Заключение
Сегментация клиентов на разные группы по их характеристикам и поведению всегда была важной темой. Сегментация клиентов может привести к лучшему пониманию клиентов и таргетингу, что, в свою очередь, приводит к более эффективной адаптации продукта и маркетинговым стратегиям. Методы интеллектуального анализа данных — это мощные методы, которые можно использовать при сегментации клиентов для поиска клиентов со схожими характеристиками.
Спасибо, что прочитали эту статью. Вы можете получить доступ к подробным кодам проекта и других проектов в мой аккаунт Github или аккаунт Kaggle. Удачного кодирования!
Пожалуйста, не стесняйтесь связаться со мной, если вам нужна дополнительная информация.