技術(shù) | 使用Python來學(xué)習(xí)數(shù)據(jù)科學(xué)的完整教程
我在SAS工作了5年多之后,決定走出舒適區(qū)。作為一名數(shù)據(jù)科學(xué)家,我在尋找其他好用的工具,幸運的是,沒過多久,我發(fā)現(xiàn)了Python。
一直以來,我喜歡敲代碼。事實證明,有了Python,敲代碼變得更為容易。
我花了一周時間來學(xué)習(xí)Python的基礎(chǔ)知識,從那時起,我不僅深入鉆研Python,而且還幫助許多其他人學(xué)習(xí)這門語言。起初,Python是門通用語言,多年來,隨著社區(qū)的大力支持,現(xiàn)在有了數(shù)據(jù)分析及預(yù)測建模庫。
由于缺少Python數(shù)據(jù)科學(xué)資源,我決定創(chuàng)建本教程,旨在幫助大家快速入門。在本教程中,我們將討論如何使用Python來進行數(shù)據(jù)分析,在實踐中總結(jié)方法。
Python數(shù)據(jù)分析基礎(chǔ)
為什么要學(xué)習(xí)使用Python來進行數(shù)據(jù)分析?
使用Python來進行數(shù)據(jù)分析的原因有很多,過去一段時間通過對比SAS和R,有以下幾點理由:
- 開源免費
- 強大社區(qū)支持
- 易學(xué)
- 成為數(shù)據(jù)科學(xué)和web產(chǎn)品分析的通用語言
誠然,它還有很多缺點:
Python是一種解釋語言而不是編譯語言,因此占用更多的CPU時間。然而,由于節(jié)省了程序員時間(易學(xué)),Python仍然是一個不錯的選擇。
Python 2.7與3.4版本的比較
這是Python中最受爭議的話題之一,作為初學(xué)者,你繞不開這個問題。其實選擇哪個版本都沒有對錯,完全取決于你的需要和實際使用場景。我會嘗試給大家一些指引,幫助大家做出明智的選擇。
為什么選擇Python 2.7?
社區(qū)支持,這是早期需要的,Python 2版本在2000年下半年發(fā)布,超過15年的使用了。
第三方庫支持,雖然許多庫提供3.X的支持,但仍然有大量庫只能在2.X版本上運行。如果你打算將Python用于特定的場景,如網(wǎng)頁開發(fā),高度依賴外部模塊,你可能選擇2.7版本會更好。
3.X版本的一些功能向后兼容,可以使用2.7版本。
為什么選擇Python 3.4?
簡潔快速,Python開發(fā)人員已經(jīng)修復(fù)了一些自身的Bug,為其發(fā)展打下更堅實的基礎(chǔ)。最初這些可能與你不是很相關(guān),終將是很重要的。
未來趨勢,2.7版本是2.X系列的最后一個版本,最終大家都必須轉(zhuǎn)到3.X版本。Python 3已經(jīng)發(fā)布了5年的穩(wěn)定版本,并將持續(xù)推進。
沒有明確顯示到底誰好,但我認為最重要的是大家應(yīng)該專注于將Python當(dāng)作一門語言來學(xué)習(xí)。版本之間的轉(zhuǎn)換是一個時間的問題。遲點,繼續(xù)關(guān)注Python 2.X與3.X比較的文章。
如何安裝Python?
有兩種安裝Python的方法:
你可以直接在官網(wǎng)上下載Python,并安裝所需要的組件和庫。
或者,你可以下載安裝預(yù)裝庫的軟件包,我建議你下載Anaconda,另外可以是Canopy Express。
第二種方法免去安裝其他庫的麻煩,因此我會推薦給初學(xué)者。如果你對單個庫的最新版本感興趣,你必須等到整個軟件包的更新。除非你在做前沿的統(tǒng)計研究,否則應(yīng)該沒有什么影響。
選擇開發(fā)環(huán)境
一旦安裝了Python,就有各種各樣的開發(fā)環(huán)境,以下是常見的3種:
- Terminal / Shell
- IDLE (默認)
- iPython notebook(類似R中的markdown)
正確的開發(fā)環(huán)境取決于你的需要,我個人更喜歡iPython Notebook。它有很多好的功能,編寫代碼時提供了文檔記錄功能,可以選擇運行代碼塊(而不是逐行執(zhí)行)。
我們將使用iPython開發(fā)環(huán)境完成本教程。
預(yù)熱:運行你的第一個Python程序
你可以使用Python作為簡單的計算器開始
提醒幾點
你可以在terminal / cmd上輸入“ipython notebook”來啟動iPython Notebook,這取決于你正在使用的操作系統(tǒng)。
可以通過點擊“UntitledO”來重命名。
界面顯示In [*]表示輸入,Out[*]表示輸出。
執(zhí)行當(dāng)前代碼塊按快捷鍵“Shift + Enter”,運行當(dāng)前塊并插入額外的塊按快捷鍵“ALT + Enter”。
在深入解決問題之前,讓我們回顧一下,了解Python的基礎(chǔ)知識。 我們知道數(shù)據(jù)結(jié)構(gòu)、迭代和條件結(jié)構(gòu)構(gòu)成任何語言的關(guān)鍵。 在Python中,這些包括列表,字符串,元組,字典,for循環(huán),while循環(huán),if-else等。我們來看看其中的一些。
Python庫及數(shù)據(jù)結(jié)構(gòu)
Python數(shù)據(jù)結(jié)構(gòu)
以下是一些在Python中使用的數(shù)據(jù)結(jié)構(gòu)。你應(yīng)該熟悉它們,以便適當(dāng)使用它們。
Lists – 列表是Python中最常用的數(shù)據(jù)結(jié)構(gòu)之一。 可以通過在方括號中寫入逗號分隔值的序列來簡單地定義列表。列表可以包含不同類型的項,但通常這些項都具有相同的類型。 Python列表是可變的,可以更改列表的各個元素。
下面是一個快速定義一個列表然后訪問它的例子:
Strings – 字符串可以簡單地通過使用單個(’),雙(“)或三個(’’’)的逗號來定義。 用三引號(’’’)括起來的字符串允許跨行,并且在文檔字符串中經(jīng)常使用(Python的記錄函數(shù)的方法)。 “\”用作轉(zhuǎn)義字符。 請注意,Python字符串是不可變的,因此不能更改字符串的一部分。
Tuples – 一個元組用逗號分隔的值來表示。元組是不可變的,輸出被圓括號包圍,以便嵌套元組被正確處理。 此外,即使元組是不可變的,如果需要,可以保存可變數(shù)據(jù)。
由于元組是不可變的,不能改變,與列表相比,它的處理速度更快。 因此,如果你的列表不太可能更改,應(yīng)該使用元組,而不是列表。
Dictionary – 字典是一組無序的鍵:值對,要求鍵是唯一的(在一個字典內(nèi))。一對大括號創(chuàng)建一個空字典:{}。
Python迭代和條件構(gòu)造
像大多數(shù)語言一樣,Python也有一個FOR循環(huán),它是最廣泛使用的迭代方法。它有一個簡單的語法:
- for i in [Python Iterable]:
- expression(i)
這里“Python Iterable”可以是列表,元組或其他高級數(shù)據(jù)結(jié)構(gòu),我們將在后面的部分中討論。我們來看一個簡單的例子,確定一個數(shù)字的階乘。
- fact = 1
- for i in range(1,N+1):
- fact *= i
根據(jù)條件語句,這些語句用于根據(jù)條件執(zhí)行代碼片段。最常用的結(jié)構(gòu)是if-else,具有以下語法:
- if [condition]:
- __execution if ture__
- else:
- __execution if false__
例如,如果我們要打印數(shù)字N是偶數(shù)還是奇數(shù):
- if N%2 == 0:
- print 'Even'
- else:
- print 'Odd'
現(xiàn)在,你已經(jīng)熟悉Python的基礎(chǔ)知識了,我們進一步了解一下,如果必須執(zhí)行以下任務(wù),該怎么辦?
1.兩個矩陣相乘
2.找到二次方程的根
3.繪制條形圖和直方圖
4.網(wǎng)頁訪問
如果你嘗試從頭開始編寫代碼,那將成為一場惡夢,你將在Python上不會堅持超過2天!但是不用擔(dān)心, 幸運的是,有許多預(yù)定義的庫,我們可以直接導(dǎo)入到我們的代碼中,使我們的編程工作變得容易。
例如,考慮我們剛剛看到的階乘例子。完成只需一個步驟:
- math.factorial(N)
當(dāng)然,我們需要導(dǎo)入math庫。我們來研究一下各種庫。
Python庫
通過了解一些有用的庫,將在我們學(xué)習(xí)Python的過程中領(lǐng)先一步。第一步顯然是學(xué)會將它們導(dǎo)入我們的環(huán)境中。在Python中有以下幾種方法:
- import math as m
- from math import *
在第一種方式中,我們定義了一個別名為m的math庫?,F(xiàn)在我們可以使用別名m.factorial()引用它,從math庫(例如階乘)中使用各種函數(shù)。
第二種方式,導(dǎo)入了math庫的整個名稱空間,即可以直接使用factorial()而不引用math。
提示:Google建議你使用第一種導(dǎo)入庫方式,因為你將知道函數(shù)來自哪里。
以下是庫列表,任何科學(xué)計算和數(shù)據(jù)分析會用到:
- NumPy:代表的是Numerical Python。NumPy最強大的功能是n維數(shù)組。該庫還包含基本的線性代數(shù)函數(shù),傅里葉變換,隨機數(shù)函數(shù)和與其他底層語言(如Fortran,C和C ++)集成的工具。
- SciPy:代表的是Scientific Python。SciPy建立在NumPy基礎(chǔ)上。它是離散傅里葉變換,線性代數(shù),優(yōu)化和稀疏矩陣等多種高級科學(xué)和工程模塊最有用的庫之一。
- Matplotlib:用于繪制各種各樣的圖形,從直方圖到線圖、熱力圖。你可以使用ipython notebook中的Pylab功能(ipython notebook -pylab = inline)在線使用這些繪圖功能。如果忽略內(nèi)聯(lián)選項,pylab將ipython環(huán)境轉(zhuǎn)換為與Matlab非常相似的環(huán)境。還可以使用Latex命令在圖像添加數(shù)學(xué)符號。
- Pandas:用于結(jié)構(gòu)化數(shù)據(jù)的運算和操作。廣泛用于數(shù)據(jù)整理和預(yù)處理。相較而言,Pandas被添加到Python時間不久,其有助于提高Python在數(shù)據(jù)科學(xué)社區(qū)的使用。
- Scikit:用于機器學(xué)習(xí)。該庫建立在NumPy,SciPy和matplotlib基礎(chǔ)上,包含許多有效的機器學(xué)習(xí)和統(tǒng)計建模工具,例如分類,回歸,聚類和降維。
- Statsmodels:用于統(tǒng)計建模。Statsmodels是一個Python中提供用戶探索數(shù)據(jù)、估計統(tǒng)計模型和執(zhí)行統(tǒng)計測試的模組??捎糜诓煌愋蛿?shù)據(jù)的描述性統(tǒng)計,統(tǒng)計測試,繪圖功能和結(jié)果統(tǒng)計。
- Seaborn:用于數(shù)據(jù)可視化。Seaborn是一個用于在Python中制作有吸引力和翔實的統(tǒng)計圖形庫。它是基于matplotlib。Seaborn旨在使可視化成為探索和理解數(shù)據(jù)的核心組成。
- Bokeh:用于在現(xiàn)代網(wǎng)絡(luò)瀏覽器上創(chuàng)建交互式圖表,儀表盤和數(shù)據(jù)應(yīng)用程序。它賦予用戶以D3.js的風(fēng)格生成優(yōu)雅簡潔的圖形。此外,它具有超大型或流式數(shù)據(jù)集的高性能交互能力。
- Blaze:將Numpy和Pandas的能力擴展到分布式和流式傳輸數(shù)據(jù)集。它可以用于從眾多來源(包括Bcolz,MongoDB,SQLAlchemy,Apache Spark,PyTables等)訪問數(shù)據(jù)。與Bokeh一起,Blaze可以作為在巨型數(shù)據(jù)塊上創(chuàng)建有效可視化和儀表盤的強大的工具。
- Scrapy:用于網(wǎng)絡(luò)爬蟲。它是獲取特定模式數(shù)據(jù)的非常有用的框架。它從網(wǎng)站首頁url開始,然后挖掘網(wǎng)站內(nèi)的網(wǎng)頁內(nèi)容來收集信息。
- SymPy:用于符號計算。它具有從基本算術(shù)符號到微積分,代數(shù),離散數(shù)學(xué)和量子物理學(xué)的廣泛能力。另一個有用的功能是將計算結(jié)果格式化為LaTeX代碼。
- Requests:用于web訪問。它類似于標準python庫urllib2,但是代碼更容易。你會發(fā)現(xiàn)與urllib2的微妙差異,但是對于初學(xué)者來說,Requests可能更方便。
你可能需要的額外的庫:
- os用于操作系統(tǒng)和文件操作
- networkx和igraph為基于圖的數(shù)據(jù)操作
- regular expressions用于在文本中查找特定模式的數(shù)據(jù)
- BeautifulSoup用于網(wǎng)絡(luò)爬蟲。它不如Scrapy,因為它只是單個網(wǎng)頁中提取信息。
既然我們熟悉Python基礎(chǔ)知識和庫,那么我們可以通過Python深入解決問題。做預(yù)測模型過程中,我們會使用到一些功能強大的庫,也會遇到不同的數(shù)據(jù)結(jié)構(gòu)。我們將帶你進入三個關(guān)鍵階段:
- 數(shù)據(jù)探索 – 詳細了解我們的數(shù)據(jù)
- 數(shù)據(jù)清洗 – 清理數(shù)據(jù),使其更適合統(tǒng)計建模
- 預(yù)測建模 – 運行實際算法并獲得結(jié)果
使用pandas進行數(shù)據(jù)探索
為了進一步探索我們的數(shù)據(jù),給你介紹另一個動物(好像Python還不夠!)- Pandas
Pandas是Python中最有好用的數(shù)據(jù)分析庫之一(我知道這些名字聽起來很奇怪,先這樣!)促使越來越多數(shù)據(jù)科學(xué)界人士使用Python?,F(xiàn)在我們將使用pandas從Analytics Vidhya比賽中讀取數(shù)據(jù)集,進行探索性分析,并構(gòu)建我們的第一個基礎(chǔ)分類算法來解決這個問題。
在數(shù)據(jù)加載之前,先了解Pandas中2個關(guān)鍵數(shù)據(jù)結(jié)構(gòu) – Series和DataFrames。
Series及DataFrame介紹
Series可以理解為1維標簽/索引數(shù)組。你可以通過這些標簽訪問series的各個元素。
Dataframe類似于Excel工作簿,列名稱引用列,使用行號訪問行。本質(zhì)區(qū)別在于dataframes中列名稱和行號稱為列和行索引。
Series和DataFrames構(gòu)成了Pandas在Python中的核心數(shù)據(jù)模型。數(shù)據(jù)集首先被讀入Dataframes,然后各種操作(例如分組、聚合等)可以非常容易地應(yīng)用于其列。
應(yīng)用案例 – 貸款預(yù)測問題
以下是變量的描述:
變量 | 描述 |
Loan_ID | 貸款I(lǐng)D |
Gender | 男/女 |
Married | 已婚(Y/N) |
Dependents | 贍養(yǎng)人數(shù) |
Education | 教育程度(Graduate/Under Graduate) |
Self_Employed | 自雇人士(Y/N) |
ApplicantIncome | 申報收入 |
CoapplicantIncome | 綜合收入 |
LoanAmount | 貸款金額 |
Loan_Amount_Term | 貸款月數(shù) |
Credit_History | 信用記錄 |
Property_Area | 房產(chǎn)位置(Urban/Semi Urban/Rural) |
Loan_Status | 貸款批準狀態(tài)(Y/N) |
開始數(shù)據(jù)探索
首先,在terminal/ Windows命令提示符下鍵入以下命令,以Inline Pylab模式啟動iPython界面:
- ipython notebook --pylab=inline
這樣在pylab環(huán)境中打開了iPython notebook,它已經(jīng)導(dǎo)入了一些有用的庫。此外,可以內(nèi)聯(lián)繪制數(shù)據(jù),這使得它成為一個非常好的交互式數(shù)據(jù)分析環(huán)境。 你可以通過鍵入以下命令(并獲得如下圖所示的輸出)來檢查環(huán)境是否加載正確:
- plot(arange(5))
我當(dāng)前在Linux中工作,并將數(shù)據(jù)集存儲在以下位置: /home/kunal/Downloads/Loan_Prediction/train.csv
導(dǎo)入庫和數(shù)據(jù)集:
以下是我們將在本教程中使用的庫:
- numpy
- matplotlib
- pandas
請注意,由于Pylab環(huán)境,你不需要導(dǎo)入matplotlib和numpy。我仍然將它們保留在代碼中,以便在不同的環(huán)境中使用代碼。
導(dǎo)入庫后,使用函數(shù)read_csv()讀取數(shù)據(jù)集。代碼如下:
- import pandas as pd
- import numpy as np
- import matplotlib as plt
- df = pd.read_csv("/home/kunal/Downloads/Loan_Prediction/train.csv") #使用Pandas讀入數(shù)據(jù)集轉(zhuǎn)換成dataframe
快速數(shù)據(jù)探索
讀取數(shù)據(jù)集后,可以使用head()函數(shù)查看前幾行
- df.head(10)
這樣輸出了10行,或者,也可以打印查看更多行數(shù)據(jù)集。
接下來,可以使用describe()函數(shù)來查看數(shù)值字段的摘要
- df.describe()
describe()函數(shù)將在其輸出中提供計數(shù)、平均值、標準偏差(std)、最小值、四分位數(shù)和最大值。
這里有幾個發(fā)現(xiàn),你可以通過看看describe()函數(shù)的輸出來繪制:
1.LoanAmount有(614 – 592)22個缺失值。
2.Loan_Amount_Term有(614 – 600)14個缺失值。
3.Credit_History有(614 – 564)50個缺失值。
4.我們也可以看到,約84%的申請人有信用記錄,怎么樣?Credit_History字段的平均值為0.84(記住,Credit_History對于具有信用記錄的用戶而言為1,否則為0)
5.申請人收入分布似乎符合預(yù)期。與CoapplicantIncome相同。
請注意,我們可以通過比較平均值與中位數(shù)來了解數(shù)據(jù)中可能的偏差。
對于非數(shù)值(例如Property_Area,Credit_History等),我們可以查看頻率分布來了解它們是否有意義。頻率表可以通過以下命令打印輸出:
- df['Property_Area'].value_counts()
同樣,我們可以看看信用歷史的獨特價值。請注意,dfname [‘column_name’]是一種基本的索引方法來訪問dataframe的特定列。它也可以是一個列名的列表。
分布分析
現(xiàn)在我們熟悉基本的數(shù)據(jù)特征,我們來研究各種變量的分布。從數(shù)字變量ApplicantIncome和LoanAmount開始。
首先使用以下命令繪制ApplicantIncome的直方圖:
- df['ApplicantIncome'].hist(bins=50)
在這里我們觀察到很少極端值。這也是為什么需要50個箱子來明確分配分配的原因。
接下來,我們來看一下箱線圖來了解分布。箱線圖可以通過以下方式繪制:
- df.boxplot(column='ApplicantIncome')
這證實了許多異常值/極端值的存在。這可歸因于社會的收入差距。部分原因可能是由于我們研究了不同教育水平的人。通過教育變量將其分離開:
- df.boxplot(column='ApplicantIncome', by = 'Education')
我們可以看到大學(xué)學(xué)歷和非大學(xué)學(xué)歷的平均收入之間沒有實質(zhì)性差異。但是,高學(xué)歷中高收入人數(shù)更多,這似乎是離群值。
現(xiàn)在,我們來看看變量LoanAmount的直方圖和boxplot,使用以下命令:
- df['LoanAmount'].hist(bins=50)
- df.boxplot(column='LoanAmount')
再次,有一些離群值。顯然,ApplicantIncome和LoanAmount都需要一定量的數(shù)據(jù)清洗。 LoanAmount有缺失值和離群值,同時,ApplicantIncome有一些離群值,接下來我們將分幾個部分,做更深入的了解。
分類變量的分析
現(xiàn)在我們了解ApplicantIncome和LoanIncome的分布,為了更詳細地理解分類變量,我們將使用Excel的透視表和交叉表。例如,我們來看根據(jù)信用記錄獲得貸款的機會,這可以在MS Excel中使用數(shù)據(jù)透視表來實現(xiàn):
注意:這里的貸款狀態(tài)重編碼了,1代表是,0代表否,平均值表示貸款的概率。
現(xiàn)在我們將看看使用Python生成類似洞察所需的步驟。
- temp1 = df['Credit_History'].value_counts(ascending=True)
- temp2=df.pivot_table(values='Loan_Status',index=['Credit_History'],aggfunc=lambda x: x.map({'Y':1,'N':0}).mean())
- print 'Frequency Table for Credit History:'
- print temp1
- print '\nProbility of getting loan for each Credit History class:'
- print temp2
現(xiàn)在可以看到,我們得到一個類似MS Excel一樣的透視表,這可以使用“matplotlib”庫,用以下代碼畫條形圖:
- import matplotlib.pyplot as plt
- fig = plt.figure(figsize=(8,4))
- ax1 = fig.add_subplot(121)
- ax1.set_xlabel('Credit_History')
- ax1.set_ylabel('Count of Applicants')
- ax1.set_title("Applicants by Credit_History")
- temp1.plot(kind='bar')
- ax2 = fig.add_subplot(122)
- temp2.plot(kind = 'bar')
- ax2.set_xlabel('Credit_History')
- ax2.set_ylabel('Probability of getting loan')
- ax2.set_title("Probability of getting loan by credit history")
這表明如果申請人有有效的信用記錄,獲得貸款的機會是沒有有效信用記錄的8倍。你可以通過已婚,自雇,居住地區(qū)等繪制相似的圖表。
或者,這兩個圖也可以通過將它們組合在堆疊圖表中來進行可視化:
- temp3 = pd.crosstab(df['Credit_History'], df['Loan_Status'])
- temp3.plot(kind='bar', stacked=True, color=['red','blue'], grid=False)
還可以添加性別(類似于Excel中的數(shù)據(jù)透視表):
如果你還沒有意識到,我們在這里創(chuàng)建了兩個基本的分類算法,一個基于信用記錄,另一個基于2分類變量(包括性別)。你可以快速編碼,以便在AV Datahacks上創(chuàng)建你的第一次提交版本。
我們看到如何在Python中使用pandas進行探索性數(shù)據(jù)分析,希望你對pandas(熊貓)的愛將會增加,pandas庫為你的數(shù)據(jù)集分析提供一些幫助。
接下來,我們進一步探討ApplicantIncome和LoanStatus變量,執(zhí)行數(shù)據(jù)運算并創(chuàng)建一個數(shù)據(jù)集以應(yīng)用各種建模技術(shù)。強烈建議再選擇一個數(shù)據(jù)集和問題,閱讀一個獨立的例子,然后再做進一步分析。
python數(shù)據(jù)清洗:Pandas
對于從事數(shù)據(jù)分析的人來說,下面這些是你必須要做的。
數(shù)據(jù)清洗 – 重構(gòu)數(shù)據(jù)
在數(shù)據(jù)探索時,為了構(gòu)建一個好的模型,需要先解決掉數(shù)據(jù)集中發(fā)現(xiàn)了的一些問題。這個過程通常稱為“數(shù)據(jù)清洗”。針對以下問題,我們看到:
1.變量缺失值。我們應(yīng)該根據(jù)缺失值的數(shù)量和變量的預(yù)期重要性明智地估計這些值。
2.在分析這些分布的同時,我們看到變量ApplicantIncome和LoanAmount似乎都包含了離群值。雖然他們可能會有直觀的意義,但應(yīng)該得到適當(dāng)?shù)奶幚怼?/p>
除了這些數(shù)值型的數(shù)據(jù)問題之外,我們還應(yīng)該關(guān)注非數(shù)值型數(shù)據(jù),如性別、區(qū)域、已婚、教育程度和贍養(yǎng)人數(shù),用以挖掘任何有用的信息。
檢查數(shù)據(jù)集中的缺失值
一起看看所有變量中的缺失值,因為大多數(shù)模型不能使用含缺失值的數(shù)據(jù),缺失值填補很重要。所以,我們檢查數(shù)據(jù)集中的null / NaN的數(shù)量。
- df.apply(lambda x: sum(x.isnull()),axis=0)
如果值為null則isnull()返回1,那么該命令計算出每個列中缺失值的數(shù)量。
雖然缺失值數(shù)量不是很多,但是大多變量都有缺失值,需要估算并填補缺失值。
注意:缺失值可能并不總是NaN。例如,如果Loan_Amount_Term為0,那么是否有意義,或者是否是缺失值?我想你的答案是缺失值,你是對的。所以我們應(yīng)該檢查數(shù)據(jù)是否有實際意義。
如何填補LoanAmount中的缺失值?
有許多方法來填補貸款額度的缺失值,最簡單的是用均值替換,可以通過以下代碼來完成:
- df['LoanAmount'].fillna(df['LoanAmount'].mean(), inplace=True)
另外也可以是建立一個監(jiān)督學(xué)習(xí)模型,以其他變量如年齡等為基礎(chǔ)預(yù)測貸款額度。
既然現(xiàn)在是數(shù)據(jù)清洗的步驟,我寧愿采取介于兩者之間的一種方法。一個關(guān)鍵的假設(shè)是,一個人教育程度或者個體經(jīng)營戶與否,可以結(jié)合起來給出一個很好的貸款額度的估計。
首先,我們來看一下箱線圖,看看是否存在趨勢規(guī)律:
因此,我們看到每個組的貸款額中位數(shù)有一些變化,可以用來作估算值。但是,我們必須先確保Self_Employed和Education變量中的每一個都不應(yīng)該有缺少值。
如前所述,Self_Eployee有一些缺失的值。看看頻率表:
大約86%的值為“No”,將缺失值估計為“No”是安全的,因為正確的概率會更高??梢允褂靡韵麓a完成:
- df['Self_Employed'].fillna('No',inplace=True)
現(xiàn)在,我們將創(chuàng)建一個數(shù)據(jù)透視表,它提供了貸款額度中位數(shù)按Self_Eployed和Education交叉分組。接下來,我們定義一個函數(shù),它返回這些單元格的值并應(yīng)用它來填補貸款金額的缺失值:
- table = df.pivot_table(values='LoanAmount', index='Self_Employed' ,columns='Education', aggfunc=np.median)
- # Define function to return value of this pivot_table
- def fage(x):
- return table.loc[x['Self_Employed'],x['Education']]
- # Replace missing values
- df['LoanAmount'].fillna(df[df['LoanAmount'].isnull()].apply(fage, axis=1), inplace=True)
這樣為你提供一個很好的方式來估算貸款額度的缺失值。
如何處理LoanAmount和ApplicantIncome分布中的極端值?
我們首先分析LoanAmount。 極端值可能有實際意義的,有些人可能因為特殊需要才申請高額貸款,所以不用把它們視為離群值,我們來嘗試用對數(shù)變換來消除它們的影響:
- df['LoanAmount_log'] = np.log(df['LoanAmount'])
- df['LoanAmount_log'].hist(bins=20)
再次查看直方圖:
現(xiàn)在分布看起來更加接近正態(tài)分布,極端值的影響已經(jīng)顯示減弱。
對于變量ApplicantIncome,一個可能的直覺是,一些申請人申報收入較低,但是綜合收入高也獲得支持。所以把申報收入作為總收入結(jié)合在一起是一個好主意,并采取同樣的對數(shù)變換。
- df['TotalIncome'] = df['ApplicantIncome'] + df['CoapplicantIncome']
- df['TotalIncome_log'] = np.log(df['TotalIncome'])
- df['LoanAmount_log'].hist(bins=20)
現(xiàn)在我們看到分布比以前好多了。我會把性別、已婚、贍養(yǎng)者、貸款月數(shù)、信用歷史等缺失值的估算留給大家完成。此外,我鼓勵大家考慮可能從數(shù)據(jù)中發(fā)掘附加信息,例如,創(chuàng)建列LoanAmount / TotalIncome可能是有道理的,因為它給出了申請人如何適應(yīng)償還貸款的想法。
接下來,我們將看看創(chuàng)建預(yù)測模型。
在Python中構(gòu)建一個預(yù)測模型
現(xiàn)在,我們已經(jīng)有對建模有用的數(shù)據(jù),現(xiàn)在我們來看看python代碼,在我們的數(shù)據(jù)集上創(chuàng)建一個預(yù)測模型。Skicit-Learn(sklearn)是Python中最常用的機器學(xué)習(xí)庫,我們將會借助它來建模。
既然,sklearn要求所有輸入都是數(shù)字,所以我們應(yīng)該對類別進行編碼,將所有的分類變量轉(zhuǎn)換為數(shù)值變量。這可以使用以下代碼完成:
- from sklearn.preprocessing import LabelEncoder
- var_mod = ['Gender','Married','Dependents','Education','Self_Employed','Property_Area','Loan_Status']
- le = LabelEncoder()
- for i in var_mod:
- df[i] = le.fit_transform(df[i])
- df.dtypes
接下來,我們將導(dǎo)入所需的模塊。然后我們將定義一個通用分類函數(shù),它將模型作為輸入,并確定準確度和交叉驗證得分。既然這是一個介紹性的文章,我將不再贅述編碼的細節(jié)。
- #Import models from scikit learn module:
- from sklearn.linear_model import LogisticRegression
- from sklearn.cross_validation import KFold #For K-fold cross validation
- from sklearn.ensemble import RandomForestClassifier
- from sklearn.tree import DecisionTreeClassifier, export_graphviz
- from sklearn import metrics
- #Generic function for making a classification model and accessing performance:
- def classification_model(model, data, predictors, outcome):
- #Fit the model:
- model.fit(data[predictors],data[outcome])
- #Make predictions on training set:
- predictions = model.predict(data[predictors])
- #Print accuracy
- accuracy = metrics.accuracy_score(predictions,data[outcome])
- print "Accuracy : %s" % "{0:.3%}".format(accuracy)
- #Perform k-fold cross-validation with 5 folds
- kf = KFold(data.shape[0], n_folds=5)
- error = []
- for train, test in kf:
- # Filter training data
- train_predictors = (data[predictors].iloc[train,:])
- # The target we're using to train the algorithm.
- train_target = data[outcome].iloc[train]
- # Training the algorithm using the predictors and target.
- model.fit(train_predictors, train_target)
- #Record error from each cross-validation run
- error.append(model.score(data[predictors].iloc[test,:],data[outcome].iloc[test]))
- print "Cross-Validation Score : %s" % "{0:.3%}".format(np.mean(error))
- #Fit the model again so that it can be refered outside the function:
- model.fit(data[predictors],data[outcome])
邏輯回歸
我們來做第一個邏輯回歸模型。一種方法是將所有變量都放入模型中,但這可能會導(dǎo)致過擬合。 簡單來說,模型采用所有變量,有可能理解數(shù)據(jù)的特定的復(fù)雜關(guān)系,并不能很好地推廣。
我們可以很容易地做出一些直觀的假設(shè),獲得貸款的機會會更高:
1.具有信用記錄的申請人
2.具有較高申請收入和綜合收入的申請人
3.高等教育水平的申請人
4.具有高增長前景的城市地產(chǎn)
我們用’Credit_History’做我們的第一個模型。
- outcome_var = 'Loan_Status'
- model = LogisticRegression()
- predictor_var = ['Credit_History']
- classification_model(model, df,predictor_var,outcome_var)
準確度:80.945%,交叉驗證得分:80.946%
- #We can try different combination of variables:
- predictor_var = ['Credit_History','Education','Married','Self_Employed','Property_Area']
- classification_model(model, df,predictor_var,outcome_var)
準確度:80.945%交叉驗證得分:80.946%
一般來說,我們期望通過增加變量數(shù)量來提高準確度,但這是一個更具挑戰(zhàn)性的案例,準確度和交叉驗證得分不受重要性較小的變量的影響。信用歷史是主導(dǎo)模式。我們現(xiàn)在有兩個選擇:
1.特征工程:挖掘新信息,并嘗試預(yù)測。這個留給大家去發(fā)揮創(chuàng)造力。
2.更好的建模技術(shù)。接下來我們來探討一下。
決策樹
決策樹是構(gòu)建預(yù)測模型的另一種方法,通常比邏輯回歸模型具有更高的精度。
- model = DecisionTreeClassifier()
- predictor_var = ['Credit_History','Gender','Married','Education']
- classification_model(model, df,predictor_var,outcome_var)
準確度:81.930%,交叉驗證得分:76.656%
這里,基于分類變量的模型不會受信用歷史產(chǎn)生影響。我們來嘗試幾個數(shù)值型變量:
- #We can try different combination of variables:
- predictor_var = ['Credit_History','Loan_Amount_Term','LoanAmount_log']
- classification_model(model, df,predictor_var,outcome_var)
準確度:92.345%交叉驗證得分:71.009%
在這里我們觀察到,添加變量后模型準確度上升,交叉驗證錯誤率下降。這是模型數(shù)據(jù)過擬合的結(jié)果。我們嘗試一個更復(fù)雜的算法,看看是否有幫助。
隨機森林
隨機森林是解決分類問題的另一種算法。
隨機森林的一個優(yōu)點是我們可以將所有特征放在一起,并返回一個可用于選擇的特征重要性矩陣。
- model = RandomForestClassifier(n_estimators=100)
- predictor_var = ['Gender', 'Married', 'Dependents', 'Education',
- 'Self_Employed', 'Loan_Amount_Term', 'Credit_History', 'Property_Area',
- 'LoanAmount_log','TotalIncome_log']
- classification_model(model, df,predictor_var,outcome_var)
準確度:100.000%交叉驗證得分:78.179%
訓(xùn)練集的準確度是100%,這是過擬合的最終結(jié)果,可以通過兩種方式解決:
1.減少預(yù)測數(shù)量
2.調(diào)整模型參數(shù)
我們來試試這兩種方法,首先我們看到特征重要性矩陣,我們將從中篩選最重要的特征變量。
- #Create a series with feature importances:
- featimp = pd.Series(model.feature_importances_, index=predictor_var).sort_values(ascending=False)
- print featimp
我們使用前5個變量來創(chuàng)建一個模型。另外,我們將修改一點點隨機森林模型的參數(shù):
- model = RandomForestClassifier(n_estimators=25, min_samples_split=25, max_depth=7, max_features=1)
- predictor_var = ['TotalIncome_log','LoanAmount_log','Credit_History','Dependents','Property_Area']
- classification_model(model, df,predictor_var,outcome_var)
準確度:82.899%,交叉驗證得分:81.461%
雖然準確度降低,但交叉驗證分數(shù)在提高,表明該模型的適用性很好。記住,隨機森林模型不是完全可復(fù)用的。不同的變量運行結(jié)果會有變化,但輸出盡量保持正確。
你會注意到,即使在對隨機森林進行了一些基本的參數(shù)調(diào)整之后,我們交叉驗證的精度只比原始邏輯回歸模型略好一些。這個案例給了我們一些非常有趣、特別的學(xué)習(xí)體驗:
1.使用更復(fù)雜的模型不能保證更好的預(yù)測結(jié)果。
2.避免使用復(fù)雜的建模技術(shù)作為黑盒子而不了解基本概念。這樣做會增加過擬合趨勢,從而降低模型解釋力。
3.特征工程是成功的關(guān)鍵。大家可以使用Xgboost模型,但真正的藝術(shù)和創(chuàng)造力在于增強特征能力以更好地適應(yīng)模型。
你準備好迎接挑戰(zhàn)嗎?借助貸款預(yù)測問題開始數(shù)據(jù)科學(xué)之旅。
結(jié)束教程
我希望本教程將幫助你在使用Python開展數(shù)據(jù)科學(xué)分析時能最大限度地提高效率。我相信,這不僅給你提供一個基本的數(shù)據(jù)分析方法的引導(dǎo),而且還向你展示了如何實現(xiàn)一些更先進的編程技術(shù)。
Python真的是一個強大的工具,并且日益成為數(shù)據(jù)科學(xué)家中流行的編程語言。原因在于Python很容易學(xué)習(xí),與其他數(shù)據(jù)庫和工具(如Spark和Hadoop)集成很好。最主要還是因為Python具有很強的計算能力和強大的數(shù)據(jù)分析庫。
學(xué)習(xí)利用Python來完成任何數(shù)據(jù)科學(xué)項目的完整過程包括閱讀、分析、可視化和結(jié)果預(yù)測。