如何用@修飾器來快取資料預處理結果?

由於公眾號改版不再按照作者的釋出時間進行推送,為防止各位客官錯過月來客棧推送的最新文章,大家可以手動將公眾號設定為“星標 ”以第一時間獲得推送內容,感謝各位~

1 引言

各位朋友大家好,歡迎來到月來客棧,我是掌櫃空字元。

不知道各位客官在行走江湖的過程中有沒有遇到類似這樣的問題:由於資料集過於龐大或者說資料結構很複雜,導致每次都需要花費很長的時間來等待資料集的預處理過程。例如掌櫃最近在研究SQuAD任務時就發現每次資料預處理都需要等待很長的時間。雖然在這期間掌櫃也想過將預處理過後的結果給快取下來(之前也是這麼做的),當下次載入資料集時先進行判斷,如果本地存在快取則直接載入快取;但是想想這次寫了下次換個場景又需要重寫這些程式碼,覺得麻煩又給放棄了。

不過由於最終還是沒能忍受等待時間太長,於是思考了一下寫了一個通用的快取方法,這樣在任何地方只需要呼叫該函式便可以實現上述目的。並且為了使得呼叫方便以及程式碼簡介,掌櫃還特地將它實現為了Python中的修飾器。下面,掌櫃首先就帶著大家簡單地瞭解一下Python中修飾器的作用及用法。

2 修飾器簡介

關於什麼是修飾器(或裝飾器Decorator)掌櫃這裡就不從Python語法上來做詳細的解釋了。簡單一句話,修飾器的作用的就是在正式執行某個功能函式之前,預先執行你想要執行的某些操作。下面,我們直接從用法的層面來逐步瞭解Python中的修飾器,因為這樣帶著目的去學習能夠更快的入門。

2。1 修飾器用例

首先來看這樣一個場景,假如你已經定義了很多功能函式,但是你現在想在日誌檔案中同時也打印出當前主程式正在呼叫哪個功能函式的資訊。例如:

要實習這樣一個功能,最直接的做法就是在原始的函數里面加上一句函式的輸出資訊:

這樣我們在呼叫和這兩個函式時就能夠分別輸出對應的資訊:

雖然說上面這個做法稍微有點麻煩,但似乎還能接受。不過又過了一會兒,你還想在此基礎上打印出進入每個函式時的具體時間該怎麼辦呢?繼續像剛剛那樣再加一行程式碼?萬一有100個函式怎麼操作?

面對這樣一個問題,Python中的修飾器便可以出來大展身手了。在使用修飾器之前,需要先定義一個完成該功能的函式,如下:

可以看到,似乎就像是定義了一個巢狀的函式一樣。因此,我們可以透過函式呼叫的方式來使用方法:

這樣,對於後續需要增加的任何操作,只需要在函式中加入即可而不需要在呼叫的地方進行改動。不過這樣呼叫稍微有點麻煩,需要到每個呼叫該函式的地方修改函式傳入的方式。所以,我們還可以透過一個更加簡潔的方式來進行呼叫,那就是直接在該函式定義的地方將它作為修飾器使用:

這樣,我們直接透過呼叫對應的功能函式就能夠實現輸出該函式名和時間的資訊:

介紹到這裡,相信各位客官對於Python中修飾器的定義與使用已經有了一個基本的瞭解。下面掌櫃再來總結一下修飾器的使用方法,簡稱套路。

2。2 修飾器格式

透過上面的示例介紹可以發現,定義修飾器函式的大致格式如下:

在上述程式碼中,為修飾器的名稱;為使用該修飾器的函式;則為使用該修飾器的函式的相關引數。同時,由於透過符號來將作為修飾器呼叫本質上只是一種快速簡潔的方式,所以還等價於這樣的呼叫方式。因此,通過後者我們還能夠更加清晰的認識到整個修飾器的工作流程。

雖然上面掌櫃給出了一個定義修飾器的大致格式,但是在理解了整個修飾器的工作流程後,我們還可以根據自己的需要靈活的做出相應的修改。例如需要再統計每個函式的執行時間則可以修改為:

總結起來就是,透過符號來將作為修飾器呼叫本質上只是一種快速簡潔的函式呼叫方式,因此對於函式內部的整個處理流程依舊等價於普通的函式定義流程。

3 快取預處理結果

在介紹完修飾器的基本原理及用法之後再來看如何快取資料預處理結果就變得十分容易了。總結起來就是在正式載入資料集之前首先判斷本地是否存在快取,如果存在則直接載入快取,如果不存在則再呼叫函式進行資料預處理並進行快取。

3。1 定義資料載入類

熟悉掌櫃的客官都知道,對於資料預處理部分掌櫃一般都喜歡將其定義為一個類,並在各個成員函式內實現相應的處理邏輯。並且通常來說,這個類至少會包含3個方法:、和,其中用來初始化類中的相關引數(如、、資料集路徑等等;用來對資料集進行預處理返回預處理後的結果;用來構造最後模型訓練時的。

如下所示便是一個簡單的資料載入類(實戰示例可參考文章):

在上述程式碼中,第8行方法返回的便是預處理後的結果;第15行程式碼則是定義的一個快取檔名的字尾,因為在一些場景中可能會存在可調節的引數(例如NLP處理時對於句子的長度等等),因此對於不同引數對應的快取應該加以區分。最後,我們只需要將處理後的結果進行快取即可。

當然,雖然這裡是以構造PyTorch中的DataLoader為例進行的程式碼示例,但是同樣的處理邏輯一樣可以運用到機器學習中。

3。2 定義快取修飾器

如下所示便是根據我們實際的需要所定義的一個預處理資料快取的修飾器。在經過第1節內容的介紹之後,掌櫃相信各位客官應該很容易的就能看懂這些程式碼:

在上述程式碼中,第3-4行用來透過命名引數獲得對應的路徑以及快取檔名的字尾(這就意味著在呼叫函式時必須以命名引數的形式進行,即;第6-10行則是當快取檔案不存在時,則呼叫進行資料處理,並快取處理有的結果;第11-14行則是當對應的快取檔案存在時,直接從本地進行載入;第15行則是返回對應的預處理結果。

在這裡可以發現,對於上述快取修飾器你還可以幾乎不加修改的運用到任何一個場景中,而只需要將預處理後的結果構造成一個字典即可。

最後,當第1次透過載入資料集時會看到類似如下的結果:

當後續再次載入同一份資料預處理結果時,則會看到類似如下的結果:

從輸出提示來看,當第2次載入同一份資料預處理檔案時,會直接從快取中載入而並不需要再次執行函式中的處理邏輯。

到此,對於如何利用Python修飾器來便捷快取資料預處理結果的內容就介紹完了。

4 總結

在這篇文章中,掌櫃首先從使用示例的角度來介紹了Python修飾器的用法及工作原理,即其本質上只是Python中所支援的一種快速簡潔的函式呼叫方式;然後介紹了在機器學習中資料預處理時的一種可借鑑流程;最後介紹瞭如何實現一個可通用資料預處理快取修飾器。有了這個修飾器的加持,相信各位客官在建模過程中一定能夠極大的節約資料預處理的等待時間。

本次內容就到此結束,感謝您的閱讀!如果你覺得上述內容對你有所幫助,歡迎點贊轉發分享三連!若有任何疑問與建議,請添在文末進行留言交流。

青山不改,綠水長流,我們月來客棧見

都滑到這裡了,給掌櫃點個贊再走吧!

如何用@修飾器來快取資料預處理結果?

TAG: 修飾快取預處理函式載入