機器學習工作流程第一步:如何用Python做數據準備?
這篇的內容是一系列針對在Python中從零開始運用機器學習能力工作流的輔導第一部分,覆蓋了從小組開始的演算法編程和其他相關工具。最終會成為一套手工製成的機器語言工作包。這次的內容會首先從數據準備開始。
—— 來自Matthew Mayo, KDnuggets
似乎大家對機器學習能力的認知總是簡單到把一系列論據傳送到越來越多的資料庫和應用程序界面中,接著就期待能有一些神奇的結果出現。可能你對在這些資料庫里究竟發生了什麼有自己很好的理解—— 從數據準備到建模到結果演示呈現等等,但不得不說你依然需要依賴於這些紛繁的工具去完成自己的工作。
這其實很正常。我們用被準確檢驗證明過能運行的工具來完成一些日常的任務是無可厚非的。重新發明使用那些不能有效滾動的輪子不是最好的辦法。這樣會有很多局限,也會浪費很多的不必要的時間。無論你是使用開放源代碼還是被授權的工具來完成你工作,這些代碼工具已經被很多人反覆試用升級以確保當你上手使用的時候能夠以最好的質量完成你的工作。
然而,有些苦活累活你自己做也是有價值的,即便是作為一種教育性的努力。我不是要推薦你們從零開始通過自己深度學習練習寫出一個程序框架,至少不能一直這樣,但哪怕只有一次通過不斷的試驗和失敗,從頭開始寫出和自己的算實現它們的支持工具也是非常好的。我可能說的不對,但我認為如今在學習機器學習能力、數據科學、人工智慧等方面的大多數人都沒有在這麼做。
所以讓我們從頭開始,來學習在Python里建立一些機器學習能力的相關知識。
「From Scratch」 究竟是什麼意思?
首先,我先申明:當我提到「From Scratch」,我的意思是儘可能少的藉助外界的幫助。當然這也是相對的,但是為了達成我們的目標,我會劃定界限,當我們在寫自己的矩陣模型、數據框或者構建自己的資料庫時,我們會分別使用Python中的numpy、panda和matplotlib庫。在某些情況下,我們甚至不會使用這些庫的全部功能。我們稍後會討論,讓我們先暫時放一放它們的名字以便大家更好的理解。在Python自帶的庫中自帶的功能原則上都是可以使用的,但除此之外,我們就要自己來寫了。
我們需要從一個點入手,那就讓我們從一些簡單的數據準備任務開始吧。開始的時候我們會慢一點,但當我們對(要學習的東西)有了一點感覺以後,我們會逐漸加快速度。除了數據準備,我們還需要數據轉換、結果演示和呈現工具——更不必說機器學習能力演算法了——來達成我們我們即將要完成的目標。
我們的想法是手動拼接任何我們需要的重大功能,以便完成我們的機器學習能力任務。當序列展開的時候,我們可以添加新的工具和演算法,同時我們也能重新思考我們以前的假設(是否正確),使整個過程儘可能重複迭代,就像它會漸近一樣。慢慢的,我們會集中精力在我們的目標上,制定策略來完成目標,把它們運用到Python里,再檢驗它們是否能夠運行。
最終的結果,就想我們現在預期的一樣,會是有序排列在我們自己的簡易的機器學習資料庫中的一系列簡單的Python模型。對於初學者,我相信這是理解機器學習過程、工作流和演算法如何運行的非常寶貴的經驗。
工作流(workflow)究竟是什麼意思?
工作流對不同的人意味著不同的意思,但是我們這裡說的工作流指的是機器學習項目中的一部分。我們有很多過程框架來幫助我們追蹤我的工作進程,但現在讓我們簡化到一下的這些:
獲取數據
處理/準備數據
建立模型
解釋呈現結果
在我們真正做的時候我們可以拓展,但是這是我們現在自己設計的簡單的機器學習的過程框架。同時,「輸送管(小箭頭)」暗含了把工作流中各功能聚集在一起的能力,所以讓我們把這些記住然後繼續向前。
獲得數據
在我們建立自己的模型之前,我們需要一些數據,還需要確認這些數據與我們合理的期望相符合。為了檢測的目的(而不是訓練或測試,但只是測試我們自己的設備),我們會使用虹膜數據集,你可以從這裡下載。儘管我們可以在網上找到很多版本的數據集,但我建議我們都使用相同的原始數據,以確保我們的準備工作正常運行。
讓我們來看一看:
既然我們已經知道了這個簡單的數據集和它對應的文件,我們先來想一想我們需要做什麼使原始數據演變成我們想要的結果:
數據需要儲存成CSV格式的文件
實例大部分由有數字屬性的值組成
組別是經過分組的內容
到目前為止,以上沒有一種是對所有的數據集都適用的,但是也沒有任何一個是只能適用於某一種數據集的。這使得我們能夠有機會編寫我們可以以後重複使用的代碼。好的編程練習會讓我們集中於重複利用性和模塊性。
一些簡單的探索性數據分析被羅列如下:
準備數據
雖然數據準備在我們現在這個特定的情境中需要的很少,但是有時還是會需要。尤其是我們需要確認我們解釋了標題行,去除了任何pandas呈現出來的參數,並且把我們的每一次組的值從名字型的轉化成數值型的。因為在我們使用模型時已經沒有名字性數值了,所以到此為止至少就沒有更複雜的轉化了。
最終,我們也需要一個對我們自己的演算法的更好的數據呈現,所以我們在繼續向前進行之前會確保我們最終呈現的是一個矩陣——或者numpy nadarry。我們的數據準備工作流接下來會做一下的表格:
同時,我們需要主要我們沒有理由相信所有有趣的數據都會被儲存在被逗號分開的文件里。我們可能希望能夠從一個SQL資料庫里或者直接從網上獲取數據,從這兩個地方找到的數據我們以後還能返回去回看。
首先,讓我們寫一個簡單的函數,把一個CSV文件上傳到DataFrame。當然,這在內網做很容易,但是再往前想一步我們可能想再加一些額外的步驟到我們自己的數據集里以便我們以後上載函數。
這個編碼是相當直接的。一行一行的讀數據文件就完成了一些額外的預先加工,比如忽略了那些內容非數據的行(我們認為在數據文件中評價是由井號鍵開始的,儘管這很荒謬。)我們可以詳細說明這個數據集文件是否包括標題,我們也可以接受csv和tsv文件,csv文件是默認的設置。
有一些錯誤檢查存在,但它還並不是很健全,所以我們或許可以晚一點再回來說這個話題。此外,逐條讀文件再逐條決定要對這些行做什麼,比直接用內置功能把處理乾淨的一致的cs一文件直接讀到DataFrame中要慢,但權衡之後我們發現允許更多的靈活性,在這一階段是值得的(但讀大的文件可能會發花費很久的時間)。不要忘了,如果一部分內置操作不是最好的方法,我們可以晚一些再做調整。
在我們嘗試運行自己的編碼之前,我們需要來寫一個函數,把名字類數值轉化成數字類數值。為了推廣函數,我們需要使它能夠用於數據集中的任何屬性的數值,不僅僅是運用於不同的類別。我們還應該跟蹤屬性名稱最終是否成為了整數。有了之前把csv或ts me的數據文件上傳pandas的DataFrame的步驟經驗,這個函數應該同時接受一個pandas DataFrames以及被轉化為數字的屬性名稱。
我們還要注意,我們迴避了關於使用單熱編碼的話題,這涉及到分類的非分類屬性,但我認為我們以後還會回到這個話題。
上述的函數又是一個簡單的,但是能幫助我們完成目標函數。我們可以用很多不同的方式來完成這個任務,包括使用pandas內置的功能,但是讓你從一些會讓你有些累的苦差事開始做就是這個函數的意義。
現在我們可以從文件中載入一個數據集,然後把分類屬性值轉換成數字屬性值(我們也可以保留這些映像在字典中供以後使用)。就像之前提到的,我們希望我們的數據集最終是以numpy ndarry的形式存在,這樣我們可以在自己的演算法中很簡單的使用。同樣的,這是一個簡單的任務,但寫一個函數會讓我們在以後需要的時候還可以以此為準。
即使以前任何的功能都沒有過度的殺傷力,但這個功能有可能有。但請忍耐我,我們遵守非常全面的編程準則--如果過於謹慎的話。在我們繼續往下講的過程中會有很好的機會讓我們對已有的功能做改變或添加。這些變化如果能在一個地方實施並且記錄在案,從長遠來看非常有意義。
測試數據準備的工作流
我們的工作流迄今為止可能仍然是構建板塊的形式,但讓我們給自己的編碼一個測試。
我們的代碼正在按我們希望的方式工作,讓我們做一些簡單的房屋清理工作。一旦開始滾動,我們將為我們的編碼提供一個更全面的組織結構,但是現在我們需要把所有這些功能加到一個單獨的文件中,並保存成為dataset.py的格式。這會讓我們以後的使用更方便,下次我們會學到。
未來計劃
之後我們會學習簡單的分類演算法,k最近鄰演算法。我們會學習如何在簡單的工作流中構建分類和聚類模型。毫無疑問,這需要編寫一些限額外的工具來幫助我們完成項目,並且我確定我們還將對已經做完的部分進行修改。
練習機器學習就是理解機器學習的最好方法。運用我們的工作流中需要的演算法和支持工具最終會被證明是有用的。
推薦閱讀:
※我用flask-sqlalchemy為什麼無法更新我的sqlite文件?
※薦書:《Fluent Python》
※Python數據分析及可視化實例目錄
※有沒有什麼東西是 Go 可以做但 Python 做不到的?