본문 바로가기

Study/class note

머신러닝 / k-means 함수를 파이썬으로 직접 만들기

예제1. 숫자1과 숫자2의 순서를 랜덤으로 생성하시오.

import numpy as np

np.random.choice([1,2],2, replace = False) #비복원 추출로 숫자1과 2를 출력

예제2. 아래의 a2의 단맛,아삭한맛과 b2의 단맛, 아삭한맛 과의 유클리드 거리를 구하시오.

a2 = pd.DataFrame({'단맛': [7], '아삭한맛': [9] })
b2 = pd.DataFrame({'단맛': [10], '아삭한맛': [2] })

distance = np.sqrt(np.sum((a2-b2)**2, axis = 1))   # axis = 1 모든 요소의 합을 뜻함
distance  #7.615773

> 만약 np.num(axis = 0)이면 x축 기준으로 요소를 합함

 

예제3. 아래의 과일과 단백질 데이터셋과 아래의 중심점 2개를 생성하시오.

fruits = pd.DataFrame(
{'재료': ['사과','베이컨','배','당근','참외','치즈','햄','계란'],
 '단맛':[10,1,10,7,8,1,2,3],
 '아삭한맛':[9,3,8,10,7,1,1,2],
 '음식종류':['과일','단백질','과일','과일','과일','단백질','단백질','단백질']}
)
fruits

b2 = pd.DataFrame({'단맛':[10,5],'아삭한맛':[2,7]})
b2

 

예제4. fruits데이터에서 2개를 랜덤으로 선택하여 군집1, 군집2로 생성하시오.

def my_kmeans(test,k):
    cluster = test.iloc[np.random.choice(len(test), k, replace = False), :]
    cluster['kind'] = np.random.choice([1,2],2,replace = False)
    
    print(cluster)
    
my_kmeans(fruits,2)
>  재료  단맛  아삭한맛 음식종류  kind
0  사과  10     9   과일         2
5  치즈   1     1  단백질        1

 

예제5. 위의 함수안에 kind라는 컬럼과 거리(d) 컬럼을 가지고 있는 a라는 데이터 프레임을 생성하시오.

def my_kmeans(test,k):
    cluster = test.iloc[np.random.choice(len(test), k, replace = False), :]
    cluster['kind'] = np.random.choice([1,2],2,replace = False)
    
    a = pd.DataFrame({'kind':[0]*len(test), 'dist':[9999999]*len(test)})
    
    print(a)
    
my_kmeans(fruits,2)
   kind     dist
0     0  9999999
1     0  9999999
2     0  9999999
3     0  9999999
4     0  9999999
5     0  9999999
6     0  9999999
7     0  9999999

예제6. 위의 my_kmeans 함수 안에 a데이터 프레임의 거리(d)컬럼에 유클리드 거리를 계산해서 넣으시오. 처음에는 중심점1과의 거리를 구하고, 다음에는 중심점2와의 거리를 구하시오. 거리를 비교하여 최소값으로 갱신하시오.

def my_kmeans(test,k):
    cluster = test.iloc[np.random.choice(len(test), k, replace = False), :]
    cluster['kind'] = np.random.choice([1,2],2,replace = False)
    
    a = pd.DataFrame({'kind':[0]*len(test), 'dist':[9999999]*len(test)})
    
    for i in range(len(cluster)):
        temp = np.sqrt( np.sum( (test.values - cluster.iloc[:,:-1].values[i])**2, axis = 1))
    
        print(temp)
    
my_kmeans(fruits.iloc[:,[1,2]],2)
[10.81665383  0.         10.29563014  9.21954446  8.06225775  2.
  2.23606798  2.23606798]  > 중심점1과의 거리
  
[ 1.         10.29563014  0.          3.60555128  2.23606798 11.40175425
 10.63014581  9.21954446]  > 중심점2와의 거리

위에는 거리를 각각 구한것이고 위의 거리중에 가장 작은 것을 갱신되게 하려면 다음과 같이 해야함.

import numpy as np
def my_kmeans(test,k):
    cluster = test.iloc[np.random.choice(len(test), k, replace = False), :]
    cluster['kind'] = np.random.choice([1,2],2,replace = False)
    
    a = pd.DataFrame({'kind':[0]*len(test), 'dist':[9999999]*len(test)})
    
    for i in range(len(cluster)):
        temp = np.sqrt( np.sum( (test.values - cluster.iloc[:,:-1].values[i])**2, axis = 1))
        
        print(temp)
        
        for j in range(len(temp)):
            a['kind'][j] = cluster['kind'].values[i] if a.dist[j] > temp[j] else a['kind'][j]
            a['dist'][j] = temp[j] if a.dist[j] > temp[j] else a.dist[j]

            
    print(cluster)
    print(a)

    
my_kmeans(fruits.iloc[:,[1,2]],2)

 

문제416. 위의 코드는 평균값을 새로 구해서 그 새로운 평균값을 중심점으로 잡는 코드가 없습니다. 군집화한 좌표들끼리의 평균값 좌표를 구해서 그 평균값과 데이터와의 거리를 구해서 군집번호를 갱신할 수 있게 코드를 수정하시오.

import numpy as np

def my_kmeans(test,k):
    cluster = test.iloc[np.random.choice(len(test), k, replace = False), :]
    cluster['kind'] = np.random.choice([1,2],2,replace = False)
    
    a = pd.DataFrame({'kind':[0]*len(test), 'dist':[9999999]*len(test)})
    
    print(cluster)
    
    for i in range(len(cluster)):
        temp = np.sqrt( np.sum( (test.values - cluster.iloc[:,:-1].values[i])**2, axis = 1))
        
        for j in range(len(temp)):
            a['kind'][j] = cluster['kind'].values[i] if a.dist[j] > temp[j] else a['kind'][j]
            a['dist'][j] = temp[j] if a.dist[j] > temp[j] else a.dist[j]
     
    fruits['kind'] = a['kind']
    
    a = pd.DataFrame({'kind':[0]*len(test), 'dist':[9999999]*len(test)})
    for i in range(30):
        a_1 = fruits[['단맛']][fruits.kind == 1].mean().values[0]
        b_1 = fruits[['아삭한맛']][fruits.kind == 1].mean().values[0]
        a_2 = fruits[['단맛']][fruits.kind == 2].mean().values[0]
        b_2 = fruits[['아삭한맛']][fruits.kind == 2].mean().values[0]

    
        cluster['단맛'][cluster.kind == 1] = a_1
        cluster['아삭한맛'][cluster.kind == 1] = b_1
        cluster['단맛'][cluster.kind == 2] = a_2
        cluster['아삭한맛'][cluster.kind == 2] = b_2
        
        for i in range(len(cluster)):
            temp = np.sqrt( np.sum( (test.values - cluster.iloc[:,:-1].values[i])**2, axis = 1))
        
            for j in range(len(temp)):
                a['kind'][j] = cluster['kind'].values[i] if a.dist[j] > temp[j] else a['kind'][j]
                a['dist'][j] = temp[j] if a.dist[j] > temp[j] else a.dist[j]
        
    fruits['kind'] = a['kind']
    
my_kmeans(fruits.iloc[:,[1,2]],2)
fruits

 

문제417. 위의 코드를 수정해보시오.( 하드코딩 x, 간결하게)

 

ㅇㅇㅇ

반응형