1. 程式人生 > >mxnet:結合R與GPU加速深度學習

mxnet:結合R與GPU加速深度學習

轉載於統計之都,http://cos.name/tag/dmlc/,作者陳天奇

————————————————————————————————————————————————————————————

Matt︱R語言呼叫深度學習架構系列引文


近年來,深度學習可謂是機器學習方向的明星概念,不同的模型分別在影象處理與自然語言處理等任務中取得了前所未有的好成績。在實際的應用中,大家除了關心模型的準確度,還常常希望能比較快速地完成模型的訓練。一個常用的加速手段便是將模型放在GPU上進行訓練。然而由於種種原因,R語言似乎缺少一個能夠在GPU上訓練深度學習模型的程式包。

DMLC(Distributed (Deep) Machine Learning Community)是由一群極客發起的組織,主要目標是提供快速高質量的開源機器學習工具。近來流行的boosting模型xgboost便是出自這個組織。最近DMLC開源了一個深度學習工具mxnet,這個工具含有R,python,julia等語言的介面。本文以R介面為主,向大家介紹這個工具的效能與使用方法。

一、五分鐘入門指南

在這一節裡,我們在一個樣例資料上介紹mxnet的基本使用方法。目前mxnet還沒有登入CRAN的計劃,所以安裝方法要稍微複雜一些。

  • 如果你是Windows/Mac使用者,那麼可以通過下面的程式碼安裝預編譯的版本。這個版本會每週進行預編譯,不過為了保證相容性,只能使用CPU訓練模型。
install.packages("drat", repos="https://cran.rstudio.com")
drat:::addRepo("dmlc")
install.packages("mxnet")
  • 如果你是Linux使用者或者想嘗試GPU版本,請參考這個連結裡的詳細編譯教程在本地進行編譯。

安裝完畢之後,我們就可以開始訓練模型了,下面兩個小節分別介紹兩種不同的訓練神經網路的方法。

二分類模型與mx.mlp

首先,我們準備一份資料,並進行簡單的預處理:

require(mlbench)
require(mxnet)
data(Sonar, package="mlbench")
Sonar[,61] = as.numeric(Sonar[,61])-1
train.ind = c(1:50, 100:150)
train.x = data.matrix(Sonar[train.ind, 1:60])
train.y = Sonar[train.ind, 61]
test.x = data.matrix(Sonar[-train.ind, 1:60])
test.y = Sonar[-train.ind, 61
]

我們借用mlbench包中的一個二分類資料,並且將它分成訓練集和測試集。mxnet提供了一個訓練多層神經網路的函式mx.mlp,我們額可以通過它來訓練一個神經網路模型。下面是mx.mlp中的部分引數:

  • 訓練資料與預測變數
  • 每個隱藏層的大小
  • 輸出層的結點數
  • 啟用函式型別
  • 損失函式型別
  • 進行訓練的硬體(CPU還是GPU)
  • 其他傳給mx.model.FeedForward.create的高階引數

瞭解了大致引數後,我們就可以理解並讓R執行下面的程式碼進行訓練了。

mx.set.seed(0)
model <- mx.mlp(train.x, train.y, hidden_node=10, out_node=2,      out_activation="softmax", num.round=20, array.batch.size=15, learning.rate=0.07, momentum=0.9, eval.metric=mx.metric.accuracy)
## Auto detect layout of input matrix, use rowmajor..
## Start training with 1 devices
## [1] Train-accuracy=0.488888888888889
## [2] Train-accuracy=0.514285714285714
## [3] Train-accuracy=0.514285714285714

...

## [18] Train-accuracy=0.838095238095238
## [19] Train-accuracy=0.838095238095238
## [20] Train-accuracy=0.838095238095238

這裡要注意使用mx.set.seed而不是R自帶的set.seed函式來控制隨機數。因為mxnet的訓練過程可能會執行在不同的運算硬體上,我們需要一個足夠快的隨機數生成器來管理整個隨機數生成的過程。模型訓練好之後,我們可以很簡單地進行預測:

preds = predict(model, test.x)
## Auto detect layout of input matrix, use rowmajor..
pred.label = max.col(t(preds))-1
table(pred.label, test.y)
##           test.y
## pred.label  0  1
##          0 24 14
##          1 36 33

