태그 보관물: self-organizing-maps

self-organizing-maps

공칭 / 원형 변수에 대한 SOM 클러스터링 익숙한 사람이

공칭 입력 클러스터링에 익숙한 사람이 있는지 궁금합니다. 나는 SOM을 솔루션으로보고 있지만 분명히 숫자 기능에서만 작동합니다. 범주 형 기능에 대한 확장이 있습니까? 특히 가능한 기능으로 ‘Days of the Week’에 대해 궁금했습니다. 물론 수치 적 특징으로 변환하는 것이 가능합니다 (즉, 1-7에 해당하는 Mon-Sun) 그러나 Sun과 Mon (1 & 7) 사이의 유클리드 거리는 Mon에서 tues (1 & 2)까지의 거리와 같지 않습니다 ). 어떤 제안이나 아이디어라도 대단히 감사하겠습니다.



답변

배경:

시간을 변환하는 가장 논리적 인 방법은 동기화되지 않은 두 가지 변수로 변환하는 것입니다. 24시 시계의 시침 끝 위치를 상상해보십시오. x위치는 요동과 왕복 동기화 백업 y위치. 24 시간 시계를 들어 당신이 이것을 달성 할 수있다 x=sin(2pi*hour/24), y=cos(2pi*hour/24).

두 변수가 모두 필요하거나 시간을 통한 적절한 이동이 손실됩니다. 이것은 sin 또는 cos의 미분이 시간에 (x,y)따라 변하는 반면 위치는 단위 원 주위를 이동함에 따라 매끄럽게 변하기 때문입니다.

마지막으로, 선형 레코드를 추적하는 세 번째 기능을 추가 할 가치가 있는지 고려하십시오. 선형 레코드는 첫 번째 레코드의 시작 또는 유닉스 타임 스탬프 또는 이와 유사한 것으로 시작하여 몇 시간 또는 몇 분 또는 몇 초로 구성 될 수 있습니다. 이 세 가지 기능은 주기적 및 선형 시간 진행에 대한 프록시를 제공합니다. 예를 들어, 사람들의 움직임에서 수면주기와 같은 순환 현상과 인구 대 시간과 같은 선형 성장을 끌어낼 수 있습니다.

달성중인 경우의 예 :

# Enable inline plotting
%matplotlib inline

#Import everything I need...

import numpy as np
import matplotlib as mp

import matplotlib.pyplot as plt
import pandas as pd

# Grab some random times from here: https://www.random.org/clock-times/
# put them into a csv.
from pandas import DataFrame, read_csv
df = read_csv('/Users/angus/Machine_Learning/ipython_notebooks/times.csv',delimiter=':')
df['hourfloat']=df.hour+df.minute/60.0
df['x']=np.sin(2.*np.pi*df.hourfloat/24.)
df['y']=np.cos(2.*np.pi*df.hourfloat/24.)

df

여기에 이미지 설명을 입력하십시오

def kmeansshow(k,X):

    from sklearn import cluster
    from matplotlib import pyplot
    import numpy as np

    kmeans = cluster.KMeans(n_clusters=k)
    kmeans.fit(X)

    labels = kmeans.labels_
    centroids = kmeans.cluster_centers_
    #print centroids

    for i in range(k):
        # select only data observations with cluster label == i
        ds = X[np.where(labels==i)]
        # plot the data observations
        pyplot.plot(ds[:,0],ds[:,1],'o')
        # plot the centroids
        lines = pyplot.plot(centroids[i,0],centroids[i,1],'kx')
        # make the centroid x's bigger
        pyplot.setp(lines,ms=15.0)
        pyplot.setp(lines,mew=2.0)
    pyplot.show()
    return centroids

이제 사용해 봅시다 :

kmeansshow(6,df[['x', 'y']].values)

여기에 이미지 설명을 입력하십시오

자정 이전 녹색 클러스터에 자정 이후 시간이 포함되어 있음을 간신히 알 수 있습니다. 이제 클러스터 수를 줄이고 자정 전후에 단일 클러스터에서 더 자세히 연결할 수 있음을 보여 드리겠습니다.

