Theano 更多示例
Logistic函數(shù)
?
logistic函數(shù)的圖,其中x在x軸上,s(x)在y軸上。
如果你想對雙精度矩陣上的每個元素計算這個函數(shù),這表示你想將這個函數(shù)應(yīng)用到矩陣的每個元素上。
嗯,你是這樣做的:
x=T.dmatrix('x') s=1/(1+T.exp(-x)) logistic=theano.function([x],s) print logistic([[1,2],[3,4]])[[ 0.73105858 0.88079708][ 0.95257413 0.98201379]]在每個元素上執(zhí)行l(wèi)ogistic的原因是因為它的所有運算 —— 除法、加法、冪和除法 —— 本身是單個元素的操作。
?同時計算多個值
Theano支持多輸出功能。例如,我們可以同時計算兩個矩陣a和b之間每個元素的差、差的絕對值和平方差:
a,b=T.dmatrices('a','b') diff=a-b abs_diff=abs(a-b) squared_diff=diff**2 f=theano.function([a,b],[diff,abs_diff,squared_diff])注意:
dmatrices產(chǎn)生與你提供的名稱一樣多的輸出。它是分配符號變量的一個快捷方式,我們將在教程中經(jīng)常使用它。
當我們使用函數(shù)f,它返回三個變量。
print f([[1,1],[1,2]],[[1,1],[1,1]])[array([[ 0., 0.],[ 0., 1.]]), array([[ 0., 0.],[ 0., 1.]]), array([[ 0., 0.],[ 0., 1.]])]為參數(shù)設(shè)置默認值
x,y=T.dscalars('x','y') z=x+y f=function([x,In(y,value=2)],z) print f(2)4.0這里使用In類,它允許你更詳細地指定你的函數(shù)的參數(shù)的屬性。這里,通過創(chuàng)建value字段設(shè)置為1的In實例,為y賦予默認值1。
具有默認值的輸入必須遵循沒有默認值的輸入(類似Python的函數(shù))。可以有多個具有默認值的輸入。這些參數(shù)可以按位置或名稱設(shè)置,和在標準Python中一樣:
x,y,w=T.dscalars('x','y','w') z=(x+y)*w f=function([x,In(y,value=1),In(w,value=2,name='w_by_name')],z) print f(1) print f(1,2) print f(1,1,1) print f(1,w_by_name=1,y=0) print f(1,w_by_name=1)4.0 6.0 2.0 1.0 2.0In不知道作為參數(shù)傳遞的局部變量y和w的名稱。符號變量對象具有名稱屬性(在上面的示例中由dscalars設(shè)置)和它們是我們構(gòu)建的函數(shù)中的關(guān)鍵字參數(shù)的名稱。這是In(y, value = 1)中工作的機制。在In(w, value=2, name='w_by_name')的情況下。我們用一個這個函數(shù)使用的名稱來覆蓋符號變量的name屬性。
使用共享變量
還可以利用內(nèi)部狀態(tài)生成一個函數(shù)。例如,假設(shè)我們想要一個累加器:在開始,狀態(tài)被初始化為零。然后,在每次函數(shù)調(diào)用時,狀態(tài)通過函數(shù)的參數(shù)增加。
首先我們定義累加器函數(shù)。它將其參數(shù)添加到內(nèi)部狀態(tài),并返回舊的狀態(tài)值。
這段代碼引入了一些新的概念。shared函數(shù)構(gòu)造所謂的共享變量。它們是符號變量和非符號變量的混合,其值可以在多個函數(shù)之間共享。共享變量就像dmatrices(...)返回的對象一樣可以在符號表達式中使用,但它們還有一個內(nèi)部值,定義在所有使用這個符號變量的函數(shù)中的值。它被稱為共享變量,因為它的值在許多函數(shù)之間共享。該值可以通過.get_value()和.set_value()方法訪問和修改。
from theano import shared state=shared(0) inc=T.iscalar('inc') accumulator=function([inc],state,updates=[(state,state+inc)])該代碼中的另一個新東西是function的updates參數(shù)。updates必須提供形式為(共享變量,新表達式)對的一個列表。它也可以是一個字典,其鍵是共享變量,值是新的表達式。無論哪種方式,它意味著“每當這個函數(shù)運行時,它將用相應(yīng)表達式的結(jié)果替換每個共享變量的.value”。上面,我們的累加器用狀態(tài)和增量總和取代state的值。
print state.get_value() accumulator(1) print state.get_value() accumulator(200) print state.get_value()0 1 201可以重置狀態(tài)。只需使用.set_value()方法:
state.set_value(-1) accumulator(2) print state.get_value()1如上所述,你可以定義多個函數(shù)來使用相同的共享變量。這些函數(shù)都可以更新該值。
decrementor=function([inc],state,updates=[(state,state-inc)]) decrementor(2) print state.get_value()-1你可能想知道為什么存在更新機制。你總是可以通過返回新的表達式,并在NumPy中照常使用它們來實現(xiàn)類似的結(jié)果。更新機制可以是語法方便,但是它主要是為了效率。有時可以使用就地算法(例如低秩矩陣更新)更快地完成對共享變量的更新。此外,Theano對分配變量的位置和方式有更多的控制,這是在GPU上獲得良好性能的重要因素之一。
可能會發(fā)生這種情況,你使用共享變量表達了某個公式,但你不想使用它的值。在這種情況下,你可以使用function的givens參數(shù)為一個特定函數(shù)替換圖中的特定節(jié)點。
state=shared(0) inc=T.iscalar('inc') fn_of_state=state*2+inc #foo 必須和被替換的shared變量有相同的類型 foo=T.scalar(dtype=state.dtype) skip_shared=function([inc,foo],fn_of_state,givens=[(state,foo)]) print skip_shared(1,3)#我們使用了3作為state,而不是0 print state.get_value()#old state值不變7 0givens參數(shù)可用于替換任何符號變量,而不僅僅是共享變量。一般情況下,你可以替換常量和表達式。但要小心,不要讓givens替換引入的表達式是共同依賴的,替換的順序沒有定義,所以替換必須以任何順序工作。
在實踐中,考慮givens的一個好方法是允許你用一個不同的表達式替換你的公式的任何部分,這個表達式的計算結(jié)果是一個相同形狀和dtype的張量。
注意
Theano共享變量broadcast模式對于每個維度默認為False。共享變量大小可以隨時間改變,所以我們不能使用形狀來找到broadcastable的模式。如果你想要一個不同的模式,只要將它作為參數(shù)傳遞theano.shared(..., broadcastable=(True, False))
復(fù)制函數(shù)
Theano函數(shù)可以被復(fù)制,這對于創(chuàng)建類似的函數(shù),但是使用不同的共享變量或更新是有用的。這是使用function對象的copy()方法完成的。復(fù)制的是原始函數(shù)的優(yōu)化圖,因此編譯只需要執(zhí)行一次。
讓我們從上面定義的累加器開始:
state=shared(0) inc=T.iscalar('inc') accumulator=theano.function([inc],state,updates=[(state,state+inc)])我們可以使用它像往常一樣增加狀態(tài)。
我們可以使用copy()創(chuàng)建一個類似的累加器,但使用自己的內(nèi)部狀態(tài)使用swap參數(shù),它是一個要交換的共享變量的字典:
new_state=shared(0) new_accumulator=accumulator.copy(swap={state:new_state}) new_accumulator(100) print new_state.get_value()100第一個函數(shù)的狀態(tài)保持不變:
print state.get_value()0我們現(xiàn)在使用delete_updates參數(shù)創(chuàng)建一個刪除更新的副本,默認情況下,該參數(shù)設(shè)置為False:
null_accumulator=accumulator.copy(delete_updates=True) null_accumulator(100) print state.get_value()如預(yù)期,共享狀態(tài)不再更新。
使用隨機數(shù)
因為在Theano中你首先將一切用符號表示并在之后編譯這個表達式以獲得函數(shù),所以使用偽隨機數(shù)字不是像在NumPy中那么直接,雖然也不太復(fù)雜。
將隨機性放到Theano的計算中的考慮方式是將隨機變量放在你的圖中。Theano將為每個這樣的變量分配一個NumPy RandomStream對象(一個隨機數(shù)生成器),并根據(jù)需要繪制它。我們將這種隨機數(shù)序列稱為隨機流。隨機流的核心是它們的共享變量,因此在這里也可以對共享變量進行觀察。Theanos的隨機對象在RandomStreams中定義和實現(xiàn),底層在RandomStreamBase中定義和實現(xiàn)。
簡要示例
from theano.tensor.shared_randomstreams import RandomStreams srng=RandomStreams(seed=234) rv_u=srng.uniform((2,2)) rv_n=srng.uniform((2,2)) f=function([],rv_u) g=function([],rv_n,no_default_updates=True) print f() print f() print g() print g()[[ 0.12672381 0.97091597][ 0.13989098 0.88754825]] [[ 0.31971415 0.47584377][ 0.24129163 0.42046081]] [[ 0.12309219 0.71399385][ 0.14249561 0.36686867]] [[ 0.12309219 0.71399385][ 0.14249561 0.36686867]]這里,’rv_u’表示來自均勻分布的2×2矩陣的隨機流。同樣,’rv_n’表示來自正態(tài)分布的2×2矩陣的隨機流。分布的實現(xiàn)在RandomStreams中定義,底層在raw_random中定義。它們只在CPU上工作。
現(xiàn)在讓我們使用這些對象。隨機數(shù)發(fā)生器的內(nèi)部狀態(tài)是自動更新的,所以我們每次都得到不同的隨機數(shù)。
當我們向function添加額外參數(shù)no_default_updates=True(如在g中)時,隨機數(shù)生成器狀態(tài)不受調(diào)用返回函數(shù)影響。因此,例如,多次調(diào)用g將返回相同的數(shù)字。
一個重要的提醒是,在函數(shù)的每次執(zhí)行期間最多繪制一個隨機變量。因此,即使rv_u隨機變量在輸出表達式中出現(xiàn)三次,almost_zeros函數(shù)保證返回大約為0(舍入誤差除外)。
種子流
隨機變量可以使用單獨的種子或使用共同的種子。
你可以使用.rng.set_value(),通過播種或分配.rng屬性來播種一個隨機變量。
rng_val=rv_u.rng.get_value(borrow=True) rng_val.seed(89234) rv_u.rng.set_value(rng_val,borrow=True)你也可以通過RandomStreams對象的seed方法對該對象分配的全部隨機變量設(shè)置種子。該種子將用于設(shè)置臨時隨機數(shù)發(fā)生器的種子,這個零時隨機數(shù)發(fā)生器隨后將為每個隨機變量生成種子。?
srng.seed(89234)函數(shù)之間共享流
與通常的共享變量一樣,用于隨機變量的隨機數(shù)發(fā)生器在函數(shù)之間是共同的。因此,我們的nearly_zeros函數(shù)將更新函數(shù)f中使用的生成器的狀態(tài)。
在Theano圖之間復(fù)制隨機狀態(tài)
在一些使用情況下,用戶可能想要將與給定的theano圖(例如,具有下面的編譯函數(shù)f1的g1)相關(guān)聯(lián)的所有隨機數(shù)發(fā)生器的“狀態(tài)”轉(zhuǎn)移到第二個圖形(例如具有函數(shù)f2的g2)。這中情況例如,如果你試圖從之前的一個序列化的模型的參數(shù)初始化模型的狀態(tài)。對于和,可以通過復(fù)制state_updates參數(shù)的元素來實現(xiàn)。
每當從RandomStreams對象中繪制隨機變量時,就會將元組添加到state_updates列表中。第一個元素是一個共享變量,它表示與此特定變量相關(guān)聯(lián)的隨機數(shù)生成器的狀態(tài),而第二個元素表示與隨機數(shù)生成過程對應(yīng)的theano圖(即RandomFunction {uniform} .0)。
下面示出了如何將“隨機狀態(tài)”從一個theano函數(shù)傳遞到另一個函數(shù)的示例。
from theano.tensor.shared_randomstreams import RandomStreams from theano.sandbox.rng_mrg import MRG_RandomStreams class Graph():def __init__(self,seed=123):self.rng=RandomStreams(seed)self.y=self.rng.uniform(size=(1,)) def copy_random_state(g1,g2):if isinstance(g1.rng,MRG_RandomStreams):g2.rng.rstate=g1.rng.rstatefor(su1,su2) in zip(g1.rng.state_updates,g2.rng.state_updates):su2[0].set_value(su1[0].get_value()) g1=Graph(seed=123) f1=theano.function([],g1.y)g2=Graph(seed=987) f2=theano.function([],g2.y)#by default,兩個函數(shù)不是同步的 print f1() print f2()#現(xiàn)在復(fù)制theano隨機數(shù)生成器的狀態(tài) copy_random_state(g1,g2) print f1() print f2()[ 0.72803009] [ 0.55056769] [ 0.59044123] [ 0.59044123]?
轉(zhuǎn)載于:https://www.cnblogs.com/qniguoym/p/7662459.html
總結(jié)
以上是生活随笔為你收集整理的Theano 更多示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目实施工程师的工作
- 下一篇: 接口总结