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