Uber提出SBNet:利用激活的稀疏性加速卷積網絡

 2018-01-18 12:51:00.0

原標題:業界 | Uber提出SBNet:利用激活的稀疏性加速卷積網絡

選自Uber

作者:Mengye Ren、Andrei Pokrovsky、Bin Yang、Raquel Urtasun

自動駕駛系統有非常高的實時性需求。近日,Uber 的研究人員提出了一種可以在改善檢測準確度的同時極大提升速度的算法 SBNet 並在其工程開發博客上對該研究進行了介紹。我們對該介紹文章進行了編譯,更多詳情請參閱原論文。另外,本項目的代碼也已在 GitHub 上發佈。

  • 論文地址:https://arxiv.org/abs/1801.02108
  • 代碼地址:https://github.com/uber/sbnet

爲了實現更安全和更可靠的交通運輸解決方案,Uber ATG Toronto 的研究者正致力於開發應用了卷積神經網絡(CNN)和其它深度學習技術的技術。

CNN 在分析來自激光雷達(LiDAR)傳感器的視覺圖像和數據上有着廣泛的應用。在自動駕駛領域,CNN 能讓自動駕駛車輛看見其它汽車和行人、確定它們的準確位置以及解決許多之前無法使用傳統算法解決的其它難題。爲了確保我們的自動系統是可靠的,這樣的 CNN 必須以非常快的速度在 GPU 上運行。在降低使用 CNN 的設備成本和功耗的同時開發改善響應時間和準確度的有效方式一直以來都是一個研究重點。

作爲這種努力的一部分,我們開發了一個用於 TensorFlow 的開源算法——稀疏塊網絡(SBNet:Sparse Blocks Network),該算法可通過利用 CNN 激活中的稀疏性來加速推理。我們的研究表明,當 SBNet 與殘差網絡(ResNet)架構結合使用時,有可能帶來一個數量級的提速。SBNet 允許使用更深和更寬的網絡配置進行實時的推理,從而能在降低計算負載的情況下實現準確度的提升。

在這篇文章中,我們將討論我們構建 SBNet 的方法,並將展示該算法在我們的自動駕駛 3D LiDAR 物體檢測器中的實際應用,其實現了顯著的時鐘加速和檢測準確度提升。

背景

傳統的深度 CNN 是在數百層上一致爲所有的空間位置應用卷積算子,這需要每秒執行數萬億次運算。在我們最新的研究中,我們基於這樣一個認識進行了開發——很多運算都浪費在了對無關信息的過度分析上。在一個典型的場景中,僅有少部分被觀測數據是重要的;我們將這個現象稱爲稀疏性(sparsity)。在自然界中,視覺皮層等生物神經網絡根據周邊視覺(peripheral vision)檢測到的運動和減少視網膜周邊部分中的密度和顏色信息,從而可以通過聚焦視網膜中央凹視覺來利用稀疏性。

在人工神經網絡中,激活稀疏的 CNN 之前已經在手寫識別等小規模任務上有研究發現了,但與高度優化的密集卷積實現相比還沒有實現真正的加速。

但是,我們的研究表明通過在 CNN 激活中利用我們所說的塊稀疏性(block sparsity),可以實現高達一個數量級的實際加速。如圖 1 所示:

圖 1:在激活大小爲 700×400,具有 96 個輸入通道和 24 個輸出通道時,單個稀疏的殘差網絡塊相對於稀疏度的加速,這個結果是在一個英偉達 GTX 1080Ti 上使用 TensorFlow 1.21 + cuDNN 6.0 測得的。

SBNet 介紹

根據這些見解,我們開發了 SBNet,這是一個用於 TensorFlow 的開源算法,能夠利用 CNN 的激活中的稀疏性,因此能顯著提升推理速度。

爲了實現我們算法的目標,我們根據表示激活非零的位置的掩碼定義了塊稀疏性(block sparsity)。這種掩碼可以來自對該問題的之前已有的知識,或者可以直接根據對平均激活進行閾值化來得到。爲了利用經過高度優化的密集的卷積算子,我們定義了兩個運算操作來將稀疏的激活變換成僅包含非零元素的更小的特徵圖。

首先通過使用來自輸入張量的重疊塊來在注意掩碼上執行池化運算,然後將其轉換成一個傳遞給塊收集操作的索引列表,SBNet 實現了這一目標,如圖 2 所示:

圖 2:爲了利用 CNN 激活中的稀疏性,SBNet 首先將計算掩碼轉換成 tile 索引列表

然後聚(gather)操作會將 tile 沿批(batch)維度堆疊在一起,形成一個新的張量。然後使用已有的優化過的密集卷積實現,然後一個自定義的散(scatter) 操作會執行一個反向的運算並將結果寫在原始密集輸入張量之上。下面的圖 3 給出了我們提出的使用了稀疏 gather/scatter 操作的稀疏卷積機制:

圖 3:我們提出的稀疏卷積層能利用稀疏 gather/scatter 操作來加速推理

當我們爲 SBNet 設計稀疏操作 API 時,我們希望能將其輕鬆地整合到流行的 CNN 架構(比如 ResNet 和 Inception)和其它定製的 CNN 構造模塊中。爲了實現這一目標,我們爲我們引入的三種基本操作(reduce_mask、sparse_gather 和 sparse_scatter)發佈了 CUDA 實現(和 TensorFlow wrapper。使用這些低層面的運算,我們能爲不同的 CNN 架構和配置增加塊稀疏性。

下面我們提供了一個 TensorFlow 示例,演示了如何使用SBNet API進行單層稀疏卷積運算:

  1. #
  2. # A minimal sample implementing a single sparse convolution layer with synthetic data using SBNet primitives.
  3. #
  4. import numpy as np
  5. import tensorflow as tf
  6. sbnet_module = tf.load_op_library('../libsbnet.so')
  7. def divup(a, b):
  8. return (a+b-1) // b
  9. # Specify input tensor dimensions and block-sparsity parameters
  10. batch = 4
  11. hw = 256
  12. channels = 64
  13. blockSize = [16, 16]
  14. blockStride = [14, 14]
  15. blockOffset = [0, 0]
  16. blockCount = [divup(hw, blockStride[0]), divup(hw, blockStride[1])]
  17. # build kwargs to simplify op calls
  18. inBlockParams = { "bsize": blockSize, "boffset": blockOffset, "bstride": blockStride }
  19. outBlockParams = { "bsize": [blockSize[0]-2, blockSize[1]-2], "boffset": blockOffset, "bstride": blockStride }
  20. # create a random mask representing attention/a priori sparsity
  21. # threshold the mask to a specified percentile sparsity
  22. mask = np.random.randn(batch, blockCount[0], blockCount[1], channels).astype(np.float32)
  23. threshold = np.percentile(mask, 90)
  24. sparseMask = np.greater(mask, threshold).astype(np.float32)
  25. # upsample the mask to full resolution
  26. upsampledMask = sparseMask.repeat(blockStride[0], axis=1).repeat(blockStride[1], axis=2)
  27. # create a random input tensor
  28. x = tf.constant( np.random.randn(batch, hw, hw, channels).astype(np.float32) )
  29. # create a random weight tensor
  30. w = tf.constant( np.random.randn(3, 3, channels, channels).astype(np.float32) )
  31. # reduce the mask to indices by using a fused pooling+indexing operation
  32. indices = sbnet_module.reduce_mask(mask, blockCount, tol=0.5, **inBlockParams)
  33. # stack active overlapping tiles to batch dimension
  34. blockStack = sbnet_module.sparse_gather(
  35. x, indices.bin_counts, indices.active_block_indices, transpose=True, **inBlockParams)
  36. # perform dense convolution on a sparse stack of tiles
  37. convBlocks = tf.nn.conv2d(
  38. blockStack, w, strides=[1, 1, 1, 1], padding='VALID', data_format='NCHW')
  39. # write/scatter the tiles back on top of original tensor
  40. # note that the output tensor is reduced by 1 on each side due to 'VALID' convolution
  41. validX = x[:, 1:hw-1, 1:hw-1, :]
  42. y = sbnet_module.sparse_scatter(
  43. convBlocks, indices.bin_counts, indices.active_block_indices,
  44. validX, transpose=True, add=False, atomic=False, **outBlockParams)
  45. sess = tf.Session()
  46. y_output, = sess.run([y])

更多示例請參閱我們的 GitHub 庫:https://github.com/uber/sbnet,其中還包含一個完整的 ResNet 模塊實現。

接下來,我們將討論如何將 SBNet 用於訓練 Uber ATG 的 3D 車輛檢測系統。

應用:根據 LiDAR 點檢測 3D 車輛

在 Uber ATG Toronto,我們在根據 LiDAR 點檢測 3D 車輛的任務上驗證了 SBNet;由於這個任務需要稀疏的輸入並且對推理的時間限制要求挺高,所以是一個有效的用例。在我們的模型中,LiDAR 能以每秒 10 次徑向掃描的速度產生周圍環境的 3D 點雲。對於每一次掃描,我們都會採用人工的方式爲周圍的所有車輛標註 3D 邊界框。除了點雲和 3D 標籤,我們也有從地圖提取的道路佈局信息。

圖 4 給出了數據、車輛標籤和道路地圖的一張鳥瞰圖:

圖 4:我們的 LiDAR 3D 車輛檢測使用了道路地圖作爲計算掩碼(藍色),ground-truth 用方框表示(綠色)

首先,我們應用了一個基於 CNN 的方法來解決這一任務,並且從一個俯視視角以每像素 0.1m 的分辨率對該 LiDAR 點雲進行了離散化;結果數據表徵展現出了超過 95% 的稀疏度。然後,這些數據被輸入了一個基於 ResNet 的單發檢測器(ResNet-based single-shot detector)。(有關我們的基準檢測器的更多詳情,請參閱我們的研究論文)。

我們根據一個傳統的密集卷積的基準檢測器,對 SBNet 的兩種變體進行了基準評估——我們將其中的所有層都替換成了對應的塊稀疏的版本。這些變體基於兩個不同的稀疏性信息來源:一個使用了預計算的道路地圖(事先已知),另一個使用了預測得到的前景掩碼。道路地圖可以從離線的地圖中提取,這不會給檢測器增加計算時間。預測得到的前景掩碼是使用另一個低分辨率 CNN 生成的,並且比道路地圖都更高的稀疏度。

在使用 SBNet 時,我們測量了兩種變體相對於基準檢測器的顯著提速。在下面的圖 5 中,我們給出了輸入數據在不同稀疏程度下測得的速度提升。

圖 5:使用 SBNet,我們的全 3D 車輛檢測器網絡實現了提速。這是在英偉達 Titan X Pascal 上使用 TensorFlow 1.2.1 和 cuDNN 6.0 得到的結果。

使用道路地圖的變體平均有 80% 的稀疏度,對應實現了 2 倍的加速;使用預測掩碼的變體平均有大約 90% 的稀疏度,對應實現了 3 倍的加速.

在檢測準確度方面,使用 SBNet 架構重新訓練檢測器會在平均精度上得到 2 個百分點的增益。這說明使用數據稀疏性能夠通過減少噪聲和方差來使模型訓練穩定化,從而在更快的推理時間之外還能得到更準確的 3D 車輛檢測。

接下來

我們相信 SBNet 能夠廣泛應用於各種深度學習架構、模型、應用和稀疏源,我們期待看到深度學習研究社區通過不同的方式使用這些架構構建模塊。有關 SBNet 和我們的研究的更詳細解釋,我們希望你能閱讀我們的論文。

對最近這項成果的總結請參看下面的視頻:

擴展閱讀

  • M. Ren, A. Pokrovsky, B. Yang, R. Urtasun,「SBNet: Sparse Blocks Network for Fast Inference,」arXiv preprint arXiv:1801.02108, 2018. (GitHub)
  • Y. LeCun, L. Bottou, Y. Bengio, P. Haffner,「Gradient-based learning applied to document recognition,」in Proceedings of the IEEE, 86 (11): 2278–2324, doi:10.1109/5.726791, 1998.
  • Abadi et al,「TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems,」arXiv preprint arXiv:1603.04467, 2016.
  • B. Graham and L. van der Maaten,「Submanifold sparse convolutional networks,」arXiv preprint, arXiv:1706.01307, 2017.
  • K. He, X. Zhang, S. Ren, J. Sun,「Deep residual learning for image recognition,」in Proceedings of IEEE Conference on Computer Vision and Pattern Recognition, 2017.
  • A. Lavin and S. Gray,「Fast algorithms for convolutional neural networks,」in Proceedings of IEEE Conference on Computer Vision and Pattern Recognition, 2016.


文章來源:機器之心