이번에는 K-Means를 직접 구현 해볼것이다.
우선 클러스터링에 대해서 간략하게 설명부터 해보자!
만약 위처럼 사과,배,바나나를 분류하는 문제를 구현해본다고 생각해보자. 이전에 배웠던 인공신경망을 활용할 수도 있겠지만 이번에는 클러스터링을 이용하여 군집을 나누어 볼 것이다.
어떠한 특성을 잘 집어낸다면 결국 사과,배,바나나들은 군집처럼 분류될 것이다. 이들의 군집의 중심점을 찾은 후, 근처에 있는것들을 한 군집을 분다면 우리는 분류를 할 수 있다.
클러스터링의 기본적인 프로세스는 아래와 같다.
즉 랜덤의 중심점을 설정한 후에, 가까운곳들을 해당 군집으로 묶어준다. 그이후 같은 군집내의 중심을 다시 중심점으로 잡은 후에 군집의 분류를 시켜준다. 이를 계속 반복하여 군집이 더이상 변하지 않을떄까지 한다면, 우리는 군집의 분류를 할 수 있다.
클러스터링의 장점은 인공신경망에 비해 연산량이 적고 많은 데이터셋에 적용이 가능하다는 것이다. 하지만 첫 중심점에 따라 결과가 상이하게 나오는 단점이 있다. 즉, 첫 중심점에 따라 결과가 다르게 나올 수 있다는 것이다.
라이브러리를 사용하면 K-means 알고리즘을 쉽게 구현해볼 수 있다.
여러 속성에 따른 고객들을 분류해보는 문제를 적용시켜보자.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.cluster import KMeans
import os
current_path = os.path.dirname(os.path.abspath(__file__))
df = pd.read_csv("Mall_Customers.csv")
print(df)
data = df[['Annual Income (k$)', 'Spending Score (1-100)']]
k = 3
model = KMeans(n_clusters = k, init = 'k-means++', random_state = 10)
def elbow(X):
sse = []
for i in range(1,11):
km = KMeans(n_clusters=i,init='k-means++',random_state=0)
km.fit(X)
sse.append(km.inertia_)
plt.plot(range(1,11),sse,marker='o')
plt.xlabel('# of clusters')
plt.ylabel('Inertia')
plt.show()
elbow(data)
df['cluster'] = model.fit_predict(data)
final_centroid = model.cluster_centers_
print(final_centroid)
plt.figure(figsize=(8,8))
for i in range(k):
plt.scatter(df.loc[df['cluster'] == i, 'Annual Income (k$)'], df.loc[df['cluster'] == i, 'Spending Score (1-100)'], label = 'cluster' + str(i))
plt.scatter(final_centroid[:,0], final_centroid[:,1],s=50,c='violet',marker = 'x', label = 'Centroids')
plt.legend()
plt.title(f'K={k} results',size = 15)
plt.xlabel('Annual Income',size = 12)
plt.ylabel('Spending Score',size = 12)
plt.show()
학습에 따라서 분류가 잘 된것을 알 수 있다.
자, 그렇다면 직접구현을 해보자. 해당 알고리즘을 만들기 위해서는 중심점과 속성들과의 거리를 정하는것이 중요하다.
거리에는 여러가지 거리가 있을 수 있다. 일반적인 좌표계에서 사용하는 거리나 맨해튼 거리 등등 여러가지가 있지만 선택하여 쓰면 된다.
해당 csv파일을 보면 속성이 4개가 있다. 즉, 중심점과 4개의 속성들간의 거리를 잰 후, 가장 가깝다고 생각하는 군집에 넣어주고 위에서 설명한 알고리즘 방식을 반복하면 된다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
current_path = os.path.dirname(os.path.abspath(__file__)) #파일 불러읽기
raw_data = pd.read_csv('Mall_Customers.csv',encoding='utf-8', engine = 'python')
Customers_data = raw_data[['Gender','Age','Annual Income (k$)','Spending Score (1-100)']].to_numpy() # x 데이터 받기
for i in range(len(Customers_data)): #남성,여성을 숫자로 생각할 수 있게
if Customers_data[i][0] =='Male':
Customers_data[i][0] = 1
else:
Customers_data[i][0] = 0
Annual_Income = raw_data[['Annual Income (k$)']].to_numpy()
Spending_Score = raw_data[['Spending Score (1-100)']].to_numpy()
plt.scatter(Annual_Income, Spending_Score,s=50,c='violet',marker = 'o', label = 'Centroids')
plt.legend()
plt.title(f'results',size = 15)
plt.xlabel('Annual Income',size = 12)
plt.ylabel('Spending Score',size = 12)
plt.show() #데이터 그래프 표시
class K_Means: #K-Means 알고리즘을 클래스로 구현
def __init__(self,k,data,p): #k,학습시킬데이터,p를 받아옴
self.k = k
self.data = data
self.p = p
self.N = len(data)
self.standard = []
self.Cluster = np.array([0 for _ in range(self.N)])#군집을 저장하는 공간
while(len(self.standard) < k): #k값에 따라 처음값 설정
tmp = np.random.randint(self.N) #중복값은 설정 안되게설정
if tmp not in self.standard:
self.standard.append(tmp)
self.Cluster[tmp] = len(self.standard) #초기군집을 1,2,3으로 넣어줌
for i in range(k): #계산하기 편하게 처음 세개 값을 index가 아닌 실제값으로 변환
self.standard[i] = self.data[self.standard[i]]
def distance(self,I,J): #거리 구하는 함수
return sum(abs(I-J)**self.p)**(1/self.p)
def Clustering(self): #Clustering 알고리즘
for _ in range(100): ##iteration 100회로 임의 설정
Old_Cluster = np.array(self.Cluster)
for i in range(self.N):
dist = []
for standard in self.standard:
dist.append(self.distance(self.data[i],standard))
self.Cluster[i] = np.argmin(dist) + 1
Clusters = [[] for __ in range(self.k + 1)]
for i in range(self.N):
Clusters[self.Cluster[i]].append(self.data[i])
for i in range(1,self.k+1):
Clusters[i] = np.array(Clusters[i])
self.standard[i-1] = Clusters[i].mean(axis=0)
#cluster가 변화없어질때 종료조건을 넣을 수 있다.
# if np.array_equal(Old_Cluster,self.Cluster):
# break
Algorism = K_Means(k = 4,data = Customers_data,p=1) #모델 구현
Algorism.Clustering()#Clustering 실행
Annual = [ [] for _ in range(Algorism.k+1)] #값을 볼 수 있는 형태로 변환
Spending = [ [] for _ in range(Algorism.k+1)]
for i in range(Algorism.N): #같은 군집끼리 값을 모은다
Annual[Algorism.Cluster[i]].append(Annual_Income[i])
Spending[Algorism.Cluster[i]].append(Spending_Score[i])
for i in range(1,Algorism.k+1): # k개의 군집 출력
plt.scatter(Annual[i], Spending[i],s=50,marker = 'o', label = f'cluster{i}')
plt.scatter(Algorism.standard[i-1][2],Algorism.standard[i-1][3],label=f"{i}'s Centroids",marker='x')#중심점
plt.legend()
plt.title(f'results',size = 15)
plt.xlabel('Annual Income',size = 12)
plt.ylabel('Spending Score',size = 12)
plt.show()
'Python > 인공지능' 카테고리의 다른 글
Minist 데이터 활용 0,1,2 구분 인공지능 직접구현 (0) | 2022.06.19 |
---|---|
인공신경망 직접구현 (0) | 2022.06.07 |
Training , Test 선택 가우시안 모델 구현하기 (0) | 2022.04.30 |
파이참에서 GPU사용! (0) | 2022.04.24 |
가우스 함수를 이용한 선형회귀 모델 직접구현 (0) | 2022.04.17 |