《利用Python進行數(shù)據(jù)分析·第2版》第13章 Python建模庫介紹


第1章 準備工作
第2章 Python語法基礎敷待,IPython和Jupyter
第3章 Python的數(shù)據(jù)結構、函數(shù)和文件
第4章 NumPy基礎:數(shù)組和矢量計算
第5章 pandas入門
第6章 數(shù)據(jù)加載凌唬、存儲與文件格式
第7章 數(shù)據(jù)清洗和準備
第8章 數(shù)據(jù)規(guī)整:聚合腹殿、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運算
第11章 時間序列
第12章 pandas高級應用
第13章 Python建模庫介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級應用
附錄B 更多關于IPython的內(nèi)容(完)


本書中舷蒲,我已經(jīng)介紹了Python數(shù)據(jù)分析的編程基礎。因為數(shù)據(jù)分析師和科學家總是在數(shù)據(jù)規(guī)整和準備上花費大量時間扇谣,這本書的重點在于掌握這些功能昧捷。

開發(fā)模型選用什么庫取決于應用本身。許多統(tǒng)計問題可以用簡單方法解決罐寨,比如普通的最小二乘回歸靡挥,其它問題可能需要復雜的機器學習方法。幸運的是鸯绿,Python已經(jīng)成為了運用這些分析方法的語言之一跋破,因此讀完此書,你可以探索許多工具瓶蝴。

本章中毒返,我會回顧一些pandas的特點,在你膠著于pandas數(shù)據(jù)規(guī)整和模型擬合和評分時舷手,它們可能派上用場拧簸。然后我會簡短介紹兩個流行的建模工具,statsmodels和scikit-learn男窟。這二者每個都值得再寫一本書盆赤,我就不做全面的介紹贾富,而是建議你學習兩個項目的線上文檔和其它基于Python的數(shù)據(jù)科學、統(tǒng)計和機器學習的書籍弟劲。

13.1 pandas與模型代碼的接口

模型開發(fā)的通常工作流是使用pandas進行數(shù)據(jù)加載和清洗祷安,然后切換到建模庫進行建模。開發(fā)模型的重要一環(huán)是機器學習中的“特征工程”兔乞。它可以描述從原始數(shù)據(jù)集中提取信息的任何數(shù)據(jù)轉換或分析,這些數(shù)據(jù)集可能在建模中有用凉唐。本書中學習的數(shù)據(jù)聚合和GroupBy工具常用于特征工程中庸追。

優(yōu)秀的特征工程超出了本書的范圍,我會盡量直白地介紹一些用于數(shù)據(jù)操作和建模切換的方法台囱。

pandas與其它分析庫通常是靠NumPy的數(shù)組聯(lián)系起來的淡溯。將DataFrame轉換為NumPy數(shù)組,可以使用.values屬性:

In [10]: import pandas as pd

In [11]: import numpy as np

In [12]: data = pd.DataFrame({
   ....:     'x0': [1, 2, 3, 4, 5],
   ....:     'x1': [0.01, -0.01, 0.25, -4.1, 0.],
   ....:     'y': [-1.5, 0., 3.6, 1.3, -2.]})

In [13]: data
Out[13]: 
   x0    x1    y
0   1  0.01 -1.5
1   2 -0.01  0.0
2   3  0.25  3.6
3   4 -4.10  1.3
4   5  0.00 -2.0

In [14]: data.columns
Out[14]: Index(['x0', 'x1', 'y'], dtype='object')

In [15]: data.values
Out[15]: 
array([[ 1.  ,  0.01, -1.5 ],
       [ 2.  , -0.01,  0.  ],
       [ 3.  ,  0.25,  3.6 ],
       [ 4.  , -4.1 ,  1.3 ],
       [ 5.  ,  0.  , -2.  ]])

要轉換回DataFrame簿训,可以傳遞一個二維ndarray咱娶,可帶有列名:

In [16]: df2 = pd.DataFrame(data.values, columns=['one', 'two', 'three'])

In [17]: df2
Out[17]: 
   one   two  three
0  1.0  0.01   -1.5
1  2.0 -0.01    0.0
2  3.0  0.25    3.6
3  4.0 -4.10    1.3
4  5.0  0.00   -2.0

筆記:最好當數(shù)據(jù)是均勻的時候使用.values屬性。例如强品,全是數(shù)值類型膘侮。如果數(shù)據(jù)是不均勻的,結果會是Python對象的ndarray:

In [18]: df3 = data.copy()

In [19]: df3['strings'] = ['a', 'b', 'c', 'd', 'e']

In [20]: df3
Out[20]: 
  x0    x1    y strings
0   1  0.01 -1.5       a
1   2 -0.01  0.0       b
2   3  0.25  3.6       c
3   4 -4.10  1.3       d
4   5  0.00 -2.0       e

In [21]: df3.values
Out[21]: 
array([[1, 0.01, -1.5, 'a'],
      [2, -0.01, 0.0, 'b'],
      [3, 0.25, 3.6, 'c'],
      [4, -4.1, 1.3, 'd'],
      [5, 0.0, -2.0, 'e']], dtype=object)

對于一些模型的榛,你可能只想使用列的子集琼了。我建議你使用loc,用values作索引:

In [22]: model_cols = ['x0', 'x1']

In [23]: data.loc[:, model_cols].values
Out[23]: 
array([[ 1.  ,  0.01],
       [ 2.  , -0.01],
       [ 3.  ,  0.25],
       [ 4.  , -4.1 ],
       [ 5.  ,  0.  ]])

一些庫原生支持pandas夫晌,會自動完成工作:從DataFrame轉換到NumPy雕薪,將模型的參數(shù)名添加到輸出表的列或Series。其它情況晓淀,你可以手工進行“元數(shù)據(jù)管理”所袁。

在第12章,我們學習了pandas的Categorical類型和pandas.get_dummies函數(shù)凶掰。假設數(shù)據(jù)集中有一個非數(shù)值列:

In [24]: data['category'] = pd.Categorical(['a', 'b', 'a', 'a', 'b'],
   ....:                                   categories=['a', 'b'])

In [25]: data
Out[25]: 
   x0    x1    y category
0   1  0.01 -1.5        a
1   2 -0.01  0.0        b
2   3  0.25  3.6        a
3   4 -4.10  1.3        a
4   5  0.00 -2.0        b

如果我們想替換category列為虛變量燥爷,我們可以創(chuàng)建虛變量,刪除category列锄俄,然后添加到結果:

In [26]: dummies = pd.get_dummies(data.category, prefix='category')

In [27]: data_with_dummies = data.drop('category', axis=1).join(dummies)

In [28]: data_with_dummies
Out[28]: 
   x0    x1    y  category_a  category_b
0   1  0.01 -1.5           1           0
1   2 -0.01  0.0           0           1
2   3  0.25  3.6           1           0
3   4 -4.10  1.3           1           0
4   5  0.00 -2.0           0           1

用虛變量擬合某些統(tǒng)計模型會有一些細微差別局劲。當你不只有數(shù)字列時,使用Patsy(下一節(jié)的主題)可能更簡單奶赠,更不容易出錯鱼填。

13.2 用Patsy創(chuàng)建模型描述

Patsy是Python的一個庫,使用簡短的字符串“公式語法”描述統(tǒng)計模型(尤其是線性模型)毅戈,可能是受到了R和S統(tǒng)計編程語言的公式語法的啟發(fā)苹丸。

Patsy適合描述statsmodels的線性模型愤惰,因此我會關注于它的主要特點,讓你盡快掌握赘理。Patsy的公式是一個特殊的字符串語法宦言,如下所示:

y ~ x0 + x1

a+b不是將a與b相加的意思,而是為模型創(chuàng)建的設計矩陣商模。patsy.dmatrices函數(shù)接收一個公式字符串和一個數(shù)據(jù)集(可以是DataFrame或數(shù)組的字典)奠旺,為線性模型創(chuàng)建設計矩陣:

In [29]: data = pd.DataFrame({
   ....:     'x0': [1, 2, 3, 4, 5],
   ....:     'x1': [0.01, -0.01, 0.25, -4.1, 0.],
   ....:     'y': [-1.5, 0., 3.6, 1.3, -2.]})

In [30]: data
Out[30]: 
   x0    x1    y
0   1  0.01 -1.5
1   2 -0.01  0.0
2   3  0.25  3.6
3   4 -4.10  1.3
4   5  0.00 -2.0

In [31]: import patsy

In [32]: y, X = patsy.dmatrices('y ~ x0 + x1', data)

現(xiàn)在有:

In [33]: y
Out[33]: 
DesignMatrix with shape (5, 1)
     y
  -1.5
   0.0
   3.6
   1.3
  -2.0
  Terms:
    'y' (column 0)

In [34]: X
Out[34]: 
DesignMatrix with shape (5, 3)
  Intercept  x0     x1
          1   1   0.01
          1   2  -0.01
          1   3   0.25
          1   4  -4.10
          1   5   0.00
  Terms:
    'Intercept' (column 0)
    'x0' (column 1)
    'x1' (column 2)

這些Patsy的DesignMatrix實例是NumPy的ndarray,帶有附加元數(shù)據(jù):

In [35]: np.asarray(y)
Out[35]: 
array([[-1.5],
       [ 0. ],
       [ 3.6],
       [ 1.3],
       [-2. ]])

In [36]: np.asarray(X)
Out[36]: 
array([[ 1.  ,  1.  ,  0.01],
       [ 1.  ,  2.  , -0.01],
       [ 1.  ,  3.  ,  0.25],
       [ 1.  ,  4.  , -4.1 ],
       [ 1.  ,  5.  ,  0.  ]])

你可能想Intercept是哪里來的施流。這是線性模型(比如普通最小二乘回歸)的慣例用法响疚。添加 +0 到模型可以不顯示intercept:

In [37]: patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
Out[37]: 
DesignMatrix with shape (5, 2)
  x0     x1
   1   0.01
   2  -0.01
   3   0.25
   4  -4.10
   5   0.00
  Terms:
    'x0' (column 0)
    'x1' (column 1)

Patsy對象可以直接傳遞到算法(比如numpy.linalg.lstsq)中,它執(zhí)行普通最小二乘回歸:

In [38]: coef, resid, _, _ = np.linalg.lstsq(X, y)

模型的元數(shù)據(jù)保留在design_info屬性中忿晕,因此你可以重新附加列名到擬合系數(shù),以獲得一個Series,例如:

In [39]: coef
Out[39]: 
array([[ 0.3129],
       [-0.0791],
       [-0.2655]])

In [40]: coef = pd.Series(coef.squeeze(), index=X.design_info.column_names)

In [41]: coef
Out[41]: 
Intercept    0.312910
x0          -0.079106
x1          -0.265464
dtype: float64

用Patsy公式進行數(shù)據(jù)轉換

你可以將Python代碼與patsy公式結合确丢。在評估公式時褂始,庫將嘗試查找在封閉作用域內(nèi)使用的函數(shù):

In [42]: y, X = patsy.dmatrices('y ~ x0 + np.log(np.abs(x1) + 1)', data)

In [43]: X
Out[43]: 
DesignMatrix with shape (5, 3)
  Intercept  x0  np.log(np.abs(x1) + 1)
          1   1                 0.00995
          1   2                 0.00995
          1   3                 0.22314
          1   4                 1.62924
          1   5                 0.00000
  Terms:
    'Intercept' (column 0)
    'x0' (column 1)
    'np.log(np.abs(x1) + 1)' (column 2)

常見的變量轉換包括標準化(平均值為0舀寓,方差為1)和中心化(減去平均值)。Patsy有內(nèi)置的函數(shù)進行這樣的工作:

In [44]: y, X = patsy.dmatrices('y ~ standardize(x0) + center(x1)', data)

In [45]: X
Out[45]: 
DesignMatrix with shape (5, 3)
  Intercept  standardize(x0)  center(x1)
          1         -1.41421        0.78
          1         -0.70711        0.76
          1          0.00000        1.02
          1          0.70711       -3.33
          1          1.41421        0.77
  Terms:
    'Intercept' (column 0)
    'standardize(x0)' (column 1)
    'center(x1)' (column 2)

作為建模的一步,你可能擬合模型到一個數(shù)據(jù)集,然后用另一個數(shù)據(jù)集評估模型。另一個數(shù)據(jù)集可能是剩余的部分或是新數(shù)據(jù)。當執(zhí)行中心化和標準化轉變翠胰,用新數(shù)據(jù)進行預測要格外小心膏潮。因為你必須使用平均值或標準差轉換新數(shù)據(jù)集,這也稱作狀態(tài)轉換。

patsy.build_design_matrices函數(shù)可以使用原始樣本數(shù)據(jù)集的保存信息崇众,來轉換新數(shù)據(jù)幔睬,:

In [46]: new_data = pd.DataFrame({
   ....:     'x0': [6, 7, 8, 9],
   ....:     'x1': [3.1, -0.5, 0, 2.3],
   ....:     'y': [1, 2, 3, 4]})

In [47]: new_X = patsy.build_design_matrices([X.design_info], new_data)

In [48]: new_X
Out[48]: 
[DesignMatrix with shape (4, 3)
   Intercept  standardize(x0)  center(x1)
           1          2.12132        3.87
           1          2.82843        0.27
           1          3.53553        0.77
           1          4.24264        3.07
   Terms:
     'Intercept' (column 0)
     'standardize(x0)' (column 1)
     'center(x1)' (column 2)]

