久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

當(dāng)TensorFlow遇見CNTK

 LZS2851 2016-03-21

本文從程序員的角度對CNTK和TensorFlow做高層次的對比,。本文也不屬于性能分析,,而是編程模型分析。文中會夾雜著大量的代碼,。

當(dāng)TensorFlow遇見CNTK

CNTK是微軟用于搭建深度神經(jīng)網(wǎng)絡(luò)的計算網(wǎng)絡(luò)工具包,,此項目已在Github上開源。因為我最近寫了關(guān)于TensorFlow的文章,,所以想比較一下這兩個系統(tǒng)的相似和差異之處,。畢竟,CNTK也是許多圖像識別挑戰(zhàn)賽的衛(wèi)冕冠軍,。為了內(nèi)容的完整性,,我應(yīng)該也對比一下Theano、Torch和Caffe,。后三者也是現(xiàn)在非常流行的框架,。但是本文僅限于討論CNTK和TensorFlow,其余的框架將在今后討論,。Kenneth Tran對這五個深度學(xué)習(xí)工具包做過一次高水平(以他個人觀點)的分析,。本文并不是一個CNTK或者TensorFlow的使用教程。我的目的在于從程序員的角度對它們做高層次的對比,。本文也不屬于性能分析,,而是編程模型分析。文中會夾雜著大量的代碼,,如果你討厭閱讀代碼,,請直接跳到結(jié)論部分,。

CNTK有一套極度優(yōu)化的運行系統(tǒng)來訓(xùn)練和測試神經(jīng)網(wǎng)絡(luò),,它是以抽象的計算圖形式構(gòu)建。如此看來,,CNTK和TensorFlow長得非常相似,。但是,,它們有一些本質(zhì)上的區(qū)別。為了演示這些特性和區(qū)別,,我會用到兩個標(biāo)準(zhǔn)示例,,它們分別包括了兩個系統(tǒng)及調(diào)用各自系統(tǒng)完成的任務(wù)。第一個例子是用較淺的卷積神經(jīng)網(wǎng)絡(luò)來解決標(biāo)準(zhǔn)的MNIST手寫數(shù)字集的識別任務(wù),。我會針對它們兩種遞歸神經(jīng)網(wǎng)絡(luò)方法的差異性做一些點評總結(jié),。

TensorFlow和CNTK都屬于腳本驅(qū)動型的。我的意思是說神經(jīng)網(wǎng)絡(luò)構(gòu)建的流程圖都是在一個腳本里完成,,并調(diào)用一些智能的自動化步驟完成訓(xùn)練,。TensorFlow的腳本是與Python語言捆綁的,Python操作符能夠用來控制計算圖的執(zhí)行過程,。CNTK目前還沒有和Python或是C++綁定(盡管已經(jīng)承諾過),,所以它目前訓(xùn)練和測試的流程控制還是需要精心編制設(shè)計的。等會我將展示,,這個過程并不能算是一種限制,。CNTK網(wǎng)絡(luò)需要用到兩個腳本:一個控制訓(xùn)練和測試參數(shù)的配置文件和一個用于構(gòu)建網(wǎng)絡(luò)的網(wǎng)絡(luò)定義語言(Network Definition Language, NDL)文件。

我會首先描述神經(jīng)網(wǎng)絡(luò)的流程圖,,因為這是與TensorFlow最相似之處,。CNTK支持兩種方式來定義網(wǎng)絡(luò)。一種是使用“Simple Network Builder”,,只需設(shè)置幾個參數(shù)就能生成一個簡單的標(biāo)準(zhǔn)神經(jīng)網(wǎng)絡(luò),。另一種是使用網(wǎng)絡(luò)定義語言(NDL)。此處例子(直接從Github下載的)使用的是NDL,。下面就是Convolution.ndl文件的縮略版本,。(為了節(jié)省頁面空間,我把多行文件合并到同一行,,并用逗號分隔)

CNTK網(wǎng)絡(luò)圖有一些特殊的節(jié)點,。它們是描述輸入數(shù)據(jù)和訓(xùn)練標(biāo)簽的FeatureNodes和LabelNodes,用來評估訓(xùn)練結(jié)果的CriterionNodes和EvalNodes,,和表示輸出的OutputNodes,。當(dāng)我們在下文中遇到它們的時候我再具體解釋。在文件頂部還有一些用來加載數(shù)據(jù)(特征)和標(biāo)簽的宏定義,。如下所示,,我們將MNIST數(shù)據(jù)集的圖像作為特征讀入,經(jīng)過歸一化之后轉(zhuǎn)化為若干浮點數(shù)組,。得到的數(shù)組“featScaled”將作為神經(jīng)網(wǎng)絡(luò)的輸入值,。

