本文首發在集智專欄
本文較長,全是乾貨,建議收藏後作為長期的學習指南。
前段時間我們分享過如何一步步通過Python成為資料分析高手:戳這裡
不過這篇指南只是從巨集觀上指引了大家的學習步驟以及通過哪些資源學習,我們今天接著詳細談談怎樣依靠Python從零開始成為一名資料分析師,期間會以一個借貸資料集為例,分享利用Python進行資料分析所需的基礎知識和工具,相信能為你藉助Python迅速成為資料分析師提供一些幫助。
內容目錄
1.用於資料分析的Python基本知識
- 為何學習Python用於資料分析?
- 怎樣安裝Python?
- 用Python做一些簡單的專案
2.Python庫和資料結構
- Python資料結構
- Python迭代和條件構造
- 用於資料分析的Python庫
3.利用Python和Pandas進行探索性資料分析
- Pandas的Series和Dataframe入門簡介
- 以借貸資料集為例完成資料分析專案
4.用Python的Pandas進行資料再加工
- 如何推定缺失值
- 如何應對極值
5.用Python建立預測模型,根據資料做預測
- 邏輯迴歸模型
- 決策樹模型
- 隨機森林模型
集智注:本文原作者為資料科學家Kunal Jain,其畢業於印度最頂尖的IT院校印度理工學院,從事資料科學領域已逾10年,在英國和印度等多家大型跨國公司擔任資深資料分析師。
大概幾年前,在SAS領域工作了5年後,我(作者Kunal Jain——譯者注)決定走出我的舒適區,勵志成為一名資料科學家。在多方尋找能助我成為資料科學家的學習工具後,我最終決定選擇Python。
我一直都很喜歡寫程式碼,這是我內心的熱愛。
我花了大概一週的時間學習了Python的基礎知識,然後不僅我自己深入掌握了這門語言,還幫助了其他人也學習了Python。最初Python是一種通用語言,但是隨著這些年的發展和強大的社群支援,Python湧現了很多用於資料分析和預測建模的程式庫。
由於很多人尚不知道如何將Python用於資料科學以及缺少相關的資源,我決定寫這篇教程,幫更多人更快的學習Python。在教程中,我也會教大家如何用Python進行資料分析,最終熟練掌握,為己所用。
1.Python用於資料分析的基本知識
為何學習Python用於資料分析?
近年來,Python被很多人選擇用於資料分析,我將它和SAS、R語言做了一番比較,覺得以下是你學習Python用於資料分析的好處:
- 開源——免費安裝和使用
- 很強大的線上社群支援
- 非常容易學習(沒任何程式設計基礎也能很快上手)
- 能成為資料科學和部署基於資料分析產品的通用語言
當然也存在一些缺點:
它是一門解釋性語言而非編譯語言,因此會花費更多的CPU時間。不過考慮到我們能大幅節約程式設計學習時間(因為很容易學),兩者相抵,這算不上是什麼大缺點。
怎樣安裝Python?
安裝Python有2種方法:
1.你可以從Python的專案網站(https://www.python.org/download/releases/2.7/)直接下載,安裝你需要的各個元件和庫。
2.你也可以下載和安裝程式包,裡面內建了預先安裝的庫。我建議下載Anaconda。另一個選擇是Enthought Canopy Express。第二種方法提供無憂安裝,所以我建議初學者選這種方法。這種方法的缺點就是你必須等待整個包升級完畢,哪怕你只是對某個庫的最新版感興趣。
選擇開發環境
一旦安裝好Python,選擇開發環境時也有多種選項。這裡是3個最常見的選項:
- 基於終端和Shell
- IDLE(預設環境)
- iPython notebook——相當於R語言中的Markdown
雖然應該根據自己的需要選擇正確的環境,但我個人更喜歡iPython notebook一些。 它提供了很多很好的功能供你在寫程式碼時寫文件,你還可以選擇以程式碼塊的方式執行程式碼(而不是逐行執行)。
本文的整篇教程我們都會使用iPython環境。
熱身:執行你的第一個Python專案
你可以首先用Python寫一個簡單的計算器:
需要注意的一些事情:
- 根據所用作業系統,你可以在你的terminal/cmd上編寫“ipython notebook”啟動ipython notebook。
- 你可以在名稱上簡單點選就可以命名一個iPython notebook——例如上面截圖中的UntitledO。
- 如果你想在後面插入一行額外行,可以通過按“shift+Enter”或“ALT+Enter”執行程式碼。
在我們深入解決問題前,先後退一步瞭解一下Python的基礎知識。我們知道資料結構、迭代和條件結構是任何程式語言的關鍵。在Python中,這些資訊包括列表,字串,元組,字典,for迴圈,while迴圈,if-else等等。我們看看其中一些。
2.Python 庫和資料結構
Python 資料結構
下面是Python中用到的一些資料結構。你應該對它們非常熟悉,以便後面能正確使用它們。
列表——列表是Python中最為通用的資料結構之一。在方括號內寫一列常見的逗號分隔的值就能簡單定義一個列表。列表可能包含不同型別的資料項,但通常資料項都屬相同的型別。 Python列表是可變的,列表中的單個元素可以改變。
下面是在Python中定義一個列表並獲取列表的示例:
字串——使用單引號(‘),雙引號(“)或三引號(“ ‘)定義字串。以三引號結尾的字串可以橫跨多個程式碼行,在docstrings(Python中註釋函式的一種方法)中使用非常頻繁。\被用作轉義字元。注意Python字串是不可變的,所以你不能更改字串內容。
元組——元組由若干被逗號分隔的值表示。元組是不可變的,輸出被圓括號括起,因此要正確處理巢狀元組。此外,雖然元素是不可變的,如果有需要,它們也能包含可變資料。而由於元組不可變的特點,它們在處理方面要快於列表。所以,如果你的列表無法改變,就應該使用元組而非列表。
字典——字典是一種可變容器模型,且可儲存任意型別物件。 字典的每個鍵值 key=>value 對用冒號 : 分割,每個鍵值對之間用逗號 , 分割,整個字典包括在花括號 {} 中。一對花括號就能建立一個空字典:{}。
Python迭代和條件結構
和大多數語言一樣,Python也有for迴圈,是Python迭代中應用最廣泛的一種方法。它的語法比較簡單:
for i in [Python Iterable]:
expression(i)
複製程式碼
這裡的“Python iterable”可以是個列表,元組或其它高階的資料結構,我們在下一部分會講到。我們先看一個簡單的例子,確定一個數字的階乘。
fact=1
for i in range(1,N+1):
fact *= i
複製程式碼
至於條件語句,它們是用於根據一定條件來執行程式碼片段。最常用的結構是if-else,語法如下:
if [condition]:
__execution if true__
else:
__execution if false__
複製程式碼
例如,如果我們想列印數字N是偶數還是奇數,程式碼這樣寫就可以了:
if N%2 == 0:
print 'Even'
else:
print 'Odd'
複製程式碼
現在你已經熟悉了Python的基本知識點,下面我們更近一步。如果你有以下一些任務,該怎麼辦:
- 相乘2個矩陣
- 求解一元二次方程的根
- 繪出條形圖和直方圖
- 建立統計模型
- 獲取網頁
如果你試圖從頭開始寫程式碼完成它們,那這任務量簡直是噩夢一般的大,肯定沒兩天你就堅持不下去了。不過不用太擔心,幸好有很多預定義的Python庫,我們在程式碼中可以直接匯入它們,讓我們的任務更輕鬆容易。 例如,拿我們上面所舉的階乘例子來說,我們只需一步即可:
math.factorial(N)
複製程式碼
當然我們需要匯入math庫來解決這個問題。我們在下部分就講解一些程式庫。
Python庫
在這部分,我們會認識一些實用的Python庫。很顯然第一步是學習怎麼將它們匯入到我們的環境中,有好幾種方法:
import math as m
複製程式碼
from math import *
複製程式碼
在第一種方法中,我們為庫math定義了一個別名m,我們現在可以通過用alias m.factorial()來引用math庫來使用它內部的多種函式(比如factorial)。
在第二種方法中,我們匯入了math中的整個名字空間,也就是說可以無需引用math直接使用factorial()。
小提示:谷歌建議大家使用第一種匯入庫的方法,因為這樣你能知道函式來自哪裡。
下面是一系列的程式庫,不管是你做任何資料分析工作都會用到它們,所以務必熟練掌握:
- Numpy:Python語言的一個擴充程式庫。支援高階大量的維度陣列與矩陣運算,此外也針對陣列運算提供大量的數學函式庫。
- SciPy:構建於NumPy之上,提供了一個用於在Python中進行科學計算的工具集,如數值計算的演算法和一些功能函式,可以方便的處理資料。
- Matplotlib:一個 Python 的 2D繪相簿,它以各種硬拷貝格式和跨平臺的互動式環境生成出版質量級別的圖形。通過 Matplotlib,開發者可以僅需要幾行程式碼,便可以生成繪圖,直方圖,功率譜,條形圖,錯誤圖,散點圖等。
- Pandas:基於NumPy 的一種工具,該工具是為了解決資料分析任務而建立的。Pandas 納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的工具。pandas提供了大量能使我們快速便捷地處理資料的函式和方法。
- Scikit Learn:用Python開發的機器學習庫,其中包含大量機器學習演算法、資料集,是資料探勘方便的工具。
- Statsmodels:一個包含統計模型、統計測試和統計資料探勘python模組。對每一個模型都會生成一個對應的統計結果。統計結果會和現有的統計包進行對比來保證其正確性。
- Seaborn:用於統計資料視覺化的一款Python視覺化工具。依靠它,你可以用Python繪出非常美觀、直觀和吸引人的圖形。是從事資料分析和挖掘工作的利器。
- Bokeh:一款互動式視覺化Python包,能夠在瀏覽器上建立互動式圖形、資料皮膚和資料應用。
- Blaze:能夠擴充套件Numpy和Pandas處理分散式和流媒體資料集的能力。可以用於從包括Bcolz,MongoDB,SQLAIchemy,Apache Spark PyTables等多維資料來源中獲取資料。和Bokeh一起使用時,Blaze能夠作為一種非常強大資料,幫我們繪製大量資料的視覺化圖。
- Scrapy:用於Python開發的一個快速、高層次的螢幕抓取和web抓取框架,用於抓取web站點並從頁面中提取結構化的資料。Scrapy用途廣泛,可以用於資料探勘、監測和自動化測試。
- SymPy:用於符號計算的Python庫,包括了積分,微分方程等各種數學運算方法,為python提供了強大的數學運算支援。
- Requests:是用Python語言編寫,基於 urllib,採用 Apache2 Licensed 開源協議的 HTTP 庫。它比 urllib 更加方便,可以節約我們大量的工作,完全滿足 HTTP 測試需求。
還有其他一些可能會用到的庫:
- os用於作業系統和檔案操作
- Networkx和igraph用於基於資料操作的圖形
- Regular expressions用於發現文字資料中的模式
- BeautifulSoup用於爬取網路資料。
以上這些所有程式庫在學習初期不必全部掌握,視自己需求學習即可,但是像Numpy,Pandas這樣的資料探勘和分析工具,必須熟悉使用。
到了這裡我們已經學習了Python基礎知識和一些程式庫,下面我們深入瞭解一下如何用Python解決問題。沒錯,用Python建立預測模型!在這個過程中,我們會用到一些強大的程式庫,也會涉及更高層次的Python資料結構。主要有3個階段:
- 資料探索——探索我們手中資料的更多資訊
- 資料再加工——清洗資料,處理資料,讓資料更適合統計建模
- 預測建模——執行演算法,從資料中獲取有趣有意義的結果
3.使用Python和Pandas對資料進行探索性分析
為了進一步挖掘我們的資料,我們要用到Pandas。
Pandas是Python中一款最實用的資料分析庫。下面我們會用Pandas從Analytic Vidhya大賽資料中讀取資料集,對所得資料進行探索性分析,並建立簡單的分類演算法解決這個問題。
在我們載入資料之前,先理解Pandas中兩個關鍵的資料結構——Series和dataframes 。
Series和Dataframes簡介
Series可以理解為一個1維的標籤或索引陣列,你可以通過series中單個元素的標籤獲取它們。
Dataframe和Excel表很像,我們有列名指代列,也有行,使用行號就能獲取它。不過在dataframe中,列名和行號都是列和行索引。
Series和dataframe組成了Python庫Pandas的核心資料模式。首先Pandas會將資料集讀取為dataframe格式,然後就能很容易地應用各種各樣的操作,比如分組、聚集等等。
如果你對Pandas不是很熟悉,可以檢視這篇10分鐘Pandas入門教程: https://jizhi.im/blog/post/10min2pandas01
練習資料集——借貸預測問題
我們從這裡下載資料,下面是變數描述:
我們開始探索資料。
首先,在你的terminal或Windows命令列輸入以下內容,啟動Pylab模式下的iPython介面:
ipython notebook --pylab=inline
複製程式碼
這會在Pylab環境中開啟ipython notebook,其中內建了一些很有用的庫。而且,你能在行內繪製資料,從而使其非常適合互動式資料分析。可以輸入以下程式碼,檢查環境是否正確載入:
plot(arange(5))
複製程式碼
我當前在Linux上工作,已將資料儲存在如下位置: /home/kunal/Downloads/Loan_Prediction/train.csv
匯入程式庫和資料集:
我們本教程會用到如下程式庫:
- Numpy
- Matplotlib
- Pandas
請注意,因為使用Pylab環境,你無需匯入matplotlib和Numpy。我將它們保留在了程式碼中,以防你在其它環境下使用本程式碼。
匯入庫以後,我們用函式read_csv()讀取資料集。到這個階段為止程式碼如下所示:
import pandas as pd
import numpy as np
import matplotlib as plt
df = pd.read_csv("/home/kunal/Downloads/Loan_Prediction/train.csv") #Reading the dataset in a dataframe using Pandas
複製程式碼
快速資料探索
讀取資料集後,我們就可以用函式head()檢視頂部幾行。
df.head(10)
複製程式碼
應該會列印10行。你也可以通過列印資料集檢視更多行。接著,你通過使用describe()函式檢視數值欄位的總結。
df.describe()
複製程式碼
describe()函式可以在其輸出中展示計數、平均值、標準方差、最小值、最大值等。
通過檢視describe()函式的輸出,我們可以發現如下資訊:
LoanAmount有22個缺失值
Loan_Amount_Term有14個缺失值
Credit_History有50個缺失值
我們還可以看到84%的客戶有credit_history。
怎麼來的?
Credit_History欄位的平均值為0.84. Applicantlncome分佈似乎和預期一致,Coapplicantlncome也是如此。
注意我們通過將平均值和中位數比較,也能看到資料中可能出現了偏差。
對於非數字值(比如Property_Area,Credit_History等),我們可以檢視頻率分佈以理解它們是否合理。可以通過如下命令列印頻率表:
df['Property_Area'].value_counts()
複製程式碼
同樣,我們也能檢視Credit_History的特殊值。
注意dfname[‘column_name’]是一個基本的索引技巧用以獲取dataframe的具體列。它也可以是列的列表。
分佈分析:
現在我們已經瞭解了基本的資料特徵,接著來學習多種變數的分佈。我們先從數值變數開始,即Applicantlncome和LoanAmount。
我們先用如下命令繪製Applicantlncome的直方圖:
df['ApplicantIncome'].hist(bins=50)
複製程式碼
這裡我們觀察到有少數極值,這也是為何我們需要用50個bins來清楚地描繪分佈情況。
接著,我們檢視箱型圖來理解資料的分佈。用如下命令可以繪製箱型圖:
df.boxplot(column='ApplicantIncome')
複製程式碼
這確認了資料中有很多異常值,從中也反映出社會上收入差距很大,這或許是因為人們的受教育水平不同。我們通過Education將他們進行分離:
df.boxplot(column='ApplicantIncome', by = 'Education')
複製程式碼
我們可以看到受過高等教育的群體和未受過高等教育的群體的平均收入並未有顯著差異。但受過高等教育的群體中高收入者更多,有些收入非常之高,成為資料中的異常值。
現在,我們用以下命令檢視LoanAmount的直方圖和箱型圖:
df['LoanAmount'].hist(bins=50)
複製程式碼
df.boxplot(column='LoanAmount')
複製程式碼
我們再次發現了一些極端值。很明顯,Applicantlncome和LoanAmount需要一些資料再加工。LoanAmount中包含缺失值和不少極值,而Applicantlncome中的極值要少一些,需要我們更深入的理解。我們會在接下來的部分解決這個任務。
分類變數分析
現在我們理解了Applicantlncome和Loanlncome的資料分佈,接著探索更詳細的分類變數資訊。我們會用到Excel型別的資料透視表和交叉表,例如,我們可以檢視根據信用記錄獲取貸款的機率。使用透視表可以獲取結果:
注意:這裡我們將借貸狀態編寫為1表示“是”,0表示“否”。所以平均值表示獲取貸款的概率。
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
複製程式碼
現在我們看看用Python生成相同資料洞察所需的步驟,我們可以觀察得到的和Excel表一樣的pivot_table。我們可以用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倍。我們也可以按照Married(婚否),Self-Employed(是否受僱於他人),Property_Area(財產狀況)等繪製相似的圖表。 另外,我們也可以將這兩個圖疊加在一起:
temp3 = pd.crosstab(df['Credit_History'], df['Loan_Status'])
temp3.plot(kind='bar', stacked=True, color=['red','blue'], grid=False)
複製程式碼
還可以將性別因素新增進來:
如果你看得不是很明白,其實我們這裡是建立了兩個基本的分類演算法。一個基於信用記錄,另一個基於兩個分類變數(包括性別)。
剛剛我們展示瞭如何用Python和Pandas進行探索性資料分析。接著我們進一步探索Applicantlncome和LoanStatus變數,進行資料再加工,並建立一個資料集應用多種多樣的建模技巧。強烈建議你應用另一個資料集和類似問題,根據我們剛才的教程實際練習一番。
4.利用Pandas和Python進行資料再加工
到了這個進度,一定要認真學習了,準備好上手練習。
資料再加工——“需求翻新”
在我們探索資料時,發現資料集中存在一些問題,需要加以解決以便後面用來搭建效能良好的模型。那麼解決有問題資料的任務就被稱為“資料再加工”(data munging)。下面是我們已經注意到的問題:
某些變數中存在缺失值,我們應根據缺失值數量和變數的預期重要性明智地預估這些值。
在檢視資料的分佈狀況時,我們發現ApplicantIncome和LoanAmount似乎在兩邊都包含極值。雖然出現這些極端情況也能說得通,但是我們必須恰當地處理這些異常資料。
除了數值欄位存在的這些問題外,我們還應該檢視非數值欄位,也就是Gender,Property_Area,Married,Education和Dependents等等,看看它們是否包含有用資訊。 如果對Pandas不是很熟悉,可以看看這篇見解Pandas中一些技巧的文章: 戳這裡
檢查資料集中的缺失值
我們檢視所有變數中的缺失值,因為大部分模型無法應對缺失值,即便它們能夠應對,也幫不上忙。所以我們檢查一下資料集中的空值。
df.apply(lambda x: sum(x.isnull()),axis=0)
複製程式碼
如果值為空,這行命令應該能告訴我們每列中的缺失值數量。
雖然缺失值的數量並不是很多,但是很多變數中存在缺失值,那麼我們應該將它們預估出來並進行相加。關於更多更詳細的缺失值推定方法,可以檢視這篇文章:戳這裡
注意:記住缺失值並非一直都是空值。比如,如果Loan_Amount_Term為0,你覺得說得通嗎?或者你會將它當做缺失值嗎?假設你就是這麼認為,而且答案正確,那麼我們應該檢查那些不切實際的值。
如何填補LoanAmount的缺失值?
填補缺失值有很多種方法,最簡單的一種就是用平均值取代,用如下程式碼可以實現:
df['LoanAmount'].fillna(df['LoanAmount'].mean(), inplace=True)
複製程式碼
另一種方式就是建立一個監督學習模型,根據其它變數預測LoanAmount的數量,然後再結合其它變數來預測缺失值。
由於我們這裡的目標是資料再加工的操作步驟,所以我會採取一種介乎這兩者之間的方法。我們需要做個重要的假設:不管申請人是否受過良好教育,或者是否受僱於人,都能預期獲得較大數額的貸款。
首先,我們檢視箱型圖,看看是否存在一定的趨勢:
我們看到每組申請人的貸款額度的中位數出現了一些變化,可以用來推定缺失值。但是首先,我們必須確保Self_Employed和Education特徵中全都沒有缺失值。
我們之前說過,Self_Employed有一些缺失值,我們看一下頻率表格:
由於~86%的值為“否”,因此推定缺失值也為“否”要靠譜一些,用如下程式碼可以完成:
df['Self_Employed'].fillna('No',inplace=True)
複製程式碼
現在,我們會建立一個資料透視表,得到Self_Employed和Education特徵下所有唯一值的中位數。接著,我們定義一個函式,返回這些單元格的值,然後用函式來填充LoanAmount的缺失值:
table = df.pivot_table(values='LoanAmount', index='Self_Employed' ,columns='Education', aggfunc=np.median)
# 定義函式以返回 pivot_table的值
def fage(x):
return table.loc[x['Self_Employed'],x['Education']]
# 替換缺失值
df['LoanAmount'].fillna(df[df['LoanAmount'].isnull()].apply(fage, axis=1), inplace=True)
複製程式碼
以上就是我們推定LoanAmount中缺失值的方法。
如何應對LoanAmount和Applicantlncome資料分佈中的極值?
我們們首先分析LoanAmount。由於極值在實際情況中是可能存在的,也就是說有些人可能會由於特定需求申請數額非常高的貸款,所以我們不將它們看作異常值,而是嘗試對數轉換來抵消它們的影響:
df['LoanAmount_log'] = np.log(df['LoanAmount'])
df['LoanAmount_log'].hist(bins=20)
複製程式碼
我們再次檢視直方圖:
現在資料的分佈看起來更接近正常情況了,極值的影響力也被大幅減弱。
現在看Applicantlncome。直覺告訴我們有些申請人會收入較低,但能作為很合格的共同申請人,也就是兩個或兩個以上的人共同申請一筆貸款。所以將共同申請人的收入合併為總收入,然後進行對數轉換,會是個不錯的方法。
df['TotalIncome'] = df['ApplicantIncome'] + df['CoapplicantIncome']
df['TotalIncome_log'] = np.log(df['TotalIncome'])
df['LoanAmount_log'].hist(bins=20)
複製程式碼
現在我們看到資料的分佈狀況比之前好多了。你可以自己試著推定Gender,Married,Dependents,Loan_Amount_Term和Credit_History這些特徵下的缺失值。另外我也建議大家多考慮一下從資料中可以挖掘出的其它一些資訊。例如,可以為LoanAmount/Totallncome建立一個列,因為從中我們可以知道申請人有多大程度會歸還貸款。
下面我們檢視如何建立預測模型。
5.用Python建立預測模型
在經過一番努力,將資料預處理後,我們現在用Python根據我們的資料集建立一個預測模型。在Python中,Skicit-learn是最常用的建立預測模型的庫。如果你對Sklearn不是很熟悉,集智建議檢視這份入門教程:
由於Sklearn需要所有的輸入必須為數值型,所以我們應將全部分類變數轉換為數值變數。用如下程式碼可以完成:
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
複製程式碼
接著,我們匯入所需的模組。然後我們會定義一個通用分類函式,它會將模型作為輸入,確定準確率和交叉驗證率。由於本文只是入門文章,這裡不再深入講解程式碼,關於如何用通過交叉驗證來優化模型效能,可以參考這篇文章。
#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
#建立分類模型和獲取重要性的通用函式:
def classification_model(model, data, predictors, outcome):
# 擬合模型:
model.fit(data[predictors],data[outcome])
# 用資料集做出預測:
predictions = model.predict(data[predictors])
# 列印準確度
accuracy = metrics.accuracy_score(predictions,data[outcome])
print "Accuracy : %s" % "{0:.3%}".format(accuracy)
# 以5折執行K折交叉驗證
kf = KFold(data.shape[0], n_folds=5)
error = []
for train, test in kf:
# 過濾訓練資料
train_predictors = (data[predictors].iloc[train,:])
# 我們用於訓練演算法的目標值
train_target = data[outcome].iloc[train]
# 用目標值和預測因子訓練演算法
model.fit(train_predictors, train_target)
#記錄每次執行交叉驗證的誤差值
error.append(model.score(data[predictors].iloc[test,:], data[outcome].iloc[test]))
print "Cross-Validation Score : %s" % "{0:.3%}".format(np.mean(error))
# 再次擬合模型,以便被外部函式引用
model.fit(data[predictors],data[outcome])
複製程式碼
邏輯迴歸
我們建立我們的第一個邏輯迴歸模型。一種方法就是將所有變數輸入模型中,但這樣可能會造成過擬合,模型無法很好泛化。
我們可以做出一些直觀的假設解決問題,如果是以下情況,申請人獲取貸款的機率會更高:
- 申請人有信用記錄(我們前面解釋過這種情況)
- 申請人的收入很高,或作為共同申請人時的收入很高
- 申請人有較高的受教育程度
- 在城區有固定資產且有較高的升值前景
我們根據“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%
通常我們預期增加變數後準確度能增加,但這很有挑戰性。不夠重要的變數對準確度和交叉驗證得分影響並不大。Credit_History處於主導地位。現在我們有兩個選擇:
- 特徵工程:挖取新資訊,嘗試預測。這一步就留給你做吧。
- 選擇更好的建模方法。
決策樹
決策樹是另一種建立預測模型的方法,而且眾所周知它能得到比邏輯迴歸模型更高的準確度。
model = DecisionTreeClassifier()
predictor_var = ['Credit_History','Gender','Married','Education']
classification_model(model, df,predictor_var,outcome_var)
複製程式碼
準確度:81.930% 交叉驗證得分:76.656%
這裡模型基於分類變數無法產生影響,因為Credit_History處於主導地位。我們嘗試一些數值變數。
# 我們可以嘗試不同的變數組合
predictor_var = ['Credit_History','Loan_Amount_Term','LoanAmount_log']
classification_model(model, df,predictor_var,outcome_var)
複製程式碼
準確度:92.345% 交叉驗證得分:71.009%
這裡我們觀察到雖然隨著變數增多準確度也增加了,但交叉驗證誤差也下降了。這是因為模型出現了過擬合的結果。我們嘗試一種更復雜的演算法,看看是否有幫助。
隨機森林
隨機森林是另一種解決分類問題的演算法。詳細瞭解隨機森林可以參看集智的這篇文章。
隨機森林的一個優點就是我們可以讓它處理所有特徵,它會返回一個特徵重要性矩陣,能夠用於選擇特徵。
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.00% 交叉驗證得分:78.179%
這裡我們看到模型在訓練集上的準確度達到了100%,這種屬於過擬合的極端情況,可以通過以下兩種方法解決:
- 減少預測因子的數量
- 除錯模型引數
這兩種方式我們都嘗試一下。首先我們看看特徵重要性矩陣,選出最重要的特徵。
用特徵重要性建立一個series:
Featimp = pd.Series(model.feature_importances_, index=predictor_var).sort_values(ascending=False)
print featimp
複製程式碼
我們使用重要性最高的5個變數建立模型。同樣,我們也會略微調整隨機森林模型的引數:
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%
注意,雖然準確度下降了,但交叉驗證得分也得到了優化,顯示模型能夠很好的泛化。記住隨機森林模型並非可重複,由於隨機性的緣故,每次執行得到的結果會略有不同。但是輸出大體保持穩定。
你可能也注意到,雖然除錯了隨機森林模型中的基本函式,但我們得到的交叉驗證得分只是略微好於第一個邏輯迴歸模型的結果。從中我們也可以得到一些有趣的發現:
- 使用更復雜的模型並不能保證得到更好的結果
- 在沒有理解概念前,避免使用非常複雜的建模技巧。貿然使用會造成模型過擬合。
- 特徵工程是解決問題的重要手段,每個人都可以使用Xgboost模型,但還是要依靠你能否增強特徵以更好的匹配模型。
結語
希望本文能幫你入門如何藉助從事資料科學工作,高效成長為一名資料分析師。通過學習以上內容,不僅能讓你瞭解基本的資料分析方法,也能學習如何應用其中一些複雜的方法。
Python真的是一種很棒的工具,因為易於學習,有大量的程式庫支援,故而成為資料科學領域越來越受歡迎的程式語言。
所以建議學好Python,相信你最終能輕鬆應對任何資料科學專案,包括讀取、分析和視覺化資料,並根據資料做出預測。
0806期《人工智慧-從零開始到精通》限時折扣中!
談笑風生 線上程式設計 瞭解一下?
(前25位同學還可領取¥200優惠券哦)