吳裕雄 數據挖掘與分析案例實戰(15)——DBSCAN與層次聚類分析


# 導入第三方模塊
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import cluster
from sklearn.datasets.samples_generator import make_blobs

# 模擬數據集
X,y = make_blobs(n_samples = 2000, centers = [[-1,-2],[1,3]], cluster_std = [0.5,0.5], random_state = 1234)
# 將模擬得到的數組轉換為數據框,用於繪圖
plot_data = pd.DataFrame(np.column_stack((X,y)), columns = ['x1','x2','y'])
# 設置繪圖風格
plt.style.use('ggplot')
# 繪制散點圖(用不同的形狀代表不同的簇)
sns.lmplot('x1', 'x2', data = plot_data, hue = 'y',markers = ['^','o'],
fit_reg = False, legend = False)
# 顯示圖形
plt.show()

# 導入第三方模塊
from sklearn import cluster

# 構建Kmeans聚類和密度聚類
kmeans = cluster.KMeans(n_clusters=2, random_state=1234)
kmeans.fit(X)
dbscan = cluster.DBSCAN(eps = 0.5, min_samples = 10)
dbscan.fit(X)
# 將Kmeans聚類和密度聚類的簇標簽添加到數據框中
plot_data['kmeans_label'] = kmeans.labels_
plot_data['dbscan_label'] = dbscan.labels_

# 繪制聚類效果圖
# 設置大圖框的長和高
plt.figure(figsize = (12,6))
# 設置第一個子圖的布局
ax1 = plt.subplot2grid(shape = (1,2), loc = (0,0))
# 繪制散點圖
ax1.scatter(plot_data.x1, plot_data.x2, c = plot_data.kmeans_label)
# 設置第二個子圖的布局
ax2 = plt.subplot2grid(shape = (1,2), loc = (0,1))
# 繪制散點圖(為了使Kmeans聚類和密度聚類的效果圖顏色一致,通過序列的map“方法”對顏色作重映射)
ax2.scatter(plot_data.x1, plot_data.x2, c=plot_data.dbscan_label.map({-1:1,0:2,1:0}))
# 顯示圖形
plt.show()

# 導入第三方模塊
from sklearn.datasets.samples_generator import make_moons

# 構造非球形樣本點
X1,y1 = make_moons(n_samples=2000, noise = 0.05, random_state = 1234)
# 構造球形樣本點
X2,y2 = make_blobs(n_samples=1000, centers = [[3,3]], cluster_std = 0.5, random_state = 1234)
# 將y2的值替換為2(為了避免與y1的值沖突,因為原始y1和y2中都有0這個值)
y2 = np.where(y2 == 0,2,0)
# 將模擬得到的數組轉換為數據框,用於繪圖
plot_data = pd.DataFrame(np.row_stack([np.column_stack((X1,y1)),np.column_stack((X2,y2))]), columns = ['x1','x2','y'])

# 繪制散點圖(用不同的形狀代表不同的簇)
sns.lmplot('x1', 'x2', data = plot_data, hue = 'y',markers = ['^','o','>'],
fit_reg = False, legend = False)
# 顯示圖形
plt.show()

# 構建Kmeans聚類和密度聚類
kmeans = cluster.KMeans(n_clusters=3, random_state=1234)
kmeans.fit(plot_data[['x1','x2']])
dbscan = cluster.DBSCAN(eps = 0.3, min_samples = 5)
dbscan.fit(plot_data[['x1','x2']])
# 將Kmeans聚類和密度聚類的簇標簽添加到數據框中
plot_data['kmeans_label'] = kmeans.labels_
plot_data['dbscan_label'] = dbscan.labels_

# 繪制聚類效果圖
# 設置大圖框的長和高
plt.figure(figsize = (12,6))
# 設置第一個子圖的布局
ax1 = plt.subplot2grid(shape = (1,2), loc = (0,0))
# 繪制散點圖
ax1.scatter(plot_data.x1, plot_data.x2, c = plot_data.kmeans_label)
# 設置第二個子圖的布局
ax2 = plt.subplot2grid(shape = (1,2), loc = (0,1))
# 繪制散點圖(為了使Kmeans聚類和密度聚類的效果圖顏色一致,通過序列的map“方法”對顏色作重映射)
ax2.scatter(plot_data.x1, plot_data.x2, c=plot_data.dbscan_label.map({-1:1,0:0,1:3,2:2}))
# 顯示圖形
plt.show()

# 構造兩個球形簇的數據樣本點
X,y = make_blobs(n_samples = 2000, centers = [[-1,0],[1,0.5]], cluster_std = [0.2,0.45], random_state = 1234)
# 將模擬得到的數組轉換為數據框,用於繪圖
plot_data = pd.DataFrame(np.column_stack((X,y)), columns = ['x1','x2','y'])
# 繪制散點圖(用不同的形狀代表不同的簇)
sns.lmplot('x1', 'x2', data = plot_data, hue = 'y',markers = ['^','o'],
fit_reg = False, legend = False)
# 顯示圖形
plt.show()

# 設置大圖框的長和高
plt.figure(figsize = (16,5))
# 設置第一個子圖的布局
ax1 = plt.subplot2grid(shape = (1,3), loc = (0,0))
# 層次聚類--最小距離法
agnes_min = cluster.AgglomerativeClustering(n_clusters = 2, linkage='ward')
agnes_min.fit(X)
# 繪制聚類效果圖
ax1.scatter(X[:,0], X[:,1], c=agnes_min.labels_)

