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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM