Machine Learning – 27 – Clustering Algorithm

Clustering with K-Means:

Unsupervised learning-ல் நாம் கற்க இருக்கும் முதல் algorithm இதுவே. இதுவரை நாம் கண்ட அனைத்தும் supervised-ன் கீழ் அமையும். logistic regression, multi-class classification போன்ற அனைத்திலும், உள்ளீடு(X) மற்றும் வெளியீடு(Y) இரண்டையும் கொடுத்து பயிற்சி அளிப்போம். பல்வேறு வெளியீட்டு வகைகளின் கீழ் தரவுகளைப் பிரிப்பதற்கு அத்தனை வகையான எல்லைகளையும் நாமே வரையறை செய்வோம். ஆனால் இந்த unsupervised-ல் வெறும் உள்ளீடுகள் மட்டுமே கொடுக்கப்படும். எத்தனை வகையில் பிரிக்க வேண்டும் என்பதோ, அவற்றின் எல்லைகள் என்ன என்பதோ கொடுக்கப்படாது. இது போன்ற clustering-ல் எல்லைகள் K-means மூலமாக கணக்கிடப்படுகின்றன. எவ்வளவு வகைகளில் பிரிக்க வேண்டும் என்பதை elbow method-மூலம் கணக்கிடலாம். அதாவது ஒரு வரையறையைக் கொடுத்து கற்கச் சொல்லுவது supervised என்றால், எவ்வித வரையறையும் இல்லாமல் கற்கச் சொல்லுவது unsupervised ஆகும்.

கீழ்க்கண்ட உதாரணத்தில் X1, X2 எனும் இரண்டு அம்சங்கள்(features) கொடுக்கப்பட்டுள்ளன. Y என்று எதுவும் இல்லை. அதாவது வெறும் உள்ளீட்டுக்கான தரவுகளைக் கொண்டு மட்டுமே நாமாகவே பல்வேறு குழுக்களில் அவற்றை வகைப்படுத்திக் கொடுக்க வேண்டும்.

x1 = [15, 19, 15, 5, 13, 17, 15, 12, 8, 6, 9, 13]
x2 = [13, 16, 17, 6, 17, 14, 15, 13, 7, 6, 10, 12]

இதற்கான நிரல் மற்றும் விளக்கம் பின்வருமாறு.


import matplotlib.pyplot as plt
import math
def plots(cluster1_x1,cluster1_x2,cluster2_x1,cluster2_x2):
plt.figure()
plt.plot(cluster1_x1,cluster1_x2,'.')
plt.plot(cluster2_x1,cluster2_x2,'*')
plt.grid(True)
plt.show()
def round1(c1_x1,c1_x2,c2_x1,c2_x2):
cluster1_x1 = []
cluster1_x2 = []
cluster2_x1 = []
cluster2_x2 = []
for i,j in zip(x1,x2):
a = math.sqrt(((i-c1_x1)**2 + (j-c1_x2)**2))
b = math.sqrt(((i-c2_x1)**2 + (j-c2_x2)**2))
if a < b:
cluster1_x1.append(i)
cluster1_x2.append(j)
else:
cluster2_x1.append(i)
cluster2_x2.append(j)
plots(cluster1_x1,cluster1_x2,cluster2_x1,cluster2_x2)
c1_x1 = sum(cluster1_x1)/len(cluster1_x1)
c1_x2 = sum(cluster1_x2)/len(cluster1_x2)
c2_x1 = sum(cluster2_x1)/len(cluster2_x1)
c2_x2 = sum(cluster2_x2)/len(cluster2_x2)
round2 (c1_x1,c1_x2,c2_x1,c2_x2)
def round2(c1_x1,c1_x2,c2_x1,c2_x2):
cluster1_x1 = []
cluster1_x2 = []
cluster2_x1 = []
cluster2_x2 = []
for i,j in zip(x1,x2):
c = math.sqrt(((i-c1_x1)**2 + (j-c1_x2)**2))
d = math.sqrt(((i-c2_x1)**2 + (j-c2_x2)**2))
if c < d:
cluster1_x1.append(i)
cluster1_x2.append(j)
else:
cluster2_x1.append(i)
cluster2_x2.append(j)
plots(cluster1_x1,cluster1_x2,cluster2_x1,cluster2_x2)
x1 = [15, 19, 15, 5, 13, 17, 15, 12, 8, 6, 9, 13]
x2 = [13, 16, 17, 6, 17, 14, 15, 13, 7, 6, 10, 12]
plots(x1,x2,[],[])
round1(x1[4],x2[4],x1[10],x2[10])