# 設置第二個子圖的布局
ax2 = plt.subplot2grid(shape = (1,3), loc = (0,1))
# 層次聚類--最大距離法
agnes_max = cluster.AgglomerativeClustering(n_clusters = 2, linkage='complete')
agnes_max.fit(X)
ax2.scatter(X[:,0], X[:,1], c=agnes_max.labels_)

# 設置第三個子圖的布局
ax2 = plt.subplot2grid(shape = (1,3), loc = (0,2))
# 層次聚類--平均距離法
agnes_avg = cluster.AgglomerativeClustering(n_clusters = 2, linkage='average')
agnes_avg.fit(X)
plt.scatter(X[:,0], X[:,1], c=agnes_avg.labels_)
plt.show()

# 讀取外部數據
Province = pd.read_excel(r'F:\\python_Data_analysis_and_mining\\16\\Province.xlsx')
Province.head()
# 繪制出生率與死亡率散點圖
plt.scatter(Province.Birth_Rate, Province.Death_Rate, c = 'steelblue')
# 添加軸標簽
plt.xlabel('Birth_Rate')
plt.ylabel('Death_Rate')
# 顯示圖形
plt.show()

# 讀入第三方包
from sklearn import preprocessing

# 中文亂碼和坐標軸負號的處理
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 選取建模的變量
predictors = ['Birth_Rate','Death_Rate']
# 變量的標准化處理
X = preprocessing.scale(Province[predictors])
X = pd.DataFrame(X)
# 構建空列表,用於保存不同參數組合下的結果
res = []
# 迭代不同的eps值
for eps in np.arange(0.001,1,0.05):
# 迭代不同的min_samples值
for min_samples in range(2,10):
dbscan = cluster.DBSCAN(eps = eps, min_samples = min_samples)
# 模型擬合
dbscan.fit(X)
# 統計各參數組合下的聚類個數(-1表示異常點)
n_clusters = len([i for i in set(dbscan.labels_) if i != -1])
# 異常點的個數
outliners = np.sum(np.where(dbscan.labels_ == -1, 1,0))
# 統計每個簇的樣本個數
stats = str(pd.Series([i for i in dbscan.labels_ if i != -1]).value_counts().values)
res.append({'eps':eps,'min_samples':min_samples,'n_clusters':n_clusters,'outliners':outliners,'stats':stats})
# 將迭代后的結果存儲到數據框中
df = pd.DataFrame(res)
# 根據條件篩選合理的參數組合
df.loc[df.n_clusters == 3, :]
# 利用上述的參數組合值,重建密度聚類算法
dbscan = cluster.DBSCAN(eps = 0.801, min_samples = 3)
# 模型擬合
dbscan.fit(X)
Province['dbscan_label'] = dbscan.labels_
# 繪制聚類聚類的效果散點圖
sns.lmplot(x = 'Birth_Rate', y = 'Death_Rate', hue = 'dbscan_label', data = Province,
markers = ['*','d','^','o'], fit_reg = False, legend = False)
# 添加省份標簽
for x,y,text in zip(Province.Birth_Rate,Province.Death_Rate, Province.Province):
plt.text(x+0.1,y-0.1,text, size = 8)
# 添加參考線
plt.hlines(y = 5.8, xmin = Province.Birth_Rate.min(), xmax = Province.Birth_Rate.max(),
linestyles = '--', colors = 'red')
plt.vlines(x = 10, ymin = Province.Death_Rate.min(), ymax = Province.Death_Rate.max(),
linestyles = '--', colors = 'red')
# 添加軸標簽
plt.xlabel('Birth_Rate')
plt.ylabel('Death_Rate')
# 顯示圖形
plt.show()

# 利用最小距離法構建層次聚類
agnes_min = cluster.AgglomerativeClustering(n_clusters = 3, linkage='ward')
# 模型擬合
agnes_min.fit(X)
Province['agnes_label'] = agnes_min.labels_
# 繪制層次聚類的效果散點圖
sns.lmplot(x = 'Birth_Rate', y = 'Death_Rate', hue = 'agnes_label', data = Province,
markers = ['d','^','o'], fit_reg = False, legend = False)
# 添加軸標簽
plt.xlabel('Birth_Rate')
plt.ylabel('Death_Rate')
# 顯示圖形
plt.show()

# 導入第三方模塊
from sklearn import metrics

# 構造自定義函數,用於繪制不同k值和對應輪廓系數的折線圖
def k_silhouette(X, clusters):
K = range(2,clusters+1)
# 構建空列表,用於存儲個中簇數下的輪廓系數
S = []
for k in K:
kmeans = cluster.KMeans(n_clusters=k)
kmeans.fit(X)
labels = kmeans.labels_
# 調用字模塊metrics中的silhouette_score函數,計算輪廓系數
S.append(metrics.silhouette_score(X, labels, metric='euclidean'))

# 中文和負號的正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 設置繪圖風格
plt.style.use('ggplot')
# 繪制K的個數與輪廓系數的關系
plt.plot(K, S, 'b*-')
plt.xlabel('簇的個數')
plt.ylabel('輪廓系數')
# 顯示圖形
plt.show()

# 聚類個數的探索
k_silhouette(X, clusters = 10)

# 利用Kmeans聚類
kmeans = cluster.KMeans(n_clusters = 3)
# 模型擬合
kmeans.fit(X)
Province['kmeans_label'] = kmeans.labels_
# 繪制Kmeans聚類的效果散點圖
sns.lmplot(x = 'Birth_Rate', y = 'Death_Rate', hue = 'kmeans_label', data = Province,
markers = ['d','^','o'], fit_reg = False, legend = False)
# 添加軸標簽
plt.xlabel('Birth_Rate')
plt.ylabel('Death_Rate')
plt.show()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM