将函数应用于三维张量,同时忽略零行和填充

2024-10-01 13:45:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在努力提高运行时间的最昂贵的操作我的tensorflow管道。你知道吗

我正在尝试完成以下工作:我得到一个包含一些患者数据的多个样本的三维张量,例如,这些数据可以如下所示

n_hidden = 3  #number of elements per 1D tensor
batch_size = 3 #number of patients
n_mc_samples = 2 #number of samples per patient
rnn_grid_times = [2,3,1] #number of non zero 1D tensors per patient
all_outputs = tf.constant([[[0.15, 0.874, 0.2], [0.1,0.00878,0.58],[0.0,0.0,0.0]], #beginning of patient 1
                               [[0.456,0.454,0.003],[0.4564,0.4984,0.21], [0.0,0.0,0.0]],
                               [[0.121,0.22,0.45],[0.15,0.488,0.222], [0.11,0.849,0.45]],  #beginning of patient 2
                               [[0.15, 0.5646, 0.15], [0.45,0.48949,0.56465], [0.4489,0.456,0.9]],
                               [[0.121, 0.22, 0.01], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], #beginning of patient 3
                               [[0.15, 0.89, 0.42], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]])

该数据对应于3名患者,每个患者取样两次。如您所见,患者1和3的数据被填充为与患者2的数据大小相同。你知道吗

我的目标是将每个非零一维张量输入到一个具有一个隐层的单输出神经网络中,然后在零张量的位置添加额外的pedding,以便在患者之间保持统一的维数。所以这里一个有效的结果可能是

[[-0.11379365, -0.11188659,  0.        ],
 [-0.11379365, -0.11379365,  0.        ],
 [-0.1135166 , -0.11379365, -0.11379365],
 [-0.11379365, -0.11359671, -0.11270589],
 [-0.11379365,  0.        ,  0.        ],
 [-0.11379365,  0.        ,  0.        ]]

只是重申一下,因为我意识到这有点复杂,第一个代码块中与[0.15, 0.874, 0.2]关联的输出是第二个代码块中的-0.11379365。你知道吗

下面是单独的代码,上面是玩具数据。如果您有一个工作的tensorflow环境,这个应该可以毫无问题地运行

import tensorflow as tf    
RANDOM_SEED = 42
tf.set_random_seed(RANDOM_SEED)

def code():
    n_hidden = 3
    batch_size = 3
    n_mc_samples = 2
    num_rnn_grid_times = tf.constant([2, 3, 1])
    all_outputs = tf.constant([[[0.15, 0.874, 0.2], [0.1,0.00878,0.58],[0.0,0.0,0.0]], #beginning of patient 1
                               [[0.456,0.454,0.003],[0.4564,0.4984,0.21], [0.0,0.0,0.0]],
                               [[0.121,0.22,0.45],[0.15,0.488,0.222], [0.11,0.849,0.45]],  #beginning of patient 2
                               [[0.15, 0.5646, 0.15], [0.45,0.48949,0.56465], [0.4489,0.456,0.9]],
                               [[0.121, 0.22, 0.01], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], #beginning of patient 3
                               [[0.15, 0.89, 0.42], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]])


    n_extra_hidden_nodes = 2
    extra_hidden_weights = tf.Variable(tf.random_normal([n_hidden, n_extra_hidden_nodes], stddev=0.1), name="HiddenSoftmax/W")
    extra_hidden_biases = tf.Variable(tf.random_normal([n_extra_hidden_nodes], stddev=0.1), name="HiddenSoftmax/b")


    out_weights = tf.Variable(tf.random_normal([n_extra_hidden_nodes, 1], stddev=0.1), name="Softmax/W") 
    out_biases = tf.Variable(tf.random_normal([1], stddev=0.1), name="Softmax/b")



    nneth_array_total = tf.Variable([])
    n = tf.constant(0)
    inner_cond = lambda i, nneth_array, n: tf.less(i, num_rnn_grid_times[tf.floordiv(n,n_mc_samples)])
    cond = lambda n, nneth_array_total: tf.less(n, batch_size*n_mc_samples)

    def inner_body(i, nneth_array, n):
        hidden = tf.nn.relu(tf.matmul(tf.expand_dims(all_outputs[n][i], 0), extra_hidden_weights) + extra_hidden_biases)
        nneth = tf.matmul(hidden, out_weights) + out_biases
        nneth = tf.reshape(nneth, [1]) #single output for the neural net
        nneth_array = tf.concat([nneth_array, nneth], 0)
        return i + 1, nneth_array, n

    def body(n, nneth_array_total):
        nneth_array = tf.Variable([])
        i = tf.constant(0) #iterator over 1D tensors
        i, nneth_array, n = tf.while_loop(inner_cond, inner_body, loop_vars=[i, nneth_array, n], shape_invariants=[i.get_shape(), tf.TensorShape([None]), n.get_shape()])
        padding = tf.zeros([tf.reduce_max(num_rnn_grid_times) - num_rnn_grid_times[tf.floordiv(n,n_mc_samples)]],dtype=tf.float32)
        nneth_array = tf.concat([nneth_array, padding],0) #add extra zeros so that all nneth_arrays have same shape
        nneth_array_total= tf.concat([nneth_array_total, nneth_array], 0)
        return n+1, nneth_array_total


    n, nneth_array_total = tf.while_loop(cond, body, loop_vars=[n, nneth_array_total],
                                         shape_invariants=[n.get_shape(), tf.TensorShape([None])])

    nneth_array_total = tf.reshape(nneth_array_total, [batch_size*n_mc_samples, tf.reduce_max(num_rnn_grid_times)])

    preds = nneth_array_total
    return preds



if __name__ == '__main__':
    pred = code()
    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)



    sess.run(init)
    print(sess.run([pred]))

代码可以工作,但是速度很慢。这是一个管道的一部分,在一个病人身上迭代大约需要1.25秒,而且似乎很大一部分运行时间是由上面的代码造成的。这意味着使用我的数据集的一个历元大约需要12个小时,这与类似的方法相比有点太多了。你知道吗

我在谷歌上搜索了一下,找到了将函数应用于多维张量的方法,但没有一种方法同时考虑到填充。有什么见解吗?你知道吗


Tags: of数据患者tfmcarrayextrahidden
1条回答
网友
1楼 · 发布于 2024-10-01 13:45:54

即使输入向量为零,也能提供最快的处理时间。但正如你所说,由于网络中的偏差,这将返回一个非零输出。因为当输入向量需要为零时,您希望输出为零,所以一个简单的技巧是应用一个掩码,如果输入向量为零,则该掩码将使预测为零。你知道吗

当输入向量为非零时返回1,否则返回0的掩码可通过简单逻辑获得:

a_sum = tf.reduce_sum(all_outputs, 2)

mask = tf.cast(tf.greater(a_sum, tf.zeros_like(a_sum)), tf.float32)

然后将预测与遮罩相乘。你知道吗

相关问题 更多 >