你寫的ML程式碼佔多少記憶體?這件事很重要,但很多人還不懂

選自towardsdatascience

作者:Tirthajyoti Sarkar

機器之心編譯

編輯:蛋醬

演算法完美是重要的,但更重要的是成功部署,這篇文章能夠幫助你了解有關程式碼記憶體佔用的一切。

在進行機器學習任務時,你需要學會使用程式碼快速檢查模型的記憶體佔用量。原因很簡單,硬體資源是有限的,單個機器學習模組不應該佔用系統的所有記憶體,這一點在邊緣運算場景中尤其重要。

比如,你寫了一個很棒的機器學習程序,或者搭建了一個不錯的神經網路模型,然後想在某些 Web 服務或 REST API 上部署模型。或者你是基於工廠傳感器的資料流開發了模型,計劃將其部署在其中一臺工業計算機上。

這時,你的模型可能是硬體上運行的幾百個模型之一,所以你必須對記憶體佔用峰值有所了解。否則多個模型同時達到了記憶體佔用峰值,系統可能會崩潰。

因此,搞清楚程式碼運行時的記憶體配置檔案(動態數量)非常重要。這與模型的大小和壓縮均無關,可能是你事先已經將其保存在磁碟上的特殊對象,例如 Scikit-learn Joblib dump、Python Pickle dump,TensorFlow HFD5 等。

Scalene:簡潔的記憶體 / CPU/GPU 分析器

首先要討論的是 Scalene,它是一個 Python 的高性能 CPU 和記憶體分析器,由馬薩諸塞大學研發。其 GitHub 頁面是這樣介紹的:「 Scalene 是適用於 Python 的高性能 CPU、GPU 和記憶體分析器,它可以執行許多其他 Python 分析器無法做到的事情,提供詳細資訊比其他分析器快幾個數量級。」

安裝

