在python 2.7(numpy)中是否可以在没有循环的情况下进行这些矩阵运算?

时间:2017-08-28 02:13:24

标签: arrays python-2.7 numpy numpy-broadcasting

我想在Python中使用矩阵实现下面的循环:

import numpy as np

n = 5 # samples
k = 2 # inputs
m = 3 # gaussians

# X is nxk
X = np.array([[0.0, 10.0], [20.0, 30.0],[40, 50],[60,70],[80,90]])

#locations is mxk
locations = np.array([[0.01, 0.02], [0.03,0.04], [0.05, 0.06]])

dev = np.empty([n,k,m])

for samples in range(n):
    for inputs in range(k):
        for gaussians in range(m):
            dev[samples,inputs,gaussians]=X[samples,inputs]-locations[gaussians,inputs]

output = np.empty([n,m]) 

for samples in range(n):
    for gaussians in range(m):
        output[samples,gaussians]=np.sum(dev[samples,:,gaussians]*dev[samples,:,gaussians])

我知道Numpy能够使用不同维度的数组(Broadcast)进行操作,但我不能在这里使用这个概念。请注意,我基本上做的是删除矢量样本的平均值并计算其平方范数。

1 个答案:

答案 0 :(得分:1)

你可以像这样对你的for循环进行矢量化; dev基本上是Xlocations相对于第一维的外部操作,因此您可以在locations(或X中插入新轴,这只会影响你如何转置结果),减法会触发numpy广播并返回笛卡尔/外部减法;对于第二个,您需要将dev与其自身相乘,并将sum与第二维(轴= 1)相乘:

mydev = np.transpose(X - locations[:,None], (1,2,0))

(mydev == dev).all()
# True

myoutput = (mydev**2).sum(axis=1)

(myoutput == output).all()
# True

或者放在一起:

((X[:,None] - locations) ** 2).sum(axis=-1)

#array([[    99.6005,     99.2025,     98.8061],
#       [  1298.4005,   1296.4025,   1294.4061],
#       [  4097.2005,   4093.6025,   4090.0061],
#       [  8496.0005,   8490.8025,   8485.6061],
#       [ 14494.8005,  14488.0025,  14481.2061]])