因為Patsy中的加號不是加法的意義摹芙,當你按照名稱將數(shù)據(jù)集的列相加時,你必須用特殊I函數(shù)將它們封裝起來:

In [49]: y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)

In [50]: X
Out[50]: 
DesignMatrix with shape (5, 2)
  Intercept  I(x0 + x1)
          1        1.01
          1        1.99
          1        3.25
          1       -0.10
          1        5.00
  Terms:
    'Intercept' (column 0)
    'I(x0 + x1)' (column 1)

Patsy的patsy.builtins模塊還有一些其它的內(nèi)置轉換匆帚。請查看線上文檔。

分類數(shù)據(jù)有一個特殊的轉換類,下面進行講解替废。

分類數(shù)據(jù)和Patsy

非數(shù)值數(shù)據(jù)可以用多種方式轉換為模型設計矩陣柄瑰。完整的講解超出了本書范圍,最好和統(tǒng)計課一起學習译断。

當你在Patsy公式中使用非數(shù)值數(shù)據(jù)授翻,它們會默認轉換為虛變量。如果有截距,會去掉一個堪唐,避免共線性:

In [51]: data = pd.DataFrame({
   ....:     'key1': ['a', 'a', 'b', 'b', 'a', 'b', 'a', 'b'],
   ....:     'key2': [0, 1, 0, 1, 0, 1, 0, 0],
   ....:     'v1': [1, 2, 3, 4, 5, 6, 7, 8],
   ....:     'v2': [-1, 0, 2.5, -0.5, 4.0, -1.2, 0.2, -1.7]
   ....: })

In [52]: y, X = patsy.dmatrices('v2 ~ key1', data)

In [53]: X
Out[53]: 
DesignMatrix with shape (8, 2)
  Intercept  key1[T.b]
          1          0
          1          0
          1          1
          1          1
          1          0
          1          1
          1          0
          1          1
  Terms:
    'Intercept' (column 0)
    'key1' (column 1)

如果你從模型中忽略截距巡语,每個分類值的列都會包括在設計矩陣的模型中:

In [54]: y, X = patsy.dmatrices('v2 ~ key1 + 0', data)

In [55]: X
Out[55]: 
DesignMatrix with shape (8, 2)
  key1[a]  key1[b]
        1        0
        1        0
        0        1
        0        1
        1        0
        0        1
        1        0
        0        1
  Terms:
    'key1' (columns 0:2)

使用C函數(shù),數(shù)值列可以截取為分類量:

In [56]: y, X = patsy.dmatrices('v2 ~ C(key2)', data)

In [57]: X
Out[57]: 
DesignMatrix with shape (8, 2)
  Intercept  C(key2)[T.1]
          1             0
          1             1
          1             0
          1             1
          1             0
          1             1
          1             0
          1             0
  Terms:
    'Intercept' (column 0)
    'C(key2)' (column 1)

當你在模型中使用多個分類名淮菠,事情就會變復雜男公,因為會包括key1:key2形式的相交部分,它可以用在方差(ANOVA)模型分析中:

In [58]: data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})

In [59]: data
Out[59]: 
  key1  key2  v1   v2
0    a  zero   1 -1.0
1    a   one   2  0.0
2    b  zero   3  2.5
3    b   one   4 -0.5
4    a  zero   5  4.0
5    b   one   6 -1.2
6    a  zero   7  0.2
7    b  zero   8 -1.7

In [60]: y, X = patsy.dmatrices('v2 ~ key1 + key2', data)

In [61]: X
Out[61]: 
DesignMatrix with shape (8, 3)
  Intercept  key1[T.b]  key2[T.zero]
          1          0             1
          1          0             0
          1          1             1
          1          1             0
          1          0             1
          1          1             0
          1          0             1
          1          1             1
  Terms:
    'Intercept' (column 0)
    'key1' (column 1)
    'key2' (column 2)

In [62]: y, X = patsy.dmatrices('v2 ~ key1 + key2 + key1:key2', data)

In [63]: X
Out[63]: 
DesignMatrix with shape (8, 4)
  Intercept  key1[T.b]  key2[T.zero]
key1[T.b]:key2[T.zero]
          1          0             1                       0
          1          0             0                       0
          1          1             1                       1
          1          1             0                       0
          1          0             1                       0
          1          1             0                       0
          1          0             1                       0
          1          1             1                       1
  Terms:
    'Intercept' (column 0)
    'key1' (column 1)
    'key2' (column 2)
    'key1:key2' (column 3)