load = ndlMnistMacros

# the actual NDL that defines the network

run = DNN

ndlMnistMacros = [

imageW = 28, imageH = 28

labelDim = 10

features = ImageInput(imageW, imageH, 1)

featScale = Const(0.00390625)

featScaled = Scale(featScale, features)

labels = Input(labelDim)

]

DNN=[

# conv1

kW1 = 5, kH1 = 5

cMap1 = 16

hStride1 = 1, vStride1 = 1

conv1_act = ConvReLULayer(featScaled,cMap1,25,kW1,kH1,hStride1,vStride1,10, 1)

# pool1

pool1W = 2, pool1H = 2

pool1hStride = 2, pool1vStride = 2

pool1 = MaxPooling(conv1_act, pool1W, pool1H, pool1hStride, pool1vStride)

# conv2

kW2 = 5, kH2 = 5

cMap2 = 32

hStride2 = 1, vStride2 = 1

conv2_act = ConvReLULayer(pool1,cMap2,400,kW2, kH2, hStride2, vStride2,10, 1)

# pool2

pool2W = 2, pool2H = 2

pool2hStride = 2, pool2vStride = 2

pool2 = MaxPooling(conv2_act, pool2W, pool2H, pool2hStride, pool2vStride)

h1Dim = 128

h1 = DNNSigmoidLayer(512, h1Dim, pool2, 1)

ol = DNNLayer(h1Dim, labelDim, h1, 1)

ce = CrossEntropyWithSoftmax(labels, ol)

err = ErrorPrediction(labels, ol)

# Special Nodes

FeatureNodes = (features)

LabelNodes = (labels)

CriterionNodes = (ce)

EvalNodes = (err)

OutputNodes = (ol)

]

DNN小節(jié)定義了網(wǎng)絡(luò)的結(jié)構(gòu)。此神經(jīng)網(wǎng)絡(luò)包括了兩個卷積-最大池化層,,接著是有一個128節(jié)點隱藏層的全連接標(biāo)準(zhǔn)網(wǎng)絡(luò),。

在卷積層I 我們使用5x5的卷積核函數(shù),,并且在參數(shù)空間定義了16個(cMap1)。操作符ConvReLULayer實際上是在宏文件中定義的另一個子網(wǎng)絡(luò)的縮寫,。

在計算時,,我們想把卷積的參數(shù)用矩陣W和向量B來表示,那么如果輸入的是X,,網(wǎng)絡(luò)的輸出將是f(op(W, X) + B)的形式,。在這里操作符op就是卷積運算,f是標(biāo)準(zhǔn)規(guī)則化函數(shù)relu(x)=max(x,0),。

ConvReLULayer的NDL代碼如下圖所示:

ConvReLULayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue) =

[

convW = Parameter(outMap, inWCount, init='uniform', initValueScale=wScale)

convB = Parameter(outMap, 1, init='fixedValue', value=bValue)

conv = Convolution(convW, inp, kW, kH, outMap, hStride,vStride,

zeroPadding=false)

convPlusB = Plus(conv, convB);

act = RectifiedLinear(convPlusB);

]

矩陣W和向量B是模型的參數(shù),,它們會被賦予一個初始值,并在訓(xùn)練的過程中不斷更新直到生成最終模型,。這里,,convW是一個16行25列的矩陣,B是長度為16的向量,。Convolution是內(nèi)置的卷積函數(shù),,默認(rèn)不使用補零的方法。也就是說對28x28的圖像做卷積運算,,實際上只是對24x24的中心區(qū)域操作,,得到的結(jié)果是16個24x24的sudo-image。

接著我們用2x2的區(qū)域應(yīng)用最大池化操作,,最后得到的結(jié)果是16個12x12的矩陣,。

當(dāng)TensorFlow遇見CNTK

