Theano 中文文檔 0.9 - 7.2.5 循環(huán)

7.2.5 循環(huán)

譯者:Python 文檔協(xié)作翻譯小組戳表,原文:Loop

本文以 CC BY-NC-SA 4.0 協(xié)議發(fā)布昼伴,轉載請保留作者署名和文章出處匾旭。

Python 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們圃郊,完全公益性質价涝。交流群:467338606。

Scan

  • 重復的一般形式持舆,可用于循環(huán)色瘩。
  • Reductionmap(在前面的維度上循環(huán))是scan的特殊情況。
  • 你沿著某個輸入序列scan一個函數逸寓,在每個時間步驟產生輸出居兆。
  • 這個函數可以看到你的函數的以前的K個時間步長
  • sum()可以通過在一個列表上scan z + x(i)函數計算得到竹伸,其中初始狀態(tài)為z=0泥栖。
  • 通常簇宽,for循環(huán)可以表示為scan()操作,scan是Theano對循環(huán)最接近的實現吧享。
  • 使用scan比使用for循環(huán)的優(yōu)點:
    • 作為符號圖一部分的迭代次數魏割。
    • 最小化GPU傳輸(如果涉及GPU)。
    • 通過連續(xù)步驟計算梯度钢颂。
    • 使用編譯的Theano函數比在Python中使用for循環(huán)稍快钞它。
    • 可以通過檢測所需的實際內存量來降低總體內存使用量。

完整的文檔可以在庫中找到:Scan殊鞭。

一個很好的ipython筆記遭垛,帶有解釋和更多的例子。

Scan示例:按元素計算tanh(x(t).dot(W) + b)

import theano
import theano.tensor as T
import numpy as np

# defining the tensor variables
X = T.matrix("X")
W = T.matrix("W")
b_sym = T.vector("b_sym")

results, updates = theano.scan(lambda v: T.tanh(T.dot(v, W) + b_sym), sequences=X)
compute_elementwise = theano.function(inputs=[X, W, b_sym], outputs=results)

# test values
x = np.eye(2, dtype=theano.config.floatX)
w = np.ones((2, 2), dtype=theano.config.floatX)
b = np.ones((2), dtype=theano.config.floatX)
b[1] = 2

print(compute_elementwise(x, w, b))

# comparison with numpy
print(np.tanh(x.dot(w) + b))

[[ 0.96402758  0.99505475]
 [ 0.96402758  0.99505475]]
[[ 0.96402758  0.99505475]
 [ 0.96402758  0.99505475]]

Scan示例:計算序列x(t) = tanh(x(t - 1).dot(W) + y(t).dot(U) + p(T - t).dot(V))

import theano
import theano.tensor as T
import numpy as np

# define tensor variables
X = T.vector("X")
W = T.matrix("W")
b_sym = T.vector("b_sym")
U = T.matrix("U")
Y = T.matrix("Y")
V = T.matrix("V")
P = T.matrix("P")

results, updates = theano.scan(lambda y, p, x_tm1: T.tanh(T.dot(x_tm1, W) + T.dot(y, U) + T.dot(p, V)),
          sequences=[Y, P[::-1]], outputs_info=[X])
compute_seq = theano.function(inputs=[X, W, Y, U, P, V], outputs=results)

# test values
x = np.zeros((2), dtype=theano.config.floatX)
x[1] = 1
w = np.ones((2, 2), dtype=theano.config.floatX)
y = np.ones((5, 2), dtype=theano.config.floatX)
y[0, :] = -3
u = np.ones((2, 2), dtype=theano.config.floatX)
p = np.ones((5, 2), dtype=theano.config.floatX)
p[0, :] = 3
v = np.ones((2, 2), dtype=theano.config.floatX)

print(compute_seq(x, w, y, u, p, v))

# comparison with numpy
x_res = np.zeros((5, 2), dtype=theano.config.floatX)
x_res[0] = np.tanh(x.dot(w) + y[0].dot(u) + p[4].dot(v))
for i in range(1, 5):
    x_res[i] = np.tanh(x_res[i - 1].dot(w) + y[i].dot(u) + p[4-i].dot(v))
print(x_res)

[[-0.99505475 -0.99505475]
 [ 0.96471973  0.96471973]
 [ 0.99998585  0.99998585]
 [ 0.99998771  0.99998771]
 [ 1\.          1\.        ]]
[[-0.99505475 -0.99505475]
 [ 0.96471973  0.96471973]
 [ 0.99998585  0.99998585]
 [ 0.99998771  0.99998771]
 [ 1\.          1\.        ]]

Scan示例:計算X行的范數

import theano
import theano.tensor as T
import numpy as np

# define tensor variable
X = T.matrix("X")
results, updates = theano.scan(lambda x_i: T.sqrt((x_i ** 2).sum()), sequences=[X])
compute_norm_lines = theano.function(inputs=[X], outputs=results)

# test value
x = np.diag(np.arange(1, 6, dtype=theano.config.floatX), 1)
print(compute_norm_lines(x))

# comparison with numpy
print(np.sqrt((x ** 2).sum(1)))

[ 1\.  2\.  3\.  4\.  5\.  0.]
[ 1\.  2\.  3\.  4\.  5\.  0.]

Scan示例:計算X列的范數

import theano
import theano.tensor as T
import numpy as np

# define tensor variable
X = T.matrix("X")
results, updates = theano.scan(lambda x_i: T.sqrt((x_i ** 2).sum()), sequences=[X.T])
compute_norm_cols = theano.function(inputs=[X], outputs=results)

# test value
x = np.diag(np.arange(1, 6, dtype=theano.config.floatX), 1)
print(compute_norm_cols(x))

# comparison with numpy
print(np.sqrt((x ** 2).sum(0)))

[ 0\.  1\.  2\.  3\.  4\.  5.]
[ 0\.  1\.  2\.  3\.  4\.  5.]

掃描示例:計算X的跡

import theano
import theano.tensor as T
import numpy as np
floatX = "float32"

# define tensor variable
X = T.matrix("X")
results, updates = theano.scan(lambda i, j, t_f: T.cast(X[i, j] + t_f, floatX),
                  sequences=[T.arange(X.shape[0]), T.arange(X.shape[1])],
                  outputs_info=np.asarray(0., dtype=floatX))
result = results[-1]
compute_trace = theano.function(inputs=[X], outputs=result)

# test value
x = np.eye(5, dtype=theano.config.floatX)
x[0] = np.arange(5, dtype=theano.config.floatX)
print(compute_trace(x))

# comparison with numpy
print(np.diagonal(x).sum())

4.0
4.0

Scan示例:計算序列x(t) = x(t - 2).dot(U) + x(t - 1).dot(V) + tanh(x(t - 1).dot(W) + b)

import theano
import theano.tensor as T
import numpy as np

# define tensor variables
X = T.matrix("X")
W = T.matrix("W")
b_sym = T.vector("b_sym")
U = T.matrix("U")
V = T.matrix("V")
n_sym = T.iscalar("n_sym")

results, updates = theano.scan(lambda x_tm2, x_tm1: T.dot(x_tm2, U) + T.dot(x_tm1, V) + T.tanh(T.dot(x_tm1, W) + b_sym),
                    n_steps=n_sym, outputs_info=[dict(initial=X, taps=[-2, -1])])
compute_seq2 = theano.function(inputs=[X, U, V, W, b_sym, n_sym], outputs=results)

# test values
x = np.zeros((2, 2), dtype=theano.config.floatX) # the initial value must be able to return x[-2]
x[1, 1] = 1
w = 0.5 * np.ones((2, 2), dtype=theano.config.floatX)
u = 0.5 * (np.ones((2, 2), dtype=theano.config.floatX) - np.eye(2, dtype=theano.config.floatX))
v = 0.5 * np.ones((2, 2), dtype=theano.config.floatX)
n = 10
b = np.ones((2), dtype=theano.config.floatX)

print(compute_seq2(x, u, v, w, b, n))