如果進行的是多分類預測,mxnet的輸出格式是類數X樣本數。

迴歸模型與自定義神經網路

mx.mlp介面固然很方便,但是神經網路的一大特點便是它的靈活性,不同的結構可能有著完全不同的特性。mxnet的亮點之一便是它賦予了使用者極大的自由度,從而可以任意定義需要的神經網路結構。我們在這一節用一個簡單的迴歸任務介紹相關的語法。

首先,我們仍然要準備好一份資料。

data(BostonHousing, package="mlbench")

train.ind = seq(1, 506, 3)
train.x = data.matrix(BostonHousing[train.ind, -14])
train.y = BostonHousing[train.ind, 14]
test.x = data.matrix(BostonHousing[-train.ind, -14])
test.y = BostonHousing[-train.ind, 14]

mxnet提供了一個叫做“Symbol”的系統,從而使我們可以定義結點之間的連線方式與啟用函式等引數。下面是一個定義沒有隱藏層神經網路的簡單例子:

# 定義輸入資料
data <- mx.symbol.Variable("data")
# 完整連線的隱藏層
# data: 輸入源
# num_hidden: 該層的節點數
fc1 <- mx.symbol.FullyConnected(data, num_hidden=1)

# 針對迴歸任務,定義損失函式
lro <- mx.symbol.LinearRegressionOutput(fc1)

在神經網路中,迴歸與分類的差別主要在於輸出層的損失函式。這裡我們使用了平方誤差來訓練模型。希望能更進一步瞭解Symbol的讀者可以繼續閱讀這兩份分別以程式碼配圖為主的文件。

定義了神經網路之後,我們便可以使用mx.model.FeedForward.create進行訓練了。

mx.set.seed(0)
model <- mx.model.FeedForward.create(lro, X=train.x, y=train.y, ctx=mx.cpu(), num.round=50, array.batch.size=20, learning.rate=2e-6, momentum=0.9, eval.metric=mx.metric.rmse)
## Auto detect layout of input matrix, use rowmajor..
## Start training with 1 devices
## [1] Train-rmse=16.063282524034
## [2] Train-rmse=12.2792375712573
## [3] Train-rmse=11.1984634005885

...

## [48] Train-rmse=8.26890902770415
## [49] Train-rmse=8.25728089053853
## [50] Train-rmse=8.24580511500735

這裡我們還針對迴歸任務修改了eval.metric引數。目前我們提供的評價函式包括”accuracy”,”rmse”,”mae” 和 “rmsle”,使用者也可以針對需要自定義評價函式,例如:

demo.metric.mae <- mx.metric.custom("mae", function(label, pred) {
  res <- mean(abs(label-pred))
  return(res)
})
mx.set.seed(0)
model <- mx.model.FeedForward.create(lro, X=train.x, y=train.y, ctx=mx.cpu(), num.round=50, array.batch.size=20, learning.rate=2e-6, momentum=0.9, eval.metric=demo.metric.mae)
## Auto detect layout of input matrix, use rowmajor..
## Start training with 1 devices
## [1] Train-mae=13.1889538083225
## [2] Train-mae=9.81431959337658
## [3] Train-mae=9.21576419870059

...

## [48] Train-mae=6.41731406417158
## [49] Train-mae=6.41011292926139
## [50] Train-mae=6.40312503493494

至此,你已經掌握了基本的mxnet使用方法。接下來,我們將介紹更好玩的應用。

二、手寫數字競賽

在這一節裡,我們以Kaggle上的手寫數字資料集(MNIST)競賽為例子,介紹如何通過mxnet定義一個強大的神經網路,並在GPU上快速訓練模型。

第一步,我們從Kaggle上下載資料,並將它們放入data/資料夾中。然後我們讀入資料,並做一些預處理工作。

require(mxnet)
train <- read.csv('data/train.csv', header=TRUE) 
test <- read.csv('data/test.csv', header=TRUE) 
train <- data.matrix(train) 
test <- data.matrix(test) 

train.x <- train[,-1] 
train.y <- train[,1]

train.x <- t(train.x/255)
test <- t(test/255)

