利用 TensorFlow 實現排序和搜索算法

做者:chen_h
微信號 & QQ:862251340
微信公衆號:coderpai
簡書地址http://www.jianshu.com/p/1da0...

TensorFlow 所構成的計算圖是圖靈完備的。
圖片描述python

當咱們提到 TensorFlow 的時候,咱們僅僅只會關注它是一個很好的神經網絡和深度學習的庫。可是,它也知足數據流編程(DFP)的各個方面。git

因爲 TensorFlow 具備 tf.cond 和 tf.while_loop 函數,前者能夠處理判斷語句,後者能夠處理循環語句,因此它就具備通常編程語言相同的表達式。簡單的說,咱們能夠用 C 語言或者 Python 語言實現的排序和搜索算法均可以在 TensorFlow 圖中實現。github

在本文中,我將介紹的就是 TensorFlow 的另外一面,它的通常編程語言表達方式。我利用 TensorFlow 圖實現了一些算法,諸如 FizzBuzzBubble SortQuick SortBinary Search 等等。算法

在 TensorFlow 中實現算法

Fizz Buzz 問題編程

請依次打印從1至100的整數,在該數能被3整除的時候,打印"Fizz",能被5整除的時候打印"Buzz",若是既能被3又能被5整除的時候,打印"FizzBuzz"。api

import tensorflow as tf

class FizzBuzz():
    def __init__(self, length=30):
        self.length = length  # 程序須要執行的序列長度
        self.array = tf.Variable([str(i) for i in range(1, length+1)], dtype=tf.string, trainable=False)  # 最後程序返回的結果
        self.graph = tf.while_loop(self.cond, self.body, [1, self.array],)   # 對每個值進行循環判斷

    def run(self):
        with tf.Session() as sess:
            tf.global_variables_initializer().run()
            return sess.run(self.graph)    

    def cond(self, i, _):
        return (tf.less(i, self.length+1)) # 判斷是不是最後一個值

    def body(self, i, _):
        flow = tf.cond(
            tf.equal(tf.mod(i, 15), 0),  # 若是值能被 15 整除,那麼就把該位置賦值爲 FizzBuzz
                lambda: tf.assign(self.array[i - 1], 'FizzBuzz'),
            
                lambda: tf.cond(tf.equal(tf.mod(i, 3), 0), # 若是值能被 3 整除,那麼就把該位置賦值爲 Fizz
                        lambda: tf.assign(self.array[i - 1], 'Fizz'),
                        lambda: tf.cond(tf.equal(tf.mod(i, 5), 0),   # 若是值能被 5 整除,那麼就把該位置賦值爲 Buzz
                                lambda: tf.assign(self.array[i - 1], 'Buzz'),
                                lambda: self.array  # 最後返回的結果
                )
            )
        )
        return (tf.add(i, 1), flow)

if __name__ == '__main__':
    fizzbuzz = FizzBuzz(length=50)
    ix, array = fizzbuzz.run()
    print(array)

輸出結果:微信

['1' '2' 'Fizz' '4' 'Buzz' 'Fizz' '7' '8' 'Fizz' 'Buzz' '11' 'Fizz' '13'
 '14' 'FizzBuzz' '16' '17' 'Fizz' '19' 'Buzz' 'Fizz' '22' '23' 'Fizz'
 'Buzz' '26' 'Fizz' '28' '29' 'FizzBuzz' '31' '32' 'Fizz' '34' 'Buzz'
 'Fizz' '37' '38' 'Fizz' 'Buzz' '41' 'Fizz' '43' '44' 'FizzBuzz' '46' '47'
 'Fizz' '49' 'Buzz']

Linear Search網絡

給定一個序列和一個目標值,從這個序列中找到這個目標值的位置。less

import numpy as np
import tensorflow as tf

class LinearSearch():
    def __init__(self, array, x):
        self.x = tf.constant(x)
        self.array = tf.constant(array)
        self.length = len(array)
        self.graph = tf.while_loop(self.cond, self.body, [0, self.x, False])

    def run(self):
        with tf.Session() as sess:
            tf.global_variables_initializer().run()
            return sess.run(self.graph)

    def cond(self, i, _, is_found):
        return tf.logical_and(tf.less(i, self.length), tf.logical_not(is_found))

    def body(self, i, _, is_found):
        return tf.cond(tf.equal(self.array[i], self.x),
                    lambda: (i, self.array[i], True),
                    lambda: (tf.add(i, 1), -1, False))

if __name__ == '__main__':
    array, x = [1, 22, 33, 1, 7, 3, 8], 3
    search = LinearSearch(array, x)
    ix, xx, is_found = search.run()
    print('Array :', array)
    print('Number to search :', x)
    if is_found:
        print('{} is at index {}.'.format(xx, ix))
    else:
        print('Not found.')

輸出結果:dom

Array : [1, 22, 33, 1, 7, 3, 8]
Number to search : 3
3 is at index 5.

