13.4 scikit-learn介绍

机器学习方面的学习和应用scikit-learn和TensorFlow解决实际问题的线上和纸质资料很多。本节中,我会简要介绍scikit-learn API的风格。

写作此书的时候,scikit-learn并没有和pandas深度结合,但是有些第三方包在开发中。尽管如此,pandas非常适合在模型拟合前处理数据集。

举个例子,我用一个Kaggle竞赛的经典数据集,关于泰坦尼克号乘客的生还率。我们用pandas加载测试和训练数据集:

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

  1. Out[89]:
  2. PassengerId 0
  3. Survived 0
  4. Pclass 0
  5. Name 0
  6. Sex 0
  7. Age 177
  8. SibSp 0
  9. Parch 0
  10. Ticket 0
  11. Fare 0
  12. Cabin 687
  13. Embarked 2
  14. dtype: int64
  15. In [90]: test.isnull().sum()
  16. Out[90]:
  17. PassengerId 0
  18. Pclass 0
  19. Name 0
  20. Sex 0
  21. Age 86
  22. Parch 0
  23. Ticket 0
  24. Fare 1
  25. Cabin 327
  26. Embarked 0
  27. dtype: int64

我想用年龄作为预测值,但是它包含缺失值。缺失数据补全的方法有多种,我用的是一种简单方法,用训练数据集的中位数补全两个表的空值:

  1. In [91]: impute_value = train['Age'].median()
  2. In [92]: train['Age'] = train['Age'].fillna(impute_value)
  3. In [93]: test['Age'] = test['Age'].fillna(impute_value)

现在我们需要指定模型。我增加了一个列IsFemale,作为“Sex”列的编码:

然后,我们确定一些模型变量,并创建NumPy数组:

  1. In [96]: predictors = ['Pclass', 'IsFemale', 'Age']
  2. In [97]: X_train = train[predictors].values
  3. In [98]: X_test = test[predictors].values
  4. In [99]: y_train = train['Survived'].values
  5. In [100]: X_train[:5]
  6. Out[100]:
  7. array([[ 3., 0., 22.],
  8. [ 3., 1., 26.],
  9. [ 1., 1., 35.],
  10. [ 3., 0., 35.]])
  11. In [101]: y_train[:5]
  12. Out[101]: array([0, 1, 1, 1, 0])

我不能保证这是一个好模型,但它的特征都符合。我们用scikit-learn的LogisticRegression模型,创建一个模型实例:

  1. In [102]: from sklearn.linear_model import LogisticRegression
  2. In [103]: model = LogisticRegression()

现在,我们可以用model.predict,对测试数据进行预测:

  1. In [105]: y_predict = model.predict(X_test)
  2. In [106]: y_predict[:10]
  3. Out[106]: array([0, 0, 0, 0, 1, 0, 1, 0, 1, 0])

如果你有测试数据集的真是值,你可以计算准确率或其它错误度量值:

  1. (y_true == y_predict).mean()

在实际中,模型训练经常有许多额外的复杂因素。许多模型有可以调节的参数,有些方法(比如交叉验证)可以用来进行参数调节,避免对训练数据过拟合。这通常可以提高预测性或对新数据的健壮性。

交叉验证通过分割训练数据来模拟样本外预测。基于模型的精度得分(比如均方差),可以对模型参数进行网格搜索。有些模型,如logistic回归,有内置的交叉验证的估计类。例如,logisticregressioncv类可以用一个参数指定网格搜索对模型的正则化参数C的粒度:

  1. In [110]: from sklearn.model_selection import cross_val_score
  2. In [111]: model = LogisticRegression(C=10)
  3. In [112]: scores = cross_val_score(model, X_train, y_train, cv=4)
  4. In [113]: scores
  5. Out[113]: array([ 0.7723, 0.8027, 0.7703, 0.7883])

默认的评分指标取决于模型本身,但是可以明确指定一个评分。交叉验证过的模型需要更长时间来训练,但会有更高的模型性能。