最後兩行預處理的作用有兩個:

  • 原始灰度圖片數值處在[0,255]之間,我們將其變換到[0,1]之間。
  • mxnet接受 畫素X圖片 的輸入格式,所以我們對輸入矩陣進行了轉置。

接下來我們定義一個特別的神經網路結構:LeNet。這是Yann LeCun提出用於識別手寫數字的結構,也是最早的卷積神經網路之一。同樣的,我們使用Symbol語法來定義,不過這次結構會比較複雜。

# input
data <- mx.symbol.Variable('data')
# first conv
conv1 <- mx.symbol.Convolution(data=data, kernel=c(5,5), num_filter=20)
tanh1 <- mx.symbol.Activation(data=conv1, act_type="tanh")
pool1 <- mx.symbol.Pooling(data=tanh1, pool_type="max",
                          kernel=c(2,2), stride=c(2,2))
# second conv
conv2 <- mx.symbol.Convolution(data=pool1, kernel=c(5,5), num_filter=50)
tanh2 <- mx.symbol.Activation(data=conv2, act_type="tanh")
pool2 <- mx.symbol.Pooling(data=tanh2, pool_type="max",
                          kernel=c(2,2), stride=c(2,2))
# first fullc
flatten <- mx.symbol.Flatten(data=pool2)
fc1 <- mx.symbol.FullyConnected(data=flatten, num_hidden=500)
tanh3 <- mx.symbol.Activation(data=fc1, act_type="tanh")
# second fullc
fc2 <- mx.symbol.FullyConnected(data=tanh3, num_hidden=10)
# loss
lenet <- mx.symbol.SoftmaxOutput(data=fc2)

為了讓輸入資料的格式能對應LeNet,我們要將資料變成R中的array格式:

train.array <- train.x
dim(train.array) <- c(28, 28, 1, ncol(train.x))
test.array <- test
dim(test.array) <- c(28, 28, 1, ncol(test))

接下來我們將要分別使用CPU和GPU來訓練這個模型,從而展現不同的訓練效率。

n.gpu <- 1
device.cpu <- mx.cpu()
device.gpu <- lapply(0:(n.gpu-1), function(i) {
  mx.gpu(i)
})

我們可以將GPU的每個核以list的格式傳遞進去,如果有BLAS等自帶矩陣運算並行的庫存在,則沒必要對CPU這麼做了。

我們先在CPU上進行訓練,這次我們只進行一次迭代:

mx.set.seed(0)
tic <- proc.time()
model <- mx.model.FeedForward.create(lenet, X=train.array, y=train.y, ctx=device.cpu, num.round=1, array.batch.size=100, learning.rate=0.05, momentum=0.9, wd=0.00001, eval.metric=mx.metric.accuracy, epoch.end.callback=mx.callback.log.train.metric(100))
## Start training with 1 devices
## Batch [100] Train-accuracy=0.1066
## Batch [200] Train-accuracy=0.16495
## Batch [300] Train-accuracy=0.401766666666667
## Batch [400] Train-accuracy=0.537675
## [1] Train-accuracy=0.557136038186157
print(proc.time() - tic)
##    user  system elapsed
## 130.030 204.976  83.821

在CPU上訓練一次迭代一共花了83秒。接下來我們在GPU上訓練5次迭代:

mx.set.seed(0)
tic <- proc.time()
model <- mx.model.FeedForward.create(lenet, X=train.array, y=train.y, ctx=device.gpu, num.round=5, array.batch.size=100, learning.rate=0.05, momentum=0.9, wd=0.00001, eval.metric=mx.metric.accuracy, epoch.end.callback=mx.callback.log.train.metric(100))
## Start training with 1 devices
## Batch [100] Train-accuracy=0.1066
## Batch [200] Train-accuracy=0.1596
## Batch [300] Train-accuracy=0.3983
## Batch [400] Train-accuracy=0.533975
## [1] Train-accuracy=0.553532219570405
## Batch [100] Train-accuracy=0.958
## Batch [200] Train-accuracy=0.96155
## Batch [300] Train-accuracy=0.966100000000001
## Batch [400] Train-accuracy=0.968550000000003
## [2] Train-accuracy=0.969071428571432
## Batch [100] Train-accuracy=0.977
## Batch [200] Train-accuracy=0.97715
## Batch [300] Train-accuracy=0.979566666666668
## Batch [400] Train-accuracy=0.980900000000003
## [3] Train-accuracy=0.981309523809527
## Batch [100] Train-accuracy=0.9853
## Batch [200] Train-accuracy=0.985899999999999
## Batch [300] Train-accuracy=0.986966666666668
## Batch [400] Train-accuracy=0.988150000000002
## [4] Train-accuracy=0.988452380952384
## Batch [100] Train-accuracy=0.990199999999999
## Batch [200] Train-accuracy=0.98995
## Batch [300] Train-accuracy=0.990600000000001
## Batch [400] Train-accuracy=0.991325000000002
## [5] Train-accuracy=0.991523809523812
print(proc.time() - tic)
##    user  system elapsed
##   9.288   1.680   6.889