view raw

clustering.py

hosted with ❤ by GitHub

முதலில் X1, X2 எனும் இரண்டு அம்சங்களும் எவ்வாறு அமைந்துள்ளன என்பதை scatter plot மூலம் காணலாம். இன்னும் இரண்டாவது கொத்தில் என்னென்ன அம்சங்களை அமைக்க வேண்டும் என்பது கண்டறியப்படவில்லை. எனவே அவை காலிப் பட்டியலாக அனுப்பப்படுகின்றன.

plots(x1,x2,[],[])

Centroids (திணிவுக்கான புள்ளி ):

இரண்டு clusters-ஐ உருவாக்குவதற்கு முதலில் X1-லிருந்து இரண்டு எண்களையும், X2-லிருந்து இரண்டு எண்களையும் random-ஆக தேர்வு செய்ய வேண்டும். முதல் கொத்துக்கு X1-லிருந்து 13-ஐயும், X2-லிருந்து 17-ஐயும் தேர்வு செய்துள்ளோம். அவ்வாறே இரண்டாவது கொத்துக்கு X1-லிருந்து 9-ஐயும், X2-லிருந்து 10-ஐயும் தேர்வு செய்துள்ளோம். இவையே திணிப்புக்கான புள்ளிகள் (centroids) என்றழைக்கப்படுகின்றன. அதாவது இவற்றை அடிப்படையாக வைத்தே அனைத்தையும் நாம் இரண்டு கொத்தாகப் பிரிக்கப் போகிறோம். எனவே இரண்டு அம்சங்களில் உள்ள ஒவ்வொரு தரவுகளுக்கும், தேர்ந்தெடுக்கப்பட்ட இரண்டு திணிப்புப் புள்ளிகளுக்குமான தூரம் கீழ்க்கண்ட வாய்ப்பாடு மூலம் கணக்கிடப்படுகிறது.
தூரம்1 = (x1_data – 13)**2 + (x2_data – 17)**2
தூரம்2 = (x1_data – 9)**2 + (x2_data – 10)**2

இந்த இரண்டு கொத்துக்களில் முதல் கொத்தினுடைய தூரம் குறைவாக இருந்தால் அந்தப் புள்ளிகள் முதல் கொத்திலும், இல்லையெனில் இரண்டாவது கொத்திலும் அமைக்கின்றன. இவை முறையே மஞ்சள் மற்றும் ஊதா நிறத்தில் மேற்கண்ட படத்தில் காட்டப்பட்டுள்ளது. இவ்வாறாக முதல் கொத்துக்கான x1, x2 மற்றும் இரண்டாவது கொத்துக்கான x1, x2 என்று 4 அம்சங்கள் கணக்கிடப்படுகின்றன. அவை முறையே புள்ளி வடிவிலும், நட்சத்திர வடிவிலும் வரைபடமாக வரைந்து காட்டப்படுகின்றன.
cluster1_x1 = [15, 19, 15, 13, 17, 15, 12]
cluster1_x2 = [13, 16, 17, 17, 14, 15, 13]
cluster2_x1 = [5, 8, 6, 9, 13]
cluster2_x2 = [6, 7, 6, 10, 12]

plots(cluster1_x1,cluster1_x2,cluster2_x1,cluster2_x2)

இவ்வாறாக முதலில் இரண்டு கொத்துக்கள் உருவாக்கப்பட்ட பின்னர், அவற்றிலிருந்து மீண்டும் இரண்டு திணிப்புப் புள்ளிகள் தேர்ந்தெடுக்கப்படுகின்றன. ஆனால் இம்முறை இவை random-ஆக தேர்வு செய்யப்படுவதில்லை. இரண்டு கொத்துக்களிலும் அமைந்துள்ள x1, x2-க்கான mean கணக்கிடப்பட்டு அவையே திணிப்புப் புள்ளிகளாக அமைகின்றன. எனவே இன்னும் சற்று துல்லியமான இரண்டு கொத்துக்களை நாம் உருவாக்க முடியும்.