Patsy提供轉換分類數(shù)據(jù)的其它方法合陵,包括以特定順序轉換枢赔。請參閱線上文檔。

13.3 statsmodels介紹

statsmodels是Python進行擬合多種統(tǒng)計模型拥知、進行統(tǒng)計試驗和數(shù)據(jù)探索可視化的庫踏拜。Statsmodels包含許多經(jīng)典的統(tǒng)計方法,但沒有貝葉斯方法和機器學習模型低剔。

statsmodels包含的模型有:

  • 線性模型速梗,廣義線性模型和健壯線性模型
  • 線性混合效應模型
  • 方差(ANOVA)方法分析
  • 時間序列過程和狀態(tài)空間模型
  • 廣義矩估計

下面,我會使用一些基本的statsmodels工具襟齿,探索Patsy公式和pandasDataFrame對象如何使用模型接口镀琉。

估計線性模型

statsmodels有多種線性回歸模型,包括從基本(比如普通最小二乘)到復雜(比如迭代加權最小二乘法)的蕊唐。

statsmodels的線性模型有兩種不同的接口:基于數(shù)組和基于公式。它們可以通過API模塊引入:

import statsmodels.api as sm
import statsmodels.formula.api as smf

為了展示它們的使用方法烁设,我們從一些隨機數(shù)據(jù)生成一個線性模型:

def dnorm(mean, variance, size=1):
    if isinstance(size, int):
        size = size,
    return mean + np.sqrt(variance) * np.random.randn(*size)

# For reproducibility
np.random.seed(12345)

N = 100
X = np.c_[dnorm(0, 0.4, size=N),
          dnorm(0, 0.6, size=N),
          dnorm(0, 0.2, size=N)]
eps = dnorm(0, 0.1, size=N)
beta = [0.1, 0.3, 0.5]

y = np.dot(X, beta) + eps

這里替梨,我使用了“真實”模型和可知參數(shù)beta。此時装黑,dnorm可用來生成正態(tài)分布數(shù)據(jù)副瀑,帶有特定均值和方差。現(xiàn)在有:

In [66]: X[:5]
Out[66]: 
array([[-0.1295, -1.2128,  0.5042],
       [ 0.3029, -0.4357, -0.2542],
       [-0.3285, -0.0253,  0.1384],
       [-0.3515, -0.7196, -0.2582],
       [ 1.2433, -0.3738, -0.5226]])

In [67]: y[:5]
Out[67]: array([ 0.4279, -0.6735, -0.0909, -0.4895,-0.1289])

像之前Patsy看到的恋谭,線性模型通常要擬合一個截距糠睡。sm.add_constant函數(shù)可以添加一個截距的列到現(xiàn)存的矩陣:

In [68]: X_model = sm.add_constant(X)

In [69]: X_model[:5]
Out[69]: 
array([[ 1.    , -0.1295, -1.2128,  0.5042],
       [ 1.    ,  0.3029, -0.4357, -0.2542],
       [ 1.    , -0.3285, -0.0253,  0.1384],
       [ 1.    , -0.3515, -0.7196, -0.2582],
       [ 1.    ,  1.2433, -0.3738, -0.5226]])

sm.OLS類可以擬合一個普通最小二乘回歸:

In [70]: model = sm.OLS(y, X)

這個模型的fit方法返回了一個回歸結果對象,它包含估計的模型參數(shù)和其它內(nèi)容:

In [71]: results = model.fit()

In [72]: results.params
Out[72]: array([ 0.1783,  0.223 ,  0.501 ])

對結果使用summary方法可以打印模型的詳細診斷結果:

In [73]: print(results.summary())
OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.430
Model:                            OLS   Adj. R-squared:                  0.413
Method:                 Least Squares   F-statistic:                     24.42
Date:                Mon, 25 Sep 2017   Prob (F-statistic):           7.44e-12
Time:                        14:06:15   Log-Likelihood:                -34.305
No. Observations:                 100   AIC:                             74.61
Df Residuals:                      97   BIC:                             82.42
Df Model:                           3                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
x1             0.1783      0.053      3.364      0.001       0.073       0.283
x2             0.2230      0.046      4.818      0.000       0.131       0.315
x3             0.5010      0.080      6.237      0.000       0.342       0.660
==============================================================================
Omnibus:                        4.662   Durbin-Watson:                   2.201
Prob(Omnibus):                  0.097   Jarque-Bera (JB):                4.098
Skew:                           0.481   Prob(JB):                        0.129
Kurtosis:                       3.243   Cond. No.
1.74
==============================================================================
Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly 
specified.