kmeansshow(3,df[['x', 'y']].values)

여기에 이미지 설명을 입력하십시오

파란색 클러스터에 자정 전후의 시간이 동일한 클러스터에 함께 클러스터 된 시간을 포함하는 방법을 확인하십시오.

시간, 요일, 매주, 달, 계절 또는 기타 모든 작업에 대해이 작업을 수행 할 수 있습니다.


답변

일반적으로 명목 형 변수는 SOM에서 사용될 때 더미 코딩됩니다 (예 : 월요일이 아닌 월요일 0은 1이고 변수는 화요일 등).

인접한 요일의 결합 된 카테고리를 작성하여 추가 정보를 통합 할 수 있습니다. 예를 들어 월요일 및 화요일, 화요일 및 수요일 등입니다. 그러나 데이터가 사람의 행동과 관련이있는 경우 주중 및 주말을 범주로 사용하는 것이 더 유용합니다.


답변

명목 형 변수의 경우 신경망 또는 전기 공학 컨텍스트에서 일반적인 인코딩을 “one-hot” 이라고 합니다.이 값은 변수 값의 적절한 위치에 1이 1 인 모든 0의 벡터입니다. 예를 들어 요일에는 7 일이 있으므로 원핫 벡터의 길이는 7입니다. 그런 다음 월요일은 [1 0 0 0 0]으로 표시되고 화요일은 [0 0 0 0 0] 등으로 표시됩니다.

Tim이 암시 한 것처럼이 접근 방식은 임의의 부울 피처 벡터를 포함하도록 쉽게 일반화 할 수 있습니다. 여기서 벡터의 각 위치는 데이터에서 관심있는 피처에 해당하고 해당 위치의 존재 여부를 나타 내기 위해 위치는 1 또는 0으로 설정됩니다. 특색.

이진 벡터가 있으면 유클리드 거리도 사용되지만 해밍 거리는 자연 메트릭이됩니다. one-hot 이진 벡터의 경우 SOM (또는 다른 함수 근 사기)은 각 벡터 위치에 대해 자연스럽게 0과 1 사이에서 보간됩니다. 이 경우 이러한 벡터는 종종 공칭 변수의 공간에 대한 Boltzmann 또는 softmax 분포의 매개 변수로 처리됩니다. 이 처리는 어떤 종류의 KL 발산 시나리오에서도 벡터를 사용하는 방법을 제공합니다.

순환 변수는 훨씬 까다 롭습니다. Arthur가 의견에서 말했듯이 변수의 순환 특성을 통합하는 거리 메트릭을 직접 정의해야합니다.


답변

요일 (dow)이 [0, 6]에서 시작한다고 가정하면 데이터를 원에 투영하는 대신 다른 옵션을 사용할 수 있습니다.

dist = min(abs(dow_diff), 7 - abs(dow_diff))

그 이유를 이해하려면 다우를 시계로 생각하십시오.

  6  0
5      1
4      2
    3

6과 1 사이의 차이는 6-1 = 5 (시계 방향으로 1에서 6으로 이동) 또는 7-(6-1) = 2 일 수 있습니다.

일반적으로 다음을 사용할 수 있습니다. min(abs(diff), range - abs(diff))


답변

나는 그의 의견에서 강조된 whuber로 요일 (및 년)을 튜플 (cos, sin)로 성공적으로 인코딩했습니다. 사용 된 유클리드 거리보다.

다음은 r 코드의 예입니다.

circularVariable = function(n, r = 4){
 #Transform a circular variable (e.g. Month so the year or day of the week) into two new variables (tuple).
 #n = upper limit of the sequence. E.g. for days of the week this is 7.
 #r =  number of digits to round generated variables.
 #Return
 #
 coord = function(y){
   angle = ((2*pi)/n) *y
   cs = round(cos(angle),r)
   s = round(sin(angle),r)
   c(cs,s)
 }
 do.call("rbind", lapply((0:(n-1)), coord))
}

0과 6 사이의 유클리드 거리는 0과 1과 같습니다.


답변