1. 程式人生 > >入門|三行Python程式碼,讓資料預處理速度提高2到6倍 python入門

入門|三行Python程式碼,讓資料預處理速度提高2到6倍 python入門

在 Python 中,我們可以找到原生的並行化運算指令。本文可以教你僅使用 3 行程式碼,大大加快資料預處理的速度。在這裡插入圖片描述

入門|三行Python程式碼,讓資料預處理速度提高2到6倍 Python 是機器學習領域內的首選程式語言,它易於使用,也有很多出色的庫來幫助你更快處理資料。但當我們面臨大量資料時,一些問題就會顯現……

目前,大資料(Big Data)這個術語通常用於表示包含數十萬資料點的資料集。在這樣的尺度上,工作程序中加入任何額外的計算都需要時刻注意保持效率。在設計機器學習系統時,資料預處理非常重要——在這裡,我們必須對所有資料點使用某種操作。

在預設情況下,Python 程式是單個程序,使用單 CPU 核心執行。而大多數當代機器學習硬體都至少搭載了雙核處理器。這意味著如果沒有進行優化,在資料預處理的時候會出現「一核有難九核圍觀」的情況——超過 50% 的算力都會被浪費。在當前四核處理器(英特爾酷睿 i5)和 6 核處理器(英特爾酷睿 i7)大行其道的時候,這種情況會變得更加明顯。在這裡插入圖片描述

入門|三行Python程式碼,讓資料預處理速度提高2到6倍 幸運的是,Python 庫中內建了一些隱藏的特性,可以讓我們充分利用所有 CPU 核心的能力。通過使用 Python 的 concurrent.futures 模組,我們只需要 3 行程式碼就可以讓一個普通的程式轉換成適用於多核處理器並行處理的程式。

萬事開頭難,給要學習python的同學開個好頭,初入程式設計行業不清楚自己是否真的可以或者擔心自己學不會。 那麼在學習之前咱們得有一個明確的學習目標,詳細的學習線路,做到不盲目學習,少走彎路,在這裡給大家分享一些python入門的學習教程和方法,以及目前python最新的學習線路,歡迎大家加入python學習交流qq群:515267276

標準方法

讓我們舉一個簡單的例子,在單個資料夾中有一個圖片資料集,其中有數萬張圖片。在這裡,我們決定使用 1000 張。我們希望在所有圖片被傳遞到深度神經網路之前將其調整為 600×600 畫素解析度的形式。以下是你經常會在 GitHub 上看到的標準 Python 程式碼:

import glob import os import cv2

Loop through all jpg files in the current folder

Resize each one to size 600x600

for image_filename in glob.glob("*.jpg"):

Read in the image data

img = cv2.imread(image_filename)

Resize the image

img = cv2.resize(img, (600, 600)) 上面的程式遵循你在處理資料指令碼時經常看到的簡單模式:

  1. 首先從需要處理內容的檔案(或其他資料)列表開始。

  2. 使用 for 迴圈逐個處理每個資料,然後在每個迴圈迭代上執行預處理。

讓我們在一個包含 1000 個 jpeg 檔案的資料夾上測試這個程式,看看執行它需要多久:

time python standard_res_conversion.py 在我的酷睿 i7-8700k 6 核 CPU 上,執行時間為 7.9864 秒!在這樣的高階 CPU 上,這種速度看起來是難以讓人接受的,看看我們能做點什麼。

更快的方法

為了便於理解並行化的提升,假設我們需要執行相同的任務,比如將 1000 個釘子釘入木頭,假如釘入一個需要一秒,一個人就需要 1000 秒來完成任務。四個人組隊就只需要 250 秒。

在我們這個包含 1000 個影象的例子中,可以讓 Python 做類似的工作:

將 jpeg 檔案列表分成 4 個小組;

執行 Python 直譯器中的 4 個獨立例項;

讓 Python 的每個例項處理 4 個數據小組中的一個;

結合四個處理過程得到的結果得出最終結果列表。

這一方法的重點在於,Python 幫我們處理了所有棘手的工作。我們只需告訴它我們想要執行哪個函式,要用多少 Python 例項,剩下的就交給它了!只需改變三行程式碼。例項:

import glob import os import cv2 import concurrent.futures

def load_and_resize(image_filename):

Read in the image data

img = cv2.imread(image_filename)

Resize the image

img = cv2.resize(img, (600, 600))

Create a pool of processes. By default, one is created for each CPU in your machine.

with concurrent.futures.ProcessPoolExecutor as executor:

Get a list of files to process

image_files = glob.glob("*.jpg")

Process the list of files, but split the work across the process pool to use all CPUs

Loop through all jpg files in the current folder

Resize each one to size 600x600

executor.map(load_and_resize, image_files) 從以上程式碼中摘出一行:

with concurrent.futures.ProcessPoolExecutor as executor: 你的 CPU 核越多,啟動的 Python 程序越多,我的 CPU 有 6 個核。實際處理程式碼如下:

executor.map(load_and_resize, image_files) 「executor.map」將你想要執行的函式和列表作為輸入,列表中的每個元素都是我們函式的單個輸入。由於我們有 6 個核,我們將同時處理該列表中的 6 個專案!

如果再次用以下程式碼執行我們的程式:

time python fast_res_conversion.py 我們可以將執行時間降到 1.14265 秒,速度提升了近 6 倍!

注意:在生成更多 Python 程序及在它們之間整理資料時會有一些開銷,所以速度提升並不總是這麼明顯。但是總的來說,速度提升還是非常可觀的。

它總是那麼快嗎?

如果你有一個數據列表要處理,而且在每個資料點上執行相似的運算,那麼使用 Python 並行池是一個很好的選擇。但有時這不是最佳解決方案。並行池處理的資料不會在任何可預測的順序中進行處理。如果你對處理後的結果有特殊順序要求,那麼這個方法可能不適合你。

你處理的資料也必須是 Python 可以「炮製」的型別。所幸這些指定類別都很常見。以下來自 Python 官方檔案:

None, True, 及 False

整數、浮點數、複數

字串、位元組、位元組陣列

只包含可挑選物件的元組、列表、集合和字典

在模組頂層定義的函式(使用 def ,而不是 lambda )

在模組頂層定義的內建函式

在模組頂層定義的類

這種類的例項,其 dict 或呼叫__getstate__ 的結果是可選擇的(參見「Pickling Class Instances」一節)