這里的參數(shù)名為通用名x1, x2等等疚颊。假設所有的模型參數(shù)都在一個DataFrame中:

In [74]: data = pd.DataFrame(X, columns=['col0', 'col1', 'col2'])

In [75]: data['y'] = y

In [76]: data[:5]
Out[76]: 
       col0      col1      col2         y
0 -0.129468 -1.212753  0.504225  0.427863
1  0.302910 -0.435742 -0.254180 -0.673480
2 -0.328522 -0.025302  0.138351 -0.090878
3 -0.351475 -0.719605 -0.258215 -0.489494
4  1.243269 -0.373799 -0.522629 -0.128941

現(xiàn)在狈孔,我們使用statsmodels的公式API和Patsy的公式字符串:

In [77]: results = smf.ols('y ~ col0 + col1 + col2', data=data).fit()

In [78]: results.params
Out[78]: 
Intercept    0.033559
col0         0.176149
col1         0.224826
col2         0.514808
dtype: float64

In [79]: results.tvalues
Out[79]: 
Intercept    0.952188
col0         3.319754
col1         4.850730
col2         6.303971
dtype: float64

觀察下statsmodels是如何返回Series結果的,附帶有DataFrame的列名材义。當使用公式和pandas對象時均抽,我們不需要使用add_constant。

給出一個樣本外數(shù)據(jù)其掂,你可以根據(jù)估計的模型參數(shù)計算預測值:

In [80]: results.predict(data[:5])
Out[80]: 
0   -0.002327
1   -0.141904
2    0.041226
3   -0.323070
4   -0.100535
dtype: float64

statsmodels的線性模型結果還有其它的分析油挥、診斷和可視化工具。除了普通最小二乘模型,還有其它的線性模型深寥。

估計時間序列過程

statsmodels的另一模型類是進行時間序列分析攘乒,包括自回歸過程、卡爾曼濾波和其它態(tài)空間模型惋鹅,和多元自回歸模型则酝。

用自回歸結構和噪聲來模擬一些時間序列數(shù)據(jù):

init_x = 4

import random
values = [init_x, init_x]
N = 1000

b0 = 0.8
b1 = -0.4
noise = dnorm(0, 0.1, N)
for i in range(N):
    new_x = values[-1] * b0 + values[-2] * b1 + noise[i]
    values.append(new_x)

這個數(shù)據(jù)有AR(2)結構(兩個延遲),參數(shù)是0.8和-0.4负饲。擬合AR模型時堤魁,你可能不知道滯后項的個數(shù),因此可以用較多的滯后量來擬合這個模型:

In [82]: MAXLAGS = 5

In [83]: model = sm.tsa.AR(values)

In [84]: results = model.fit(MAXLAGS)

結果中的估計參數(shù)首先是截距返十,其次是前兩個參數(shù)的估計值:

In [85]: results.params
Out[85]: array([-0.0062,  0.7845, -0.4085, -0.0136,  0.015 ,  0.0143])

更多的細節(jié)以及如何解釋結果超出了本書的范圍妥泉,可以通過statsmodels文檔學習更多。

13.4 scikit-learn介紹

scikit-learn是一個廣泛使用洞坑、用途多樣的Python機器學習庫盲链。它包含多種標準監(jiān)督和非監(jiān)督機器學習方法和模型選擇和評估、數(shù)據(jù)轉換迟杂、數(shù)據(jù)加載和模型持久化工具刽沾。這些模型可以用于分類、聚合排拷、預測和其它任務侧漓。

機器學習方面的學習和應用scikit-learn和TensorFlow解決實際問題的線上和紙質資料很多。本節(jié)中监氢,我會簡要介紹scikit-learn API的風格布蔗。

寫作此書的時候,scikit-learn并沒有和pandas深度結合浪腐,但是有些第三方包在開發(fā)中纵揍。盡管如此,pandas非常適合在模型擬合前處理數(shù)據(jù)集议街。

舉個例子泽谨,我用一個Kaggle競賽的經(jīng)典數(shù)據(jù)集,關于泰坦尼克號乘客的生還率特漩。我們用pandas加載測試和訓練數(shù)據(jù)集:

In [86]: train = pd.read_csv('datasets/titanic/train.csv')

In [87]: test = pd.read_csv('datasets/titanic/test.csv')

