• 8 tensorflow修改tensor张量矩阵的某一列


    1.tensorflow的数据流图限制了它的tensor是只读属性,因此对于一个Tensor(张量)形式的矩阵,想修改特定位置的元素,比较困难。

    2.我要做的是将所有的操作定义为符号形式的操作。也就是抽象概念的数据流图。当用feed_dict传入具体值以后,就能用sess.run读出具体值。

    一、相关内容

    https://blog.csdn.net/Cerisier/article/details/79584851

    Tensorflow小技巧整理:修改张量特定元素的值

    二、修改矩阵的某一列

    代码:

    # -*- coding: utf-8 -*-
    """
    Created on Sat Dec  1 16:53:26 2018
    
    @author: a
    """
    import tensorflow as tf
    x = tf.placeholder(tf.float32, shape=(2, 2), name="input")
    xx=tf.zeros([2,3],tf.float32)
    xx2=tf.concat([x,xx],axis=1)
    columnTensor=tf.ones([2,1],tf.float32)
    print (xx2)
    w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1),trainable=False)
    w2= tf.Variable(xx2,trainable=False)
    #编写程序修改Tensor矩阵的某一列
    embed_size=300
    max_sentence_length=50
    max_node_size=max_sentence_length*2-1#训练语料库句子节点的最大长度。注意,是句子节点的最大长度。不是句子单词的最大数目。
    #test=tf.Variable(name="test",trainable=False,dtype=tf.float64,shape=[embed_size,max_node_size])
    def modify_one_column(tensor,columnTensor,index):#index也是tensor
    #tensor为二维矩阵
    #columnTensor的维度就是tensor中的一列
        numlines=tensor.shape[0].value #行数
        numcolunms=tensor.shape[1].value #列数
        new_tensor_left=tf.slice(tensor, [0, 0], [numlines, index])
        new_tensor_right=tf.slice(tensor, [0, index+1], [numlines, numcolunms-(index+1)])
        new_tensor=tf.concat([new_tensor_left,columnTensor,new_tensor_right],1)
        return new_tensor_left,new_tensor_right,new_tensor
    #    def f1():#index为0的情形
    #        new_tensor_right=tf.slice(tensor, [0, 1], [numlines, numcolunms-1])
    #        new_tensor=tf.concat([columnTensor,new_tensor_right],1)
    #        return new_tensor
    #    if (tf.equal(index,0)):
    #        new_tensor_right=tf.slice(tensor, [0, 1], [numlines, numcolunms-1])
    #        new_tensor=tf.concat([columnTensor,new_tensor_right],1)
    #        return new_tensor
    
    sess = tf.Session()
    init_op = tf.global_variables_initializer()  
    #print(sess.run(x, feed_dict={x: [[0.7,0.9]]}))
    sess.run(init_op,feed_dict={x: [[0.7,0.9],[80.0,90.0]]})
    print (sess.run((w1,w2)))
    print (w2)
    for index in range(5):
        index_tensor=tf.constant(index,tf.int32)
        new_tensor_left,new_tensor_right,w22=modify_one_column(w2,columnTensor,index_tensor)
        print (sess.run([new_tensor_left,columnTensor,new_tensor_right,w22]))
    for index in range(5):
        index_tensor=tf.constant(index,tf.int32)
        new_tensor_left,new_tensor_right,w2=modify_one_column(w2,columnTensor,index_tensor)
        print (sess.run([new_tensor_left,columnTensor,new_tensor_right,w2]))
    #print (sess.run(w2,feed_dict={x: [[0.7,0.9]]}))

    要注意的是:for循环中传入的是index_tensor而不是index。也就是定义的所有操作都是符号上的操作。这是写tensorflow计算图要遵循的一个重要原则。

    上述第二个代码的for循环会在index=1的时候报错。这是因为index=0的时候,w2还是一个固定shape的Tensor矩阵。但是当执行完一次如下代码以后

    new_tensor_left,new_tensor_right,w2=modify_one_column(w2,columnTensor,index_tensor)

    w2的shape会变成(2,?),这是因为第一次调用modify_one_column中执行的时候,传入的index_tensor是一个Tensor,就会导致函数体内的new_tensor_left和new_tensor_right等的列数都变成了Tensor,即?,也就导致最后返回的new_tensor的列数也是Tensor,即?。

    因此,第二次调用modify_one_column执行的时候,计算numcolunms=tensor.shape[1].value时得到的numcolunms是None。因此程序会报出:

    ipdb> ValueError: None values not supported.

    三、总结

    第一,被修改的tensor矩阵用tf.variable保存,并且指定trainable=false,并且是根据tf.place_holder的数据流构建。这样的话,我们执行

    init_op = tf.global_variables_initializer()  
    #print(sess.run(x, feed_dict={x: [[0.7,0.9]]}))
    sess.run(init_op,feed_dict={x: [[0.7,0.9],[80.0,90.0]]})

    以后就可以将被修改的tensor矩阵与输入之间建立直接的关联。

    不用tf.constant的原因是,tf.constant不能根据tf.place_hodler的数据流构建。tf.constant的函数说明如下,可以看到,其不能基于Tensor构建Tensor。

    而tf.variable可以基于Tensor构建tensor。也就是接受tensor数据输入,然后variable节点输出tensor数据。(传入的Tensor必须是shape specified。否则不能作为tf.Variable的参数)

    第二,如果反复对一个矩阵的列进行修改,正如上述代码第二个for循环,通过反复运算,能够将矩阵的每一列都变成[1,1]。这个时候,要记住,一定要在第一次将被修改矩阵的行数和列数保存下来,而不是每一次在循环体内进行计算。

    因为循环体内对矩阵某一列进行修改,实际上是一个只读的操作,也就是取出被修改列前,被修改列后,然后要修改成的列,拼接而成。这样的话,截取这个矩阵的时候,就会导致列数变成了?,也就是不能确定具体多少列。

    如此以来,下一次循环体内如果还想计算列数,就比较困难。

    为什么会导致这样。这是因为我传入的index就是一个Tensor。也就是矩阵哪一列被修改,我传入的是Tensor。这就导致了tf.slice切片以后的输出矩阵的列数仍然是一个tensor。

    为什么我要传入Tensor,而不是一个具体的值。这是因为我有一个任务需求,是根据实际传入的place_holder的input数据的值,去索引tensor矩阵。但是在构建计算图的时候,这个数据是不知道的,是个tensor。所以,我定义的操作都是在符号上进行的。

    上述for循环代码修改如下:

    def modify_one_column(tensor,columnTensor,index,numlines,numcolunms):#index也是tensor
    #tensor为二维矩阵
    #columnTensor的维度就是tensor中的一列
        new_tensor_left=tf.slice(tensor, [0, 0], [numlines, index])
        new_tensor_right=tf.slice(tensor, [0, index+1], [numlines, numcolunms-(index+1)])
        new_tensor=tf.concat([new_tensor_left,columnTensor,new_tensor_right],1)
        return new_tensor_left,new_tensor_right,new_tensor
    
    sess = tf.Session()
    init_op = tf.global_variables_initializer()  
    #print(sess.run(x, feed_dict={x: [[0.7,0.9]]}))
    sess.run(init_op,feed_dict={x: [[0.7,0.9],[80.0,90.0]]})
    print (sess.run((w1,w2)))
    print (w2)
    
    numlines=w2.shape[0].value
    numcolunms=w2.shape[1].value
    for index in range(5):
        index_tensor=tf.constant(index,tf.int32)
        new_tensor_left,new_tensor_right,w2=modify_one_column(w2,columnTensor,index_tensor,numlines,numcolunms)
        print (sess.run([new_tensor_left,columnTensor,new_tensor_right,w2]))

    最后一次for循环结束时的输出如下:

    可以看到,每一列都依次被修改了。

    我们还可以将numlines等具体值也变为tensor,如下:

    numlines_tensor=tf.constant(numlines,tf.int32)
    numcolunms_tensor=tf.constant(numcolunms,tf.int32)
  • 相关阅读:
    python
    python
    网站备案流程_网站备案需要什么
    php 导出 Excel 报错 exception 'PHPExcel_Calculation_Exception' with message
    EasyUI-datagrid-自动合并单元格(转)
    win2008阿里一键环境包mysql老是1067报错
    微信公众平台开发(58)自定义菜单
    Token验证失败的解决方法
    jquery设置select选中
    YII学习第二十三天,accessRules用法
  • 原文地址:https://www.cnblogs.com/xiaojieshisilang/p/10050973.html
Copyright © 2020-2023  润新知