如何设置"任意"使用Theano操作滑动窗口?

时间:2016-12-27 08:55:51

标签: python theano convolution sliding-window

我想在矩阵X上定义一些函数。例如mean(pow(X - X0, 2)),其中X0是另一个矩阵(X0是固定/常量)。为了使其更具体,我们假设XX0都是10 x 10矩阵。操作的结果是一个实数。

现在我有一个大矩阵(让我们说500 x 500)。我想将上面定义的操作应用于" big"的所有10 x 10子矩阵。矩阵。换句话说,我想将10 x 10窗口滑过" big"矩阵。对于窗口的每个位置,我应该得到一个实数。所以,作为最终结果,我需要得到一个实值矩阵(或2D张量)(它的形状应该是491 x 491)。

我想要的是接近卷积层但不完全相同,因为我想使用均方偏差而不是神经元代表的线性函数。

1 个答案:

答案 0 :(得分:2)

这只是一个Numpy解决方案,希望它足够了。 我假设你的函数是由对矩阵元素和平均值(即缩放的和)的运算组成的。因此,在

中查看Y就足够了
Y = np.power(X-X0, 2)

所以我们只需要处理确定窗口均值。请注意,对于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情况类似,但有两个矩阵乘法,一个用于行,一个用于列。 E.g。

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]] 

计算所有总和

S = np.dot(np.dot(H, Y), H.T)

具有(n, n)窗口的(m, m)矩阵的完整示例将是

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(空格表示标量或矩阵乘法以及.T转置向量)推广到矩阵情形:

我们假设W是包含块(m,n)单位矩阵的(m.m)矩阵,可以提取(k0,k1) - (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

术语Y0可以从上面的方法解释为H Z H.T。术语Y1可以解释为Z和{{1}上的加权平均值是一个常数,只需要确定一次。 因此,可能的实现方式是:

Y2