Python 中向量化代码和朴素循环代码之间的不同结果

Different results between vectorized code and naive loopy one in Python

logPi=np.random.normal(0,1,3)+10
logB=np.random.normal(0,1,(5,3))+10
logA=np.random.normal(0,1,(3,3))+10
logPi=np.log(logPi/np.sum(logPi))
logA=np.log(logA/np.sum(logA,axis=1,keepdims=1))
logB=np.log(logB/np.sum(logB,axis=1,keepdims=1))
N, M = logB.shape


theta = np.zeros_like(logB)
theta[0] = logPi + logB[0]
for t in range(1,N):
    for i in range(M):
        temp = theta[t-1]+logA.T[i]+logB[t][i]
        theta[t][i]=np.max(temp)
print("loop:\n",theta)


theta = np.zeros_like(logB)
theta[0] = logPi + logB[0]
for t in range(1,N):
    temp = theta[t-1]+logA.T+logB[t]    #theta[t-1]:(3,) logA.T (3,3) logB[t]:(3,)
    theta[t]=np.max(temp,axis=0)
print("vectorized:\n",theta)

以上是我的玩具代码。在 运行 之后,我得到了以下输出。最后两行的差异更为明显。虽然这里没什么大不了的,但当 N 很大时就会成为问题。我想知道为什么这两个看起来相同的代码之间存在如此大的差异。我查阅了一些博客,但它们主要是关于数据依赖性和提供很少帮助的操作顺序。提前致谢。

loop:
[[ -2.13807344  -2.08414176  -2.40187496]
[ -4.18153958  -4.13865644  -4.37805603]
[ -6.16769508  -6.28860493  -6.3818191 ]
[ -8.26547308  -8.33614274  -8.36669173]
[-10.47121378 -10.35391286 -10.38243085]]
vectorized:
[[ -2.13807344  -2.08414176  -2.40187496]
[ -4.23034598  -4.08985004  -4.60149803]
[ -6.25425934  -6.20204067  -6.76141802]
[ -8.22600221  -8.3756136   -8.92005515]
[-10.35594798 -10.46917867 -10.9966534 ]]

矢量化与循环代码不同。首先,为 logA.T 的每一行添加一些 logB[t] 的值。因此,对于矢量化形式,您应该添加转置 logB[t]。其次,在循环代码中,您会在 logA.T 行中找到最大值,因此在矢量化形式中,您应该使用 axis=1。所以对于代码

import numpy as np
np.random.seed(13)
logPi=np.random.normal(0,1,3)+10
logB=np.random.normal(0,1,(5,3))+10
logA=np.random.normal(0,1,(3,3))+10
logPi=np.log(logPi/np.sum(logPi))
logA=np.log(logA/np.sum(logA,axis=1,keepdims=1))
logB=np.log(logB/np.sum(logB,axis=1,keepdims=1))
N, M = logB.shape


theta = np.zeros_like(logB)
theta[0] = logPi + logB[0]
for t in range(1,N):
    for i in range(M):
        temp = theta[t-1]+logA.T[i]+logB[t][i]
        theta[t][i]=np.max(temp)
print("loop:\n",theta)


theta = np.zeros_like(logB)
theta[0] = logPi + logB[0]
for t in range(1,N):
    temp = theta[t-1]+logA.T+logB[t].reshape(-1, 1)    #theta[t-1]:(3,) logA.T (3,3) logB[t]:(3,)
    theta[t]=np.max(temp,axis=1)
print("vectorized:\n",theta)

我得到输出:

loop:
 [[ -2.30160901  -2.07302345  -2.22449041]
 [ -4.18171262  -4.24723468  -4.39804805]
 [ -6.30798908  -6.34130214  -6.49489672]
 [ -8.41830021  -8.5470397   -8.54808458]
 [-10.59480359 -10.67493831 -10.59373409]]
vectorized:
 [[ -2.30160901  -2.07302345  -2.22449041]
 [ -4.18171262  -4.24723468  -4.39804805]
 [ -6.30798908  -6.34130214  -6.49489672]
 [ -8.41830021  -8.5470397   -8.54808458]
 [-10.59480359 -10.67493831 -10.59373409]]