對于第二個卷積層,我們把卷積濾波器的個數(shù)由16個提升到32個,。這一次我們有16通道的輸入數(shù)據(jù),,因此W矩陣的尺寸為32行25×16 = 400列,向量B的長度為32,。這次的卷積運算針對12x12圖像幀的中心區(qū)域,,所以得到的結(jié)果是32個8x8的矩陣。第二次池化操作的結(jié)果是32個4x4的幀,,或者32x16=512,。

最后兩層,是由512個池化輸出結(jié)果經(jīng)過128個節(jié)點的隱藏層連接到10個輸出節(jié)點,,經(jīng)歷了兩次運算操作,。

DNNSigmoidLayer(inDim, outDim, x, parmScale) = [

W = Parameter(outDim, inDim, init='uniform', initValueScale=parmScale)

b = Parameter(outDim, 1, init='uniform', initValueScale=parmScale)

t = Times(W, x)

z = Plus(t, b)

y = Sigmoid(z)

]

DNNLayer(inDim, outDim, x, parmScale) = [

W = Parameter(outDim, inDim, init='uniform', initValueScale=parmScale)

b = Parameter(outDim, 1, init='uniform', initValueScale=parmScale)

t = Times(W, x)

z = Plus(t, b)

]

如你所見,這些運算步驟都是標(biāo)準(zhǔn)的線性代數(shù)運算形式W*x+b,。

圖定義的最后部分是交叉熵和誤差節(jié)點,,以及將它們綁定到特殊的節(jié)點名稱。

我們接著要來定義訓(xùn)練的過程,但是先把它與用TensorFlow構(gòu)建相似的網(wǎng)絡(luò)模型做個比較,。我們在之前的文章里討論過這部分內(nèi)容,,這里再討論一次,。你是否注意到我們使用了與CNTK相同的一組變量,,只不過這里我們把它稱作變量,而在CNTK稱作參數(shù),。維度也略有不同,。盡管卷積濾波器都是5x5,在CNTK我們前后兩級分別使用了16個和32個濾波器,,但是在TensorFlow的例子里我們用的是32個和64個,。

def weight_variable(shape, names):

initial = tf.truncated_normal(shape, stddev=0.1)

return tf.Variable(initial, name=names)

def bias_variable(shape, names):

initial = tf.constant(0.1, shape=shape)

return tf.Variable(initial, name=names)

x = tf.placeholder(tf.float32, [None, 784], name='x')

sess = tf.InteractiveSession

W_conv1 = weight_variable([5, 5, 1, 32], 'wconv')

b_conv1 = bias_variable([32], 'bconv')

W_conv2 = weight_variable([5, 5, 32, 64], 'wconv2')

b_conv2 = bias_variable([64], 'bconv2')

W_fc1 = weight_variable([7 * 7 * 64, 1024], 'wfc1')

b_fc1 = bias_variable([1024], 'bfcl')

W_fc2 = weight_variable([1024, 10], 'wfc2')

b_fc2 = bias_variable([10], 'bfc2')

網(wǎng)絡(luò)的構(gòu)建過程也大同小異。

def conv2d(x, W):

return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):

return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],

strides=[1, 2, 2, 1], padding='SAME')

#first convolutional layer

x_image = tf.reshape(x, [-1,28,28,1])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

h_pool1 = max_pool_2x2(h_conv1)

#second convolutional layer

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)

h_pool2 = max_pool_2x2(h_conv2)

#final layer

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])

h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

卷積運算的唯一不同之處是這里定義了補零,,因此第一次卷積運算的輸出是28x28,,經(jīng)過池化后,降為14x14,。第二次卷積運算和池化之后的結(jié)果降為了7x7,,所以最后一層的輸入是7x7x64 = 3136維,有1024個隱藏節(jié)點(使用relu而不是sigmoid函數(shù)),。(在訓(xùn)練時,,最后一步用到了dropout函數(shù)將模型數(shù)值隨機地置零。如果keep_prob=1則忽略這步操作,。)

當(dāng)TensorFlow遇見CNTK

網(wǎng)絡(luò)訓(xùn)練

CNTK中設(shè)置網(wǎng)絡(luò)模型訓(xùn)練的方式與TensorFlow差別巨大,。訓(xùn)練和測試步驟是在一個convolution.config的文件內(nèi)設(shè)置。CNTK和TensorFlow都是通過符號化分析流程圖來計算梯度下降訓(xùn)練算法中所用到的梯度值,。CNTK組給出了一本非常贊的“書”來闡述梯度是如何計算的?,F(xiàn)階段CNTK只支持一種學(xué)習(xí)方法:Mini-batch隨機梯度下降法,但他們承諾今后加入更多的算法,。He, Zhang, Ren 和 Sun發(fā)表了一篇優(yōu)秀的論文介紹他們是如何用嵌套殘留還原法(nested residual reduction)來訓(xùn)練極度深層(深達(dá)1000層)的網(wǎng)絡(luò)模型,,所以讓我們拭目以待這個方法被融入到CNTK中。配置文件的縮略版如下所示,。

