450 KiB
import pandas as pd
df = pd.read_csv("..//static//csv//ds_salaries.csv")
df
Цель работы
Я буду кластеризовать данные сотрудников на основе их характеристик для выделения групп с общими профессиональными и экономическими признаками. Это может быть полезно для анализа рынка труда, планирования кадровой стратегии или разработки программ по удержанию и привлечению специалистовНе много бработаем данные
from sklearn.preprocessing import StandardScaler
# Преобразование категориальных данных в числовые с помощью one-hot encoding
df = pd.get_dummies(df, drop_first=True)
# Сделаем данные сравнивыми
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df)
df_scaled
Используем PCA(анализ главных компонент) для визуализации данных
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# Применяем PCA для снижения размерности до 2
pca = PCA(n_components=2)
df_pca = pca.fit_transform(df_scaled)
# Визуализация
plt.figure(figsize=(8, 6))
plt.scatter(df_pca[:, 0], df_pca[:, 1], c='blue', edgecolor='k', alpha=0.6)
plt.title("PCA: Визуализация данных после снижения размерности")
plt.xlabel("Главная компонента 1")
plt.ylabel("Главная компонента 2")
plt.show()
Определение оптимального количества кластеров
# Метод локтя
from sklearn.cluster import KMeans
border_l = 2
border_r = 5
inertia = []
for k in range(border_l, border_r):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(df_scaled)
inertia.append(kmeans.inertia_)
# Визуализация метода локтя
plt.figure(figsize=(8, 6))
plt.plot(range(border_l, border_r), inertia, marker='o')
plt.title('Метод локтя для выбора количества кластеров')
plt.xlabel('Количество кластеров')
plt.ylabel('Инерция')
plt.show()
# Коэффициент силуэта
from sklearn.metrics import silhouette_score
silhouette_scores = []
for k in range(border_l, border_r):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(df_scaled)
score = silhouette_score(df_scaled, kmeans.labels_)
silhouette_scores.append(score)
# Визуализация коэффициента силуэта
plt.figure(figsize=(8, 6))
plt.plot(range(border_l, border_r), silhouette_scores, marker='o')
plt.title('Коэффициент силуэта для различных кластеров')
plt.xlabel('Количество кластеров')
plt.ylabel('Коэффициент силуэта')
plt.show()
Кластеризация с помощью K-means(группирует данные вокруг центров (центроидов) кластеров)
# Кластеризация с помощью K-means
optimal_clusters = 3
kmeans = KMeans(n_clusters=optimal_clusters, random_state=42)
df['Cluster'] = kmeans.fit_predict(df_scaled)
# Визуализация кластеров с использованием PCA
plt.figure(figsize=(8, 6))
plt.scatter(df_pca[:, 0], df_pca[:, 1], c=df['Cluster'], cmap='viridis', edgecolor='k', alpha=0.6)
plt.title("Кластеры, определенные K-means (PCA)")
plt.xlabel("Главная компонента 1")
plt.ylabel("Главная компонента 2")
plt.colorbar(label='Кластер')
plt.show()
Иерархическая кластеризация
Иерархическая кластеризация — метод, который строит древовидную структуру кластеров (дендрограмму).
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram
import numpy as np
import matplotlib.pyplot as plt
# Применение иерархической кластеризации
hierarchical = AgglomerativeClustering(n_clusters=optimal_clusters, compute_distances=True)
df['Hierarchical Cluster'] = hierarchical.fit_predict(df_scaled)
# Функция для получения матрицы linkage
def get_linkage_matrix(model: AgglomerativeClustering) -> np.ndarray:
counts = np.zeros(model.children_.shape[0]) # type: ignore
n_samples = len(model.labels_)
for i, merge in enumerate(model.children_): # type: ignore
current_count = 0
for child_idx in merge:
if child_idx < n_samples:
current_count += 1
else:
current_count += counts[child_idx - n_samples]
counts[i] = current_count
return np.column_stack([model.children_, model.distances_, counts]).astype(float)
# Построение дендрограммы
linkage_matrix = get_linkage_matrix(hierarchical)
plt.figure(figsize=(12, 8))
dendrogram(linkage_matrix)
plt.title("Дендограмма, восстановленная из модели AgglomerativeClustering")
plt.xlabel("Индексы объектов")
plt.ylabel("Евклидово расстояние")
plt.show()
# Визуализация кластеров
plt.figure(figsize=(8, 6))
plt.scatter(df_pca[:, 0], df_pca[:, 1], c=df['Hierarchical Cluster'], cmap='viridis', edgecolor='k', alpha=0.6)
plt.title("Кластеры, определенные иерархической кластеризацией (PCA)")
plt.xlabel("Главная компонента 1")
plt.ylabel("Главная компонента 2")
plt.colorbar(label='Кластер')
plt.show()
Оценка качества кластеризации
Оценим качество кластеров, сравнив коэффициенты силуэта для двух методов.
# Оценка качества
silhouette_kmeans = silhouette_score(df_scaled, df['Cluster'])
silhouette_hierarchical = silhouette_score(df_scaled, df['Hierarchical Cluster'])
print(f"Коэффициент силуэта для K-means: {silhouette_kmeans:.4f}")
print(f"Коэффициент силуэта для иерархической кластеризации: {silhouette_hierarchical:.4f}")
Можно сделать вывод:
K-means и иерархическая кластеризация дают схожие результаты, но могут отличаться по точности в зависимости от структуры данных.
Как интерпретировать значения?
Коэффициент силуэта находится в диапазоне от -1 до 1:
Близко к 1: Отличные кластеры (чётко разделённые).
Около 0: Кластеры пересекаются или слабо разделены.
Меньше 0: Объекты часто попадают не в свои кластеры.
K-means = 0.7657 успешно справился с задачей кластеризации, сформировав чётко разделённые кластеры.
Иерархическая кластеризация показала средний результат с коэффициентом силуэта 0.4890, что указывает на менее чётко сформированные кластеры.