Bubble Sort

import numpy as np
import tensorflow as tf

class BubbleSort():
    def __init__(self, array):
        self.i = tf.constant(0)
        self.j = tf.constant(len(array)-1)
        self.array = tf.Variable(array, trainable=False)
        self.length = len(array)

        cond = lambda i, j, _: tf.less(i-1, self.length-1)
        self.graph = tf.while_loop(cond, self.outer_loop, loop_vars=[self.i, self.j, self.array])

    def run(self):
        with tf.Session() as sess:
            tf.global_variables_initializer().run()
            return sess.run(self.graph)

    def outer_loop(self, i, j, _):
        cond = lambda i, j, _: tf.greater(j, i)
        loop = tf.while_loop(cond, self.inner_loop, loop_vars=[i, self.length-1, self.array])
        return tf.add(i, 1), loop[1], loop[2]

    def inner_loop(self, i, j, _):
        body = tf.cond(tf.greater(self.array[j-1], self.array[j]),
                    lambda: tf.scatter_nd_update(self.array, [[j-1],[j]], [self.array[j],self.array[j-1]]),
                    lambda: self.array)
        return i, tf.subtract(j, 1), body

if __name__ == '__main__':
    x = np.array([1.,7.,3.,8.])
    _, _, sorted_array = BubbleSort(x).run()
    print(x)
    print(sorted_array)

輸出結果:

[ 1.  7.  3.  8.]
[ 1.  3.  7.  8.]

還有更多的實現算法,你能夠查看這個 Github

API 解釋

相似判斷語句的 API:tf.cond()

cond(
    pred,
    true_fn=None,
    false_fn=None,
    strict=False,
    name=None,
    fn1=None,
    fn2=None
)

tf.cond(...) 是一個等效於 if 語句的節點。根據其中的參數 pred 返回的布爾值來判斷返回什麼值,好比當參數 pred 爲 true 值時,節點返回參數 true_fn 的值,當參數 pred 爲 false 時,節點返回參數 false_fn 的值。可是,其中的參數 true_fn 和參數 false_fn 都是須要是 lambda 或者函數。好比:

z = tf.multiply(a, b)
result = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))

當 x < y 是 true 時,節點就會去執行 tf.add 操做。當 x < y 是 false 時,節點就會去執行 tf.square 操做。

接下來,咱們來看一個完整的例子,以下:

x = tf.constant(2)
y = tf.constant(5)
def f1():
    return tf.multiply(x, 17)

def f2():
    return tf.add(y, 23)

r = tf.cond(tf.less(x, y), f1, f2)
with tf.Session() as sess:
    print(sess.run(r))

請注意:API 中的某些參數被忽略了,由於它們將在之後的版本中被刪除。

相似判斷語句的 API: tf.while_loop()

while_loop(
    cond, # Condition  
    body, # Process to be executed when cond is True
    loop_vars, # Argument to body
    shape_invariants=None,
    parallel_iterations=10,
    back_prop=True,
    swap_memory=False,
    name=None
)

tf.while_loop(...) 是一個等效於 while 語句的節點。根據其中的參數 cond 的布爾值來判斷是否將循環繼續,好比當參數 pred 爲 true 值時,節點去執行 body 中的語句,當參數 pred 爲 false 時,那麼退出這個函數。好比:

i = tf.constant(0)
c = lambda i: tf.less(i, 10)
b = lambda i: tf.add(i, 1)
r = tf.while_loop(c, b, [i])

當 i < 10 時,cond 返回的值是 true,因此節點會去執行 body 中的語句。當 i == 10 時,cond 返回的值是 false,那麼節點就會退出。這種執行方式和通常語言中的 while 很是像。

咱們也能夠將循環式表達成以下:

while(condition(tensors))
{ 
     tensors = body(tensors); 
}

接下來,咱們來看一個完整的例子,以下:

import tensorflow as tf
import numpy as np

def body(x):
    a = tf.random_uniform(shape=[2, 2], dtype=tf.int32, maxval=100)
    b = tf.constant(np.array([[1, 2], [3, 4]]), dtype=tf.int32)
    c = a + b
    return tf.nn.relu(x + c)

def condition(x):
    return tf.reduce_sum(x) < 100

x = tf.Variable(tf.constant(0, shape=[2, 2]))

with tf.Session():
    tf.initialize_all_variables().run()
    result = tf.while_loop(condition, body, [x])
    print(result.eval())

做者:chen_h

微信號 & QQ:862251340

博客地址:http://www.jianshu.com/p/1da0...

CoderPai 是一個專一於算法實戰的平臺,從基礎的算法到人工智能算法都有設計。若是你對算法實戰感興趣,請快快關注咱們吧。加入AI實戰微信羣,AI實戰QQ羣,ACM算法微信羣,ACM算法QQ羣。長按或者掃描以下二維碼,關注 「CoderPai」 微信號(coderpai

算法社區直播間

相關文章
相關標籤/搜索