我有一个大小为n的正方形2d数组,用数值填充。
对于每个条目,我对该条目的行和列求和,但减去原始条目。
while 1:
new = np.copy(next)
for i in xrange(n):
for j in xrange(n):
val = new[i][j]
rowsum = np.sum(new[i])
colsum = np.sum(new[:,j])
next[i][j] = rowsum+colsum-val-val
完成我想要的东西,但经过一些迭代后,条目通常会变得太大(因为它们几乎加倍)。我想定期缩减我的价值观,但我想这样做,这样我就不会丢失信息。重要信息是任何两个条目之间的百分比差异。
我希望以一种使条目为负的方式避免缩放。
输入范围不受任何限制。如果我能以某种方式扩展它以使负面条目变为正数,那将是特别好的。
我认为对矩阵进行归一化可能会有效,但它最终会将值推到一起,并且经过一些循环后,所有值都非常相等。
答案 0 :(得分:2)
你可以在求和后应用一个像sigmoid函数一样有界的函数。 https://en.wikipedia.org/wiki/Sigmoid_function
因此,如果你取一个值的行和列的总和,然后将该值插入sigmoid函数,这将防止数字超出范围(0,1)。这样,无论您执行此操作多少次,都不会使数字爆炸。
可能有其他功能可能更适合您的想法,但想法是一样的。使用具有有界范围的函数,如果您的输出是此函数的输出,那么您使用的数字将始终具有相同的边界。
这(或类似的东西)是在神经网络的节点中使用的。由于节点的输出是网络中较早的所有连接节点的总和,因此在数字爆炸时可以获得相同的效果。有时在NN中他们称之为压扁功能,或者压扁。
答案 1 :(得分:1)
&#34;我认为对矩阵进行标准化可能会有效,但最终会将值推到一起,并且在一些循环之后所有值都非常相等。&#34; < / p>
这实际上是预期的,不是规范化的效果。
要理解为什么首先观察到你的操作实际上是循环卷积,内核除了第一行和第一列以外都是零,而左上角也是零,并且非零值都等于。
我们可以在numpy中查看这个
>>> from scipy.fftpack import fftn, ifftn
>>>
>>> def iterate(new):
... next = new.copy()
... for i in xrange(n):
... for j in xrange(n):
... val = new[i][j]
... rowsum = np.sum(new[i])
... colsum = np.sum(new[:,j])
... next[i][j] = rowsum+colsum-val-val
... return next
...
>>> n = 8
>>> kernel = np.arange(n)==0
>>> kernel = np.bitwise_xor.outer(kernel, kernel)
>>>
>>> data = np.random.random((n, n))
>>>
>>> np.allclose(ifftn(fftn(data) * fftn(kernel)).real, iterate(data))
True
多次迭代与在傅里叶域中获取内核的功能相同:
>>> np.allclose(ifftn(fftn(data) * fftn(kernel)**3).real, iterate(iterate(iterate(data))))
True
让我们看看傅立叶空间中的内核:
>>> fftn(kernel).real
array([[14., 6., 6., 6., 6., 6., 6., 6.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.],
[ 6., -2., -2., -2., -2., -2., -2., -2.]])
正如我们所看到的,左上角有一个显性条目,即恒定模式,即转换后的全局偏移。 显然,如果我们掌握这个FT内核的强大功能,那么恒定模式将变得越来越占主导地位。这也适用于具有此功率的FT数据产品,因此后重变换元素之间的相对差异将变得越来越小。
您可以尝试通过全局平均减法来解决这个问题。很容易验证FT内核的功能是否会收敛到原始内核的标量倍数:
>>> np.round((fftn(kernel-kernel.mean()).real)**100 / 10.**75, 20)
array([[ 0. , 653.32, 653.32, 653.32, 653.32, 653.32, 653.32, 653.32],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[653.32, 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])
由于一切都是真实的,这背面的FT与我们已经看到的前向FT相同。因此,使用平均减法进行迭代会将标量因子收敛到使用原始内核的FT的循环卷积。