MXNet设计和实现简介
神經(jīng)網(wǎng)絡(luò)本質(zhì)上是一種語(yǔ)言,我們通過(guò)它來(lái)表達(dá)對(duì)應(yīng)用問(wèn)題的理解。例如我們用卷積層來(lái)表達(dá)空間相關(guān)性,RNN來(lái)表達(dá)時(shí)間連續(xù)性。根據(jù)問(wèn)題的復(fù)雜性和信息如何從輸入到輸出一步步提取,我們將不同大小的層按一定原則連接起來(lái)。近年來(lái)隨著數(shù)據(jù)的激增和計(jì)算能力的大幅提升,神經(jīng)網(wǎng)絡(luò)也變得越來(lái)越深和大。例如最近幾次imagnet競(jìng)賽的冠軍都使用有數(shù)十至百層的網(wǎng)絡(luò)。對(duì)于這一類神經(jīng)網(wǎng)絡(luò)我們通常稱之為深度學(xué)習(xí)。從應(yīng)用的角度而言,對(duì)深度學(xué)習(xí)最重要的是如何方便地表述神經(jīng)網(wǎng)絡(luò),以及如何快速訓(xùn)練得到模型。
對(duì)于一個(gè)優(yōu)秀的深度學(xué)習(xí)系統(tǒng),或者更廣來(lái)說(shuō)優(yōu)秀的科學(xué)計(jì)算系統(tǒng),最重要的是編程接口的設(shè)計(jì)。他們都采用將一個(gè)領(lǐng)域特定語(yǔ)言(domain specific language)嵌入到一個(gè)主語(yǔ)言中。例如numpy將矩陣運(yùn)算嵌入到python中。這類嵌入一般分為兩種,其中一種嵌入的較淺,其中每個(gè)語(yǔ)句都按原來(lái)的意思執(zhí)行,且通常采用命令式編程(imperative programming),其中numpy和Torch就是屬于這種。而另一種則用一種深的嵌入方式,提供一整套針對(duì)具體應(yīng)用的迷你語(yǔ)言。這一種通常使用聲明式語(yǔ)言(declarative programing),既用戶只需要聲明要做什么,而具體執(zhí)行則由系統(tǒng)完成。這類系統(tǒng)包括Caffe,theano和剛公布的TensorFlow。
這兩種方式各有利弊,總結(jié)如下
| 如何執(zhí)行?a=b+1 | 需要b已經(jīng)被賦值。立即執(zhí)行加法,將結(jié)果保存在a中。 | 返回對(duì)應(yīng)的計(jì)算圖(computation graph),我們可以之后對(duì)b進(jìn)行賦值,然后再執(zhí)行加法運(yùn)算 |
| 優(yōu)點(diǎn) | 語(yǔ)義上容易理解,靈活,可以精確控制行為。通常可以無(wú)縫地和主語(yǔ)言交互,方便地利用主語(yǔ)言的各類算法,工具包,debug和性能調(diào)試器。 | 在真正開(kāi)始計(jì)算的時(shí)候已經(jīng)拿到了整個(gè)計(jì)算圖,所以我們可以做一系列優(yōu)化來(lái)提升性能。實(shí)現(xiàn)輔助函數(shù)也容易,例如對(duì)任何計(jì)算圖都提供forward和backward函數(shù),對(duì)計(jì)算圖進(jìn)行可視化,將圖保存到硬盤(pán)和從硬盤(pán)讀取。 |
| 缺點(diǎn) | 實(shí)現(xiàn)統(tǒng)一的輔助函數(shù)和提供整體優(yōu)化都很困難。 | 很多主語(yǔ)言的特性都用不上。某些在主語(yǔ)言中實(shí)現(xiàn)簡(jiǎn)單,但在這里卻經(jīng)常麻煩,例如if-else語(yǔ)句 。debug也不容易,例如監(jiān)視一個(gè)復(fù)雜的計(jì)算圖中的某個(gè)節(jié)點(diǎn)的中間結(jié)果并不簡(jiǎn)單。 |
目前現(xiàn)有的系統(tǒng)大部分都采用上兩種編程模式的一種。與它們不同的是,MXNet嘗試將兩種模式無(wú)縫的結(jié)合起來(lái)。在命令式編程上MXNet提供張量運(yùn)算,而聲明式編程中MXNet支持符號(hào)表達(dá)式。用戶可以自由的混合它們來(lái)快速實(shí)現(xiàn)自己的想法。例如我們可以用聲明式編程來(lái)描述神經(jīng)網(wǎng)絡(luò),并利用系統(tǒng)提供的自動(dòng)求導(dǎo)來(lái)訓(xùn)練模型。另一方便,模型的迭代訓(xùn)練和更新模型法則中可能涉及大量的控制邏輯,因此我們可以用命令式編程來(lái)實(shí)現(xiàn)。同時(shí)我們用它來(lái)進(jìn)行方便地調(diào)式和與主語(yǔ)言交互數(shù)據(jù)。
下表我們比較MXNet和其他流行的深度學(xué)習(xí)系統(tǒng)
| Caffe | C++ | Python/Matlab | CPU/GPU | x | x | v |
| Torch | Lua | - | CPU/GPU/FPGA | x | v | x |
| Theano | Python | - | CPU/GPU | x | v | x |
| TensorFlow | C++ | Python | CPU/GPU/Mobile | v | x | v |
| MXNet1 | C++ | Python/R/Julia/Go | CPU/GPU/Mobile | v | v | v |
MXNet的系統(tǒng)架構(gòu)如下圖所示:
從上到下分別為各種主語(yǔ)言的嵌入,編程接口(矩陣運(yùn)算,符號(hào)表達(dá)式,分布式通訊),兩種編程模式的統(tǒng)一系統(tǒng)實(shí)現(xiàn),以及各硬件的支持。接下一章我們將介紹編程接口,然后下一章介紹系統(tǒng)實(shí)現(xiàn)。之后我們給出一些實(shí)驗(yàn)對(duì)比結(jié)果,以及討論MXNet的未來(lái)。
編程接口
Symbol: 聲明式的符號(hào)表達(dá)式
MXNet使用多值輸出的符號(hào)表達(dá)式來(lái)聲明計(jì)算圖。符號(hào)是由操作子構(gòu)建而來(lái)。一個(gè)操作子可以是一個(gè)簡(jiǎn)單的矩陣運(yùn)算“+”,也可以是一個(gè)復(fù)雜的神經(jīng)網(wǎng)絡(luò)里面的層,例如卷積層。一個(gè)操作子可以有多個(gè)輸入變量和多個(gè)輸出變量,還可以有內(nèi)部狀態(tài)變量。一個(gè)變量既可以是自由的,我們可以之后對(duì)其賦值;也可以是某個(gè)操作子的輸出。例如下面的代碼中我們使用Julia來(lái)定義一個(gè)多層感知機(jī),它由一個(gè)代表輸入數(shù)據(jù)的自由變量,和多個(gè)神經(jīng)網(wǎng)絡(luò)層串聯(lián)而成。
using MXNet mlp = @mx.chain mx.Variable(:data) =>mx.FullyConnected(num_hidden=64) =>mx.Activation(act_type=:relu) =>mx.FullyConnected(num_hidden=10) =>mx.Softmax()在執(zhí)行一個(gè)符號(hào)表達(dá)式前,我們需要對(duì)所有的自由變量進(jìn)行賦值。上例中,我們需要給定數(shù)據(jù),和各個(gè)層里隱式定義的輸入,例如全連接層的權(quán)重和偏值。我們同時(shí)要申明所需要的輸出,例如softmax的輸出。
除了執(zhí)行獲得softmax輸出外(通常也叫forward),符號(hào)表達(dá)式也支持自動(dòng)求導(dǎo)來(lái)獲取各權(quán)重和偏值對(duì)應(yīng)的梯度(也稱之為backward)。此外,我們還可以提前估計(jì)計(jì)算時(shí)需要的內(nèi)存,符號(hào)表達(dá)式的可視化,讀入和輸出等。
NDArray:命令式的張量計(jì)算
MXNet提供命令式的張量計(jì)算來(lái)橋接主語(yǔ)言的和符號(hào)表達(dá)式。下面代碼中,我們?cè)贕PU上計(jì)算矩陣和常量的乘法,并使用numpy來(lái)打印結(jié)果
>>> import MXNet as mx >>> a = mx.nd.ones((2, 3), ... mx.gpu()) >>> print (a * 2).asnumpy() [[ 2. 2. 2.][ 2. 2. 2.]]另一方面,NDArray可以無(wú)縫和符號(hào)表達(dá)式進(jìn)行對(duì)接。假設(shè)我們使用Symbol定義了一個(gè)神經(jīng)網(wǎng)絡(luò),那么我們可以如下實(shí)現(xiàn)一個(gè)梯度下降算法
for (int i = 0; i < n; ++i) {net.forward();net.backward();net.weight -= eta * net.grad }這里梯度由Symbol計(jì)算而得。Symbol的輸出結(jié)果均表示成NDArray,我們可以通過(guò)NDArray提供的張量計(jì)算來(lái)更新權(quán)重。此外,我們還利用了主語(yǔ)言的for循環(huán)來(lái)進(jìn)行迭代,學(xué)習(xí)率eta也是在主語(yǔ)言中進(jìn)行修改。
上面的混合實(shí)現(xiàn)跟使用純符號(hào)表達(dá)式實(shí)現(xiàn)的性能相差無(wú)二,然后后者在表達(dá)控制邏輯時(shí)會(huì)更加復(fù)雜。其原因是NDArray的執(zhí)行會(huì)和Symbol類似的構(gòu)建一個(gè)計(jì)算圖,并與其他運(yùn)算一同交由后臺(tái)引擎執(zhí)行。對(duì)于運(yùn)算-=由于我們只是將其結(jié)果交給另一個(gè)Symbol的forward作為輸入,因此我們不需要立即得到結(jié)果。當(dāng)上面的for循環(huán)結(jié)束時(shí),我們只是將數(shù)個(gè)Symbol和NDarray對(duì)應(yīng)的計(jì)算圖提交給了后臺(tái)引擎。當(dāng)我們最終需要結(jié)果的時(shí)候,例如將weight復(fù)制到主語(yǔ)言中或者保存到磁盤(pán)時(shí),程序才會(huì)被阻塞直到所有計(jì)算完成。
KVStore:多設(shè)備間的數(shù)據(jù)交互
MXNet提供一個(gè)分布式的key-value存儲(chǔ)來(lái)進(jìn)行數(shù)據(jù)交換。它主要有兩個(gè)函數(shù), 1. push: 將key-value對(duì)從一個(gè)設(shè)備push進(jìn)存儲(chǔ) 2. pull:將某個(gè)key上的值從存儲(chǔ)中pull出來(lái)此外,KVStore還接受自定義的更新函數(shù)來(lái)控制收到的值如何寫(xiě)入到存儲(chǔ)中。最后KVStore提供數(shù)種包含最終一致性模型和順序一致性模型在內(nèi)的數(shù)據(jù)一致性模型。
在下面例子中,我們將前面的梯度下降算法改成分布式梯度下降。
KVStore kv("dist_async"); kv.set_updater([](NDArray w, NDArray g) {w -= eta * g;}); for (int i = 0; i < max_iter; ++i) {kv.pull(net.weight);net.forward();net.backward();kv.push(net.grad); }在這里我們先使用最終一致性模型創(chuàng)建一個(gè)kvstore,然后將更新函數(shù)注冊(cè)進(jìn)去。在每輪迭代前,每個(gè)計(jì)算節(jié)點(diǎn)先將最新的權(quán)重pull回來(lái),之后將計(jì)算的得到的梯度push出去。kvstore將會(huì)利用更新函數(shù)來(lái)使用收到的梯度更新其所存儲(chǔ)的權(quán)重。
這里push和pull跟NDArray一樣使用了延后計(jì)算的技術(shù)。它們只是將對(duì)應(yīng)的操作提交給后臺(tái)引擎,而引擎則調(diào)度實(shí)際的數(shù)據(jù)交互。所以上述的實(shí)現(xiàn)跟我們使用純符號(hào)實(shí)現(xiàn)的性能相差無(wú)幾。
讀入數(shù)據(jù)模塊
數(shù)據(jù)讀取在整體系統(tǒng)性能上占重要地位。MXNet提供工具能將任意大小的樣本壓縮打包成單個(gè)或者數(shù)個(gè)文件來(lái)加速順序和隨機(jī)讀取。
通常數(shù)據(jù)存在本地磁盤(pán)或者遠(yuǎn)端的分布式文件系統(tǒng)上(例如HDFS或者Amazon S3),每次我們只需要將當(dāng)前需要的數(shù)據(jù)讀進(jìn)內(nèi)存。MXNet提供迭代器可以按塊讀取不同格式的文件。迭代器使用多線程來(lái)解碼數(shù)據(jù),并使用多線程預(yù)讀取來(lái)隱藏文件讀取的開(kāi)銷(xiāo)。
訓(xùn)練模塊
MXNet實(shí)現(xiàn)了常用的優(yōu)化算法來(lái)訓(xùn)練模型。用戶只需要提供數(shù)據(jù)數(shù)據(jù)迭代器和神經(jīng)網(wǎng)絡(luò)的Symbol便可。此外,用戶可以提供額外的KVStore來(lái)進(jìn)行分布式的訓(xùn)練。例如下面代碼使用分布式異步SGD來(lái)訓(xùn)練一個(gè)模型,其中每個(gè)計(jì)算節(jié)點(diǎn)使用兩塊GPU。
import MXNet as mx model = mx.model.FeedForward(ctx = [mx.gpu(0), mx.gpu(1)],symbol = network,num_epoch = 100,learning_rate = 0.01,momentum = 0.9,wd = 0.00001,initializer = mx.init.Xavier(factor_type="in", magnitude=2.34)) model.fit(X = train_iter,eval_data = val_iter,kvstore = mx.kvstore.create('dist_async'),epoch_end_callback = mx.callback.do_checkpoint('model_'))系統(tǒng)實(shí)現(xiàn)
計(jì)算圖
一個(gè)已經(jīng)賦值的符號(hào)表達(dá)式可以表示成一個(gè)計(jì)算圖。下圖是之前定義的多層感知機(jī)的部分計(jì)算圖,包含forward和backward。
其中圓表示變量,方框表示操作子,箭頭表示數(shù)據(jù)依賴關(guān)系。在執(zhí)行之前,MXNet會(huì)對(duì)計(jì)算圖進(jìn)行優(yōu)化,以及為所有變量提前申請(qǐng)空間。
計(jì)算圖優(yōu)化
計(jì)算圖優(yōu)化已經(jīng)在數(shù)據(jù)庫(kù)等領(lǐng)域被研究多年,我們目前只探索了數(shù)個(gè)簡(jiǎn)單的方法。 1. 注意到我們提前申明了哪些輸出變量是需要的,這樣我們只需要計(jì)算這些輸出需要的操作。例如,在預(yù)測(cè)時(shí)我們不需要計(jì)算梯度,所以整個(gè)backforward圖都可以忽略。而在特征抽取中,我們可能只需要某些中間層的輸出,從而可以忽略掉后面的計(jì)算。 2. 我們可以合并某些操作。例如?ab+1*只需要一個(gè)blas或者cuda函數(shù)即可,而不需要將其表示成兩個(gè)操作。 3. 我們實(shí)現(xiàn)了一些“大”操作,例如一個(gè)卷積層就只需要一個(gè)操作子。這樣我們可以大大減小計(jì)算圖的大小,并且方便手動(dòng)的對(duì)這個(gè)操作進(jìn)行優(yōu)化。
內(nèi)存申請(qǐng)
內(nèi)存通常是一個(gè)重要的瓶頸,尤其是對(duì)GPU和智能設(shè)備而言。而神經(jīng)網(wǎng)絡(luò)計(jì)算時(shí)通常需要大量的臨時(shí)空間,例如每個(gè)層的輸入和輸出變量。對(duì)每個(gè)變量都申請(qǐng)一段獨(dú)立的空間會(huì)帶來(lái)高額的內(nèi)存開(kāi)銷(xiāo)。幸運(yùn)的是,我們可以從計(jì)算圖推斷出所有變量的生存期,就是這個(gè)變量從創(chuàng)建到最后被使用的時(shí)間段,從而可以對(duì)兩個(gè)不交叉的變量重復(fù)使用同一內(nèi)存空間。這個(gè)問(wèn)題在諸多領(lǐng)域,例如編譯器的寄存器分配上,有過(guò)研究。然而最優(yōu)的分配算法需要?O(n2)?時(shí)間復(fù)雜度,這里n是圖中變量的個(gè)數(shù)。
MXNet提供了兩個(gè)啟發(fā)式的策略,每個(gè)策略都是線性的復(fù)雜度。 1. inplace。在這個(gè)策略里,我們模擬圖的遍歷過(guò)程,并為每個(gè)變量維護(hù)一個(gè)還有多少其他變量需要它的計(jì)數(shù)。當(dāng)我們發(fā)現(xiàn)某個(gè)變量的計(jì)數(shù)變成0時(shí),我們便回收其內(nèi)存空間。 2. co-share。我們?cè)试S兩個(gè)變量使用同一段內(nèi)存空間。這么做當(dāng)然會(huì)使得這兩個(gè)變量不能同時(shí)在寫(xiě)這段空間。所以我們只考慮對(duì)不能并行的變量進(jìn)行co-share。每一次我們考慮圖中的一條路(path),路上所有變量都有依賴關(guān)系所以不能被并行,然后我們對(duì)其進(jìn)行內(nèi)存分配并將它們從圖中刪掉。
引擎
在MXNet中,所有的任務(wù),包括張量計(jì)算,symbol執(zhí)行,數(shù)據(jù)通訊,都會(huì)交由引擎來(lái)執(zhí)行。首先,所有的資源單元,例如NDArray,隨機(jī)數(shù)生成器,和臨時(shí)空間,都會(huì)在引擎處注冊(cè)一個(gè)唯一的標(biāo)簽。然后每個(gè)提交給引擎的任務(wù)都會(huì)標(biāo)明它所需要的資源標(biāo)簽。引擎則會(huì)跟蹤每個(gè)資源,如果某個(gè)任務(wù)所需要的資源到到位了,例如產(chǎn)生這個(gè)資源的上一個(gè)任務(wù)已經(jīng)完成了,那么引擎會(huì)則調(diào)度和執(zhí)行這個(gè)任務(wù)。
通常一個(gè)MXNet運(yùn)行實(shí)例會(huì)使用多個(gè)硬件資源,包括CPU,GPU,PCIe通道,網(wǎng)絡(luò),和磁盤(pán),所以引擎會(huì)使用多線程來(lái)調(diào)度,既任何兩個(gè)沒(méi)有資源依賴沖突的任務(wù)都可能會(huì)被并行執(zhí)行,以求最大化資源利用。
與通常的數(shù)據(jù)流引擎不同的是,MXNet的引擎允許一個(gè)任務(wù)修改現(xiàn)有的資源。為了保證調(diào)度正確性,提交任務(wù)時(shí)需要分開(kāi)標(biāo)明哪些資源是只讀,哪些資源會(huì)被修改。這個(gè)附加的寫(xiě)依賴可以帶來(lái)很多便利。例如我們可以方便實(shí)現(xiàn)在numpy以及其他張量庫(kù)中常見(jiàn)的數(shù)組修改操作,同時(shí)也使得內(nèi)存分配時(shí)更加容易,比如操作子可以修改其內(nèi)部狀態(tài)變量而不需要每次都重來(lái)內(nèi)存。再次,假如我們要用同一個(gè)種子生成兩個(gè)隨機(jī)數(shù),那么我們可以標(biāo)注這兩個(gè)操作會(huì)同時(shí)修改種子來(lái)使得引擎不會(huì)并行執(zhí)行,從而使得代碼的結(jié)果可以很好的被重復(fù)。
數(shù)據(jù)通訊
KVStore的實(shí)現(xiàn)是基于參數(shù)服務(wù)器。但它跟前面的工作有兩個(gè)顯著的區(qū)別。 1. 我們通過(guò)引擎來(lái)管理數(shù)據(jù)一致性,這使得參數(shù)服務(wù)器的實(shí)現(xiàn)變得相當(dāng)簡(jiǎn)單,同時(shí)使得KVStore的運(yùn)算可以無(wú)縫的與其他結(jié)合在一起。 2. 我們使用一個(gè)兩層的通訊結(jié)構(gòu),原理如下圖所示。第一層的服務(wù)器管理單機(jī)內(nèi)部的多個(gè)設(shè)備之間的通訊。第二層服務(wù)器則管理機(jī)器之間通過(guò)網(wǎng)絡(luò)的通訊。第一層的服務(wù)器在與第二層通訊前可能合并設(shè)備之間的數(shù)據(jù)來(lái)降低網(wǎng)絡(luò)帶寬消費(fèi)。同時(shí)考慮到機(jī)器內(nèi)和外通訊帶寬和延時(shí)的不同性,我們可以對(duì)其使用不同的一致性模型。例如第一層我們用強(qiáng)的一致性模型,而第二層我們則使用弱的一致性模型來(lái)減少同步開(kāi)銷(xiāo)。
可移植性
輕量和可移植性是MXNet的一個(gè)重要目標(biāo)。MXNet核心使用C++實(shí)現(xiàn),并提供C風(fēng)格的頭文件。因此方便系統(tǒng)移植,也使得其很容易被其他支持C FFI (forigen language interface )的語(yǔ)言調(diào)用。此外,我們也提供一個(gè)腳本將MXNet核心功能的代碼連同所有依賴打包成一個(gè)單一的只有數(shù)萬(wàn)行的C++源文件,使得其在一些受限的平臺(tái),例如智能設(shè)備,方便編譯和使用。
實(shí)驗(yàn)結(jié)果
這里我們提供一些早期的實(shí)驗(yàn)結(jié)果。
與其他系統(tǒng)相比
我們首先使用一個(gè)流行卷積網(wǎng)絡(luò)測(cè)試方案來(lái)對(duì)比MXNet與Torch,Caffe和TensorFlow在過(guò)去幾屆imagenet競(jìng)賽冠軍網(wǎng)絡(luò)上的性能。每個(gè)系統(tǒng)使用同樣的CUDA 7.0和CUDNN 3,但TensorFlow使用其只支持的CUDA 6.5 和CUDNN 2。我們使用單塊GTX 980并報(bào)告單個(gè)forward和backward的耗時(shí)。
可以看出MXNet,Torch和Caffe三者在性能上不相上下。這個(gè)符合預(yù)期,因?yàn)樵趩慰ㄉ衔覀冊(cè)u(píng)測(cè)的幾個(gè)網(wǎng)絡(luò)的絕大部分運(yùn)算都由CUDA和CUDNN完成。TensorFlow比其他三者都慢2倍以上,這可能由于是低版本的CUDNN和項(xiàng)目剛開(kāi)源的緣故。
內(nèi)存的使用
接下來(lái)我們考察不同的內(nèi)存分配算法對(duì)內(nèi)存占用的影響。下圖分別表示使用batch=128時(shí),在做預(yù)測(cè)時(shí)和做訓(xùn)練時(shí)的不同算法在內(nèi)部變量(除去模型,最初輸入和最終輸出)上的內(nèi)存開(kāi)銷(xiāo)。
可以看出,inplace和co-share兩者都可以極大的降低內(nèi)存使用。將兩者合起來(lái)可以在訓(xùn)練時(shí)減少2倍內(nèi)存使用,在預(yù)測(cè)時(shí)則可以減小4倍內(nèi)存使用。特別的,即使是最復(fù)雜的vggnet,對(duì)單張圖片進(jìn)行預(yù)測(cè)時(shí),MXNet只需要16MB額外內(nèi)存。
Scalability
最后我們報(bào)告在分布式訓(xùn)練下的性能。我們使用imagenet 1k數(shù)據(jù)(120萬(wàn)224x224x3圖片,1000類),并用googlenet加上batch normalization來(lái)訓(xùn)練。我們使用Amazon EC2 g2.8x,單機(jī)和多機(jī)均使用同樣的參數(shù),下圖表示了使用單機(jī)和10臺(tái)g2.8x時(shí)的收斂情況。
從訓(xùn)練精度來(lái)看,單機(jī)的收斂比多機(jī)快,這個(gè)符合預(yù)期,因?yàn)槎鄼C(jī)時(shí)有效的batch大小比單機(jī)要大,在處理同樣多的數(shù)據(jù)上收斂通常會(huì)慢。但有意思的是兩者在測(cè)試精度上非常相似。
單機(jī)下每遍歷一次數(shù)據(jù)需要1萬(wàn)4千秒,而在十臺(tái)機(jī)器上,每次只需要1千4百秒。如果考慮運(yùn)行時(shí)間對(duì)比測(cè)試精度,10臺(tái)機(jī)器帶來(lái)了10倍的提升。
過(guò)去,現(xiàn)狀,和未來(lái)
大半年前我們拉來(lái)數(shù)個(gè)優(yōu)秀的C++機(jī)器學(xué)習(xí)系統(tǒng)的開(kāi)發(fā)人員成立了DMLC,本意是更方便共享各自項(xiàng)目的代碼,并給用戶提供一致的體驗(yàn)。當(dāng)時(shí)我們有兩個(gè)深度學(xué)習(xí)的項(xiàng)目,一個(gè)是CXXNet,其通過(guò)配置來(lái)定義和訓(xùn)練神經(jīng)網(wǎng)絡(luò)。另一個(gè)是Minerva,提供類似numpy一樣的張量計(jì)算接口。前者在圖片分類等使用卷積網(wǎng)絡(luò)上很方便,而后者更靈活。那時(shí)候我們想能不能做一個(gè)兩者功能都具備的系統(tǒng),于是這樣就有了MXNet。其名字來(lái)自Minerva的M和CXXNet的XNet。其中Symbol的想法來(lái)自CXXNet,而NDArray的想法來(lái)自Minerva。我們也常把MXNet叫“mix net”。
MXNet是DMLC第一個(gè)結(jié)合了所有成員努力的項(xiàng)目,也同時(shí)吸引了很多核心成員的加入。MXNet的目的是做一個(gè)有意思的系統(tǒng),能夠讓大家用著方便的系統(tǒng),一個(gè)輕量的和可以快速測(cè)試系統(tǒng)和算法想法的系統(tǒng)。對(duì)于未來(lái),我們主要關(guān)注下面四個(gè)方向:
接下來(lái)我們希望能夠在更多應(yīng)用,例如語(yǔ)音、翻譯、問(wèn)答上有所產(chǎn)出。
我們忠心希望MXNet能為大家做深度學(xué)習(xí)相關(guān)研究和應(yīng)用帶來(lái)便利。也希望能與更多的開(kāi)發(fā)者一起學(xué)習(xí)和進(jìn)步。
擴(kuò)展閱讀
TensforFlow暫時(shí)沒(méi)有公開(kāi)其分布式實(shí)現(xiàn)??
原文地址: http://mli.github.io/2015/12/03/mxnet-overview/
總結(jié)
以上是生活随笔為你收集整理的MXNet设计和实现简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 干货 | 你真的了解 Convoluti
- 下一篇: 深度增强学习前沿算法思想