【譯】Effective TensorFlow Chapter9——使用Python ops進行核心設計和高階視覺化

僱個城管打天下發表於2019-02-27

【譯】Effective TensorFlow Chapter9——使用Python ops進行核心設計和高階視覺化

本文翻譯自: 《Prototyping kernels and advanced visualization with Python ops》, 如有侵權請聯絡刪除,僅限於學術交流,請勿商用。如有謬誤,請聯絡指出。

TensorFlow中的核心操作完全用C ++編寫,以提高效率。但是用C++編寫TensorFlow核心的話可能會非常痛苦。因此,在花費數小時實現屬於自己的核心之前,你也許需要先實現一個操作的原型,儘管這樣的效率會很低。通過tf.py_func()你可以將任何一個python原始碼轉換為TensorFlow的操作。

舉個例子而言,這裡有一個用python自己實現的ReLU非線性啟用函式,通過tf.py_func()轉換為TensorFlow操作的例子:

import numpy as np
import tensorflow as tf
import uuid

def relu(inputs):
    # Define the op in python
    def _relu(x):
        return np.maximum(x, 0.)

    # Define the op's gradient in python
    def _relu_grad(x):
        return np.float32(x > 0)

    # An adapter that defines a gradient op compatible with TensorFlow
    def _relu_grad_op(op, grad):
        x = op.inputs[0]
        x_grad = grad * tf.py_func(_relu_grad, [x], tf.float32)
        return x_grad

    # Register the gradient with a unique id
    grad_name = "MyReluGrad_" + str(uuid.uuid4())
    tf.RegisterGradient(grad_name)(_relu_grad_op)

    # Override the gradient of the custom op
    g = tf.get_default_graph()
    with g.gradient_override_map({"PyFunc": grad_name}):
        output = tf.py_func(_relu, [inputs], tf.float32)
    return output
複製程式碼

通過TensorFlow的gradient checker,你可以確認這些梯度是否計算正確:

x = tf.random_normal([10])
y = relu(x * x)

with tf.Session():
    diff = tf.test.compute_gradient_error(x, [10], y, [10])
    print(diff)
複製程式碼

compute_gradient_error()數值化地計算梯度,返回與理論上的梯度的差別,我們所期望的是一個非常小的差別。 注意到我們的這種實現是非常低效率的,這僅僅在實現模型原型的時候起作用,因為python程式碼並不能並行化而且不能在GPU上運算(導致速度很慢)。一旦你確定了你的idea,你就需要用C++重寫其核心。 在實踐中,我們一般在Tensorboard中用python操作進行視覺化。如果你是在構建一個圖片分類模型,而且想要在訓練過程中視覺化你的模型預測,那麼TF允許你通過tf.summary.image()函式進行圖片的視覺化。

image = tf.placeholder(tf.float32)
tf.summary.image("image", image)
複製程式碼

但是這僅僅是視覺化了輸入的圖片,為了視覺化其預測結果,你還必須找一個方法在圖片上新增預測標識,當然這在現有的tensorflow操作中是不存在的。一個更簡單的方法就是通過python將預測標誌繪製到圖片上,然後再封裝它。

import io
import matplotlib.pyplot as plt
import numpy as np
import PIL
import tensorflow as tf

def visualize_labeled_images(images, labels, max_outputs=3, name="image"):
    def _visualize_image(image, label):
        # Do the actual drawing in python
        fig = plt.figure(figsize=(3, 3), dpi=80)
        ax = fig.add_subplot(111)
        ax.imshow(image[::-1,...])
        ax.text(0, 0, str(label),
          horizontalalignment="left",
          verticalalignment="top")
        fig.canvas.draw()

        # Write the plot as a memory file.
        buf = io.BytesIO()
        data = fig.savefig(buf, format="png")
        buf.seek(0)

        # Read the image and convert to numpy array
        img = PIL.Image.open(buf)
        return np.array(img.getdata()).reshape(img.size[0], img.size[1], -1)

    def _visualize_images(images, labels):
        # Only display the given number of examples in the batch
        outputs = []
        for i in range(max_outputs):
            output = _visualize_image(images[i], labels[i])
            outputs.append(output)
        return np.array(outputs, dtype=np.uint8)

    # Run the python op.
    figs = tf.py_func(_visualize_images, [images, labels], tf.uint8)
    return tf.summary.image(name, figs)
複製程式碼

請注意,因為summary通常只評估一次(並不是每步都執行),因此可以在實踐中可以使用而不必擔心效率。

相關文章