選自Stanford 作者:李飛飛等 機(jī)器之心編譯 參與:Smith 斯坦福大學(xué)的課程 CS231n (Convolutional Neural Networks for Visual Recognition) 作為深度學(xué)習(xí)和計算機(jī)視覺方面的重要基礎(chǔ)課程,在學(xué)界廣受推崇。今年 4 月,CS231n 再度開課,全新的 CS231n Spring 2017 仍舊由李飛飛帶頭,帶來了很多新鮮的內(nèi)容。今天機(jī)器之心給大家分享的是其中的第八講——深度學(xué)習(xí)軟件(Deep Learning Software)。主要內(nèi)容有:CPU 和 GPU 的對比;深度學(xué)習(xí)框架簡介;TensorFlow 和 PyTorch 的實(shí)例;以及各種深度學(xué)習(xí)框架的比較。 一、 CPU 和 GPU CPU:核芯的數(shù)量更少; 但是每一個核芯的速度更快,性能更強(qiáng); 更適用于處理連續(xù)性(sequential)任務(wù)。 GPU:核芯的數(shù)量更多; 但是每一個核芯的處理速度較慢; 更適用于并行(parallel)任務(wù)。 二、深度學(xué)習(xí)框架簡介 去年我們還僅有 Caffe、Torch、Theano 和 TensorFlow 這些深度學(xué)習(xí)框架可供使用;但是到了今年,在此基礎(chǔ)上我們又新增加了 Caffe2、Pytorch、TensorFlow、PaddlePaddle、 CNDK、MXNet 等等一系列新的框架,可謂「百花齊放」。如今最常用的框架當(dāng)數(shù) Pytorch 和 TensorFlow 了, 而 Caffe 和 Caffe2 次之。 深度學(xué)習(xí)框架的關(guān)鍵點(diǎn)在于: (1)易于建造大型的計算機(jī)圖形; (2)易于在計算機(jī)圖形中進(jìn)行梯度計算; (3)能在 GPU 上高效運(yùn)行(cuDNN, cuBLA 等) 三、TensorFlow 簡單實(shí)例 下面我們將詳細(xì)說明一個在 TensorFlow 下訓(xùn)練神經(jīng)網(wǎng)絡(luò)的簡單實(shí)例:即用隨機(jī)數(shù)據(jù)訓(xùn)練一個兩層的網(wǎng)絡(luò),激活函數(shù)為 ReLU。 a. 定義計算機(jī)圖形: 1. 為輸入 x,權(quán)重系數(shù) w1、w2, 和目標(biāo)函數(shù) y 創(chuàng)建 placeholder: 2. 定義前向傳輸:這是為了計算 y 的預(yù)測值和誤差損失(loss);實(shí)際上這里是沒有計算過程的——僅僅是為了創(chuàng)建圖形! 3. 告訴 Tensorflow 去計算關(guān)于 w1 和 w2 的梯度損失;這里仍然不產(chǎn)生計算過程——僅僅是為了創(chuàng)建圖形。 b. 運(yùn)行 現(xiàn)在已經(jīng)完成了創(chuàng)建圖形的步驟,所以我們進(jìn)入對圖形進(jìn)行運(yùn)算的部分。 創(chuàng)建 Numpy 數(shù)組,這個數(shù)組將會被填進(jìn)上方的 placeholder 中。 對圖形進(jìn)行運(yùn)算:將 x、y、w1、w2 輸入到 numpy 數(shù)組中;得到關(guān)于損失(loss),w1 梯度和 w2 梯度的 numpy 數(shù)組。 訓(xùn)練網(wǎng)絡(luò):反復(fù)對圖形進(jìn)行運(yùn)算,用梯度(gradient)來更新權(quán)重(weights)。 把 w1 和 w2 的相應(yīng)函數(shù)從 placeholder() 改為 Variable()。 添加 assign 操作來更新 w1 和 w2(圖形的一部分)。 對圖形進(jìn)行一次運(yùn)算來初始化 w1 和 w2,然后進(jìn)行多次迭代訓(xùn)練。 完整代碼如下: 但是產(chǎn)生一個問題:誤差損失(loss)并沒有下降!這是因為 Assign 指令實(shí)際上并沒有被執(zhí)行。 這時我們就需要添加虛擬圖形節(jié)點(diǎn),并且告訴圖形去計算虛擬節(jié)點(diǎn)。 可以使用 optimizer 來計算梯度和更新權(quán)重系數(shù);記得要執(zhí)行 optimizer 的輸出! 使用預(yù)先定義的常用損失函數(shù): 使用 Xavier 進(jìn)行初始化;tf.layer 會自動設(shè)置權(quán)重系數(shù)(weight)和偏置項(bias)! c. 高級 Wrapper——Keras Keras 可以理解為是一個在 TensorFlow 頂部的 layer,它可以讓一些工作變得更加簡單(也支持 Theano 后端)。 把模型目標(biāo)定義成一系列的 layer : 定義優(yōu)化器目標(biāo)(optimizer object): 創(chuàng)建模型,明確規(guī)定損失函數(shù)(loss function): 僅用一行代碼就能訓(xùn)練模型! 除了 Keras, 還有一些其他類型的高級容器(Wrapper)可供使用: 四、PyTorch 實(shí)例 PyTorch 是 Facebook 推出的深度學(xué)習(xí)框架,不論是在工業(yè)界還是學(xué)術(shù)界,它都得到了廣泛的應(yīng)用。它包括三個等級的抽象概念:
PyTorch 和 TensorFlow 中抽象概念的等價對應(yīng)關(guān)系: a. Pytorch 中的張量(Tensor)設(shè)置 PyTorch 中的張量就像 numpy 中的數(shù)組,但是這些張量可以在 GPU 上運(yùn)行; 這里我們用 PyTorch 的張量設(shè)置了一個兩層網(wǎng)絡(luò): 下面我們來分步解讀: 1. 為數(shù)據(jù)和權(quán)重(weights)創(chuàng)建隨機(jī)張量: 2. 設(shè)置前向傳播:計算預(yù)測值(prediction)和損失(loss): 3. 設(shè)置反向傳播:計算梯度(gradients): 4. 梯度下降(Gradient descent)和權(quán)重(weights)相對應(yīng): 5. 為了在 GPU 上運(yùn)行,將張量(tensors)設(shè)置為 cuda 數(shù)據(jù)類型: b. PyTorch 中的 Autogradient 設(shè)置 PyTorch 的張量(Tensors)和變量(Variables)擁有相同的應(yīng)用編程接口 API。變量(Variables)可以記憶它們是怎么產(chǎn)生的(因為反向傳播的緣故)。 下面仍進(jìn)行分步解讀: 1. 我們不希望(損失 loss 的)梯度和數(shù)據(jù)(data)有相關(guān)性,但我們希望梯度和權(quán)重(weights)是相關(guān)的。相關(guān)設(shè)置如圖: 2. 這里的前向傳播看上去和上述張量(Tensor)的對應(yīng)版本很相似,但是需要注意的是現(xiàn)在這里全部都是變量(variable)。 3. 計算損失函數(shù)對 w1 和 w2 的梯度(開始的時候梯度置零): 4. 讓梯度和權(quán)重(weights)相對應(yīng): C. 定義新型 Autograd 函數(shù) 通過張量的前向和反向傳播來定義你自己的 autograd 函數(shù): 可以在前向傳播中使用新的 autograd 函數(shù): d. PyTorch 中的神經(jīng)網(wǎng)絡(luò)(nn)設(shè)置 用更高級的「容器」(wrapper)來處理神經(jīng)網(wǎng)絡(luò)(neural nets), 和 Keras 相似。完整代碼如下: 下面進(jìn)行分步解讀: 把我們的模型定義成一系列的 layers: 也要定義常用損失函數(shù): 前向傳播:給模型輸入數(shù)據(jù);給損失函數(shù)(loss function)輸入預(yù)測信息(prediction): 反向傳播:計算所有的梯度(gradients): 讓梯度和每一個模型參數(shù)對應(yīng): 下面我們添加一個優(yōu)化器(optimizer): 在計算完梯度以后對所有的參數(shù)(parameters)進(jìn)行更新: E. PyTorch 中的神經(jīng)網(wǎng)絡(luò)——定義新的模型 Pytorch 中的模塊(Module)其實(shí)是一個神經(jīng)網(wǎng)絡(luò)層(neural net layer),需要注意它的輸入和輸出都是變量;模塊(Module)中包含著權(quán)重 (當(dāng)作變量處理) 或者其他模塊;你可以使用 autograd 來定義你自己的模塊。詳細(xì)代碼如下: 下面進(jìn)行分步解讀: 1. 把我們的整體模型定義成一個單一的模塊: 2. 用初始化程序來設(shè)置兩個子模塊(一個父模塊可以包含子模塊) 3. 用子模塊和變量上的 autograd ops 定義前向傳播;不需要定義反向傳播——因為 autograd 會作相應(yīng)處理: 4. 創(chuàng)建并訓(xùn)練一個模型實(shí)例: E. PyTorch 中的資料存儲器(Dataloaders) 資料存儲器(DataLoader)包括一個數(shù)據(jù)集 (Dataset),而且給你提供了小批量處理(minibatching),「洗牌」處理(shuffling)和多線程處理(multithreading);當(dāng)你需要載入自定義數(shù)據(jù)(custom data)時,寫下你自己的數(shù)據(jù)集類型(dataset class)就可以了。 通過遍歷存儲器(loader)來形成小批量(minibatch);存儲器會給你提供張量(Tensors), 所以你需要將其「打包」(wrap)進(jìn)變量中: 注意:使用帶有 torchvision 的預(yù)先訓(xùn)練好的模型(pretrained model)將會更加簡單易行。 F. Torch 和 pytorch 的簡單對比 結(jié)論:盡量使用 PyTorch 來做你的新項目。 五、Caffe2 簡介 六、深度學(xué)習(xí)框架之爭,究竟誰更勝一籌? 其實(shí)具體選擇何種框架來進(jìn)行深度學(xué)習(xí)取決于我們要做什么。在參閱相關(guān)文獻(xiàn)之后,我們大致可以得出以下結(jié)論(僅供參考):
附參考文獻(xiàn)(斯坦福課程 CS231n; 以及港中文課程 ELEG5491):
|
|