如何使用 Theano 将 "arbitrary" 操作放入滑动 window 中?
How to put an "arbitrary" operation into a sliding window using Theano?
我想在矩阵 X
上定义一些函数。例如 mean(pow(X - X0, 2))
,其中 X0
是另一个矩阵(X0
是固定的/常量)。为了更具体,我们假设 X
和 X0
都是 10 x 10
矩阵。运算结果为实数。
现在我有一个大矩阵(比方说 500 x 500
)。我想将上面定义的操作应用于 "big" 矩阵的所有 10 x 10
子矩阵。换句话说,我想将 10 x 10
window 滑动到 "big" 矩阵上。对于 window 的每个位置,我应该得到一个实数。所以,作为最终结果,我需要得到一个实值矩阵(或二维张量)(它的形状应该是491 x 491
)。
我想要的是接近于卷积层但不完全相同的,因为我想使用均方差而不是神经元表示的线性函数。
这只是一个 Numpy 解决方案,希望它足够了。
我假设您的函数由对矩阵元素的运算和均值(即缩放和)组成。因此,将 Y
视为
就足够了
Y = np.power(X-X0, 2)
因此我们只需要处理确定 windowed 均值。请注意,对于一维情况,可以确定具有适当矢量的矩阵乘积以计算平均值,例如
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
二维情况类似,但有两个矩阵乘法,一个用于行,一个用于列。例如
m_2 = np.dot(np.dot(h, Y), h) / 2**2
要构造一个滑动window,我们需要构建一个移位windows的矩阵,例如
H = [[1, 1, 1, 0, 0, ..., 0],
[0, 1, 1, 1, 0, ..., 0],
.
.
.
[0, ..., 0, 0, 1, 1, 1]]
计算所有的总和
S = np.dot(np.dot(H, Y), H.T)
具有 (m, m)
window 的 (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)
构建 H
的另一种但效率可能稍低的方法是
H = np.sum(np.diag(np.ones(n-k), k)[:-m+1, :] for k in range(m))
更新
用这种方法也可以计算均方差。为此,我们将向量恒等式 |x-x0|^2 = (x-x0).T (x-x0) = x.T x - 2 x0.T x + x0.T x0
(space 表示标量或矩阵乘法,.T
表示转置向量)推广到矩阵情况:
我们假设 W
是一个包含块 (m.m)
单位矩阵的 (m,n)
矩阵,它能够提取第 (k0,k1)
-th (m,m)
子-矩阵 Y = W Z W.T
,其中 Z
是包含数据的 (n,n)
矩阵。计算差值
D = Y - X0 = Y = W Z W.T - X0
很简单,其中 X0
和 D
是一个 (m,m)
矩阵。元素平方和的平方根称为Frobenius norm. Based on those 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
Y0
项可以解释为 above.The 方法中的 H Z H.T
项 Y1
可以解释为 Z
上的加权平均值,并且Y2
是一个常数,只需要确定一次。
因此,一个可能的实现是:
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
我想在矩阵 X
上定义一些函数。例如 mean(pow(X - X0, 2))
,其中 X0
是另一个矩阵(X0
是固定的/常量)。为了更具体,我们假设 X
和 X0
都是 10 x 10
矩阵。运算结果为实数。
现在我有一个大矩阵(比方说 500 x 500
)。我想将上面定义的操作应用于 "big" 矩阵的所有 10 x 10
子矩阵。换句话说,我想将 10 x 10
window 滑动到 "big" 矩阵上。对于 window 的每个位置,我应该得到一个实数。所以,作为最终结果,我需要得到一个实值矩阵(或二维张量)(它的形状应该是491 x 491
)。
我想要的是接近于卷积层但不完全相同的,因为我想使用均方差而不是神经元表示的线性函数。
这只是一个 Numpy 解决方案,希望它足够了。
我假设您的函数由对矩阵元素的运算和均值(即缩放和)组成。因此,将 Y
视为
Y = np.power(X-X0, 2)
因此我们只需要处理确定 windowed 均值。请注意,对于一维情况,可以确定具有适当矢量的矩阵乘积以计算平均值,例如
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
二维情况类似,但有两个矩阵乘法,一个用于行,一个用于列。例如
m_2 = np.dot(np.dot(h, Y), h) / 2**2
要构造一个滑动window,我们需要构建一个移位windows的矩阵,例如
H = [[1, 1, 1, 0, 0, ..., 0],
[0, 1, 1, 1, 0, ..., 0],
.
.
.
[0, ..., 0, 0, 1, 1, 1]]
计算所有的总和
S = np.dot(np.dot(H, Y), H.T)
具有 (m, m)
window 的 (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)
构建 H
的另一种但效率可能稍低的方法是
H = np.sum(np.diag(np.ones(n-k), k)[:-m+1, :] for k in range(m))
更新
用这种方法也可以计算均方差。为此,我们将向量恒等式 |x-x0|^2 = (x-x0).T (x-x0) = x.T x - 2 x0.T x + x0.T x0
(space 表示标量或矩阵乘法,.T
表示转置向量)推广到矩阵情况:
我们假设 W
是一个包含块 (m.m)
单位矩阵的 (m,n)
矩阵,它能够提取第 (k0,k1)
-th (m,m)
子-矩阵 Y = W Z W.T
,其中 Z
是包含数据的 (n,n)
矩阵。计算差值
D = Y - X0 = Y = W Z W.T - X0
很简单,其中 X0
和 D
是一个 (m,m)
矩阵。元素平方和的平方根称为Frobenius norm. Based on those 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
Y0
项可以解释为 above.The 方法中的 H Z H.T
项 Y1
可以解释为 Z
上的加权平均值,并且Y2
是一个常数,只需要确定一次。
因此,一个可能的实现是:
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