802 KiB
802 KiB
Загрузка датасета¶
In [1]:
import pandas as pd
df = pd.read_csv("C://Users//annal//aim//static//csv//Forbes_Billionaires.csv")
df
Out[1]:
Подготовим данные. Удалим неинформативные столбцы, преобразуем категориальные столбцы в числовые и нормализуем¶
In [2]:
# Удаляем неинформативные столбцы
df = df.drop(columns=["Rank ", "Name"])
# Преобразование категориальных данных в числовые с помощью one-hot encoding
df = pd.get_dummies(df, drop_first=True)
# Нормализация числовых данных
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df)
In [3]:
# Импортируем 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='red', edgecolor='k', alpha=0.6)
plt.title("PCA: Визуализация данных после снижения размерности")
plt.xlabel("Главная компонента 1")
plt.ylabel("Главная компонента 2")
plt.show()
Определим количество кластеров¶
Это важно, потому что оптимальное количество кластеров позволит разделить данные так, чтобы не были упущенны важные моменты. Кроме того, это сделает данные понятными и полезными, повлияет и на способность обощения модели. Если кластеров слишком много, то модель будет обращать излишнее внимание на шум, если кластеров слишком мало, то модель будет игнорировать важные моменты¶
Для разделения на кластеры воспользуемся методом локтя и коэффициентом силуэта¶
Метод локтя измеряет инерцию, то есть размерность ошибок внутри кластеров. Инерция — это сумма квадратов расстояний от точек до центроидов их кластеров. Чем меньше будет значение, тем лучше¶
Коэффициет силуэта покажет, насколько хорошо распределены объекты по кластерам. Он оценивает плотность кластеров и принимает значения от -1 до 1. Чем ближе результат к 1, тем лучше.¶
In [30]:
# Метод локтя
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()
In [28]:
# Кластеризация с помощью K-means
optimal_clusters = 2
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()
In [29]:
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()
Оценим коэффициенты силуэтов двух методов кластеризации¶
In [31]:
# Оценка качества
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}")