它是一個 Python 包,所以按照通常方法安裝:

    pip install scalene

    這樣適用於 Linux OS,作者沒有在 Windows 10 上進行測試。

    在 CLI 或 Jupyter Notebook 內部使用

    Scalene 的使用非常簡單:

      scalene <yourapp.py>

      也可以使用魔術命令在 Jupyter notebook 中使用它:

        %load_ext scalene

        輸出示例

        下面是一個輸出示例。稍後將對此進行更深入的研究。

        這些是 Scalene 一些很酷的功能

        這些是 Scalene 一些很酷的功能:

        • 行和函數:報告有關整個函數和每個獨立程式碼行的資訊;

        • 執行緒:支持 Python 執行緒;

        • 多進程處理:支持使用 multiprocessing 庫;

        • Python 與 C 的時間:Scalene 用在 Python 與本機程式碼(例如庫)上的時間;

        • 系統時間:區分系統時間(例如,休眠或執行 I / O 操作);

        • GPU:報告在英偉達 GPU 上使用的時間(如果有);

        • 複製量:報告每秒要複製的資料量;

        • 洩漏檢測:自動查明可能造成記憶體洩漏的線路。

        ML 程式碼具體示例

        接下來看一下 Scalene 用於記憶體配置標準機器學習程式碼的工作。對三個模型使用 Scikit-learn 庫,並利用其綜合資料生成功能來創建資料集。

        對比的是兩種不同類型的 ML 模型:

        • 多元線性迴歸模型;

        • 具有相同資料集的深度神經網路模型。

        線性迴歸模型

        線性迴歸模型

        使用標準匯入和 NUM_FEATURES 、 NUM_SMPLES 兩個變數進行一些實驗。

        這裡沒有展示資料生成和模型擬合程式碼,它們是非常標準的。作者將擬合的模型另存為 pickled dump,並將其與測試 CSV 檔案一起載入以進行推斷。

        為了清晰起見,將所有內容置於 Scalene 執行和報告環境下循環運行。

        當運行命令時:

          $ scalene linearmodel.py --html >> linearmodel-scalene.html

          將這些結果作為輸出。注意,此處使用了 –html 標誌並將輸出通過管道傳輸到 HTML 檔案,以便於報告。

          令人驚訝的是,記憶體佔用幾乎完全由外部 I / O(例如 Pandas 和 Scikit-learn estimator 載入)控制,少量會將測試資料寫到磁碟上的 CSV 檔案中。實際的 ML 建模、Numpy、Pandas 操作和推理,根本不會影響記憶體。

          我們可以縮放資料集大小(行數)和模型複雜度(特徵數),並運行相同的記憶體配置檔案以記錄各種操作在記憶體消耗方面的表現。結果顯示在這裡。

          此處,X 軸代表特徵 / 資料點集。注意該圖描繪的是百分比,而不是絕對值,展示了各種類型操作的相對重要性。

          從這些實驗中得出的結論是,Scikit-learn 線性迴歸估計非常高效,並且不會為實際模型擬合或推理消耗大量記憶體。

          但就程式碼而言,它確實有固定的記憶體佔用,並在載入時會消耗大量記憶體。不過隨著資料大小和模型複雜性的增加,整個程式碼佔用百分比會下降。如果使用這樣的模型,則可能需要關注資料檔案 I / O,最佳化程式碼以獲得更好的記憶體性能。

          深度神經網路如何?

          如果我們使用 2 個隱藏層的神經網路(每個隱藏層有 50 個神經元)運行類似的實驗,那麼結果如下所示。

          程式碼地址:https://github.com/tirthajyoti/Machine-Learning-with-Python/blob/master/Memory-profiling/Scalene/mlp.py

          與線性迴歸模型不同,神經網路模型在訓練 / 擬合步驟中消耗大量記憶體。但是,由於特徵少且資料量大,擬合佔用的記憶體較少。此外,還可以嘗試各種體系結構和超參數,並記錄記憶體使用情況,達到合適的設置。

          復現說明

          如果你使用相同的程式碼復現實驗,結果可能會因硬體、磁碟 / CPU / GPU / 記憶體類型的不同而大相徑庭。

          一些關鍵建議

          • 最好在程式碼中編寫專注於單個任務的小型函數;

          • 保留一些自由變數,例如特徵數和資料點,藉助最少的更改來運行相同的程式碼,在資料 / 模型縮放時檢查記憶體配置檔案;

          • 如果要將一種 ML 演算法與另一種 ML 演算法進行比較,請讓整體程式碼的結構和流程儘可能相同以減少混亂。最好只更改 estimator 類並對比記憶體配置檔案;

          • 資料和模型 I / O(匯入語句,磁碟上的模型永續性)在記憶體佔用方面可能會出乎意料地佔主導地位,具體取決於建模方案,最佳化時切勿忽略這些;

          • 出於相同原因,請考慮比較來自多個實現 / 程序包的同一演算法的記憶體配置檔案(例如 Keras、PyTorch、Scikitlearn)。如果記憶體最佳化是主要目標,那麼即使在功能或性能上不是最佳,也必須尋找一種佔用最小記憶體且可以滿意完成工作的實現方式;

          • 如果資料 I / O 成為瓶頸,請探索更快的選項或其他儲存類型,例如,用 parquet 檔案和 Apache Arrow 儲存替換 Pandas CSV。可以看看這篇文章:

          《How fast is reading Parquet file (with Arrow) vs. CSV with Pandas?》

          https://towardsdatascience.com/how-fast-is-reading-parquet-file-with-arrow-vs-csv-with-pandas-2f8095722e94

          Scalene 能做的其他事

          在本文中,僅討論了記憶體分析的一小部分,目光放在了規範機器學習建模程式碼上。事實上 Scalene CLI 也有其他可以利用的選項:

          • 僅分析 CPU 時間,不分析記憶體;

          • 僅使用非零記憶體減少資源佔用;

          • 指定 CPU 和記憶體分配的最小閾值;

          • 設置 CPU 取樣率;

          • 多執行緒並行,隨後檢查差異。

          最終驗證(可選)

          在資源較少的情況下,你最好託管一個驗證環境 / 伺服器,該伺服器將接受給定的建模程式碼(如已開發),並通過這樣的記憶體分析器運行它以創建運行時統計資訊。如果它通過記憶體佔用空間的預定標準,則只有建模程式碼會被接受用於進一步部署。

          總結

          總結

          在本文中,我們討論了對機器學習程式碼進行記憶體配置的重要性。我們需要使其更好地部署在服務和機器中,讓平臺或工程團隊能夠方便運用。分析記憶體也可以讓我們找到更高效的、面向特定資料或演算法的最佳化方式。

          希望你能在使用這些工具和技術進行機器學習部署時能夠獲得成功。

          原文連結:https://towardsdatascience.com/how-much-memory-is-your-ml-code-consuming-98df64074c8f