最近在修改一個論文的tensorflow代碼, 因爲源代碼使用的是
tf.placehold
作爲網絡的輸入, 當我在對網絡的一些中間變量進行操作時會常常因爲tf.placehold
的維度是None或?而無從下手將修改成我想要的網絡結果, 好在接觸到了tf.py_func()
這一內置函數, 才解決了我的問題
一. tensor存在問題
tensorflow 不同於 pyrorch, 正是其所構建的是靜態圖, 即在網絡裏並沒有實際的值(指在執行sess.run()
操作之前), 不能進行鍼對 tensor 進行類似取值、賦值、判定之類的操作.
顯然, numpy在這一塊的操作上遠遠比tensorflow的tensor要靈活的多.
二. 解決思路
tf.py_func()
正是通往numpy靈活操作的一個大門.
其接受tensor, 然後在函數內將其轉換成numpy array, 經過我們內部自定義的一個函數處理後, 得到的處理過的numpy array再轉換成tensor返回. 即, 輸入tensor, 執行numpy array的操作, 返回tensor.
給tensor的操作帶來了極大的靈活性!
三. tf.py_func()
tf.py_func(func, inp, Tout)
func
: 自定義的函數, 在內部執行的是numpy array的操作, 即定義成輸入的是numpy array, 返回的也是 numpy arrayinp
: 自定義的func
函數的輸入名稱,- 對於單變量輸入以
[inputArrary]
的形式進行組織 - 對於多變量輸入以
[inputArray1, inputArray2,...]
的形式進行組織
- 對於單變量輸入以
Tout
: 自定義的func
函數的輸出數據類型,- 對於單變量輸出以
outputArray
或[outputArray]
的形式進行組織 - 對於多變量輸出以
[outputArrayType1, outputArryType2,...]
的形式進行組織
- 對於單變量輸出以
3.1. 舉例
3.1.1. 多變量輸入, 單變量輸出
import numpy as np
import tensorflow as tf
# array1 和 array2 有相同的size [2, 3]
# 執行加操作
def addTensor(array1, array2):
for i in range(array1.shape[0]):
for j in range(array1.shape[1]):
array2[i][j] = array2[i][j]+array1[i][j]
return array2
a1 = tf.convert_to_tensor(np.array([[1,2,3],[4,5,6]]))
a2 = tf.convert_to_tensor(np.array([[1,1,1],[1,1,1]]))
sum_array = tf.py_func(addTensor, [a1, a2], tf.int32)
#或寫成
# sum_array, = tf.py_func(addTensor, [a1, a2], [tf.int32])
print("sum_array before sess: \n", sum_array)
sess=tf.Session()
sum_array_ = sess.run(sum_array)
print("sum_array after sess: \n", sum_array_)
# 輸出
sum_array before sess:
Tensor("PyFunc:0", dtype=int32)
sum_array after sess:
[[ 2 3 4]
[ 5 6 7]]
3.1.2. 單變量輸入, 多變量輸出
import numpy as np
import tensorflow as tf
# array1 size [2, 3]
# 執行維度分離操作
def removeTensor(array1):
arr1 = np.zeros([3], np.int32)
arr2 = np.zeros([3], np.int32)
for i in range(array1.shape[0]):
for j in range(array1.shape[1]):
if i:
arr2[j] = array1[i][j]
else:
arr1[j] = array1[i][j]
return arr1, arr2
a1 = tf.convert_to_tensor(np.array([[1,2,3],[4,5,6]]))
arr1, arr2 = tf.py_func(removeTensor, [a1], [tf.int32, tf.int32])
#或寫成
# sum_array, = tf.py_func(addTensor, [a1, a2], [tf.int32])
print("arr1 before sess: \n", arr1)
print("----------------------------")
print("arr2 before sess: \n", arr2)
sess=tf.Session()
arr1_,arr2_=sess.run([arr1, arr2])
print("arr1 after sess: \n", arr1_)
print("----------------------------")
print("arr2 after sess: \n", arr2_)
# 輸出
arr1 before sess:
Tensor("PyFunc:0", dtype=int32)
----------------------------
arr2 before sess:
Tensor("PyFunc:1", dtype=int32)
arr1 after sess:
[1 2 3]
----------------------------
arr2 after sess:
[4 5 6]