๐ ๊ผญ K๊ฐ ๋ค์ด๊ฐ์ ํ๊ตญ ๋ถ์ฌ์ผ๋ก ๊ผญ ์์์ผ(?)ํ ๊ฒ ๋ง ๊ฐ์ ๋ฐ,, ํ์๋ก ์์์ผ ํ๋ ๊ฐ๋ ๋ง์ฆ!
๐ ์์ ์ฐ๋ฆฌ๊ฐ Unsupervised Learning์ ์ผ์ข ์ผ๋ก ๋ํ์ ์ธ clustering ๊ฐ๋ ์ ๋ํด์ ๋ฐฐ์ ๊ณ , ์ด ์ค ๊ฐ์ฅ ๋ํ์ ์ธ K-Means์ ๋ํด์ ์์๋ณด์!
Unsupervised Learning
๐ ์ฌ์ค ML์์ ์ง๋ํ์ต(Supervised Learning)๋ณด๋ค ์ ๋ต์ด ์ฃผ์ด์ ธ ์์ง ์์, ๋น์ง๋ํ์ต(Unsupervised Learning) ๊ธฐ๋ฒ์ด ๋ ๊น๋ค๋กญ๊ณ , ์ ๋ต์ด ์ฃผ์ด์ ธ ์์ง ์์์ ๋ถ์์ ํ์ด ๋ค ๋๊ฐ ๋ง๋ค. ๐ ๋น์ง๋ํ์ต
sh-avid-learner.tistory.com
๐ ์ผ๋จ k-means๋ unsupervised learning ๊ธฐ๋ฒ ์ค clustering - centroid-based clustering (hard clustering)๊ธฐ๋ฒ์ด๋ค.
step-by-step>
โ cluster์ ๊ฐ์ k๋ฅผ ์ ํ๋ค (k๋ฅผ ์ ํ๋ ๋ฐฉ๋ฒ์ ํ๋จ ๋ด์ฉ ์ฐธ์กฐ!) (์๋ algorithm1 ์์ 1)
โก ์ฃผ์ด์ง data์์ ๋๋คํ k๊ฐ์ data๋ฅผ cluster์ ์ค์ฌ์ ์ผ๋ก ์ค์ ํ๋ค. (์๋ algorithm1 ์์ 2)
โข ์ฒซ ๋ฒ์งธ data์์ ๊ฐ cluster ์ค์ฌ์ ๊น์ง์ ๊ฑฐ๋ฆฌ๋ฅผ cluster๋ณ๋ก ๊ฐ๊ฐ ๊ตฌํ๋ค. (์๋ algorithm1 ์์ 4)
โฃ ๊ฐ cluster๋ณ๋ก ๊ตฌํ ๊ฑฐ๋ฆฌ ์ค ์ต์๊ฐ์ ํด๋น๋๋ cluster๋ก ํด๋น data๋ฅผ ํ ๋นํ๋ค. (์๋ algorithm1 ์์ 5)
โค โข๊ณผ โฃ์ ๊ณผ์ ์ ๋ชจ๋ data์ ๋ํด ๋ฐ๋ณตํ๋ค. (์๋ algorithm line 3 - repeat)
(โปscikit-learn์์๋ KMeans()์ ์ธ์ max_iter๋ก ์กฐ์ )
โฅ ๋ณ๊ฒฝ๋ cluster ๊ฐ๊ฐ์ ์ค์ฌ์ (mean)์ ๋ค์ ๊ตฌํ๋ค.
โฆ ๋ณ๊ฒฝ๋ cluster ๊ธฐ์ค์ผ๋ก ๋ค์ ๋ชจ๋ data์ ๋ํด โข๊ณผ โฃ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค. (์๋ algorithm ์์ 6)
โง cluster๊ฐ ๋ณํ์ง ์์ผ๋ฉด ์์ฑ!
→ ์ ๊ณผ์ โฃ์์ ์ธ๊ธํ ๊ฐ cluster๋ณ ๊ตฌํ ๊ฑฐ๋ฆฌ๋ '๊ฐ data๋ณ ๊ฐ cluster๋ณ centroid์์ Euclidean distance'์ด๋ค. ์ด distance๊ฐ ๊ฐ์ฅ ์ ๊ฒ ๋์จ centroid๊ฐ ํฌํจ๋ cluster์ data๊ฐ ํฌํจ๋๋ค.
๐ clustering์ ํ๊ฐ?
→ ์ค์ฌ์ ์ด ๋ณํ์ง ์์๊ณ ์ต์ข ์ ์ผ๋ก k-means clustering์ด ๋ง๋ฌด๋ฆฌ ๋์๋ค๊ณ ํด์ ๋๋๊ฒ ์๋๋ค. ํด๋น clustering์ ์ ์ ์ฑ ํ๊ฐ๋ฅผ ์ํด ๊ฐ๊ฐ ๋ชจ๋ data์ ํด๋น data๊ฐ ์ํ cluster์ centroid์์ squared Euclidean Distance๋ฅผ data๋ณ๋ก ๋ชจ๋ ๋ํ ๊ฐ์ ์ดํด๋ณธ๋ค.
(โป ํด๋น ๋ํ ์ต์ข ๊ฐ์ SSE(Sum of Squared Error)๋ผ๊ณ ๊ฐ๋ตํ ๋ถ๋ฆ)
→ ์ k-means ํน์ง์ ๋ํด์ ์ธ๊ธํ๋ฏ์ด, k-means๋ non-deterministic์ด๋ผ ์ฒ์์ centroid๋ฅผ ์ด๋ป๊ฒ ์ก๋๋์ ๋ฐ๋ผ ๋ค๋ฅธ clustering ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์๋ ์๋ค. ์ฆ ์ด๊ธฐ ์ํ์ ๋ฐ๋ผ SSE๊ฐ์ด ์ ๊ฐ๊ฐ์ด๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก ์ฐ๊ตฌ์๋ค์ โ ๋ช ๋ฒ์ ์ด๊ธฐํ๋ฅผ ํตํด SSE๊ฐ ๊ฐ์ฅ ์ต์๊ฐ์ผ๋ก ๋์จ ๊ฒฝ์ฐ๋ฅผ ์ต์ข k-means clustering ๊ฒฐ๊ณผ๋ก ํํ๋ค.
* KMeans() (from scikit-learn)>
ใsklearn.cluster.KMeans() docuใ
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html
class sklearn.cluster.KMeans(n_clusters=8, *, init='k-means++', n_init=10, max_iter=300, tol=0.0001, verbose=0, random_state=None, copy_x=True, algorithm='lloyd')
- param ์ค๋ช -
๐ n_clusters - cluster ๊ฐ์
๐ init - '‘k-means++’ : selects initial cluster centers for k-mean clustering in a smart way to speed up convergence. See section Notes in k_init for more details. / ‘random’: choose n_clusters observations (rows) at random from data for the initial centroids.'
→ 'k-means++'๋ฅผ init ๊ฐ์ผ๋ก ์ค์ ํ๋ฉด, ์ข ๋ ๋นจ๋ฆฌ centroid๋ฅผ ์ฐพ์ ์ ์๊ฒ ์ ํฉํ clustering inital state์์ ์์๋๋ค.
→ 'random'์ผ ๊ฒฝ์ฐ ์ ํฉํ initial state๊ฐ ์๋, ์จ์ ํ randomํ ์ง์ ๋ถํฐ clustering algorithm ์ฐ์ฐ์ด ์์๋๋ค.
๐ n_init - ์ด๊ธฐํ ์นด์ดํ : ์์์ ์ธ๊ธํ๋ฏ์ด ์คํํ ๋ n_init๋ฒ clusteirng์ ์งํํ๊ณ , n_init๋ฒ์ clusteirng ์ค ๊ฐ์ฅ SSE๊ฐ ์ ๊ฒ ๋์จ ๊ฒฐ๊ณผ์ clustering ๊ฒฐ๊ณผ๋ฅผ ์ฑํํ๊ฒ ๋๋ค
๐ max_iter - clustering์์ ์ต๋ max_iter๋ฒ ํ ๋ค์ ๊ฒฐ๊ณผ๋ฅผ cluster์ centroid๋ก ์ ํ๋ค. (max_iter๋ฒ ํ๊ธฐ ์ ์ ์ด๋ฏธ centroid๊ฐ ๋ ์ด์ ๋ณํ์ง ์๋๋ค๋ฉด ๋ฐ๋ก clustering ๊ฒฐ๊ณผ๋ก ์ฑํ)
- attributes -
๐ cluster_centers_ - clusteringํ๊ณ ๋ ๋ค์ ๊ฐ๊ฐ์ cluster centroid ์ขํ๋ฅผ returnํด์ค๋ค.
๐ inertia_ - ์ฌ๋ฌ ๋ฒ์ initialization์ผ๋ก ์คํํ, ์ฌ๋ฌ ๊ฐ์ ์ต์ข cluster ์ค SSE๊ฐ ๊ฐ์ฅ ์ต์๊ฐ์ผ๋ก ๋์จ ๊ฒฐ๊ณผ๋ฅผ return
๐ labels_ - ๋ถ๋ฅํ label ์ด๋ฆ return
๐ n_iter_ - ์์์ max_iter ์ต๋ ํ์ ๋ด์์ ์ต์ข ์ ์ผ๋ก n_iter๋ฒ๋งํผ repeatํ ๋ค centroid๋ฅผ ํ์ฑํ๋ ์ง, n_iter ๊ฒฐ๊ด๊ฐ์ ์๋ ค์ค๋ค
(โป ๋น์ฐํ init๊ฐ์ 'k-means++'๋ก ์ค์ ํ์ ๊ฒฝ์ฐ n_iter๊ฐ์ด ๋ ์ ์ ๊ฒฐ๊ด๊ฐ์ผ๋ก ๋์จ๋ค)
โ kmeans.fit()์ data๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋! โ
how to select the best K?>
* ์ผ๋จ KMeans() ํจ์์ n_clusters ์ธ์๋ฅผ ์ ์ธํ ๋๋จธ์ง ์ธ์๋ค์ ์ํ๋ ๋๋ก ์ค์ ํ๋ค.
kmeans_kwargs = {
"init": "random",
"n_init": 10,
"max_iter": 300
}
1> using elbow method (+KneeLocator)
ใ SSE๊ฐ์ ๋ณํ๋ฅผ ์ดํด๋ณด๋ method์ด๋ค. cluster ๊ฐ์๊ฐ ์ฆ๊ฐํ ์๋ก SSE๊ฐ ๊ฐ์ํ๋๋ฐ, SSE๊ฐ ์ต์๊ฐ ๋๋ ์ง์ ์ '๋ชจ๋ data๊ฐ ๊ฐ๊ฐ์ cluster๋ฅผ ํ์ฑํ์ ๋'์ด๋ค. ๋ฐ๋ผ์, ์ด๋ ์ ์ ํ ์์ ์ cut ํด ์ฃผ์ด์ผ ํ๋ค. cut ํด์ฃผ๋ ์ง์ ์ SSE๊ฐ ํฐ ํญ์ผ๋ก ๊ฐ์ํ๋ ์ง์ ์ผ๋ก ์ ํจ!
ใ SSE๋ ์์์ ์ธ๊ธํ kmeans์ inertia_ ์์ฑ!
ใ 1) ์ง์ ์๊ฐํํด์ ํฌ๊ฒ ๊ฐ์ํ point์ cluster ๊ฐ์๋ฅผ ์ก์๋ด๋ ๋ฐฉ๋ฒ!
# A list holds the SSE values for each k
sse = []
for k in range(1, 11):
kmeans = KMeans(n_clusters=k, **kmeans_kwargs)
kmeans.fit(scaled_features)
sse.append(kmeans.inertia_)
plt.style.use("fivethirtyeight") #ํ์ ์ฌ์ฉํ ๋๋ default๋ก ๋ฐ๊ฟ์ค์ผ ํจ!
plt.plot(range(1, 11), sse)
plt.xticks(range(1, 11))
plt.xlabel("Number of Clusters")
plt.ylabel("SSE")
plt.show()
→ number of clusters๊ฐ 3์ธ point์์ ํฐ ํญ์ผ๋ก ๊ฐ์๋ ์ง์ ์ด๋ผ ํ ์ ์์ผ๋ฏ๋ก k๋ 3์ผ๋ก ์ง์ ํด์ผ ์ ๋นํ๋ค.
ใ 2) KneeLocator๋ฅผ ์ฌ์ฉ - elbow ์์ฑ ์ถ๋ ฅ
kl = KneeLocator(
range(1, 11), sse, curve="convex", direction="decreasing"
)
kl.elbow #3
→ 3 ๋ฐ๋ก ์ถ๋ ฅ
2> using silhouette coefficient
๐ฅ ์ค๋ฃจ์ฃ ๊ณ์๋ ์ด ๋ ๊ฐ์ง๋ฅผ ํ๊ฐํ๋ค. (1) ํด๋น data๊ฐ cluster ๋ด์์ ์ผ๋ง๋ ๋ค๋ฅธ data์ ๊ฐ๊น๊ฒ ์๋ ์ง / (2) ํด๋น data๊ฐ ๋ค๋ฅธ cluster์ ์ผ๋ง๋ ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋ ์ง - ์ฆ! ํด๋น data๊ฐ ๋ค๋ฅธ cluster๋ก๋ถํฐ๋ ๋ฉ๋ฆฌ, ์์ ์ด ์ํ cluster์์๋ ๋ค๋ฅธ data์ ๊ฐ๊น์ด ์ง - ์ผ๋ง๋ ์ ๋ชจ์ฌ์๋ ์ง๋ฅผ ํ์ธํ๋ ์ฒ๋!
๐ฅ -1๊ณผ 1 ์ฌ์ด์ ๊ฐ์ ๊ฐ์ง๋ฉฐ, ๋จ์ ์ผ๋ก ๊ฐ ํ๋๋ก ์ถ๋ ฅ์ด ๋๊ธฐ ๋๋ฌธ์ k๊ฐ์ ๊ฒฐ์ ํ๊ธฐ ๋งค์ฐ ํธ๋ฆฌํ๋ค๊ณ ํ ์ ์๋ค.
๐ฅ 1์ ๊ฐ๊น์ด ํฐ ๊ฐ์ผ์๋ก best choice๋ผ ํ๊ฐํจ!
๐ฅ silhouette_score method๋ฅผ ํตํด ์ ์ ์์ผ๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ์ฐ์ถํ๊ธฐ ์ํด์ ๋น์ฐํ ์ต์ ๋ ๊ฐ์ cluster๊ฐ ํ์(๋ค๋ฅธ cluster์์ ๋จผ ์ ๋๋ฅผ ์ธก์ ํ๋ฏ๋ก)ํ๊ณ data(์ขํ)์ ํจ๊ป ์ง์ด๋ฃ์ผ๋ฉด ๋๋ค
from sklearn.metrics import silhouette_score
# A list holds the silhouette coefficients for each k
silhouette_coefficients = []
# Notice you start at 2 clusters for silhouette coefficient
for k in range(2, 11):
kmeans = KMeans(n_clusters=k, **kmeans_kwargs)
kmeans.fit(scaled_features)
score = silhouette_score(scaled_features, kmeans.labels_)
silhouette_coefficients.append(score)
plt.style.use("fivethirtyeight")
plt.plot(range(2, 11), silhouette_coefficients)
plt.xticks(range(2, 11))
plt.xlabel("Number of Clusters")
plt.ylabel("Silhouette Coefficient")
plt.show()
→ ๊ฐฏ์๋ก ์ ํ 3์์ ์ค๋ฃจ์ฃ ๊ณ์๊ฐ์ด ๊ฐ์ฅ ํฐ ๊ฐ์ด ๋์ค๋ฏ๋ก ์ญ์ (ํด๋น data์ ๊ฒฝ์ฐ) 3์ k๋ก ์ ํ๋ฉด ๋๋ค.
w/code(using scikit-learn)>
โ import ๋ฐ clustering์ ์ํ random data ์ค๋น (make_blobs ์ฌ์ฉ)
(unsupervised learning์ ์ผ์ข ์ด๋ผ label ์์ฒด๊ฐ ์๋ data๋ฅผ clusteringํ๋ ๋ฐ,
ํด๋น data์ ๊ฒฝ์ฐ label์ด ์ด๋ฏธ ์ฃผ์ด์ ธ ์๋ค.
์ฌ๊ธฐ์๋ ์ฐ๋ฆฐ ๋จ์ํ KMeans()๋ก ์ค์ ๋ก ์ ๋ถ๋ฅ๊ฐ ๋์๋ ์ง ํ์ธํ๋ ๊ณผ์ ์ผ ๋ฟ)
import matplotlib.pyplot as plt
from kneed import KneeLocator
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
import matplotlib
import seaborn as sns
import matplotlib.pyplot as pyplot
from matplotlib import pyplot as plt
โฃ make_blobs docu() โฃ
https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html
'clustering์ ์ํ data๋ฅผ random์ผ๋ก ์์ฑํด์ค๋ค'
sklearn.datasets.make_blobs(n_samples=100, n_features=2, *, centers=None, cluster_std=1.0, center_box=(- 10.0, 10.0), shuffle=True, random_state=None, return_centers=False)
โถ 500๊ฐ์ data๊ฐ 3๊ฐ์ cluster(cluster ํ์คํธ์ฐจ๋ 3.75)๋ฅผ ํ์ฑํ๋ randomํ data๋ฅผ ์ ํํ๋ค.
#data prepared
features, true_labels = make_blobs(
n_samples=500,
centers=3,
cluster_std=3.75
)
โก standardization (*StandardScaler() ์ฌ์ฉ)
โถ ์ถ ๋ณ๋ก ๋์ผํ scale์ ๊ฐ์ง๊ฒ๋ standardization ๊ณผ์ ์ ๊ฑฐ์นจ์ผ๋ก์, data์ ์ด๋ ํ variable์ ์น์ฐ์น ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง ์๊ฒ ํ๋ค.
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
โข cluster ๊ฐ์ k ์ ํ๊ธฐ
โถ ์ elbow method & silhouette coefficients ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ํตํด k๋ฅผ 3์ผ๋ก ์ ํ์ (์ ์ฐธ์กฐ)
โฃ KMeans() ๋๋ฆฌ๊ธฐ & data fitting
โถ ์ด ๋ scaling๋ data๋ฅผ ์ง์ด๋ฃ์ด์ผ ํจ์ ์์ง ๋ง๊ธฐ!
kmeans = KMeans(
init = 'random',
n_clusters = 3,
n_init=10,
max_iter=300
#random_state=42
)
kmeans.fit(scaled_features)
โค ์ ๋ฆฌ๋ dataframe ๋ง๋ค๊ธฐ
โถ2์ฐจ์ data์ด๋ฏ๋ก scaled๋ ๋ชจ๋ data์ x์ y์ขํ - ๊ฐ๊ฐ์ data์ ์ค์ label & KMeans๋ก ๋ถ๋ฅํ label์ ๋๋ํ ๋ง๋ค์ด๋ณธ๋ค.
#making a dataframe
df = pd.DataFrame(scaled_features)
df.columns = ['x', 'y']
df['true_label'] = true_labels.tolist()
df['KMeans_label'] = KMeans_labels.tolist()
df
โถ ์ฌ๊ธฐ์ true_label๊ณผ KMeans_label ์ซ์๊ฐ ๋ง์ง ์์์ ๋ณผ ์ ์๋๋ฐ, ์ซ์๋ kmeans initializationํ ๋ ๋ง๋ค ๊ทธ ๋ ๊ทธ ๋ ๋ฌ๋ผ์ง๋ ์์์ ๊ฐ์ด๋ฏ๋ก ์๊ดํ ํ์ x
โฅ ์๊ฐํ
โถ kmeans๋ก ์ ๋ถ๋ฅ๋์๋ ์ง ์ก์์ผ๋ก ํ์ธํด ๋ณด๊ธฐ ์ํด 2์ฐจ์ graph๋ก ์๊ฐํ
centroids = kmeans.cluster_centers_
plt.style.use("default")
def plot_clusters(df, column_header, centroids):
colors = {0 : '#42f557', 1 : '#427ef5', 2 : '#f54842'}
fig, ax = plt.subplots()
plt.rcParams["figure.figsize"] = (6,6)
ax.plot(centroids[0][0], centroids[0][1], "ok") # ๊ธฐ์กด ์ค์ฌ์
ax.plot(centroids[1][0], centroids[1][1], "ok")
ax.plot(centroids[2][0], centroids[2][1], "ok")
grouped = df.groupby(column_header)
for key, group in grouped:
group.plot(ax = ax, kind = 'scatter', x = 'x', y = 'y', label = key, color = colors[key])
plt.show()
plot_clusters(df, 'KMeans_label', centroids)
→ ์๊ฐํ ๊ฒฐ๊ณผ clustering๋ data๋ฅผ ์๊น๋ณ ํ์ธ ๊ฐ๋ฅ!
* ์ถ์ฒ1) ๊ฐ STATQUEST https://www.youtube.com/watch?v=4b5d3muPQmA
* ์ถ์ฒ2) K-means & hierchical clustering https://www.youtube.com/watch?v=QXOkPvFM6NU
* ์ถ์ฒ3) kmeans code ์ฐธ์กฐ https://realpython.com/k-means-clustering-python/
* ์ถ์ฒ4) kmeans ์๊ฐํ & elbow method https://www.askpython.com/python/examples/plot-k-means-clusters-python
'Machine Learning > Models (with codes)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
(L1 Regularization) โ LASSO Regression (concepts) (0) | 2022.06.23 |
---|---|
Decision Trees (concepts) (0) | 2022.04.27 |
Logistic Regression Model (w/code) (0) | 2022.04.25 |
Polynomial Regression Model (0) | 2022.04.24 |
Logistic Regression Model (concepts) (0) | 2022.04.24 |
๋๊ธ