2016-12-27 7 views
3

행렬에 함수를 정의하고 싶습니다. X. 예를 들어 mean(pow(X - X0, 2)) 인 경우, X0은 다른 행렬입니다 (X0은 고정/상수 임). 더 구체적으로 설명하기 위해 XX010 x 10 행렬이라고 가정 해 봅시다. 연산의 결과는 실수입니다.Theano를 사용하여 슬라이딩 창에 "임의"연산을 넣는 방법?

이제 큰 매트릭스가 생겼습니다 (500 x 500라고합시다). 위에서 정의한 연산을 "큰"행렬의 모든 서브 행렬 10 x 10에 적용하고 싶습니다. 즉, "큰"행렬 위에 10 x 10 창을 밀어 넣고 싶습니다. 창의 각 위치에 대해, 나는 실수를 얻어야한다. 따라서, 최종 결과로서, 실수 값의 행렬 (또는 2D 텐서)을 얻을 필요가 있습니다 (그 모양은 491 x 491이어야합니다).

내가 원하는 것은 길쌈 레이어에 가깝지만 정확히 같은 것은 아닙니다. 왜냐하면 뉴런이 나타내는 선형 함수 대신 평균 제곱 편차를 사용하기를 원하기 때문입니다.

+1

그냥 확인, 순수 NumPy와/scipy 솔루션은 허용? (나는 하나를 염두에 둔다) 아니면 Theano를 사용하는 솔루션을 기대합니까? 추신 오타 : "...'X'와'X0' **는 **''10 x 10'' 매트릭스입니다." –

+0

@DavidZ, 순수한 numpy/scipy 솔루션이 적합합니다. 실제로 나는 numpy를 사용하여 솔루션을 찾으려고 애썼지 만 numpy로 처리하는 "기본"방법이 없다고 봅니다 (확실하지는 않지만). 나는 Theano에서 길쌈 레이어를 제공하기 때문에 더 자연 스럽다고 생각했다. (그리고 내가하고 싶은 것은 컨볼 루션과 비슷하다.) – Roman

답변

2

이것은 단지 Numpy 솔루션 일뿐입니다. 함수가 행렬 요소와 평균, 즉 스케일 된 합계에 대한 연산으로 구성된다고 가정합니다. 따라서,

Y = np.power(X-X0, 2) 

그래서 우리는 단지 윈도우 평균을 결정 다룰 필요가 같이 Y 보는 것으로 충분하다. 1D 경우에 대해, 1을 적절한 벡터로 갖는 행렬 곱을 평균 계산을 위해 결정할 수 있음을 주목한다.

h = np.array([0, 1, 1, 0]) # same dimension as y 
m1 = np.dot(h, y)/2 
m2 = (y[1] + y[2])/2 
print(m1 == m2) # True 

2D 케이스는 유사하지만 두 행렬 곱셈 (행과 열에 각각 하나씩)이 있습니다. 예 :

m_2 = np.dot(np.dot(h, Y), h)/2**2 

슬라이딩 윈도우를 구성하려면 다음과 같이 이동 된 윈도우의 매트릭스를 만들어야합니다.

H = [[1, 1, 1, 0, 0, ..., 0], 
    [0, 1, 1, 1, 0, ..., 0], 
      . 
      . 
      . 
    [0, ..., 0, 0, 1, 1, 1]] 

H 구축을위한
S = np.dot(np.dot(H, Y), H.T) 

(m, m) 윈도우와 (n, n) 매트릭스 전체 예제는 대안하지만, 아마도 약간 덜 효율적인 방법

import numpy as np 

n, m = 500, 10 
X0 = np.ones((n, n)) 
X = np.random.rand(n, n) 
Y = np.power(X-X0, 2) 

h = np.concatenate((np.ones(m), np.zeros(n-m))) # window at position 0 
H = np.vstack((np.roll(h, k) for k in range(n+1-m))) # slide the window 
M = np.dot(np.dot(H,Y), H.T)/m**2 # calculate the mean 
print(M.shape) # (491, 491) 

수있는 모든 합계

을 계산 is

평균을 계산 953,210

업데이트

편차가 접근도 가능 제곱. 우리는 W이 수있는 블록 (m.m) 행렬을 포함하는 (m,n) 매트릭스, 가정

:이를 위해, 우리는 매트릭스의 경우에 벡터 정체성 |x-x0|^2 = (x-x0).T (x-x0) = x.T x - 2 x0.T x + x0.T x0을 (공백 스칼라 또는 매트릭스 곱셈과 .T 전치 벡터를 의미) 일반화 (k0,k1) -th (m,m) 부분 행렬을 Y = W Z W.T으로 추출하고, 여기서 Z은 데이터를 포함하는 (n,n) 행렬입니다.차분

D = Y - X0 = Y = W Z W.T - X0 

계산은 X0D(m,m) 행렬이고, 간단하다. 요소의 제곱합의 제곱근을 Frobenius norm이라고합니다. 그 identities에 기초하여, 우리는

s = sum_{i,j} D_{i,j}^2 = trace(D.T D) = trace((W Z W.T - X0).T (H Z H.T - X0)) 
    = trace(W Z.T W.T W Z W.T) - 2 trace(X0.T W Z W.T) + trace(X0.T X0) 
    =: Y0 + Y1 + Y2 

Y0Y1ZY2의 가중 평균으로서 해석 될 수 above.The 기간에서 상기 방법에서 H Z H.T로 해석 될 수있는 용어로 제곱 합을 쓸 수있는 것은 일정한 , 한 번만 결정하면됩니다. 따라서 , 가능한 구현은 다음과 같습니다

import numpy as np 

n, m = 500, 10 
x0 = np.ones(m) 
Z = np.random.rand(n, n) 

Y0 = Z**2 
h0 = np.concatenate((np.ones(m), np.zeros(n-m))) 
H0 = np.vstack((np.roll(h0, k) for k in range(n+1-m))) 
M0 = np.dot(np.dot(H0, Y0), H0.T) 

h1 = np.concatenate((-2*x0, np.zeros(n-m))) 
H1 = np.vstack((np.roll(h1, k) for k in range(n+1-m))) 
M1 = np.dot(np.dot(H1, Z), H0.T) 

Y2 = np.dot(x0, x0) 
M = (M0 + M1)/m**2 + Y2 
+0

당신의 솔루션은 나에게 "창으로 표시된"평균 (그리고 그것의 가중 버전)을 계산하는 우아한 방법을 제공합니다. 그러나, 나는 그것이 내가 필요로하는 것이 정확히 있다고 생각하지 않는다. 문제는 내 창에 기본 이미지에서 빼는 "템플릿"이있는 것입니다. 그런 다음 결과를 2로 올린 다음 평균을 계산합니다. 즉, X0는'(n, n)'이 아니며'(m, m)'입니다. X0은 창과 크기가 같지만 원본 "큰"이미지와 다릅니다. – Roman

+0

@Roman 간과 - 평균 제곱 편차를 계산하는 방법으로 답변을 업데이트했습니다. – Dietrich