In [88]: train[:4]
Out[88]: 
   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   
3            4         1       1   
                                                Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1   
2                             Heikkinen, Miss. Laina  female  26.0      0   
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   
   Parch            Ticket     Fare Cabin Embarked  
0      0         A/5 21171   7.2500   NaN        S  
1      0          PC 17599  71.2833   C85        C  
2      0  STON/O2. 3101282   7.9250   NaN        S  
3      0            113803  53.1000  C123        S

statsmodels和scikit-learn通常不能接收缺失數(shù)據(jù)吧雹,因此我們要查看列是否包含缺失值:

In [89]: train.isnull().sum()
Out[89]: 
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

In [90]: test.isnull().sum()
Out[90]: 
PassengerId      0
Pclass           0
Name             0
Sex              0
Age             86
SibSp            0
Parch            0
Ticket           0
Fare             1
Cabin          327
Embarked         0
dtype: int64

在統(tǒng)計和機器學習的例子中,根據(jù)數(shù)據(jù)中的特征涂身,一個典型的任務是預測乘客能否生還吮炕。模型現(xiàn)在訓練數(shù)據(jù)集中擬合,然后用樣本外測試數(shù)據(jù)集評估访得。

我想用年齡作為預測值龙亲,但是它包含缺失值陕凹。缺失數(shù)據(jù)補全的方法有多種,我用的是一種簡單方法鳄炉,用訓練數(shù)據(jù)集的中位數(shù)補全兩個表的空值:

In [91]: impute_value = train['Age'].median()

In [92]: train['Age'] = train['Age'].fillna(impute_value)

In [93]: test['Age'] = test['Age'].fillna(impute_value)

現(xiàn)在我們需要指定模型杜耙。我增加了一個列IsFemale,作為“Sex”列的編碼:

In [94]: train['IsFemale'] = (train['Sex'] == 'female').astype(int)

In [95]: test['IsFemale'] = (test['Sex'] == 'female').astype(int)

然后拂盯,我們確定一些模型變量佑女,并創(chuàng)建NumPy數(shù)組:

In [96]: predictors = ['Pclass', 'IsFemale', 'Age']

In [97]: X_train = train[predictors].values

In [98]: X_test = test[predictors].values

In [99]: y_train = train['Survived'].values

In [100]: X_train[:5]
Out[100]: 
array([[  3.,   0.,  22.],
       [  1.,   1.,  38.],
       [  3.,   1.,  26.],
       [  1.,   1.,  35.],
       [  3.,   0.,  35.]])

In [101]: y_train[:5]
Out[101]: array([0, 1, 1, 1, 0])

我不能保證這是一個好模型,但它的特征都符合谈竿。我們用scikit-learn的LogisticRegression模型团驱,創(chuàng)建一個模型實例:

In [102]: from sklearn.linear_model import LogisticRegression

In [103]: model = LogisticRegression()

與statsmodels類似,我們可以用模型的fit方法空凸,將它擬合到訓練數(shù)據(jù):

In [104]: model.fit(X_train, y_train)
Out[104]: 
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)

現(xiàn)在嚎花,我們可以用model.predict,對測試數(shù)據(jù)進行預測:

In [105]: y_predict = model.predict(X_test)

In [106]: y_predict[:10]
Out[106]: array([0, 0, 0, 0, 1, 0, 1, 0, 1, 0])

如果你有測試數(shù)據(jù)集的真實值呀洲,你可以計算準確率或其它錯誤度量值:

(y_true == y_predict).mean()

在實際中紊选,模型訓練經(jīng)常有許多額外的復雜因素。許多模型有可以調節(jié)的參數(shù)道逗,有些方法(比如交叉驗證)可以用來進行參數(shù)調節(jié)兵罢,避免對訓練數(shù)據(jù)過擬合。這通匙仪希可以提高預測性或對新數(shù)據(jù)的健壯性卖词。

交叉驗證通過分割訓練數(shù)據(jù)來模擬樣本外預測±艉唬基于模型的精度得分(比如均方差)坏平,可以對模型參數(shù)進行網(wǎng)格搜索。有些模型锦亦,如logistic回歸,有內(nèi)置的交叉驗證的估計類令境。例如杠园,logisticregressioncv類可以用一個參數(shù)指定網(wǎng)格搜索對模型的正則化參數(shù)C的粒度:

In [107]: from sklearn.linear_model import LogisticRegressionCV

In [108]: model_cv = LogisticRegressionCV(10)