c1_x1 = (15 + 19 + 15 + 13 + 17 + 15 + 12) / 7
= 106 / 7
= 15.14

c1_x2 = [13 + 16 + 17 + 17 + 14 + 15 + 13] / 7
= 105 / 7
= 15

c2_x1 = [5 + 8 + 6 + 9 + 13] / 5
= 41 / 5
= 8.2

c2_x2 = [6 + 7 + 6 + 10+ 12] / 5
= 41 / 5
= 8.2

பின்னர் மீண்டும் ஒவ்வொரு data-க்கும், கண்டறிந்த திணிப்புப் புள்ளிகளுக்குமான தூரம் கணக்கிடப்படுகிறது.அதில் குறைவான அளவு தூரம் கொண்ட தரவுகள் அவற்றுக்கான கொத்தில் இணைகின்றன. இவ்வாறாக இங்கு மீண்டும் இரண்டு கொத்துகள் உருவாக்கப்படுகிறது. இவை தரவுகளை இன்னும் சற்று துல்லியமாகப் பிரிப்பதைக் காணலாம்.

இவ்வாறாகத் தரவுகள் தனக்குரிய கொத்தில் சரிவரப் பொருந்தும் வரையிலும், இதனையே நாம் தொடர்ச்சியாகச் செய்து கொண்டே செல்லலாம். இதுவே clustering with k-means எனப்படுகிறது. இதில் k என்பது எத்தனை கொத்துகள்/குழுக்கள் உருவாக்கப்பட வேண்டும் என்பதையும், means என்பது ஒவ்வொரு features-வுடைய சராசரியையும் கண்டுபிடித்து அதனடிப்படையில் குழுக்களை உருவாக்குவதையும் குறிப்பிடுகிறது. அடுத்ததாக இந்த k-ன் மதிப்பினை எவ்வாறு கணக்கிடுவது என்று பார்க்கலாம்.

Elbow Method:

இது கொடுக்கப்பட்ட தரவுகளுக்கு எத்தனை குழுக்களை உருவாக்கினால் சரியாக இருக்கும் என்பதை ஒரு வரைபடம் மூலம் கண்டறிய உதவுகிறது. மேற்கண்ட அதே தரவுகளை இங்கும் நாம் பயன்படுத்திக் கொள்ளலாம். 2 குழுக்கள் என்பதை இது நமக்கு சரியாகக் காட்டுகிறதா எனப் பார்க்கலாம். இதற்கான நிரல் மற்றும் விளக்கம் பின்வருமாறு.


from sklearn.cluster import KMeans
from sklearn import metrics
from scipy.spatial.distance import cdist
import numpy as np
import matplotlib.pyplot as plt
x1 = [15, 19, 15, 5, 13, 17, 15, 12, 8, 6, 9, 13]
x2 = [13, 16, 17, 6, 17, 14, 15, 13, 7, 6, 10, 12]
X = np.array(list(zip(x1, x2)))
distortions = []
K = range(1,8)
for i in K:
model = KMeans(n_clusters=i)
model.fit(X)
distortions.append(sum(np.min(cdist(X, model.cluster_centers_, 'euclidean'), axis=1)) / X.shape[0])
plt.plot()
plt.plot(K, distortions, 'bx-')
plt.show()

view raw

Elbow_method.py

hosted with ❤ by GitHub

இதில் x1, x2 எனும் இரண்டு அம்சங்களும் numpy மூலம் x எனும் ஒரே அணியாக மாற்றப்படுகிறது. பின்னர் இத்தரவுகளைக் கொண்டு kmeans-க்குப் பயிற்சி அளிக்கப்படுகிறது. இப்பயிற்சியானது 1 முதல் 7 வரை பல்வேறு எண்ணிக்கையில் குழுக்களை அமைத்து பயிற்சி அளிக்கிறது. ஒவ்வொரு முறையும் அதன் தரவுகளுக்கும், திணிவுப் புள்ளிக்குமான விலகல் எவ்வளவு தூரம் இருக்கிறது என்பதைக் கணக்கிடுகிறது. இவ்வாறாக எந்த எண்ணிக்கையில் குழுக்களை அமைக்கும் போது அவற்றிலுள்ள தரவுகளின் விலகல் குறைகிறது என்பது கண்டுபிடிக்கப்படுகிறது. இந்த விலகல் மதிப்பே cost / distortion என்று அழைக்கப்படுகிறது.