# comparison with numpy
x_res = np.zeros((10, 2))
x_res[0] = x[0].dot(u) + x[1].dot(v) + np.tanh(x[1].dot(w) + b)
x_res[1] = x[1].dot(u) + x_res[0].dot(v) + np.tanh(x_res[0].dot(w) + b)
x_res[2] = x_res[0].dot(u) + x_res[1].dot(v) + np.tanh(x_res[1].dot(w) + b)
for i in range(2, 10):
    x_res[i] = (x_res[i - 2].dot(u) + x_res[i - 1].dot(v) +
                np.tanh(x_res[i - 1].dot(w) + b))
print(x_res)

[[  1.40514825   1.40514825]
 [  2.88898899   2.38898899]
 [  4.34018291   4.34018291]
 [  6.53463142   6.78463142]
 [  9.82972243   9.82972243]
 [ 14.22203814  14.09703814]
 [ 20.07439936  20.07439936]
 [ 28.12291843  28.18541843]
 [ 39.1913681   39.1913681 ]
 [ 54.28407732  54.25282732]]
[[  1.40514825   1.40514825]
 [  2.88898899   2.38898899]
 [  4.34018291   4.34018291]
 [  6.53463142   6.78463142]
 [  9.82972243   9.82972243]
 [ 14.22203814  14.09703814]
 [ 20.07439936  20.07439936]
 [ 28.12291843  28.18541843]
 [ 39.1913681   39.1913681 ]
 [ 54.28407732  54.25282732]]

Scan示例:計算y = tanh(v.dot(A)) wrt x的Jacobian

import theano
import theano.tensor as T
import numpy as np

# define tensor variables
v = T.vector()
A = T.matrix()
y = T.tanh(T.dot(v, A))
results, updates = theano.scan(lambda i: T.grad(y[i], v), sequences=[T.arange(y.shape[0])])
compute_jac_t = theano.function([A, v], results, allow_input_downcast=True) # shape (d_out, d_in)

# test values
x = np.eye(5, dtype=theano.config.floatX)[0]
w = np.eye(5, 3, dtype=theano.config.floatX)
w[2] = np.ones((3), dtype=theano.config.floatX)
print(compute_jac_t(w, x))

# compare with numpy
print(((1 - np.tanh(x.dot(w)) ** 2) * w).T)

[[ 0.41997434  0\.          0.41997434  0\.          0\.        ]
 [ 0\.          1\.          1\.          0\.          0\.        ]
 [ 0\.          0\.          1\.          0\.          0\.        ]]
[[ 0.41997434  0\.          0.41997434  0\.          0\.        ]
 [ 0\.          1\.          1\.          0\.          0\.        ]
 [ 0\.          0\.          1\.          0\.          0\.        ]]

注意操灿,我們需要迭代y的索引耻卡,而不是y的元素。原因是scan為其內部函數創(chuàng)建一個占位符變量牲尺,并且此占位符變量與將替換它的變量不具有相同的依賴關系卵酪。

Scan示例:Scan期間累積循環(huán)次數

import theano
import theano.tensor as T
import numpy as np

# define shared variables
k = theano.shared(0)
n_sym = T.iscalar("n_sym")

results, updates = theano.scan(lambda:{k:(k + 1)}, n_steps=n_sym)
accumulator = theano.function([n_sym], [], updates=updates, allow_input_downcast=True)

k.get_value()
accumulator(5)
k.get_value()

Scan示例:計算tanh(v.dot(W) + b) * d,其中d是二項式

import theano
import theano.tensor as T
import numpy as np

# define tensor variables
X = T.matrix("X")
W = T.matrix("W")
b_sym = T.vector("b_sym")

# define shared random stream
trng = T.shared_randomstreams.RandomStreams(1234)
d=trng.binomial(size=W[1].shape)

results, updates = theano.scan(lambda v: T.tanh(T.dot(v, W) + b_sym) * d, sequences=X)
compute_with_bnoise = theano.function(inputs=[X, W, b_sym], outputs=results,
                          updates=updates, allow_input_downcast=True)
x = np.eye(10, 2, dtype=theano.config.floatX)
w = np.ones((2, 2), dtype=theano.config.floatX)
b = np.ones((2), dtype=theano.config.floatX)