command = train:test

modelPath = '$ModelDir$/02_Convolution'

ndlMacros = '$ConfigDir$/Macros.ndl'

train = [

action = 'train'

NDLNetworkBuilder = [

networkDescription = '$ConfigDir$/02_Convolution.ndl'

]

SGD = [

epochSize = 60000

minibatchSize = 32

learningRatesPerMB = 0.5

momentumPerMB = 0*10:0.7

maxEpochs = 15

]

reader = [

readerType = 'UCIFastReader'

file = '$DataDir$/Train-28x28.txt'

features = [

dim = 784

start = 1

]

labels = [

# details deleted

]

]

]

test = [

….

]

命令行顯示了執(zhí)行的順序:先訓(xùn)練后測試,。先聲明了各種文件的路徑,然后訓(xùn)練模塊設(shè)置了待訓(xùn)練的網(wǎng)絡(luò)模型以及隨機梯度下降(SGD)的參數(shù),。讀取模塊根據(jù)NDL文件中的設(shè)置讀取了“特征”和“標(biāo)簽”數(shù)據(jù),。測試模塊設(shè)置了用于測試的參數(shù)。

16核(沒有GPU)的Linux VM需要消耗62.95分鐘來執(zhí)行訓(xùn)練和測試過程,,999.01分鐘的用戶時間和4分鐘的系統(tǒng)時間,。用戶時間指的是所有16個核都在滿負(fù)荷運轉(zhuǎn)(999/63 = 15.85)。但這并不算什么,因為CNTK是為并行計算而設(shè)計的,,大規(guī)模GPU支持才是真正的設(shè)計點,。

TensorFlow的訓(xùn)練步驟在Python控制流程中設(shè)置得更清晰。而使用的算法Adam也是基于梯度計算的,,由Kingma和Ba發(fā)明,。TensorFlow的函數(shù)庫里有大量基于梯度的優(yōu)化方法,但我沒有嘗試其它的方法,。

如下所以,,cross_entropy是按照標(biāo)準(zhǔn)形式定義的,然后傳入優(yōu)化器生成一個 “train_step”對象,。

y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))

train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))

sess.run(tf.initialize_all_variables)

for i in range(20000):

batch = mnist.train.next_batch(50)

