Python 张量流,迭代张量

Python 张量流,迭代张量,python,tensorflow,Python,Tensorflow,我定义了我的损失函数,我想迭代批次中的每一项来计算损失函数。我使用了tf.map\fn但是,我发现它非常慢。有什么建议吗 def损耗(φ,μ,σ,t_φ,t_μ,t_σ): _损失=0.0 对于范围内的i(φ形状[0]): 对于范围内的j(φ形状[0]): _损耗+=phi[i]*phi[j]*pdf(μ[i],μ[j],tf.sqrt(σ[i]**2+σ[j]**2)) _损失+=t_-phi[i]*t_-phi[j]*pdf(t_-mu[i],t_-mu[j],tf.sqrt(t_-sigm

我定义了我的损失函数,我想迭代批次中的每一项来计算损失函数。我使用了
tf.map\fn
但是,我发现它非常慢。有什么建议吗

def损耗(φ,μ,σ,t_φ,t_μ,t_σ):
_损失=0.0
对于范围内的i(φ形状[0]):
对于范围内的j(φ形状[0]):
_损耗+=phi[i]*phi[j]*pdf(μ[i],μ[j],tf.sqrt(σ[i]**2+σ[j]**2))
_损失+=t_-phi[i]*t_-phi[j]*pdf(t_-mu[i],t_-mu[j],tf.sqrt(t_-sigma[i]**2+t_-sigma[j]**2))
_损耗+=-2*phi[i]*t_phi[j]*pdf(μ[i],t_μ[j],tf.sqrt(σ[i]**2+t_σ[j]**2))
返回tf.sqrt(_损失)
def减少损耗(φ、μ、西格玛、t_φ、t_μ、t_西格玛):
将tf.变量范围(“损失”)作为损失:
堆叠=tf.堆叠([phi,mu,sigma,t_phi,t_mu,t_sigma],1)
返回tf.map_fn(λx:loss(x[0],x[1],x[2],x[3],x[4],x[5]),叠加,
并行迭代次数=4)
def pdf(x,mu,sigma):
返回tf.exp(-0.5*(x-mu)**2/西格玛**2)/((2*np.pi*西格玛**2)**0.5)

批量大小为1024

您可以消除
loss
函数中的循环。这是通过矢量化一切来实现的。例如,您通过迭代
i
j
来计算
phi[i]*phi[j]
,但这是
tf.matmul(phi[:,None],phi[None,:])
的第i个元素。这样做应该比使用循环实现更快

此外,由于tensorflow是静态构建图形的,因此您的函数甚至可能需要很长时间才能构建图形。因此,通常应该避免tensorflow中的大嵌套for循环

我已经做了一个例子,将损失函数的一部分矢量化,其他部分应该很容易做到

import tensorflow as tf
from numpy import pi as PI
from time import time


# some random vectors
size = 10
phi = tf.random.uniform([size])
mu = tf.random.uniform([size])
sigma = tf.random.uniform([size])


####################################
# Your original loss
####################################

def pdf(x, m, s):
    return tf.exp(-0.5*(x-m)**2/s**2) / ((2*PI*s**2)**0.5)


def loss():
    _loss = 0.0
    for i in range(phi.shape[0]):
        for j in range(phi.shape[0]):
            _loss += phi[i] * phi[j] * pdf(mu[i], mu[j], tf.sqrt(sigma[i]**2 + sigma[j]**2))
    return tf.sqrt(_loss)


####################################
# vectorised loss
####################################

def vector_pdf(x, s):
    return tf.exp(-0.5*x**2/s**2) / ((2*PI*s**2)**0.5)


def vectorised_loss():
    phi_ij = tf.matmul(phi[:, None], phi[None, :])
    difference = mu[:, None] - mu[None, :]
    sigma_squared = sigma**2
    sigma_sum = tf.sqrt(sigma_squared[:, None] + sigma_squared[None, :])

    loss_array = phi_ij*vector_pdf(difference, sigma_sum)
    return tf.sqrt(tf.reduce_sum(loss_array))


#######################################
# Time the functions and show they are the same
#######################################

with tf.Session() as sess:
    loop_loss = loss()
    vector_loss = vectorised_loss()
    # init = tf.global_variables_initializer()
    # sess.run(init)

    t = 0.
    for _ in range(100):
        st = time()
        loop_loss_val = sess.run(loop_loss)
        t += time() - st
    print('loop took {}'.format(t/100))

    t = 0.
    for _ in range(100):
        st = time()
        vector_val = sess.run(vector_loss)
        t += time() - st
    print('vector took {}'.format(t / 100))

    l_val, v_val = sess.run([loop_loss, vector_loss])
    print(l_val, v_val)
这张照片

loop took 0.01740453243255615
vector took 0.004280190467834472
4.6466274 4.6466274
通过矢量化损失函数,reduce函数也应该可以直接矢量化。现在您需要批处理matmul,并稍微更改减法的索引。例如:

mu[:, None] - mu[None, :]
# becomes
mu[: ,:, None] - mu[:, None, :]

pdf
pdf是多元高斯分布的吗?你也可以展示一下我在问题中添加的
pdf
@mujjiga的代码。