讀:NumPy是數(shù)據(jù)計(jì)算的基礎(chǔ),更是深度學(xué)習(xí)框架的基石。但如果直接使用NumPy計(jì)算大數(shù)據(jù),其性能已成為一個(gè)瓶頸。
隨著數(shù)據(jù)爆炸式增長(zhǎng),尤其是圖像數(shù)據(jù)、音頻數(shù)據(jù)等數(shù)據(jù)的快速增長(zhǎng),迫切需要突破NumPy性能上的瓶頸。需求就是強(qiáng)大動(dòng)力!通過大家的不懈努力,在很多方面取得可喜進(jìn)展,如硬件有GPU,軟件有Theano、Keras、TensorFlow,算法有卷積神經(jīng)網(wǎng)絡(luò)、循環(huán)神經(jīng)網(wǎng)絡(luò)等。
作者:吳茂貴,王冬,李濤,楊本法
如需轉(zhuǎn)載請(qǐng)聯(lián)系華章科技
Theano是Python的一個(gè)庫(kù),為開源項(xiàng)目,在2008年,由Yoshua Bengio領(lǐng)導(dǎo)的加拿大蒙特利爾理工學(xué)院LISA實(shí)驗(yàn)室開發(fā)。對(duì)于解決大量數(shù)據(jù)的問題,使用Theano可能獲得與手工用C實(shí)現(xiàn)差不多的性能。另外通過利用GPU,它能獲得比CPU上快很多數(shù)量級(jí)的性能。
至于Theano是如何實(shí)現(xiàn)性能方面的跨越,如何用“符號(hào)計(jì)算圖”來運(yùn)算等內(nèi)容,本文都將有所涉獵,但限于篇幅無法深入分析,只做一些基礎(chǔ)性的介紹。涵蓋的主要內(nèi)容:
Theano開發(fā)者在2010年公布的測(cè)試報(bào)告中指出:在CPU上執(zhí)行程序時(shí),Theano程序性能是NumPy的1.8倍,而在GPU上是NumPy的11倍。這還是2010年的測(cè)試結(jié)果,近些年無論是Theano還是GPU,性能都有顯著提高。
這里我們把Theano作為基礎(chǔ)來講,除了性能方面的跨越外,它還是“符合計(jì)算圖”的開創(chuàng)者,當(dāng)前很多優(yōu)秀的開源工具,如TensorFlow、Keras等,都派生于或借鑒了Theano的底層設(shè)計(jì)。所以了解Theano的使用,將有助于我們更好地學(xué)習(xí)TensorFlow、Keras等其他開源工具。
這里主要介紹Linux+Anaconda+theano環(huán)境的安裝說明,在CentOS或Ubuntu環(huán)境下,建議使用Python的Anaconda發(fā)行版,后續(xù)版本升級(jí)或添加新模塊可用Conda工具。當(dāng)然也可用pip進(jìn)行安裝。但最好使用工具來安裝,這樣可以避免很多程序依賴的麻煩,而且日后的軟件升級(jí)維護(hù)也很方便。
Theano支持CPU、GPU,如果使用GPU還需要安裝其驅(qū)動(dòng)程序如CUDA等,限于篇幅,這里只介紹CPU的,有關(guān)GPU的安裝,大家可參考:
http://www.deeplearning.net/software/theano/install.html
以下為主要安裝步驟:
1. 安裝anaconda
從anaconda官網(wǎng)下載Linux環(huán)境最新的軟件包,Python版本建議選擇3系列的,2系列后續(xù)將不再維護(hù)。
anaconda官網(wǎng):
https://www.anaconda.com/download/
下載文件為一個(gè)sh程序包,如Anaconda3-4.3.1-Linux-x86_64.sh,然后在下載目錄下運(yùn)行如下命令:
bash Anaconda3-4.3.1-Linux-x86_64.sh
安裝過程中按enter或y即可,安裝完成后,程序提示是否把a(bǔ)naconda的binary加入到.bashrc配置文件中,加入后運(yùn)行python、ipython時(shí)將自動(dòng)使用新安裝的Python環(huán)境。
安裝完成后,你可用conda list命令查看已安裝的庫(kù):
conda list
安裝成功的話,應(yīng)該能看到numpy、scipy、matplotlib、conda等庫(kù)。
2. 安裝theano
利用conda 來安裝或更新程序:
conda install theano
3. 測(cè)試
先啟動(dòng)Python,然后導(dǎo)入theano模塊,如果不報(bào)錯(cuò),說明安裝成功。
$ Python Python 3.6.0 |Anaconda custom (64-bit)| (default, Dec 23 2016, 12:22:00) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import theano >>>
存儲(chǔ)數(shù)據(jù)需要用到各種變量,那Theano是如何使用變量的呢?Theano用符號(hào)變量TensorVariable來表示變量,又稱為張量(Tensor)。
張量是Theano的核心元素(也是TensorFlow的核心元素),是Theano表達(dá)式和運(yùn)算操作的基本單位。張量可以是標(biāo)量(scalar)、向量(vector)、矩陣(matrix)等的統(tǒng)稱。
具體來說,標(biāo)量就是我們通常看到的0階的張量,如12,a等,而向量和矩陣分別為1階張量和2階的張量。
如果通過這些概念,你還不很清楚,沒有關(guān)系,可以結(jié)合以下實(shí)例來直觀感受一下。
首先定義三個(gè)標(biāo)量:一個(gè)代表輸入x、一個(gè)代表權(quán)重w、一個(gè)代表偏移量b,然后計(jì)算這些標(biāo)量運(yùn)算結(jié)果z=x*w+b,Theano代碼實(shí)現(xiàn)如下:
#導(dǎo)入需要的庫(kù)或模塊 import theano from theano import tensor as T #初始化張量 x=T.scalar(name='input',dtype='float32') w=T.scalar(name='weight',dtype='float32') b=T.scalar(name='bias',dtype='float32') z=w*x+b #編譯程序 net_input=theano.function(inputs=[w,x,b],outputs=z) #執(zhí)行程序 print('net_input: %2f'% net_input(2.0,3.0,0.5))
打印結(jié)果:
net_input: 6.500000
通過以上實(shí)例我們不難看出,Theano本身是一個(gè)通用的符號(hào)計(jì)算框架,與非符號(hào)架構(gòu)的框架不同,它先使用tensor variable初始化變量,然后將復(fù)雜的符號(hào)表達(dá)式編譯成函數(shù)模型,最后運(yùn)行時(shí)傳入實(shí)際數(shù)據(jù)進(jìn)行計(jì)算。
整個(gè)過程涉及三個(gè)步驟:定義符號(hào)變量,編譯代碼,執(zhí)行代碼。這節(jié)主要介紹第一步如何定義符號(hào)變量,其他步驟將在后續(xù)小節(jié)介紹。
如何定義符號(hào)變量?或定義符號(hào)變量有哪些方式?在Theano中定義符號(hào)變量的方式有三種:使用內(nèi)置的變量類型、自定義變量類型、轉(zhuǎn)換其他的變量類型。具體如下:
1. 使用內(nèi)置的變量類型創(chuàng)建
目前Theano支持7種內(nèi)置的變量類型,分別是標(biāo)量(scalar)、向量(vector)、行(row)、列(col)、矩陣(matrix)、tensor3、tensor4等。其中標(biāo)量是0階張量,向量為1階張量,矩陣為2階張量等,以下為創(chuàng)建內(nèi)置變量的實(shí)例:
import theano from theano import tensor as T x=T.scalar(name='input',dtype='float32') data=T.vector(name='data',dtype='float64')
其中,name指定變量名字,dtype指變量的數(shù)據(jù)類型。
2. 自定義變量類型
內(nèi)置的變量類型只能處理4維及以下的變量,如果需要處理更高維的數(shù)據(jù)時(shí),可以使用Theano的自定義變量類型,具體通過TensorType方法來實(shí)現(xiàn):
import theano from theano import tensor as T mytype=T.TensorType('float64',broadcastable=(),name=None,sparse_grad=False)
其中broadcastable是True或False的布爾類型元組,元組的大小等于變量的維度,如果為True,表示變量在對(duì)應(yīng)維度上的數(shù)據(jù)可以進(jìn)行廣播,否則數(shù)據(jù)不能廣播。
廣播機(jī)制(broadcast)是一種重要機(jī)制,有了這種機(jī)制,就可以方便地對(duì)不同維的張量進(jìn)行運(yùn)算,否則,就要手工把低維數(shù)據(jù)變成高維,利用廣播機(jī)制系統(tǒng)自動(dòng)復(fù)制等方法把低維數(shù)據(jù)補(bǔ)齊(MumPy也有這種機(jī)制)。以下我們通過圖2-1所示的一個(gè)實(shí)例來說明廣播機(jī)制原理。
▲圖2-1 廣播機(jī)制
圖2-1中矩陣與向量相加的具體代碼如下:
import theano import numpy as np import theano.tensor as T r=T.row() r.broadcastable # (True, False) mtr=T.matrix() mtr.broadcastable # (False, False) f_row=theano.function([r, mtr], [r + mtr]) R=np.arange(1,3).reshape(1,2) print(R) #array([[1, 2]]) M=np.arange(1,7).reshape(3, 2) print(M) #array([[1, 2], # [3, 4], # [5, 6]]) f_row(R, M) #[array([[ 2., 4.], # [ 4., 6.], # [ 6., 8.]])]
3. 將Python類型變量或者NumPy類型變量轉(zhuǎn)化為Theano共享變量
共享變量是Theano實(shí)現(xiàn)變量更新的重要機(jī)制,后面我們會(huì)詳細(xì)講解。要?jiǎng)?chuàng)建一個(gè)共享變量,只要把一個(gè)Python對(duì)象或NumPy對(duì)象傳遞給shared函數(shù)即可,如下所示:
import theano import numpy as np import theano.tensor as T data=np.array([[1,2],[3,4]]) shared_data=theano.shared(data) type(shared_data)
符號(hào)變量定義后,需要說明這些變量間的運(yùn)算關(guān)系,那如何描述變量間的運(yùn)算關(guān)系呢?Theano實(shí)際采用符號(hào)計(jì)算圖模型來實(shí)現(xiàn)。首先創(chuàng)建表達(dá)式所需的變量,然后通過操作符(op)把這些變量結(jié)合在一起,如前文圖2-1所示。
Theano處理符號(hào)表達(dá)式時(shí)是通過把符號(hào)表達(dá)式轉(zhuǎn)換為一個(gè)計(jì)算圖(graph)來處理(TensorFlow也使用了這種方法,等到我們介紹TensorFlow時(shí),大家可對(duì)比一下),符號(hào)計(jì)算圖的節(jié)點(diǎn)有:variable、type、apply和op。
Theano是將符號(hào)表達(dá)式的計(jì)算表示成計(jì)算圖。這些計(jì)算圖是由Apply 和 Variable將節(jié)點(diǎn)連接而組成,它們分別與函數(shù)的應(yīng)用和數(shù)據(jù)相連接。操作由op 實(shí)例表示,而數(shù)據(jù)類型由type 實(shí)例表示。
下面這段代碼和圖2-2說明了這些代碼所構(gòu)建的結(jié)構(gòu)。借助這個(gè)圖或許有助于你進(jìn)一步理解如何將這些內(nèi)容擬合在一起:
import theano import numpy as np import theano.tensor as T x=T.dmatrix('x') y=T.dmatrix('y') z=x + y
▲圖2-2 符號(hào)計(jì)算圖
圖2-2中箭頭表示指向Python對(duì)象的引用。中間大的長(zhǎng)方形是一個(gè) Apply 節(jié)點(diǎn),3個(gè)圓角矩形(如X)是 Variable 節(jié)點(diǎn),帶+號(hào)的圓圈是ops,3個(gè)圓角小長(zhǎng)方形(如matrix)是Types。
在創(chuàng)建 Variables 之后,應(yīng)用 Apply ops得到更多的變量,這些變量?jī)H僅是一個(gè)占位符,在function中作為輸入。變量指向 Apply 節(jié)點(diǎn)的過程是用來表示函數(shù)通過owner 域來生成它們 。這些Apply節(jié)點(diǎn)是通過它們的inputs和outputs域來得到它們的輸入和輸出變量。
x和y的owner域的指向都是None,這是因?yàn)樗鼈儾皇橇硪粋€(gè)計(jì)算的結(jié)果。如果它們中的一個(gè)變量是另一個(gè)計(jì)算的結(jié)果,那么owner域?qū)?huì)指向另一個(gè)藍(lán)色盒。
上節(jié)我們介紹了如何把一個(gè)符號(hào)表達(dá)式轉(zhuǎn)化為符號(hào)計(jì)算圖,這節(jié)我們介紹函數(shù)的功能,函數(shù)是Theano的一個(gè)核心設(shè)計(jì)模塊,它提供一個(gè)接口,把函數(shù)計(jì)算圖編譯為可調(diào)用的函數(shù)對(duì)象。前面介紹了如何定義自變量x(不需要賦值),這節(jié)介紹如何編寫函數(shù)方程。
1. 函數(shù)定義的格式
先來看一下函數(shù)格式示例:
theano.function(inputs, outputs, mode=None, updates=None, givens=None, no_default_updates=False, accept_inplace=False, name=None,rebuild_strict=True, allow_input_downcast=None, profile=None, on_unused_input='raise')
這里參數(shù)看起來很多,但一般只用到三個(gè):inputs表示自變量;outputs表示函數(shù)的因變量(也就是函數(shù)的返回值);還有一個(gè)比較常用的是updates參數(shù),它一般用于神經(jīng)網(wǎng)絡(luò)共享變量參數(shù)更新,通常以字典或元組列表的形式指定。
此外,givens是一個(gè)字典或元組列表,記為[(var1,var2)],表示在每一次函數(shù)調(diào)用時(shí),在符號(hào)計(jì)算圖中,把符號(hào)變量var1節(jié)點(diǎn)替換為var2節(jié)點(diǎn),該參數(shù)常用來指定訓(xùn)練數(shù)據(jù)集的batch大小。
下面我們看一個(gè)有多個(gè)自變量,同時(shí)又有多個(gè)因變量的函數(shù)定義例子:
import theano x, y=theano.tensor.fscalars('x', 'y') z1=x + y z2=x*y #定義x、y為自變量,z1、z2為函數(shù)返回值(因變量) f=theano.function([x,y],[z1,z2]) #返回當(dāng)x=2,y=3的時(shí)候,函數(shù)f的因變量z1,z2的值 print(f(2,3))
打印結(jié)果:
[array(5.0, dtype=float32), array(6.0, dtype=float32)]
在執(zhí)行theano.function()時(shí),Theano進(jìn)行了編譯優(yōu)化,得到一個(gè)end-to-end的函數(shù),傳入數(shù)據(jù)調(diào)用f(2,3)時(shí),執(zhí)行的是優(yōu)化后保存在圖結(jié)構(gòu)中的模型,而不是我們寫的那行z=x+y,盡管二者結(jié)果一樣。
這樣的好處是Theano可以對(duì)函數(shù)f進(jìn)行優(yōu)化,提升速度;壞處是不方便開發(fā)和調(diào)試,由于實(shí)際執(zhí)行的代碼不是我們寫的代碼,所以無法設(shè)置斷點(diǎn)進(jìn)行調(diào)試,也無法直接觀察執(zhí)行時(shí)中間變量的值。
2. 自動(dòng)求導(dǎo)
有了符號(hào)計(jì)算,自動(dòng)計(jì)算導(dǎo)數(shù)就很容易了。tensor.grad()唯一需要做的就是從outputs逆向遍歷到輸入節(jié)點(diǎn)。對(duì)于每個(gè)op,它都定義了怎么根據(jù)輸入計(jì)算出偏導(dǎo)數(shù)。使用鏈?zhǔn)椒▌t就可以計(jì)算出梯度了。利用Theano求導(dǎo)時(shí)非常方便,可以直接利用函數(shù)theano.grad(),比如求s函數(shù)的導(dǎo)數(shù):
以下代碼實(shí)現(xiàn)當(dāng)x=3的時(shí)候,求s函數(shù)的導(dǎo)數(shù):
import theano x=theano.tensor.fscalar('x')#定義一個(gè)float類型的變量x y=1 / (1 + theano.tensor.exp(-x))#定義變量y dx=theano.grad(y,x)#偏導(dǎo)數(shù)函數(shù) f=theano.function([x],dx)#定義函數(shù)f,輸入為x,輸出為s函數(shù)的偏導(dǎo)數(shù) print(f(3))#計(jì)算當(dāng)x=3的時(shí)候,函數(shù)y的偏導(dǎo)數(shù)
打印結(jié)果:
0.045176658779382706
3. 更新共享變量參數(shù)
在深度學(xué)習(xí)中通常需要迭代多次,每次迭代都需要更新參數(shù)。Theano如何更新參數(shù)呢?
在theano.function函數(shù)中,有一個(gè)非常重要的參數(shù)updates。updates是一個(gè)包含兩個(gè)元素的列表或tuple,一般示例為updates=[old_w,new_w],當(dāng)函數(shù)被調(diào)用的時(shí)候,會(huì)用new_w替換old_w,具體看下面這個(gè)例子。
import theano w=theano.shared(1)#定義一個(gè)共享變量w,其初始值為1 x=theano.tensor.iscalar('x') f=theano.function([x], w, updates=[[w, w+x]])#定義函數(shù)自變量為x,因變量為w,當(dāng)函數(shù)執(zhí)行完畢后,更新參數(shù)w=w+x print(f(3))#函數(shù)輸出為w print(w.get_value())#這個(gè)時(shí)候可以看到w=w+x為4
打印結(jié)果:
1、4
在求梯度下降的時(shí)候,經(jīng)常用到updates這個(gè)參數(shù)。比如updates=[w,w-α*(dT/dw)],其中dT/dw就是梯度下降時(shí),代價(jià)函數(shù)對(duì)參數(shù)w的偏導(dǎo)數(shù),α是學(xué)習(xí)速率。為便于大家更全面地了解Theano函數(shù)的使用方法,下面我們通過一個(gè)邏輯回歸的完整實(shí)例來說明:
import numpy as np import theano import theano.tensor as T rng=np.random # 我們?yōu)榱藴y(cè)試,自己生成10個(gè)樣本,每個(gè)樣本是3維的向量,然后用于訓(xùn)練 N=10 feats=3 D=(rng.randn(N, feats).astype(np.float32), rng.randint(size=N, low=0, high=2).astype(np.float32)) # 聲明自變量x、以及每個(gè)樣本對(duì)應(yīng)的標(biāo)簽y(訓(xùn)練標(biāo)簽) x=T.matrix("x") y=T.vector("y") #隨機(jī)初始化參數(shù)w、b=0,為共享變量 w=theano.shared(rng.randn(feats), name="w") b=theano.shared(0., name="b") #構(gòu)造代價(jià)函數(shù) p_1=1 / (1 + T.exp(-T.dot(x, w) - b)) # s激活函數(shù) xent=-y * T.log(p_1) - (1-y) * T.log(1-p_1) # 交叉商代價(jià)函數(shù) cost=xent.mean() + 0.01 * (w ** 2).sum()# 代價(jià)函數(shù)的平均值+L2正則項(xiàng)以防過擬合,其中權(quán)重衰減系數(shù)為0.01 gw, gb=T.grad(cost, [w, b]) #對(duì)總代價(jià)函數(shù)求參數(shù)的偏導(dǎo)數(shù) prediction=p_1 > 0.5 # 大于0.5預(yù)測(cè)值為1,否則為0. train=theano.function(inputs=[x,y],outputs=[prediction, xent],updates=((w, w - 0.1 * gw), (b, b - 0.1 * gb)))#訓(xùn)練所需函數(shù) predict=theano.function(inputs=[x], outputs=prediction)#測(cè)試階段函數(shù) #訓(xùn)練 training_steps=1000 for i in range(training_steps): pred, err=train(D[0], D[1]) print (err.mean())#查看代價(jià)函數(shù)下降變化過程
編寫函數(shù)需要經(jīng)常用到條件語(yǔ)句或循環(huán)語(yǔ)句,這節(jié)我們就簡(jiǎn)單介紹Theano如何實(shí)現(xiàn)條件判斷或邏輯循環(huán)。
1. 條件判斷
Theano是一種符號(hào)語(yǔ)言,條件判斷不能直接使用Python的if語(yǔ)句。在Theano可以用ifelse和switch來表示判定語(yǔ)句。這兩個(gè)判定語(yǔ)句有何區(qū)別呢?
switch對(duì)每個(gè)輸出變量進(jìn)行操作,ifelse只對(duì)一個(gè)滿足條件的變量操作。比如對(duì)語(yǔ)句:
switch(cond, ift, iff)
如果滿足條件,則switch既執(zhí)行ift也執(zhí)行iff。而對(duì)語(yǔ)句:
if cond then ift else iff
ifelse只執(zhí)行ift或者只執(zhí)行iff。
下面通過一個(gè)示例進(jìn)一步說明:
from theano import tensor as T from theano.ifelse import ifelse import theano,time,numpy a,b=T.scalars('a','b') x,y=T.matrices('x','y') z_switch=T.switch(T.lt(a,b),T.mean(x),T.mean(y))#lt:a < b? z_lazy=ifelse(T.lt(a,b),T.mean(x),T.mean(y)) #optimizer:optimizer的類型結(jié)構(gòu)(可以簡(jiǎn)化計(jì)算,增加計(jì)算的穩(wěn)定性) #linker:決定使用哪種方式進(jìn)行編譯(C/Python) f_switch=theano.function([a, b, x, y], z_switch,mode=theano.Mode(linker='vm')) f_lazyifelse=theano.function([a, b, x, y], z_lazy,mode=theano.Mode(linker='vm')) val1=0. val2=1. big_mat1=numpy.ones((1000, 100)) big_mat2=numpy.ones((1000, 100)) n_times=10 tic=time.clock() for i in range(n_times): f_switch(val1, val2, big_mat1, big_mat2) print('time spent evaluating both values %f sec' % (time.clock() - tic)) tic=time.clock() for i in range(n_times): f_lazyifelse(val1, val2, big_mat1, big_mat2) print('time spent evaluating one value %f sec' % (time.clock() - tic))
打印結(jié)果:
time spent evaluating both values 0.005268 sec time spent evaluating one value 0.007501 sec
2. 循環(huán)語(yǔ)句
scan是Theano中構(gòu)建循環(huán)Graph的方法,scan是個(gè)靈活復(fù)雜的函數(shù),任何用循環(huán)、遞歸或者跟序列有關(guān)的計(jì)算,都可以用scan完成。其格式如下:
theano.scan(fn, sequences=None, outputs_info=None, non_sequences=None, n_steps=None, truncate_gradient=-1, go_backwards=False, mode=None, name=None, profile=False, allow_gc=None, strict=False)
參數(shù)說明:
下面通過一個(gè)例子解釋scan函數(shù)的具體使用方法。
代碼實(shí)現(xiàn)思路是:先定義函數(shù)one_step,即scan里的fn,其任務(wù)就是計(jì)算多項(xiàng)式的一項(xiàng),scan函數(shù)返回的result里會(huì)保存多項(xiàng)式每一項(xiàng)的值,然后我們對(duì)result求和,就得到了多項(xiàng)式的值。
import theano import theano.tensor as T import numpy as np # 定義單步的函數(shù),實(shí)現(xiàn)a*x^n # 輸入?yún)?shù)的順序要與下面scan的輸入?yún)?shù)對(duì)應(yīng) def one_step(coef, power, x): return coef * x ** power coefs=T.ivector() # 每步變化的值,系數(shù)組成的向量 powers=T.ivector() # 每步變化的值,指數(shù)組成的向量 x=T.iscalar() # 每步不變的值,自變量 # seq,out_info,non_seq與one_step函數(shù)的參數(shù)順序一一對(duì)應(yīng) # 返回的result是每一項(xiàng)的符號(hào)表達(dá)式組成的list result, updates=theano.scan(fn=one_step, sequences=[coefs, powers], outputs_info=None, non_sequences=x) # 每一項(xiàng)的值與輸入的函數(shù)關(guān)系 f_poly=theano.function([x, coefs, powers], result, allow_input_downcast=True) coef_val=np.array([2,3,4,6,5]) power_val=np.array([0,1,2,3,4]) x_val=10 print("多項(xiàng)式各項(xiàng)的值: ",f_poly(x_val, coef_val, power_val)) #scan返回的result是每一項(xiàng)的值,并沒有求和,如果我們只想要多項(xiàng)式的值,可以把f_poly寫成這樣: # 多項(xiàng)式每一項(xiàng)的和與輸入的函數(shù)關(guān)系 f_poly=theano.function([x, coefs, powers], result.sum(), allow_input_downcast=True) print("多項(xiàng)式和的值:",f_poly(x_val, coef_val, power_val))
打印結(jié)果:
多項(xiàng)式各項(xiàng)的值: [ 2 30 400 6000 50000] 多項(xiàng)式和的值: 56432
共享變量(shared variable)是實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法參數(shù)更新的重要機(jī)制。shared函數(shù)會(huì)返回共享變量。這種變量的值在多個(gè)函數(shù)可直接共享。可以用符號(hào)變量的地方都可以用共享變量。
但不同的是,共享變量有一個(gè)內(nèi)部狀態(tài)的值,這個(gè)值可以被多個(gè)函數(shù)共享。它可以存儲(chǔ)在顯存中,利用GPU提高性能。我們可以使用get_value和set_value方法來讀取或者修改共享變量的值,使用共享變量實(shí)現(xiàn)累加操作。
import theano import theano.tensor as T from theano import shared import numpy as np #定義一個(gè)共享變量,并初始化為0 state=shared(0) inc=T.iscalar('inc') accumulator=theano.function([inc], state, updates=[(state, state+inc)]) # 打印state的初始值 print(state.get_value()) accumulator(1) # 進(jìn)行一次函數(shù)調(diào)用 # 函數(shù)返回后,state的值發(fā)生了變化 print(state.get_value())
這里state是一個(gè)共享變量,初始化為0,每次調(diào)用accumulator(),state都會(huì)加上inc。共享變量可以像普通張量一樣用于符號(hào)表達(dá)式,另外,它還有自己的值,可以直接用.get_value()和.set_value()方法來訪問和修改。
上述代碼引入了函數(shù)中的updates參數(shù)。updates參數(shù)是一個(gè)list,其中每個(gè)元素是一個(gè)元組(tuple),這個(gè)tuple的第一個(gè)元素是一個(gè)共享變量,第二個(gè)元素是一個(gè)新的表達(dá)式。updatas中的共享變量會(huì)在函數(shù)返回后更新自己的值。
updates的作用在于執(zhí)行效率,updates多數(shù)時(shí)候可以用原地(in-place)算法快速實(shí)現(xiàn),在GPU上,Theano可以更好地控制何時(shí)何地給共享變量分配空間,帶來性能提升。最常見的神經(jīng)網(wǎng)絡(luò)權(quán)值更新,一般會(huì)用update實(shí)現(xiàn)。
Theano基于NumPy,但性能方面又高于NumPy。因Theano采用了張量(Tensor)這個(gè)核心元素,在計(jì)算方面采用符號(hào)計(jì)算模型,而且采用共享變量、自動(dòng)求導(dǎo)、利用GPU等適合于大數(shù)據(jù)、深度學(xué)習(xí)的方法,其他很多開發(fā)項(xiàng)目也深受這些技術(shù)和框架影響。
關(guān)于作者:吳茂貴,BI和大數(shù)據(jù)專家,就職于中國(guó)外匯交易中心,在BI、數(shù)據(jù)挖掘與分析、數(shù)據(jù)倉(cāng)庫(kù)、機(jī)器學(xué)習(xí)等領(lǐng)域有超過20年的工作經(jīng)驗(yàn),在Spark機(jī)器學(xué)習(xí)、TensorFlow深度學(xué)習(xí)領(lǐng)域大量的實(shí)踐經(jīng)驗(yàn)。王冬,任職于博世(中國(guó))投資有限公司,負(fù)責(zé)Bosch企業(yè)BI及工業(yè)4.0相關(guān)大數(shù)據(jù)和數(shù)據(jù)挖掘項(xiàng)目。對(duì)機(jī)器學(xué)習(xí)、人工智能有多年實(shí)踐經(jīng)驗(yàn)。李濤,參與過多個(gè)人工智能項(xiàng)目,如研究開發(fā)服務(wù)機(jī)器人、無人售后店等項(xiàng)目。熟悉python、caffe、TensorFlow等,對(duì)深度學(xué)習(xí)、尤其對(duì)計(jì)算機(jī)視覺方面有較深理解。楊本法,高級(jí)算法工程師,在機(jī)器學(xué)習(xí)、文本挖掘、可視化等領(lǐng)域有多年實(shí)踐經(jīng)驗(yàn)。熟悉Hadoop、Spark生態(tài)圈的相關(guān)技術(shù),對(duì)Python有豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。
本文摘編自《Python深度學(xué)習(xí):基于TensorFlow》,經(jīng)出版方授權(quán)發(fā)布。
延伸閱讀《Python深度學(xué)習(xí):基于TensorFlow》
推薦語(yǔ):從Python和數(shù)學(xué),到機(jī)器學(xué)習(xí)和TensorFlow,再到深度學(xué)習(xí)的應(yīng)用和擴(kuò)展,為深度學(xué)習(xí)提供全棧解決方案。
我將向您展示如何在Windows上設(shè)置機(jī)器學(xué)習(xí)環(huán)境。
我們將首先安裝Anaconda,它是用于數(shù)據(jù)科學(xué)和機(jī)器學(xué)習(xí)相關(guān)應(yīng)用程序的Python和R編程語(yǔ)言的免費(fèi)和開放源代碼發(fā)行版,旨在簡(jiǎn)化包管理和部署。
要下載Anaconda,請(qǐng)?jiān)L問官方網(wǎng)站(https://www.anaconda.com/download/)并下載Windows版本。
根據(jù)您的操作系統(tǒng)下載32位或64位安裝程序。
為了檢查您的系統(tǒng)路徑,請(qǐng)轉(zhuǎn)到控制面板>系統(tǒng)
下載后,運(yùn)行安裝程序。同意許可協(xié)議,確認(rèn)安裝路徑,然后單擊下一步。
確保你沒有選中'將Anaconda添加到我的PATH環(huán)境變量'選項(xiàng),然后單擊安裝。
安裝程序現(xiàn)在將開始在您的系統(tǒng)上安裝Anaconda。取決于您的系統(tǒng),它需要一些時(shí)間。
一旦安裝完成,我們需要設(shè)置環(huán)境變量。
在系統(tǒng)變量下,選擇'路徑'并點(diǎn)擊'編輯'。
點(diǎn)擊“新建”,然后點(diǎn)擊“確定”,添加下面的路徑,如下圖所示。
要驗(yàn)證是否安裝了conda,以管理員身份運(yùn)行CMD。
輸入'conda - version'然后按Enter鍵。
如果您沒有發(fā)現(xiàn)任何錯(cuò)誤,則表示您已成功安裝Anaconda。
要安裝不同的包和框架:
以管理員身份運(yùn)行CMD并粘貼以下行:
Scipy:
conda install scipy
Scikit-learn:
pip install sklearn
Pandas:
pip install pandas
Pandas-Datareader:
pip install pandas-datareader
Matplotlib:
pip install matplotlib
Pillow:
pip install pillow
Requests:
pip install requests
h5py:
pip install h5py
Tensorflow:
pip install tensorflow
Keras:
pip install keras
(如果在安裝keras時(shí)遇到任何錯(cuò)誤,請(qǐng)運(yùn)行該命令conda install-force html5lib,然后再次嘗試安裝keras。它應(yīng)該這次工作)
OpenCV:
conda install -c conda-forge opencv
Pytorch:
# for CPU package
conda install -c peterjc123 pytorch-cpu
# for Windows 10 and Windows Server 2016, CUDA 8
conda install -c peterjc123 pytorch
# for Windows 10 and Windows Server 2016, CUDA 9
conda install -c peterjc123 pytorch cuda90
# for Windows 7/8/8.1 and Windows Server 2008/2012, CUDA 8
conda install -c peterjc123 pytorch_legacy
Theano:
conda install numpy scipy mkl-service libpython
# for CPU only package
conda install theano
# for GPU package
conda install theano pygpu
NLTK:
conda install -c anaconda nltk
CNTK:
pip install cntk
注意:為了查看已安裝的軟件包,運(yùn)行命令'conda list'