在GPU上訓練5輪迭代只花了不到7秒,快了數十倍!可以看出,對於這樣的網路結構,GPU的加速效果是非常顯著的。有了快速訓練的辦法,我們便可以很快的做預測,並且提交到Kaggle上了:

preds <- predict(model, test.array)
pred.label <- max.col(t(preds)) - 1
submission <- data.frame(ImageId=1:ncol(test), Label=pred.label)
write.csv(submission, file='submission.csv', row.names=FALSE, quote=FALSE)

三、影象識別應用

其實對於神經網路當前的應用場景而言,識別手寫數字已經不夠看了。早些時候,Google公開了一個雲API,讓使用者能夠檢測一幅影象裡面的內容。現在我們提供一個教程,讓大家能夠自制一個影象識別的線上應用。

DMLC用在ImageNet資料集上訓練了一個模型,能夠直接拿來對真實圖片進行分類。同時,我們搭建了一個Shiny應用,只需要不超過150行R程式碼就能夠自己在瀏覽器中進行影象中的物體識別。

為了搭建這個應用,我們要安裝shiny和imager兩個R包:

install.packages("shiny", repos="https://cran.rstudio.com")
install.packages("imager", repos="https://cran.rstudio.com")

現在你已經配置好了mxnet, shiny和imager三個R包,最困難的部分已經完成了!下一步則是讓shiny直接下載並執行我們準備好的程式碼:

shiny::runGitHub("thirdwing/mxnet_shiny")

第一次執行這個命令會花上幾分鐘時間下載預先訓練好的模型。訓練的模型是Inception-BatchNorm Network,如果讀者對它感興趣,可以閱讀這篇文章。準備就緒之後,你的瀏覽器中會出現一個網頁應用,就用本地或線上圖片來挑戰它吧!

如果你只需要一個影象識別的模組,那麼我們下面給出最簡單的一段R程式碼讓你能進行影象識別。首先,我們要匯入預訓練過的模型檔案:

model <<- mx.model.load("Inception/Inception_BN", iteration = 39)
synsets <<- readLines("Inception/synset.txt")
mean.img <<- as.array(mx.nd.load("Inception/mean_224.nd")[["mean_img"]])

接下來我們使用一個函式對影象進行預處理,這個步驟對於神經網路模型而言至關重要。

preproc.image <- function(im, mean.image) {
  # crop the image
  shape <- dim(im)
  short.edge <- min(shape[1:2])
  yy <- floor((shape[1] - short.edge) / 2) + 1
  yend <- yy + short.edge - 1
  xx <- floor((shape[2] - short.edge) / 2) + 1
  xend <- xx + short.edge - 1
  croped <- im[yy:yend, xx:xend,,]
  # resize to 224 x 224, needed by input of the model.
  resized <- resize(croped, 224, 224)
  # convert to array (x, y, channel)
  arr <- as.array(resized)
  dim(arr) = c(224, 224, 3)
  # substract the mean
  normed <- arr - mean.img
  # Reshape to format needed by mxnet (width, height, channel, num)
  dim(normed) <- c(224, 224, 3, 1)
  return(normed)
}

最後我們讀入影象,預處理與預測就可以了。

im <- load.image(src)
normed <- preproc.image(im, mean.img)
prob <- predict(model, X = normed)
max.idx <- order(prob[,1], decreasing = TRUE)[1:5]
result <- synsets[max.idx]