print(compute_with_bnoise(x, w, b))

[[ 0.96402758  0\.        ]
 [ 0\.          0.96402758]
 [ 0\.          0\.        ]
 [ 0.76159416  0.76159416]
 [ 0.76159416  0\.        ]
 [ 0\.          0.76159416]
 [ 0\.          0.76159416]
 [ 0\.          0.76159416]
 [ 0\.          0\.        ]
 [ 0.76159416  0.76159416]]

注意谤碳,如果你想使用一個在scan循環(huán)中不會更新的隨機變量d溃卡,你應該將此變量作為non_sequences參數傳遞。

Scan示例:計算pow(A, k)

import theano
import theano.tensor as T
theano.config.warn.subtensor_merge_bug = False

k = T.iscalar("k")
A = T.vector("A")

def inner_fct(prior_result, B):
    return prior_result * B

# Symbolic description of the result
result, updates = theano.scan(fn=inner_fct,
                            outputs_info=T.ones_like(A),
                            non_sequences=A, n_steps=k)

# Scan has provided us with A ** 1 through A ** k.  Keep only the last
# value. Scan notices this and does not waste memory saving them.
final_result = result[-1]

power = theano.function(inputs=[A, k], outputs=final_result,
                      updates=updates)

print(power(range(10), 2))

[  0\.   1\.   4\.   9\.  16\.  25\.  36\.  49\.  64\.  81.]

Scan示例:計算多項式

import numpy
import theano
import theano.tensor as T
theano.config.warn.subtensor_merge_bug = False

coefficients = theano.tensor.vector("coefficients")
x = T.scalar("x")
max_coefficients_supported = 10000

# Generate the components of the polynomial
full_range=theano.tensor.arange(max_coefficients_supported)
components, updates = theano.scan(fn=lambda coeff, power, free_var:
                                   coeff * (free_var ** power),
                                outputs_info=None,
                                sequences=[coefficients, full_range],
                                non_sequences=x)

polynomial = components.sum()
calculate_polynomial = theano.function(inputs=[coefficients, x],
                                     outputs=polynomial)

test_coeff = numpy.asarray([1, 0, 2], dtype=numpy.float32)
print(calculate_polynomial(test_coeff, 3))

19.0

練習

運行這兩個示例蜒简。

修改并執(zhí)行多項式示例以通過scan完成reduction瘸羡。

Solution

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搓茬,隨后出現的幾起案子犹赖,更是在濱河造成了極大的恐慌,老刑警劉巖卷仑,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峻村,死亡現場離奇詭異,居然都是意外死亡锡凝,警方通過查閱死者的電腦和手機粘昨,發(fā)現死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窜锯,“玉大人张肾,你說我怎么就攤上這事∶” “怎么了吞瞪?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長驾孔。 經常有香客問我芍秆,道長惯疙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任浪听,我火速辦了婚禮,結果婚禮上眉菱,老公的妹妹穿的比我還像新娘迹栓。我一直安慰自己,他們只是感情好俭缓,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布克伊。 她就那樣靜靜地躺著,像睡著了一般华坦。 火紅的嫁衣襯著肌膚如雪愿吹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天惜姐,我揣著相機與錄音犁跪,去河邊找鬼。 笑死歹袁,一個胖子當著我的面吹牛坷衍,可吹牛的內容都是我干的。 我是一名探鬼主播条舔,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枫耳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了孟抗?” 一聲冷哼從身側響起迁杨,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凄硼,沒想到半個月后铅协,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡摊沉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年警医,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坯钦。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡预皇,死狀恐怖,靈堂內的尸體忽然破棺而出婉刀,到底是詐尸還是另有隱情吟温,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布突颊,位于F島的核電站鲁豪,受9級特大地震影響潘悼,放射性物質發(fā)生泄漏。R本人自食惡果不足惜爬橡,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一治唤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糙申,春花似錦宾添、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疙挺,卻和暖如春扛邑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背铐然。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工蔬崩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搀暑。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓舱殿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親险掀。 傳聞我的和親對象是個殘疾皇子沪袭,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容