பின்னர் இவை ஒரு வரைபடமாக வரையப்படுகின்றன. இதன் x அச்சில் குழுக்களின் எண்ணிக்கையும், y அச்சில் அதன் விலகல் மதிப்புகளும் அமைகின்றன. எனவேதான் ஒரே ஒரு கொத்தில் அனைத்துத் தரவுகளையும் அமைக்கும்போது அதனுடைய centroid-லிருந்து மற்ற தரவுகளின் விலகல் மதிப்பு 5-க்கு மேல் காட்டுவதையும், அதுவே 7 தனித்தனி கொத்துக்களாகப் பிரிக்கும்போது, அதனுடைய விலகல் மதிப்பு 1-க்குக் கீழ் காட்டுவதையும் காணலாம். இந்த வரைபடம் பார்ப்பதற்கு ஒரு முழங்கை வடிவில் இருப்பதால், இது Elbow method என்று அழைக்கப்படுகிறது. இந்த வரைபடத்தின் x-அச்சில் 2 என்ற புள்ளியில் அந்த முழங்கை போன்ற வடிவம் மடங்கி விரிவதால், அந்த எண்ணிக்கையில் தரவுகளைப் பிரித்தால் போதும் என்பதை நாம் தெரிந்து கொள்ளலாம். ஏனெனில் இதற்கு மேல் செல்லச் செல்ல விலகல் மதிப்புகள் ஓரளவுக்கே குறைகின்றன. இந்த புள்ளியில் தான் அந்த முழங்கை மடங்கும் நிலை ஏற்படுகிறது. எனவே தரவுகளை 2 குழுக்களில் பிரித்தால் சரியாக இருக்கும் என்பது கண்டுபிடிக்கப்படுகிறது.

silhouette_coefficient:

ஒரு algorithm-ன் செயல்திறன் என்பது அது எவ்வளவு தூரம் சரியாகக் கணித்துள்ளது என்பதைப் பொறுத்தே அமைகிறது. இதுவரை நாம் கண்ட அனைத்திலும், algorithm-ன் கணிப்புகளை உண்மையான மதிப்புகளுடன் ஒப்பிட்டு அதன் செயல்திறனைக் கண்டறிந்தோம். ஆனால் k-means போன்ற unsupervised learning-ல் ஒப்பிடுவதற்கு நம்மிடம் தரவுகள் ஏதும் இல்லாத காரணத்தால், இதனைக் கண்டுபிடிக்க உதவும் ஒரு வழிமுறையே silhouette_coefficient ஆகும்.

அதாவது k-means முறையில் வகைப்படுத்தப்படும் தரவுகள், சரியான முறையில்தான் வகைப்படுத்தப்பட்டுள்ளதா எனக் கண்டறிய ஏற்கனவே distortion என்ற ஒன்றை அளவிட்டோம். இது ஒவ்வொரு தரவும் அதன் திணிவுப் புள்ளியிலிருந்து எவ்வளவு தூரம் விலகியிருக்கிறது என்பதை வைத்து, kmeans-ன் செயல்திறனைக் கணக்கிடுகிறது. அதுபோலவே இந்த silhouette_coefficient என்பது பின்வரும் வாய்ப்பாடு மூலம் தரவுகள் அமைந்துள்ள ஒவ்வொரு குழுவும் எவ்வளவு கச்சிதமாகப் பிரிக்கப்பட்டுள்ளது என்பதைக் கணக்கிடுகிறது.

ba / max(a,b)

இதில் a என்பது ஒரே குழுவில் உள்ள தரவுகளுக்கிடையேயான சராசரி தூரம். b என்பது ஒரு குழுவிற்கும் அதற்கடுத்த குழுவிற்கும் இடையே உள்ள தரவுகளுக்கிடையேயான சராசரி தூரம்.

