1. 程式人生 > >8 tensorflow修改矩陣的某一列

8 tensorflow修改矩陣的某一列

tf1.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資料。

第二,如果反覆對一個矩陣的列進行修改,正如上述程式碼第二個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迴圈結束時的輸出如下:

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