Numpy에서 효과적으로 가우스 커널을 계산하는 방법 [닫기]


12

m 개의 열과 n 개의 행 이있는 numpy 배열이 있으며 열은 차원과 행 데이터 포인트입니다.

이제 각 데이터 포인트 조합에 대한 커널 값을 계산해야합니다.

선형 커널 K(xi,xj)=xi,xj I 간단히 할 수dot(X,X.T)

K(xi,xj)=expxixj22s2


1
계산의 두 가지 증가 요소에 대해 너무 신경 쓰지 않으면 S=XXT 를 수행 한 다음 K(xi,xj)=exp((Sii+Sjj2Sij)/s2) 여기서 Sij(i, j)입니다. \ m S의(i,j) 요소 . 그러나 이것은 아마도 가장 수치 적으로 안정적 이지 않습니다 . S
추기경

2
(나중에) 큰 희소 배열의 경우 scikit-learn의 sklearn.metrics.pairwise.pairwise_distances.html 을 참조하십시오 .
데니스

답변:


26

주요 문제는 쌍 거리를 효율적으로 얻는 것입니다. 일단 당신이 나머지는 요소 현명합니다.

이를 위해 scipy를 사용하고 싶을 것입니다. 이 기능 scipy.spatial.distance.pdist은 필요한 것을 수행 scipy.spatial.distance.squareform하며 인생을 편하게 할 것입니다.

커널 매트릭스를 원한다면

from scipy.spatial.distance import pdist, squareform
  # this is an NxD matrix, where N is number of items and D its dimensionalites
X = loaddata() 
pairwise_dists = squareform(pdist(X, 'euclidean'))
K = scip.exp(-pairwise_dists ** 2 / s ** 2)

설명서는 여기 에서 찾을 수 있습니다


3
bayerj의 대답은 누군가가 그것을 필요로 할 경우를 대비하여 공식에 맞게 약간의 수정이 필요하다고 생각됩니다.K = scipy.exp(-pairwise_dists**2 / s**2)
chloe

누군가가 호기심 경우에 사용되는 알고리즘은 pdist매우 간단합니다 : 그것은 바로의 거리 계산 단지 C-구현 루프의 명백한 방법 은 완료되고 루핑 여기 ; 컴파일러가 자동으로 수행 할 수있는 것 이상의 멋진 벡터화 또는 아무것도 없습니다.
Dougal

11

bayerj의 답변에 대한 작은 부록으로, scipy의 pdist함수는로 호출하여 제곱 유클리드 규범을 직접 계산할 수 있습니다 pdist(X, 'sqeuclidean'). 그러면 전체 코드를보다 효율적으로 작성할 수 있습니다

from scipy.spatial.distance import pdist, squareform
  # this is an NxD matrix, where N is number of items and D its dimensionalites
X = loaddata() 
pairwise_sq_dists = squareform(pdist(X, 'sqeuclidean'))
K = scip.exp(-pairwise_sq_dists / s**2)

1
또는 단순히 pairwise_sq_dists = cdist(X, X, 'sqeuclidean')동일한 것을 제공합니다.
user1721713

5

손으로 정사각형을 작성할 수도 있습니다.

import numpy as np
def vectorized_RBF_kernel(X, sigma):
    # % This is equivalent to computing the kernel on every pair of examples
    X2 = np.sum(np.multiply(X, X), 1) # sum colums of the matrix
    K0 = X2 + X2.T - 2 * X * X.T
    K = np.power(np.exp(-1.0 / sigma**2), K0)
    return K

추신하지만 이것은 30 % 느리게 작동합니다.


주석에서 추기경이 제안한 방법 인 인플레 이스 작업을 사용하여 약간 속도를 높일 수 있습니다. 그건 어떻게하는지 scikit 배우기 로, 전화 당신을 위해 . einsumX2
Dougal

4
def my_kernel(X,Y):
    K = np.zeros((X.shape[0],Y.shape[0]))
    for i,x in enumerate(X):
        for j,y in enumerate(Y):
            K[i,j] = np.exp(-1*np.linalg.norm(x-y)**2)
    return K

clf=SVR(kernel=my_kernel)

어느

clf=SVR(kernel="rbf",gamma=1)

위의 코드 노트에서 RBF를 효과적으로 계산할 수 있습니다. 감마 값은 1이므로 요청한 s도 같은 상수이므로 감마 값은 1입니다.


우리 사이트에 오신 것을 환영합니다! 우리는 일반적으로 코드에 중점을 두지 않고 기본 아이디어에 더 중점을두기 때문에 스택 오버플로에 대해 약간 다르게 강조합니다. 따라서 코드에 주석을 달거나 핵심 아이디어가 무엇인지에 대한 간단한 아이디어를 제공 할 가치가 있습니다. 다른 답변이 완료되었습니다. 그것은 당신의 대답이 다른 사람들과 어떻게 다른지를 설명하는 데 도움이 될 것입니다.
Silverfish

벡터화보다는 파이썬 루프를 사용하기 때문에 다른 답변보다 훨씬 느립니다.
Dougal

-1

나는 이것이 도움이 될 것이라고 생각한다.

def GaussianKernel(v1, v2, sigma):
    return exp(-norm(v1-v2, 2)**2/(2.*sigma**2))

3
@Kernel 사이트에 오신 것을 환영합니다. $ 기호 사이에 표현식을 넣고 LateX와 같은 구문을 사용하여 수학을 표시 할 수 있습니다. 그리고 줄을 4 칸 들여 써서 코드 (구문 강조 표시)를 표시 할 수 있습니다. 서식 지침 은 마크 다운 편집 도움말 및 일반적인 지침은 FAQ 를 참조하십시오.
Antoine Vernet

1
이것은 단지 질문에 무엇이 반영되어 있지 않습니까?
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.