【Tensorflow】--- tf.py_func 增強tensor靈活性

最近在修改一個論文的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 array
  • inp: 自定義的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]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章