Python Theanoの使い方(自動微分:Grad、関数:Function,乱数:RandomStream)
こんにちわ
お元気ですか?私は元気です。
さて、本日はTheanoについて
Theanoとは?
Deep Learningを実装するために作られたPythonのライブラリなのかな…
色々計算するのに便利です。
インストール
sudo pip install theano
How to Use
import
import numpy import theano import theano.tensor as T from theano.tensor.shared_randomstreams import RandomStreams
変数の作り方
x = dscalar() y = dvector() z = dmatrix() x = lscalar() y = lvector() z = lmatrix()
関数の名前はd = double l = long
もしくは値(scalar)、ベクトル(vector)、行列(matrix)で決まります。
これをシンボルというそうです。
これを元にこれから関数を作ってみましょう。
function
単純なfunctionの利用
x = T.lscalar("x") y = x*2 f = theano.function([x],y) #f = 3 * 2 print f(3) #6`
yにx * 2の式が入っています
(xはobject)つまり、yを出力しても数字が出てきません
f = theano.function([x],y)は与える引数のシンボルを入れていたらいいと思います。
f(3)にてy = x * 2のうち、x に 3を代入し実際の計算した値を出力しています(今回は6ですね)
givensの活用
theano.functionではgivenと呼ばれる引数を渡せます。
givenでは与えたシンボルから計算し、それを値として置き換えるようなことをしています。
言葉では意味不明なので、実際に例を見てみましょう。
x = T.dscalar() y = T.dscalar() c = T.dscalar() #ff = (2 * 10.0) * 2 + 5.0 = 45.0 ff = theano.function([c], x*2+y, givens=[(x, c*10.0), (y,5.0)]) print ff(2) #45.0
実際の動作ですが、cに2を渡し、x = 2 * 10.0、y = 5.0としています。
そのため実際の計算では (2 * 10.0) * 2 + 5.0 = 45.0となります。
自動微分
先程からtheano.functionの式は微分ができます。凄いですね…
むしろこれが便利だから利用している人はきっと多いはず。
z = (x+2*y)**2 gx = T.grad(z,x) #微分するとdz/dx =2(x+2*y) ,gxにその式が入る fz = theano.function([x,y],z) #functionを生成 #25.0 fgx = theano.function([x,y],gx) #functionを生成 #10 print fz(1,2) #25.0 print fgx(1,2) #10
T.gradを利用すると微分ができます。
T.grad(z,x) = zをxで微分、もちろん yでも同じことができます。
Shared(共有変数)
なんかすごい
x = T.dscalar('x') b = theano.shared(1) f = theano.function([x],b*x) print f(2) #2.0 b.get_value() b.set_value(3) print f(2) #6.0
式を構成した後に、変数にしていない部分をこの共有変数を変更することによって切り替えることができます凄い。
今回の場合、f = b * xの式があり、変数として入れるのはxのシンボルです。
しかし、bを変更したい場合にb.set_value()で変更することによって変更することができ、funcitonにも反映することができます。
1 * 2 → 3 * 2へ式が今回は変わってますね。
update
まずは簡単な例から
c = theano.shared(0) f = theano.function([],c,updates = {c:c+1}) print f print f() #0 print f() #1 print f() #2
関数を実行する時にupdatesに登録してある辞書にもとづいて
共有変数を変更してくれます。
勾配法を利用する方には素晴らしいですね。
勾配法
x = T.dvector("x") c = theano.shared(0.) y = T.sum((x-c)**2) gc = T.grad(y,c) #偏微分 d2 = theano.function([x],y,updates={c:c-0.05*gc}) for i in xrange(3): print d2([1,2,3,4,5]) print c.get_value()
55.0 1.5 21.25 2.25 12.8125 2.625
勾配法によって値が小さくなるように変化すること、そして共有変数cの値が変化していってることがわかります。
c:c-0.05*gcの0.05は学習係数です。
乱数(RandomStream)
最後に乱数の生成です。基本的にはnumpyのrandomの使い方と同じです。
numpy_rng = numpy.random.RandomState(89677) theanoRng = RandomStreams(numpy_rng.randint(2 ** 30)) #2項分布 fbino = theanoRng.binomial(size=(1,3)) funi = theanoRng.uniform(size=(3,2)) #関数化 f1 = theano.function([],fbino) f2 = theano.function([],funi) #とりあえず使う print f1() print f2()
functionから読み出せば、使えます。
気が向いたらロジスティック回帰とかDenoising Auto Encoderのソースコードの解説でもやりたいと思います。
数学をやる時間がないんだけど大丈夫かなぁ
参考文献
http://qiita.com/mokemokechicken/items/3fbf6af714c1f66f99e9
ソースコードを参考にさせて頂きました。(というかちょっとしか変えてない…)
http://deeplearning.net/tutorial/
ソースコード全文
#coding:utf-8 import numpy import theano import theano.tensor as T from theano.tensor.shared_randomstreams import RandomStreams """ Functionメソッドについて 実行しているコードの箇所 """ def functionTest(): """ Functionメソッドについて 実行しているコードの箇所 """ x = T.lscalar("x") y = x*2 """Function オーソドックス""" #f = 3 * 2 f = theano.function([x],y) print f(3) #6` """Function Given込""" x = T.dscalar() y = T.dscalar() c = T.dscalar() #ff = (2 * 10.0) * 2 + 5.0 = 45.0 ff = theano.function([c], x*2+y, givens=[(x, c*10.0), (y,5.0)]) print ff(2) #45.0 """自動微分""" z = (x+2*y)**2 gx = T.grad(z,x) #微分するとdz/dx =2(x+2*y) gxにその式が入る fz = theano.function([x,y],z) #functionを生成 fgx = theano.function([x,y],gx) #functionを生成 print fz(1,2) print fgx(1,2) """ 共有変数部分のテスト Shared """ def sharedTest(): x = T.dscalar('x') b = theano.shared(1) f = theano.function([x],b*x) print f(2) b.get_value() b.set_value(3) print f(2) """ Updateの利用方法 これをうまく使うと勾配法を実装できる。 """ def updateTest(): """ 簡単なUpdate文の使い方 """ c = theano.shared(0) f = theano.function([],c,updates = {c:c+1}) print f print f() print f() print f() x = T.dvector("x") c = theano.shared(0.) y = T.sum((x-c)**2) gc = T.grad(y,c) d2 = theano.function([x],y,updates={c:c-0.05*gc}) for i in xrange(3): print d2([1,2,3,4,5]) print c.get_value() def testRandomStream(): """Numpy Random""" numpy_rng = numpy.random.RandomState(89677) theanoRng = RandomStreams(numpy_rng.randint(2 ** 30)) #2項分布 fbino = theanoRng.binomial(size=(1,3)) funi = theanoRng.uniform(size=(3,2)) #関数化 f1 = theano.function([],fbino) f2 = theano.function([],funi) #とりあえず使う print f1() print f2() if __name__ == '__main__': functionTest() sharedTest() updateTest() testRandomStream()