본문 바로가기
Programming_Collective Intelligence/8.가격모델링

kNN + 가중치

by 볼록티 2020. 1. 7.
728x90
반응형

 물품 가중치: 알고리즘이 다소 멀리 떨어진 이웃 물품들을 사용하는 경우를 보상하는 한 가지 방법은 거리에 따라 가중치를 두는 것이다. 추천시스템 장에서 선호도에 따라서 가중치를 주어 유사도를 구했던 것과 유사하다.

 물품들이 더 비슷할수록 그들 간의 거리가 더 가까워지므로, 거리를 가중치로 변경할 방법이 있어야 한다. 몇 가지 방법이 있지만 각각 장단점이 있다. 

 

 

 1. 역 함수

 거리를 가중치로 바꿀 때 역함수를 사용한다. 그냥 역함수를 써버리면 아주 가깝거나 아주 먼 경우에 그 값이 너무 높거나 무한대 가중치를 낼 수 있지 때문에 작은 수를 (여기선 0.1) 살짝 더해서 역수를 취해준다.

def inverseweight(dist, num=1.0, const=0.1):
    return num/(dist+const)

 이 함수는 빠르고 구현도 쉬우며, 좋은 결과를 찾기 위해서 num변수의 값을 바꿔가며 실험할 수 있다. 

 가장 큰 단점은 근접한 물품 간에는 가중치가 너무 높고, 멀어질수록 급격히 내려간다는 것이다. 바람직하다고 느낄 수도 있지만 몇몇 경우 알고리즘을 노이즈에 너무 민감하게 만드는 경향이 있다.

 

 2. 빼기 함수

 이 함수는 상수에서 거리를 뺀다. 결과가 0보다 크면 뺀 결과가 가중치이고, 그렇지 않으면 결과는 0이다.

def subtractweight(dist, const=1.0):
    if dist>const:
        return 0
    else:
        return const-dist

 이 함수는 근접한 물품에 과도한 가중치를 주는 잠재 문제를 극복하지만 자체 제약을 가진다. 결국 가중치가가 0으로 떨이지기 때문에 근접 물품을 찾을 수 없는 경우가 발생한다. 이는 몇몇 물품의 경우 알고리즘이 전혀 추천을 하지 못하는 경우가 생긴다는 것을 의미한다.

 

 3. 가우스 함수

 벨 커브(bell curve)로도 알려진 가우스 함수(Gaussian function)이다. 이 함수는 좀 더 복잡하지만 이전 함수들의 한계를 극복한다.

 흔히 정규분포에도 응용이 되어있다고 알려져 있다. 이 함수의 가중치는 거리가 0일 때 1이고, 거리가 멀어지면 가중치가 줄어든다. 하지만 결코 0이 되지 않기 때문에 항상 예측을 할 수가 있다. 

 이 함수의 코드는 더 복잡해서 다른 두 함수만큼 빨리 계산하기 어렵다.

def gaussian(dist, sigma=10.0):
    return math.e**(-dist**2/(2*sigma**2))

$e^{(\frac{-dist^{2}}{(2\times sigma^{2})})}$ 처럼 나타낼 수 있다.

xxx = [randint(0,3)+random() for i in range(10000)]
plt.plot(xxx,[gaussian(i) for i in xxx], 'o')

가우스 함수를 사용하면 그 어떤 거리 점수도 아래의 그림처럼 1이 되거나 0이 될 수 없다. 수렴할 뿐.

 

 

 

 

 가중 kNN

 가중 kNN의 코드는 정렬된 거리들을 얻ㄷ고 k 근접 요소들을 구하는 방식으로 일반적인 방식으로 동작한다. 중요한 차이는 결과들의 평균을 계산하는 대신에 가중 kNN은 가중평균을 계산한다.각 물품의 가중치에다가 값을 곱한 다음에 전체 가중치의 합으로 나눠서 계산한다. 추천시스템에서 kNN을 사용할 때 그렇게 사용한다.

 

def weightedknn(data, vec1, k=5, weightf=gaussian):
    #거리를 구함
    dlist=getdistances(data, vec1)
    avg=0.0
    totalweight=0.0
    
    #가중평균을 구함
    for i in range(k):
        dist=dlist[i][0]
        idx=dlist[i][1]
        weight=weightf(dist)
        avg+=weight*data[idx]['result']
        totalweight+=weight
    avg=avg/totalweight
    return avg

이 함수는 k 근접 물품들에 대해 루프를 돌리면서 각각 거리를 전에 정의한 함수에 전달한다. 그다음 age는 각 물품의 값에 가중치를 곱하고, totalweight라는 가중치 총합으로 avg를 나누면 거리를 통해 얻은 가중치를 가지고 가중평균을 구하는 절차가 끝나게 된다.

 

 

 

 

728x90
반응형

'Programming_Collective Intelligence > 8.가격모델링' 카테고리의 다른 글

교차검증  (0) 2020.01.08
kNN을 활용한 가격 추정  (0) 2020.01.07
예제 데이터 셋 생성  (0) 2020.01.07

댓글