第13章 Python建模庫介紹--Python for Data Analysis 2nd

本書中,我已經介紹了Python數據分析的編程基礎。因爲數據分析師和科學家總是在數據規整和準備上花費大量時間,這本書的重點在於掌握這些功能。

開發模型選用什麼庫取決於應用本身。許多統計問題可以用簡單方法解決,比如普通的最小二乘迴歸,其它問題可能需要複雜的機器學習方法。幸運的是,Python已經成爲了運用這些分析方法的語言之一,因此讀完此書,你可以探索許多工具。

本章中,我會回顧一些pandas的特點,在你膠着於pandas數據規整和模型擬合和評分時,它們可能派上用場。然後我會簡短介紹兩個流行的建模工具,statsmodels和scikit-learn。這二者每個都值得再寫一本書,我就不做全面的介紹,而是建議你學習兩個項目的線上文檔和其它基於Python的數據科學、統計和機器學習的書籍。

pandas與模型代碼的接口

模型開發的通常工作流是使用pandas進行數據加載和清洗,然後切換到建模庫進行建模。開發模型的重要一環是機器學習中的“特徵工程”。它可以描述從原始數據集中提取信息的任何數據轉換或分析,這些數據集可能在建模中有用。本書中學習的數據聚合和GroupBy工具常用於特徵工程中。

優秀的特徵工程超出了本書的範圍,我會盡量直白地介紹一些用於數據操作和建模切換的方法。

pandas與其它分析庫通常是靠NumPy的數組聯繫起來的。將DataFrame轉換爲NumPy數組,可以使用.values屬性:

import numpy as np
import pandas as pd
    
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.]})
data
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
data.columns
Index(['x0', 'x1', 'y'], dtype='object')
data.values
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,可帶有列名:

df2 = pd.DataFrame(data.values, columns=['one', 'two', 'three'])
df2
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

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

df3 = data.copy()
df3['strings'] = ['a', 'b', 'c', 'd', 'e']
df3
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
df3.values
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作索引:

model_cols = ['x0', 'x1']
data.loc[:, model_cols].values
array([[ 1.  ,  0.01],
       [ 2.  , -0.01],
       [ 3.  ,  0.25],
       [ 4.  , -4.1 ],
       [ 5.  ,  0.  ]])

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

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

data['category'] = pd.Categorical(['a', 'b', 'a', 'a', 'b'],
                                   categories=['a', 'b'])
data
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列爲虛變量,我們可以創建虛變量,刪除category列,然後添加到結果:

dummies = pd.get_dummies(data.category, prefix='category')
data_with_dummies = data.drop('category', axis=1).join(dummies)
 data_with_dummies
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

用虛變量擬合某些統計模型會有一些細微差別。當你不只有數字列時,使用Patsy(下一節的主題)可能更簡單,更不容易出錯。

用Patsy創建模型描述

Patsy是Python的一個庫,使用簡短的字符串“公式語法”描述統計模型(尤其是線性模型),可能是受到了R和S統計編程語言的公式語法的啓發。
Patsy適合描述statsmodels的線性模型,因此我會關注於它的主要特點,讓你儘快掌握。Patsy的公式是一個特殊的字符串語法,如下所示:

y ~ x0 + x1

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

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.]})
data
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
import patsy
y, X = patsy.dmatrices('y ~ x0 + x1', data)

現在有:

y
DesignMatrix with shape (5, 1)
     y
  -1.5
   0.0
   3.6
   1.3
  -2.0
  Terms:
    'y' (column 0)
X
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,帶有附加元數據:

np.asarray(y)
array([[-1.5],
       [ 0. ],
       [ 3.6],
       [ 1.3],
       [-2. ]])
np.asarray(X)
array([[ 1.  ,  1.  ,  0.01],
       [ 1.  ,  2.  , -0.01],
       [ 1.  ,  3.  ,  0.25],
       [ 1.  ,  4.  , -4.1 ],
       [ 1.  ,  5.  ,  0.  ]])

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

patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
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)中,它執行普通最小二乘迴歸:

coef, resid, _, _ = np.linalg.lstsq(X, y)
/root/miniconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
  """Entry point for launching an IPython kernel.

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

coef
array([[ 0.31290976],
       [-0.07910564],
       [-0.26546384]])
coef = pd.Series(coef.squeeze(), index=X.design_info.column_names)
coef
Intercept    0.312910
x0          -0.079106
x1          -0.265464
dtype: float64

用Patsy公式進行數據轉換

你可以將Python代碼與patsy公式結合。在評估公式時,庫將嘗試查找在封閉作用域內使用的函數:

y, X = patsy.dmatrices('y ~ x0 + np.log(np.abs(x1) + 1)', data)
X
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有內置的函數進行這樣的工作:

y, X = patsy.dmatrices('y ~ standardize(x0) + center(x1)', data)
X
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)

作爲建模的一步,你可能擬合模型到一個數據集,然後用另一個數據集評估模型。另一個數據集可能是剩餘的部分或是新數據。當執行中心化和標準化轉變,用新數據進行預測要格外小心。因爲你必須使用平均值或標準差轉換新數據集,這也稱作狀態轉換。

patsy.build_design_matrices函數可以使用原始樣本數據集的保存信息,來轉換新數據,:

new_data = pd.DataFrame({
    'x0': [6, 7, 8, 9],
     'x1': [3.1, -0.5, 0, 2.3],
    'y': [1, 2, 3, 4]})
new_X = patsy.build_design_matrices([X.design_info], new_data)
new_X 
[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中的加號不是加法的意義,當你按照名稱將數據集的列相加時,你必須用特殊I函數將它們封裝起來:

y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)
X
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模塊還有一些其它的內置轉換。請查看線上文檔。

分類數據有一個特殊的轉換類,下面進行講解。

分類數據和Patsy

非數值數據可以用多種方式轉換爲模型設計矩陣。完整的講解超出了本書範圍,最好和統計課一起學習。

當你在Patsy公式中使用非數值數據,它們會默認轉換爲虛變量。如果有截距,會去掉一個,避免共線性:

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]
 })
y, X = patsy.dmatrices('v2 ~ key1', data)
X
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)

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

y, X = patsy.dmatrices('v2 ~ key1 + 0', data)

X
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函數,數值列可以截取爲分類量:

y, X = patsy.dmatrices('v2 ~ C(key2)', data)
X
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)模型分析中:

data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})
data
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
y, X = patsy.dmatrices('v2 ~ key1 + key2', data)
X

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)
y, X = patsy.dmatrices('v2 ~ key1 + key2 + key1:key2', data)
X

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提供轉換分類數據的其它方法,包括以特定順序轉換。請參閱線上文檔。

statsmodels介紹

statsmodels是Python進行擬合多種統計模型、進行統計試驗和數據探索可視化的庫。Statsmodels包含許多經典的統計方法,但沒有貝葉斯方法和機器學習模型。

statsmodels包含的模型有:

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

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

估計線性模型

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

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

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

爲了展示它們的使用方法,我們從一些隨機數據生成一個線性模型:

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

這裏,我使用了“真實”模型和可知參數beta。此時,dnorm可用來生成正態分佈數據,帶有特定均值和方差。現在有:

X[:5]
array([[-0.12946849, -1.21275292,  0.50422488],
       [ 0.30291036, -0.43574176, -0.25417986],
       [-0.32852189, -0.02530153,  0.13835097],
       [-0.35147471, -0.71960511, -0.25821463],
       [ 1.2432688 , -0.37379916, -0.52262905]])
y[:5]
array([ 0.42786349, -0.67348041, -0.09087764, -0.48949442, -0.12894109])

像之前Patsy看到的,線性模型通常要擬合一個截距。sm.add_constant函數可以添加一個截距的列到現存的矩陣:

X_model = sm.add_constant(X)
X_model[:5]
array([[ 1.        , -0.12946849, -1.21275292,  0.50422488],
       [ 1.        ,  0.30291036, -0.43574176, -0.25417986],
       [ 1.        , -0.32852189, -0.02530153,  0.13835097],
       [ 1.        , -0.35147471, -0.71960511, -0.25821463],
       [ 1.        ,  1.2432688 , -0.37379916, -0.52262905]])

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

model = sm.OLS(y, X)

這個模型的fit方法返回了一個迴歸結果對象,它包含估計的模型參數和其它內容

results = model.fit()
results.params
array([0.17826108, 0.22303962, 0.50095093])

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

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:                Sat, 23 Mar 2019   Prob (F-statistic):           7.44e-12
Time:                        11:42:32   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.

這裏的參數名爲通用名x1, x2等等。假設所有的模型參數都在一個DataFrame中:

data = pd.DataFrame(X, columns=['col0', 'col1', 'col2'])
data['y'] = y
data[:5]
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

現在,我們使用statsmodels的公式API和Patsy的公式字符串:

results = smf.ols('y ~ col0 + col1 + col2', data=data).fit()
results.params
Intercept    0.033559
col0         0.176149
col1         0.224826
col2         0.514808
dtype: float64
 results.tvalues
Intercept    0.952188
col0         3.319754
col1         4.850730
col2         6.303971
dtype: float64

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

給出一個樣本外數據,你可以根據估計的模型參數計算預測值:

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

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

估計時間序列過程

statsmodels的另一模型類是進行時間序列分析,包括自迴歸過程、卡爾曼濾波和其它態空間模型,和多元自迴歸模型。

用自迴歸結構和噪聲來模擬一些時間序列數據

import random
init_x = 4

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)

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

MAXLAGS = 5

model = sm.tsa.AR(values)

results = model.fit(MAXLAGS)

結果中的估計參數首先是截距,其次是前兩個參數的估計值:

results.params
array([-0.00616093,  0.78446347, -0.40847891, -0.01364148,  0.01496872,
        0.01429462])

更多的細節以及如何解釋結果超出了本書的範圍,可以通過statsmodels文檔學習更多。

scikit-learn介紹

scikit-learn是一個廣泛使用、用途多樣的Python機器學習庫。它包含多種標準監督和非監督機器學習方法和模型選擇和評估、數據轉換、數據加載和模型持久化工具。這些模型可以用於分類、聚合、預測和其它任務。

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

寫作此書的時候,scikit-learn並沒有和pandas深度結合,但是有些第三方包在開發中。儘管如此,pandas非常適合在模型擬合前處理數據集。

舉個例子,我用一個Kaggle競賽的經典數據集,關於泰坦尼克號乘客的生還率。我們用pandas加載測試和訓練數據集:

train = pd.read_csv('datasets/titanic/train.csv')
test = pd.read_csv('datasets/titanic/test.csv')
train.shape
(891, 12)
test.shape
(418, 11)
train[:1]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked IsFemale
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.25 NaN S 0
test[:1]
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked IsFemale
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q 0

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

train.isnull().sum()
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
test.isnull().sum()
PassengerId      0
Pclass           0
Name             0
Sex              0
Age             86
SibSp            0
Parch            0
Ticket           0
Fare             1
Cabin          327
Embarked         0
dtype: int64

在統計和機器學習的例子中,根據數據中的特徵,一個典型的任務是預測乘客能否生還。模型現在訓練數據集中擬合,然後用樣本外測試數據集評估。

我想用年齡作爲預測值,但是它包含缺失值。缺失數據補全的方法有多種,我用的是一種簡單方法,用訓練數據集的中位數補全兩個表的空值:

impute_value = train['Age'].median()
train['Age'] = train['Age'].fillna(impute_value)
test['Age'] = test['Age'].fillna(impute_value)

現在我們需要指定模型。我增加了一個列IsFemale,作爲“Sex”列的編碼:

train['IsFemale'] = (train['Sex'] == 'female').astype(int)
test['IsFemale'] = (test['Sex'] == 'female').astype(int)

然後,我們確定一些模型變量,並創建NumPy數組:

predictors = ['Pclass', 'IsFemale', 'Age']
X_train = train[predictors].values
X_train[:3]
array([[ 3.,  0., 22.],
       [ 1.,  1., 38.],
       [ 3.,  1., 26.]])
X_test = test[predictors].values
y_train = train['Survived'].values
y_train[:3]
array([0, 1, 1])

我不能保證這是一個好模型,但它的特徵都符合。我們用scikit-learn的LogisticRegression模型,創建一個模型實例:

from sklearn.linear_model import LogisticRegression
model = LogisticRegression()

與statsmodels類似,我們可以用模型的fit方法,將它擬合到訓練數據:

model.fit(X_train, y_train)
/root/miniconda3/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)





LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='warn',
          n_jobs=None, penalty='l2', random_state=None, solver='warn',
          tol=0.0001, verbose=0, warm_start=False)

現在,我們可以用model.predict,對測試數據進行預測:

y_predict = model.predict(X_test)

y_predict[:10]
array([0, 0, 0, 0, 1, 0, 1, 0, 1, 0])

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

(y_true == y_predict).mean()

在實際中,模型訓練經常有許多額外的複雜因素。許多模型有可以調節的參數,有些方法(比如交叉驗證)可以用來進行參數調節,避免對訓練數據過擬合。這通常可以提高預測性或對新數據的健壯性。

交叉驗證通過分割訓練數據來模擬樣本外預測。基於模型的精度得分(比如均方差),可以對模型參數進行網格搜索。有些模型,如logistic迴歸,有內置的交叉驗證的估計類。例如,logisticregressioncv類可以用一個參數指定網格搜索對模型的正則化參數C的粒度:

from sklearn.linear_model import LogisticRegressionCV

model_cv = LogisticRegressionCV(10)
model_cv.fit(X_train, y_train)
/root/miniconda3/lib/python3.6/site-packages/sklearn/model_selection/_split.py:2053: FutureWarning: You should specify a value for 'cv' instead of relying on the default value. The default value will change from 3 to 5 in version 0.22.
  warnings.warn(CV_WARNING, FutureWarning)





LogisticRegressionCV(Cs=10, class_weight=None, cv='warn', dual=False,
           fit_intercept=True, intercept_scaling=1.0, max_iter=100,
           multi_class='warn', n_jobs=None, penalty='l2',
           random_state=None, refit=True, scoring=None, solver='lbfgs',
           tol=0.0001, verbose=0)

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

from sklearn.model_selection import cross_val_score

model = LogisticRegression(C=10)

scores = cross_val_score(model, X_train, y_train, cv=4)
/root/miniconda3/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
/root/miniconda3/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
/root/miniconda3/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
/root/miniconda3/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
scores
array([0.77232143, 0.80269058, 0.77027027, 0.78828829])

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

繼續學習

我只是介紹了一些Python建模庫的表面內容,現在有越來越多的框架用於各種統計和機器學習,它們都是用Python或Python用戶界面實現的。
這本書的重點是數據規整,有其它的書是關注建模和數據科學工具的。其中優秀的有:

  • 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》

雖然書是學習的好資源,但是隨着底層開源軟件的發展,書的內容會過時。最好是不斷熟悉各種統計和機器學習框架的文檔,學習最新的功能和API。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章