四、參考資料

MXNet是一個在底層與介面都有著豐富功能的軟體,如果讀者對它感興趣,可以參考一些額外的材料來進一步瞭解MXNet,或者是深度學習這個領域。


相關推薦

mxnet結合RGPU加速深度學習

轉載於統計之都,http://cos.name/tag/dmlc/,作者陳天奇————————————————————————————————————————————————————————————Matt︱R語言呼叫深度學習架構系列引文近年來,深度學習可謂是機器學習方向的明

GPU加速深度學習: Windows安裝CUDA+TensorFlow教程

***根據讀者反饋,Python 3.6可用*** ***軟體安裝有時效性,如果安裝失敗請參考評論區反饋*** ***請勿私信問我為什麼“XXX安裝失敗”,我也不知道*** ***精力有限,本文不再繼續更新*** 0.背景 在的Windows上使用GPU進行深度學習

技巧結合ZabbixSNMP監控嵌入式設備

定義 監控主機 name 如果 情況 完整 默認 監控服務 列表 在如何利用Zabbix監控網絡設備三篇文章的前兩篇中,我們介紹了如何通過Zabbix代理監控網絡設備。但有些設備無法安裝Zabbix代理,需要采用其他方法監控。需要考慮無法安裝軟件的嵌入式設備或應用程序。對於

創世資本李榮彬區塊鏈物聯網深度捆綁才能落地丨筱靜觀察

(嘉賓李榮彬) 創世資本管理合夥人; 南京大學計算機與金融雙學位,滑鐵盧大學商學碩士學位; 曾任中地海外集團助理總裁,分管集團投資與諮詢業務; 擅長研究區塊鏈專案的Token經濟體設計,並主導孵化了2018年上半年度全球最受矚目專案之一——積木雲BlockCl

深度 | ICCV研討會實時SLAM的未來以及深度學習SLAM的比較(附論文和PPT)

