首页 > 解决方案 > 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 ]]

标签: pythonnumpyvectorization

解决方案


矢量化与循环代码不同。首先为logA.T您添加的每一行添加一些值logB[t]。因此,对于矢量化形式,您应该添加 transposed logB[t]。在循环代码的第二个中,您可以在logA.Tso 的行中找到您应该使用的向量化形式的最大值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]]

推荐阅读