train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print('test accuracy %g'%accuracy.eval(feed_dict={

x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

隨后Python腳本每批處理50條數(shù)據(jù),,以50%的舍棄率執(zhí)行train_step,迭代20000次,。測試步驟在整個測試集上評估準(zhǔn)確率,。

除了巧妙的自動求積分和Adam優(yōu)化器的構(gòu)建,一切都是直截了當(dāng)?shù)?。我?6核的服務(wù)器上用CNTK例子中相同的數(shù)據(jù)集又跑了一遍,。出乎我意料的是所需的時間與CNTK幾乎一模一樣。實際運行時間是62.02分鐘,,用戶時間為160.45分鐘,,所以幾乎沒用利用并行運算。我覺得這些數(shù)字不能說明什么,。CNTK和TensorFlow都是為大規(guī)模GPU運算而設(shè)計的,,它們運行的訓(xùn)練算法并不完全一致。

遞歸神經(jīng)網(wǎng)絡(luò)在CNTK和TensorFlow的實現(xiàn)

遞歸神經(jīng)網(wǎng)絡(luò)(RNNs)在語言建模方面用途廣泛,,例如打字時預(yù)測下一個輸入單詞,,或是用于自動翻譯系統(tǒng)。(更多例子請參見Andrej Karpathy的博客)真是個有趣的想法,。系統(tǒng)的輸入是一個單詞(或者一組單詞)以及系統(tǒng)基于目前所出現(xiàn)單詞而更新的狀態(tài),,輸出的是一個預(yù)測單詞列表和系統(tǒng)的新狀態(tài),如圖1所示,。

當(dāng)TensorFlow遇見CNTK

圖1

當(dāng)然,,RNN還有許多變種形式。其中一種常見的形式是長短期記憶模型(LSTM),,其定義公式如下:

當(dāng)TensorFlow遇見CNTK

圖2:LSTM方程組(來源于CNTKBook)

此處 \sigma 表示sigmoid函數(shù),。

如果你有興趣讀一篇關(guān)于LSTM及其工作原理的博文,我推薦Christopher Olah所寫的這篇,。他繪制了一張示意圖,,使得上面的等式更容易理解。我把它稍作修改,使它符合CNTK版本的方程式,,結(jié)果如下圖所示,。

當(dāng)TensorFlow遇見CNTK

圖3:改編自Christopher Olah的優(yōu)秀文章

圖中使用了sigmoid和tanh函數(shù),并且級聯(lián)變量得到了下面的表達(dá)式:

當(dāng)TensorFlow遇見CNTK

其中W和b是學(xué)習(xí)得到的權(quán)重,。

CNTK版本

下面是為LSTM模型設(shè)置的NDL,。有兩件事需要注意。一個是網(wǎng)絡(luò)模型中使用了一個稱作“PastValue”的延遲操作符直接處理了遞歸的邏輯,,它用到了維度和延遲時間兩個變量,,返回該值的一個副本,。第二件事情是注意W矩陣的處理方式,,它與上面以及圖3中所示的級聯(lián)操作有何區(qū)別。在這里,,它們把屬于x和h的所有W壓入堆棧,,把所有b值也存入堆棧。然后計算一個W*x和一個W*h并求和,,再加上b的值,。然后再使用一個行切分操作符,分別用獨立的sigmoid函數(shù)處理它們,。還需關(guān)注的是針對c的W矩陣都是對角陣,。

LSTMPComponent(inputDim, outputDim, cellDim, inputx, cellDimX2, cellDimX3, cellDimX4) = [

wx = Parameter(cellDimX4, inputDim, init='uniform', initValueScale=1);

b = Parameter(cellDimX4, 1, init='fixedValue', value=0.0);

Wh = Parameter(cellDimX4, outputDim, init='uniform', initValueScale=1);

Wci = Parameter(cellDim, init='uniform', initValueScale=1);

Wcf = Parameter(cellDim, init='uniform', initValueScale=1);

Wco = Parameter(cellDim, init='uniform', initValueScale=1);

dh = PastValue(outputDim, output, timeStep=1);

dc = PastValue(cellDim, ct, timeStep=1);

wxx = Times(wx, inputx);

wxxpb = Plus(wxx, b);

whh = Times(wh, dh);

wxxpbpwhh = Plus(wxxpb,whh)

G1 = RowSlice(0, cellDim, wxxpbpwhh)

G2 = RowSlice(cellDim, cellDim, wxxpbpwhh)

G3 = RowSlice(cellDimX2, cellDim, wxxpbpwhh);

G4 = RowSlice(cellDimX3, cellDim, wxxpbpwhh);

Wcidc = DiagTimes(Wci, dc);

it = Sigmoid (Plus ( G1, Wcidc));

bit = ElementTimes(it, Tanh( G2 ));

Wcfdc = DiagTimes(Wcf, dc);

ft = Sigmoid( Plus (G3, Wcfdc));

bft = ElementTimes(ft, dc);

ct = Plus(bft, bit);

Wcoct = DiagTimes(Wco, ct);

ot = Sigmoid( Plus( G4, Wcoct));

mt = ElementTimes(ot, Tanh(ct));

Wmr = Parameter(outputDim, cellDim, init='uniform', initValueScale=1);

output = Times(Wmr, mt);

]

TensorFlow版本

TensorFlow版本的LSTM遞歸神經(jīng)網(wǎng)絡(luò)模型與CNTK版本完全不同。盡管它們所執(zhí)行的操作符都一樣,,但TensorFlow的表示方式充分發(fā)揮了Python控制流的作用,。這個概念模型非常簡單。我們創(chuàng)建了一個LSTM單元,,并且定義一個“狀態(tài)”作為此單元的輸入,,同時也是此單元的輸出。偽代碼如下所示:

cell = rnn_cell.BasicLSTMCell(lstm_size)

# Initial state of the LSTM memory.

state = tf.zeros([batch_size, lstm.state_size])

for current_batch_of_words in words_in_dataset:

# The value of state is updated after processing each batch of words.

output, state = cell(current_batch_of_words, state)

這段摘自教程的偽代碼版本很好地反映了圖1的內(nèi)容,。折磨人的地方在于微妙細(xì)節(jié)的處理,。記住大部分時間TensorFlow的python代碼是在搭建流程圖,所以我們需要下一點功夫來繪制用于訓(xùn)練和執(zhí)行的循環(huán)流程圖,。

這里最大的挑戰(zhàn)在于如何在一個循環(huán)內(nèi)創(chuàng)建并重復(fù)使用權(quán)重矩陣和偏置向量,。CNTK使用了“PastValue”操作符來創(chuàng)建所需的循環(huán)。TensorFlow則使用了上面提到的所謂遞歸機制,,和一個非常聰明的變量保存和調(diào)用機制來完成同樣的任務(wù),。“PastValue”在TensorFlow中對應(yīng)的是一個函數(shù),, tf.get_variable( “name”, size, initializer = None) ,,它的行為取決于當(dāng)前變量域中的“reuse”這個標(biāo)志位。如果reuse==False而且在當(dāng)時不存在其它的同名變量,那么get_variable 用那個變量名返回一個新的變量,,并用初始化器對其初始化,。否則將會返回錯誤。如果reuse == True,,那么get_variable返回之前已經(jīng)存在的那個變量,。如果不存在這樣的變量,則返回一個錯誤,。

為了演示這種用法,,以下是TensorFlow的一個函數(shù)的簡化版本,用來創(chuàng)建上面等式一的sigmoid函數(shù),。它只是W*x+b 的一個演化版本,,其中x是一個list[a,b,c,…]

def linear(args, output_size, scope=None):

#Linear map: sum_i(args[i] * W[i]), where W[i] is a variable.

with vs.variable_scope(scope):

matrix = vs.get_variable('Matrix', [total_arg_size, output_size])

res = math_ops.matmul(array_ops.concat(1, args), matrix)

bias_term = vs.get_variable(

'Bias', [output_size],

initializer=init_ops.constant_initializer(1.))

return res + bias_term

接下來定義BasicLSTMCell,大致的寫法如下所示,。(想要查看這些函數(shù)的完整版本,,請前往TensorFlow Github代碼庫里的rnn_cell.py腳本。)

class BasicLSTMCell(RNNCell):

def __call__(self, inputs, state, scope=None):

with vs.variable_scope(scope):

c, h = array_ops.split(1, 2, state)

concat = linear([inputs, h], 4 * self._num_units)

i, j, f, o = array_ops.split(1, 4, concat)

new_c = c * sigmoid(f) + sigmoid(i) * tanh(j)

new_h = tanh(new_c) * sigmoid(o)

return new_h, array_ops.concat(1, [new_c, new_h])

你可以看到,,這里相當(dāng)準(zhǔn)確地再現(xiàn)圖3中的圖示,。你會注意到上面的split操作符正是對應(yīng)于CNTK的row slice操作符。

現(xiàn)在我們可以創(chuàng)建一個可以用于訓(xùn)練的遞歸神經(jīng)網(wǎng)絡(luò)模型,,在同樣的變量域我們能用共享的W和b變量創(chuàng)建另一個網(wǎng)絡(luò)模型用于測試,。具體的做法在TensorFlow的遞歸神經(jīng)網(wǎng)絡(luò)教程ptb_word_lm.py腳本中有介紹。還有兩點值得留意,。(應(yīng)該說它們對于我理解這個例子,,有著至關(guān)重要的作用)他們創(chuàng)建一個lstmModel類來訓(xùn)練和測試網(wǎng)絡(luò)模型。

class lstmModel:

def __init__(self, is_training, num_steps):

self._input_data = tf.placeholder(tf.int32, [batch_size, num_steps])

self._targets = tf.placeholder(tf.int32, [batch_size, num_steps])

cell = rnn_cell.BasicLSTMCell(size, forget_bias=0.0)

outputs =

states =

state = self._initial_state

with tf.variable_scope('RNN'):

for time_step in range(num_steps):

if time_step > 0:

tf.get_variable_scope.reuse_variables

(cell_output, state) = cell(inputs[:, time_step, :], state)

outputs.append(cell_output)

states.append(state)

… many details omitted …

我們在主程序中創(chuàng)建一個訓(xùn)練實例和一個測試實例,,并調(diào)用它們(事實上還要創(chuàng)建一個實例,,為了簡化過程我暫時先把它忽略)。

with tf.variable_scope('model', reuse=None, initializer=initializer):

m = PTBModel(is_training=True, 20)

with tf.variable_scope('model', reuse=True, initializer=initializer):

mtest = PTBModel(is_training=False, 1)

在上述代碼中,,創(chuàng)建了實例m,,初始化設(shè)置20步且不用reuse。從初始化這一步你能觀察到,,在計算流程圖中該單元被展開成20個副本,,并且在首次迭代后reuse標(biāo)志置為True,此時所有的實例都將共享同一組W和b,。訓(xùn)練過程在這個展開的版本上完成,。第二個版本mtest設(shè)置reuse=True,且在圖中只有該單元的一個實例,。但是變量域和m相同,,因此它與m共享同一組訓(xùn)練得到的變量,。

一旦訓(xùn)練完成,我們可以用一個內(nèi)核來調(diào)用這個網(wǎng)絡(luò)模型,。

cost, state = sess.run([mtest.cost, mtest.final_state],

{mtest.input_data: x,

mtest.targets: y,

mtest.initial_state: state})

x和y是輸入變量,。這和教程示例中的完整過程相去甚遠(yuǎn)。舉個例子,,我完全沒有深入到訓(xùn)練過程的細(xì)節(jié)中去,,完整的示例使用了stacked LSTM并設(shè)置了dropout的比例。我的希望是,,我在此羅列的細(xì)節(jié)將有助于讀者了解代碼的最基本結(jié)構(gòu),。

總結(jié)

我對兩個系統(tǒng)的編程模型做了比較。這里是一些頂層的想法,。

1. TensorFlow和CNTK在卷積神經(jīng)網(wǎng)絡(luò)那個簡單例子中的做法非常相似,。然而,我發(fā)現(xiàn)tensorflow版本更容易進行實驗,,因為它是由Python驅(qū)動的,。我能用IPython notebook加載它并做一些其它嘗試,。而CNTK則需要用戶完全理解如何用配置文件表達(dá)想法,。我覺得這很困難。我用TensorFlow能很容易寫一個簡單的k-means聚類算法(詳見我之前關(guān)于TensorFlow的文章),。我卻無法用CNTK來實現(xiàn),,不過這可能是由于我的無知,而不是CNTK的局限性,。如果有人能提示我該怎么做,,我會很感激的)。

2. 在LSTM遞歸神經(jīng)網(wǎng)絡(luò)的例子里,,我發(fā)現(xiàn)CNTK的版本相當(dāng)?shù)耐该?。我發(fā)現(xiàn)TensorFlow版本的頂層想法非常優(yōu)雅,但我也發(fā)現(xiàn)想了解它的所有細(xì)節(jié)卻非常困難,,因為涉及到了變量作用域和變量共享的巧妙用法,。我不得不深入地了解它的工作原理。但到現(xiàn)在我也不是十分清楚,!我在TensorFlow版本里確實發(fā)現(xiàn)了一個微小但很容易修復(fù)的bug,,而且我不相信變量作用域和reuse標(biāo)志是解決封裝問題的最好方法。但是TensorFlow的好處在于我能很容易地修改實驗,。

3. 我也必須說CNTK書和TensorFlow教程都是優(yōu)秀入門級讀物,。我相信有更多詳細(xì)的、深入的書馬上就會面世,。

我也相信,,隨著兩個系統(tǒng)的不斷成熟,,它們都會有改進,并且能更容易地使用,。我在此不討論性能問題,,但CNTK目前在解決某些挑戰(zhàn)難題的速度方面略勝一籌。但隨著這些系統(tǒng)的快速發(fā)展,,我希望看到競爭也隨之升溫,。

原文:TensorFlow Meets Microsoft’s CNTK

作者:Dennis Gannon(MSR退休數(shù)據(jù)科學(xué)家,印第安納大學(xué)計算機科學(xué)榮譽退休教授)

譯者:趙屹華 審校:劉翔宇

責(zé)編:周建?。ㄍ陡逭埪?lián)系[email protected],,優(yōu)稿優(yōu)酬)

想了解IT產(chǎn)品研發(fā)背后的那些人、技術(shù)和故事,,請關(guān)注CSDN(資訊)微信公眾號:CSDNnews

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多