கீழ்க்கண்ட எடுத்துக்காட்டில் நமது தரவுகள், kmeans மூலம் முதலில் 2 குழுக்களாகப் பிரிக்கப்படுகின்றன. அவ்வாறே for loop மூலம் அடுத்தடுத்து 3,4,5 மற்றும் 8 குழுக்களாகப் பிரிக்கப்படுகின்றன. இந்த loop-க்குள் குழுக்கள் கொடுக்கப்பட்ட எண்ணிக்கையில் ஒவ்வொரு முறை அமையும்போதும், அது தரவுகளைப் பிரிக்கும் விதத்தை வரைபடமாக வரைந்து காட்டுகிறது மற்றும் அதன் silhouette_coefficient மதிப்பை வெளிப்படுத்துகிறது.


import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics
import matplotlib.pyplot as plt
plt.subplot(3, 2, 1)
x1 = [15, 19, 15, 5, 13, 17, 15, 12, 8, 6, 9, 13]
x2 = [13, 16, 17, 6, 17, 14, 15, 13, 7, 6, 10, 12]
plt.scatter(x1, x2)
X = np.array(list(zip(x1, x2)))
c = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'b']
m = ['o', 's', 'D', 'v', '^', 'p', '*', '+']
p = 1
for i in [2, 3, 4, 5, 8]:
p += 1
plt.subplot(3, 2, p)
model = KMeans(n_clusters=i).fit(X)
print (model.labels_)
for i, j in enumerate(model.labels_):
plt.plot(x1[i], x2[i], color=c[j], marker=m[j],ls='None')
print (metrics.silhouette_score(X, model.labels_ ,metric='euclidean'))
plt.show()

print (model.labels_) என்பது முதல் குழுவை 0 என்றும் இரண்டாவது குழுவை 1 என்றும் குறிப்பிடுகிறது. எனவே x1 மற்றும் x2-ல் உள்ள 12 தரவுகளும் எந்தெந்த குழுக்களில் சேர்க்கப்பட்டுள்ளன என்பதும் அதன் coefficient மதிப்பும் பின்வருமாறு வெளிப்படுகிறது.

[1 1 1 0 1 1 1 1 0 0 0 1]
0.6366488776743281

அவ்வாறே 3 குழுக்களாகப் பிரிக்கும்போது 0 முதல் குழுவையும், 1 இரண்டாவது குழுவையும், 2 மூன்றாவது குழுவையும் பின்வருமாறு குறிப்பிடுகிறது.

[0 0 0 1 0 0 0 2 1 1 1 2]
0.38024538066050284

இதுபோன்றே 4,5 மற்றும் 8 அளவில் குழுக்காளாகப் பிரிக்கும்போது தரவுகள் சேர்ந்துள்ள குழுக்களின் மதிப்பும், அக்குழுவிற்கான செயல்திறன் மதிப்பும் பின்வருமாறு வெளிப்படுகின்றன. இதை வைத்துப் பார்க்கும்போது 2 குழுக்களாகப் பிரிக்கும் போது மட்டுமே, இது அதிக அளவு செயல் திறனை (0.63) வெளிப்படுத்துவதைக் காணலாம்.

[2 0 0 1 0 0 0 2 1 1 3 2]
0.32248773306926665

[2 4 0 1 0 4 0 2 1 1 3 2]
0.38043265897525885

[6 7 3 4 3 1 6 2 0 4 5 2]
0.27672998081717154

கீழ்க்கண்ட வரைப்படத்தில் முதலாவதாக உள்ளது வெறும் தரவுகளுக்கான படம். இரண்டாவதாக உள்ளது 2 குழுக்காளாகப் பிரிக்கும்போது வெளிப்படும் வரைபடம். அடுத்தடுத்து உள்ளது 3,4,5,8 எண்ணிக்கையில் குழுக்களை அமைக்கும்போது வெளிப்படுகின்ற வரைபடங்கள். அதிகபட்சமாக 8 குழுக்கள் வரை தரவுகள் பிரிக்கப்படுகின்றன. எனவே ஒவ்வொரு குழுவிலும் உள்ள தரவுகளை வித்தியாசப்படுத்திக் காட்ட, 8 நிற வண்ணங்களும் 8 வெவ்வேறு வடிவங்களும் கொண்ட இரண்டு பட்டியல் உருவாக்கப்படுகிறது. அவை ஒவ்வொன்றாக loop-க்குள் சென்று பின்வருமாறு வெளிப்படுகின்றன.

 

%d bloggers like this: