จัดกลุ่มข้อมูลด้วย K-Means โดยใช้ Python
Published: 2024-04-17 19:07:27

หากการจัดกลุ่มให้กับชุดข้อมูลที่มีจำนวนมาก และไม่ได้ผ่านการจัดกลุ่มมาก่อนเลย เป็นเพียงข้อมูลดิบที่จัดเรียงกันอย่างไม่มีหลักการ เป็นการจัดกลุ่มที่ยากและต้องใช้เวลาอย่างมาก หนึ่งในวิธีที่เหมาะสมกับการนำมาใช้คือ การจัดกลุ่มด้วย K-Means

ในบทความนี้จะมาศึกษาการใช้ K-means ด้วย Python และจะทำการรันโค้ดใน Google Colab โดย Dataset ที่เราจะใช้คือ Wine Dataset for Clustering ที่นำมาจาก UC Irvine Machine Learning Repository

ข้อมูลเหล่านี้เป็นผลลัพธ์ของการวิเคราะห์ทางเคมีของไวน์ที่ปลูกในภูมิภาคเดียวกันในอิตาลี เป็นปริมาณของส่วนประกอบ 13 ชนิดที่พบในไวน์แต่ละประเภท จากสามประเภท
ข้อมูลประกอบด้วย

1. Alcohol
2. Malic acid
3. Ash
4. Alcalinity of ash
5. Magnesium
6. Total phenols
7. Flavanoids
8. Nonflavanoid phenols
9. Proanthocyanins
10. Color intensity
11. Hue
12. OD280/OD315 of diluted wines
13. Proline



## ขั้นตอนที่ 1 : โหลดชุดข้อมูล และศึกษารายละเอียดของชุดข้อมูล

Import Library ที่จำเป็นต้องใช้

```
import math
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.cluster import KMeans 
from kneed import KneeLocator
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
```

```
import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
```

โหลดชุดข้อมูลตัวอย่าง

```
wine_df = pd.read_csv("/kaggle/input/wine-dataset-for-clustering/wine-clustering.csv", )
wine_df
```

ชุดข้อมูลที่ได้

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4jiqsao58g1o0lim3e9.png)

## ขั้นตอนที่ 2 : เริ่มต้นการใช้ K-Means

ทำให้ชุดข้อมูลเป็นมาตรฐาน

```
sc = StandardScaler()
wine_df_sc = sc.fit_transform(wine_df)
```

## ขั้นตอนที่ 3 : วิเคราะห์หาจำนวนกลุ่มที่เหมาะสมด้วยหลักการ Elbow

```
WSS = []

for i in range (1,15):
    kmeans = KMeans(n_clusters=i, n_init=10)
    kmeans.fit(wine_df_sc)
    WSS.append(kmeans.inertia_)
    
kl = KneeLocator(range(1, 15), WSS, curve="convex", direction="decreasing")
optimal_k = kl.elbow
print("Optimal number of clusters: ", optimal_k)
plt.figure(figsize=(10,6))
plt.title("Elbow Analysis", fontsize=18)
sns.lineplot(x=list(range(1,15)), y=WSS, color="blue", marker="o", markersize=16)
plt.xlabel("Number of clusters")
plt.ylabel("WSS")
plt.vlines(optimal_k, plt.ylim()[0], plt.ylim()[1], linestyles='dashed')
plt.show()
```

จุดของกราฟที่หักมากที่สุดเหมือนข้อศอก จะเป็นจุดที่บ่งบอกจำนวนของกลุ่มที่เหมาะสม จากภาพจะเป็นจำนวน 3 กลุ่ม

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iwa4alxrs1lrwovfhja.png)

## ขั้นตอนที่ 4 : ตรวจสอบ และยืนยันจำนวนกลุ่มที่เหมาะสมด้วยหลักการ Silhouette

```
silhouette = []

for i in range(2,15):
    kmeans = KMeans(n_clusters=i, n_init=10)
    cluster_labels = kmeans.fit_predict(wine_df_sc)
    silhouette.append(silhouette_score(wine_df_sc,cluster_labels))   

plt.figure(figsize=(10,6))
plt.title("Silhouette Analysis", fontsize=18)
sns.lineplot(x=list(range(2,15)), y=silhouette, color="green", marker="o", markersize=16)
plt.xlabel("Number of clusters")
plt.ylabel("Silhouette Score")
plt.show()
```

```
print("Best Silhouette Clustering is : ", max(silhouette), "with ", silhouette.index(max(silhouette))+2)
```

จะได้ภาพกราฟ พร้อมกับคำตอบว่าจำนวนกลุ่มที่เหมาะคือ 3

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6h9vcugko58ozkk7q12.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dbmhfi6s2t39zmuptmpw.png)

## ขั้นตอนที่ 5 : ใช้วิธี K-Means

กำหนดจำนวนกลุ่มที่เหมาะสมเป็น 3 กลุ่มที่ได้วิเคราะห์ไว้ จะได้ข้อมูลที่ถูกแบ่งเป็น 3 กลุ่มเรียบร้อยแล้ว

```
kmeans = KMeans(n_clusters=3, n_init=10, random_state=51)
kmeans.fit(wine_df_sc)
wine_df['Cluster']=kmeans.labels_
```

```
wine_df.groupby('Cluster').describe(percentiles=[])
```

(เนื่องจากภาพยาวเกินไปจึงตัดเป็น 2 ภาพ)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/god9ouhr89wd8hbpb0x6.jpg)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsg3ml8c1dn2kpemu35h.jpg)

## ขั้นตอนที่ 6 : แสดงผล

แสดงภาพผลลัพธ์

```
from sklearn.decomposition import PCA

data=wine_df.drop("Cluster",axis=1).values
data_sc=sc.fit_transform(data)
pca=PCA(n_components=2)
principal_components = pca.fit_transform(data_sc)
df_pca = pd.DataFrame(principal_components, columns=['PC1', 'PC2'])
df_pca['Cluster']=wine_df['Cluster']

plt.figure(figsize=(10, 7))  
plt.title('Clustering Results using PCA', fontsize=18)
sns.scatterplot(data=df_pca, x='PC1', y='PC2', hue="Cluster", palette="magma", s=100)
plt.grid()
plt.show()
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5m8qnnf034pvumikoej.PNG)

แสดงข้อมูล

```
cluster_means=wine_df.groupby('Cluster').mean()
cluster_means
```

(เนื่องจากภาพยาวเกินไปจึงตัดเป็น 2 ภาพ)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmhfzy7qtffue14xhws0.jpg)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxj9aff365urubol09nx.jpg)

## สรุปผล

จากการนำข้อมูลปริมาณส่วนประกอบของไวน์ต่าง ๆ มาจัดกลุ่มด้วยวิธี K-means จะสามารถแบ่งออกได้เป็น 3 กลุ่ม ดังนี้
กลุ่มที่ 0 เป็นกลุ่มไวน์ที่มี Magnesium และ Proline ในปริมาณที่สูง
กลุ่มที่ 1 เป็นกลุ่มไวน์ที่มีค่า Flavanoid และ Hue ต่ำ แต่มี Color Intensity สูง
กลุ่มที่ 2 เป็นกลุ่มไวน์ที่มี Magnesium และ Color Intensity ต่ำ

🎉