In [109]: model_cv.fit(X_train, y_train)
Out[109]: 
LogisticRegressionCV(Cs=10, class_weight=None, cv=None, dual=False,
           fit_intercept=True, intercept_scaling=1.0, max_iter=100,
           multi_class='ovr', n_jobs=1, penalty='l2', random_state=None,
           refit=True, scoring=None, solver='lbfgs', tol=0.0001, verbose=0)

要手動進行交叉驗證,你可以使用cross_val_score幫助函數(shù)舔庶,它可以處理數(shù)據(jù)分割抛蚁。例如,要交叉驗證我們的帶有四個不重疊訓練數(shù)據(jù)的模型惕橙,可以這樣做:

In [110]: from sklearn.model_selection import cross_val_score

In [111]: model = LogisticRegression(C=10)

In [112]: scores = cross_val_score(model, X_train, y_train, cv=4)

In [113]: scores
Out[113]: array([ 0.7723,  0.8027,  0.7703,  0.7883])

默認的評分指標取決于模型本身瞧甩,但是可以明確指定一個評分。交叉驗證過的模型需要更長時間來訓練弥鹦,但會有更高的模型性能肚逸。

13.5 繼續(xù)學習

我只是介紹了一些Python建模庫的表面內(nèi)容爷辙,現(xiàn)在有越來越多的框架用于各種統(tǒng)計和機器學習,它們都是用Python或Python用戶界面實現(xiàn)的朦促。

這本書的重點是數(shù)據(jù)規(guī)整膝晾,有其它的書是關注建模和數(shù)據(jù)科學工具的。其中優(yōu)秀的有:

  • Andreas Mueller and Sarah Guido (O’Reilly)的 《Introduction to Machine Learning with Python》
  • Jake VanderPlas (O’Reilly)的 《Python Data Science Handbook》
  • Joel Grus (O’Reilly) 的 《Data Science from Scratch: First Principles》
  • Sebastian Raschka (Packt Publishing) 的《Python Machine Learning》
  • Aurélien Géron (O’Reilly) 的《Hands-On Machine Learning with Scikit-Learn and TensorFlow》

雖然書是學習的好資源务冕,但是隨著底層開源軟件的發(fā)展血当,書的內(nèi)容會過時。最好是不斷熟悉各種統(tǒng)計和機器學習框架的文檔禀忆,學習最新的功能和API臊旭。


第1章 準備工作
第2章 Python語法基礎,IPython和Jupyter
第3章 Python的數(shù)據(jù)結構箩退、函數(shù)和文件
第4章 NumPy基礎:數(shù)組和矢量計算
第5章 pandas入門
第6章 數(shù)據(jù)加載离熏、存儲與文件格式
第7章 數(shù)據(jù)清洗和準備
第8章 數(shù)據(jù)規(guī)整:聚合、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運算
第11章 時間序列
第12章 pandas高級應用
第13章 Python建模庫介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級應用
附錄B 更多關于IPython的內(nèi)容(完)


最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乏德,一起剝皮案震驚了整個濱河市撤奸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌喊括,老刑警劉巖胧瓜,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異郑什,居然都是意外死亡府喳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門蘑拯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钝满,“玉大人,你說我怎么就攤上這事申窘⊥溲粒” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵剃法,是天一觀的道長碎捺。 經(jīng)常有香客問我,道長贷洲,這世上最難降的妖魔是什么收厨? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮优构,結果婚禮上诵叁,老公的妹妹穿的比我還像新娘。我一直安慰自己钦椭,他們只是感情好拧额,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布碑诉。 她就那樣靜靜地躺著,像睡著了一般势腮。 火紅的嫁衣襯著肌膚如雪联贩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天捎拯,我揣著相機與錄音泪幌,去河邊找鬼。 笑死署照,一個胖子當著我的面吹牛祸泪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播建芙,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼没隘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了禁荸?” 一聲冷哼從身側響起右蒲,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赶熟,沒想到半個月后瑰妄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡映砖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年间坐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邑退。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡竹宋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出地技,到底是詐尸還是另有隱情蜈七,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布莫矗,位于F島的核電站飒硅,受9級特大地震影響,放射性物質發(fā)生泄漏趣苏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一梯轻、第九天 我趴在偏房一處隱蔽的房頂上張望食磕。 院中可真熱鬧,春花似錦喳挑、人聲如沸彬伦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽单绑。三九已至回官,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搂橙,已是汗流浹背歉提。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留区转,地道東北人苔巨。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像废离,于是被迫代替她去往敵國和親兔港。 傳聞我的和親對象是個殘疾皇子预愤,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345