選自 Computer Vison Blog 作者:Tomasz Malisiewicz 機器之心編譯 參與:吳攀、杜夏德 深度學習、計算機視覺和演算法正在塑造人工智慧的未來。 上一屆「國際計算機視覺大會(ICCV:International Con

啟用Docker虛擬機器GPU加速深度學習

關於環境配置的文章可以算得上是月經貼了,隨便上網一搜,就有大把的文章。但我覺得還是有必要記錄一下我最近一次的深度學習環境配置,主要原因在於各種軟體在快速更新,對應的安裝配置方法也會有一些變化。 這篇深度學習環境配置有兩個關鍵詞,一個是Docker虛擬機

ICCV研討會實時SLAM的未來以及深度學習SLAM的比較

轉載宣告:本文轉載自  金木炎 的部落格http://blog.csdn.net/qq_18661939/article/details/51919329,僅供個人學習。感謝博主的無私分享,如有侵權,敬請告知。這篇短文寫的很好,我把它copy到這裡供大家學習上一屆「國際計算機

如何使用GPU雲主機加速深度學習計算

最近深度學習十分火爆,作為一個程式設計師當然要多學習一下深度學習這種酷炫的新技能啦。現在Google的Tensorflow已經把深度學習需要的一些常用計算封裝成了函式庫,已經成為了事實上的深度計算標準。本來想在自己的電腦上跑一下Tensorflow的mnist手寫數字識別de

MATLAB上的GPU加速計算——學習筆記 (2014-12-22 04:44:05)

轉自:http://blog.sina.com.cn/s/blog_6f062c360102v9ic.html   MATLAB可謂工程計算中的神器,一方面它自帶豐富的函式庫,另一方面它所有的資料都是內建的矩陣型別,最後畫圖也方便,因此解決一些小規模的計算問題如果對效能要求不高的話

利用Google免費GPU深度學習模型

還在為電腦沒有很好的GPU而煩惱麼,這個教程教你隨時利用Colab中的Tesla K80顯示卡跑深度學習模型 先從價格上感受下Tesla K80 首先想體驗Colab,必須先學會科學上網,可以利用VPS買國外結點的伺服器,利用Shadowsockes搭梯子,具體教程可以參考其他博主,在此不做贅述。

TensorRT加速深度學習線上部署

本次的分享主要分為兩部分: 一、TensorRT理論介紹:基礎介紹TensorRT是什麼;做了哪些優化;為什麼在有了框架的基礎上還需要TensorRT的優化引擎。 二、TensorRT高階介紹:對於進階的使用者,出現TensorRT不支援的網路層該如何處理;低精度運算如fp16,大家也知道

深度學習第一步windows+Anaconda下安裝tensorflow深度學習框架

一共四步,一會就成功! 第一步,首先需要安裝Anaconda。 它是一個庫管理工具,能夠管理不同環境,不同環境下可以安裝不同python版本以及其他庫。安裝Anaconda這一步非常的簡單去Anaconda官方網站(https://www.continuum.

結合了機器視覺和深度學習的人工智慧相機

相機對於我們來說並有什麼好奇,到處都有非常普及。其中一個原因是晶片規模擴大,半導體制造商的關鍵部件允許裝置製造商製造1/4尺寸的相機,這種攝像頭在農業、汽車和工業市場上越來越普遍。 現在,機器視覺相機制造商正在以影象處理的形式增加智慧功能,根據一家供應商的說法,這種功能將機

有無GPU執行深度學習mnist資料集時間對比

#硬體配置 *本人用的是 lenovo小新銳7000筆記本,cpu是intel -core -i5-7300Q 四核,記憶體4G,機械硬碟320G,雙顯示卡,整合intel® HD Graphics630 獨顯 GeForce GTX 1050,這塊顯示卡位寬1

【Dongdong Bai's Blogs】研究方向計算機視覺、SLAM、深度學習、機器學習

Dongdong Bai 2013年9月至今在國防科技大學計算機學院攻讀博士學位,師從天河一號超級計算機總設計師楊學軍院士。我目前研究方向是將深度學習技術融入到機器人和自動駕駛汽車中。研究興趣主要包括CNN、計算機視覺、SLAM和機器學習等。我目前在騰訊 AI Lab 作基礎研究

如何使用google drive的免費GPU進行深度學習

最近想玩一玩深度學習,需要訓練一些 yolo 之類的網路進行物件檢測,苦於我的本子沒有獨顯又沒有實驗室的機器給用,想起之前看到的 google 提供免費 GPU 用來學習的訊息,就嘗試一下。 利用Jupyter Notebook測試Google Drive的GP

Deep Learning 12_深度學習UFLDL教程Sparse Coding_exercise(斯坦福大學深度學習教程)

前言 實驗環境:win7, matlab2015b,16G記憶體,2T機械硬碟 本節實驗比較不好理解也不好做,我看很多人最後也沒得出好的結果,所以得花時間仔細理解才行。 實驗內容:Exercise:Sparse Coding。從10張512*512的已經白化後的灰度影象(即:Deep Learnin

Deep Learning 6_深度學習UFLDL教程Softmax Regression_Exercise(斯坦福大學深度學習教程)

前言      練習內容:Exercise:Softmax Regression。完成MNIST手寫數字資料庫中手寫數字的識別,即:用6萬個已標註資料(即:6萬張28*28的影象塊(patches)),作訓練資料集,然後利用其訓練softmax分類器,再用1萬個已標註資料(即:1萬張28*28的影象塊(pa

Deep Learning 9_深度學習UFLDL教程linear decoder_exercise(斯坦福大學深度學習教程)

前言 實驗基礎說明: 1.為什麼要用線性解碼器,而不用前面用過的棧式自編碼器等?即:線性解碼器的作用? 這一點,Ng已經在講解中說明了,因為線性解碼器不用要求輸入資料範圍一定為(0,1),而前面用過的棧式自編碼器等要求輸入資料範圍必須為(0,1)。因為a3的輸出值是f函式的輸出,而在普通的spa

佛爺芸: 深度學習演算法原理應用系列---深度學習介紹

機器學習演算法已經基本學習完了,在這一系列,佛爺將開始著手學習深度學習的各種演算法和應用,由於本身難度偏大,我會不定期的更新,基本清楚和更加深入的研究深度學習。程式碼方面我基本會使用Tensorf