第十一节 Python建模库
本章节以及后续章节的源码,当然也可以从我的github下载,在源码中我自己加了一些中文注释。
一、pandas与模型代码的接口
模型开发的通常工作流是使用pandas进行数据加载和清洗,然后切换到建模库进行建模。开发模型的重要一环是机器学习中的“特征工程”。它可以描述从原始数据集中提取信息的任何数据转换或分析,这些数据集可能在建模中有用。前面学习的数据聚合和GroupBy工具常用于特征工程中。
pandas与其它分析库通常是靠NumPy的数组联系起来的。将DataFrame转换为NumPy数组,可以使用.values属性:
![](https://img.haomeiwen.com/i10053166/2fcbc1124aa65ee1.png)
要转换回DataFrame,可以传递一个二维ndarray,可带有列名:
![](https://img.haomeiwen.com/i10053166/549f79b4459c7d1e.png)
最好当数据是均匀的时候使用.values属性。例如,全是数值类型。如果数据是不均匀的,结果会是Python对象的ndarray:
![](https://img.haomeiwen.com/i10053166/abdcab26c722eb8a.png)
对于一些模型,你可能只想使用列的子集。使用loc,用values作索引:
![](https://img.haomeiwen.com/i10053166/0e5b1da63e6dd969.png)
一些库原生支持pandas,会自动完成工作:从DataFrame转换到NumPy,将模型的参数名添加到输出表的列或Series。其它情况,你可以手工进行“元数据管理”。
我们学习了pandas的Categorical类型和pandas.get_dummies函数。
pandas.get_dummies函数用法:
![](https://img.haomeiwen.com/i10053166/86464dfbdfbd250c.png)
![](https://img.haomeiwen.com/i10053166/ee43e2c25fbb355c.png)
假设数据集中有一个非数值列:
![](https://img.haomeiwen.com/i10053166/eb12207d6558be09.png)
如果我们想替换category列为虚变量,我们可以创建虚变量,删除category列,然后添加到结果:
![](https://img.haomeiwen.com/i10053166/1047fefaae5283a7.png)
用虚变量拟合某些统计模型会有一些细微差别。当你不只有数字列时,使用Patsy可能更简单,更不容易出错。
二、用Patsy创建模型描述
Patsy是Python的一个库,使用简短的字符串“公式语法”描述统计模型(尤其是线性模型)。Patsy适合描述statsmodels的线性模型。Patsy的公式是一个特殊的字符串语法,如下所示:
![](https://img.haomeiwen.com/i10053166/d872c87ac5ca0b6f.png)
a+b不是将a与b相加的意思,而是为模型创建的设计矩阵。patsy.dmatrices函数接收一个公式字符串和一个数据集(可以是DataFrame或数组的字典),为线性模型创建设计矩阵:
![](https://img.haomeiwen.com/i10053166/b3463a81bbe02e95.png)
![](https://img.haomeiwen.com/i10053166/8bc5351ccafd206d.png)
这些Patsy的DesignMatrix实例是NumPy的ndarray,带有附加元数据:
![](https://img.haomeiwen.com/i10053166/78d7a724082762be.png)
你可能想Intercept是哪里来的。这是线性模型(比如普通最小二乘回归)的惯例用法。添加 +0 到模型可以不显示intercept(截距):
![](https://img.haomeiwen.com/i10053166/83f247b67b7c16a8.png)
Patsy对象可以直接传递到算法(比如numpy.linalg.lstsq)中,它执行普通最小二乘回归:
![](https://img.haomeiwen.com/i10053166/fcb6ba08cdd30dbf.png)
![](https://img.haomeiwen.com/i10053166/a6e0c5a4d87ab8f6.png)
模型的元数据保留在design_info属性中,因此你可以重新附加列名到拟合系数,以获得一个Series,例如:
![](https://img.haomeiwen.com/i10053166/f3d8acace1f8795f.png)
squeeze 函数:从数组的形状中删除单维度条目,即把shape中为1的维度去掉。
用法:numpy.squeeze(a,axis = None)
1、用Patsy公式进行数据转换
你可以将Python代码与patsy公式结合。在评估公式时,库将尝试查找在封闭作用域内使用的函数:
![](https://img.haomeiwen.com/i10053166/414c176e2369b0b1.png)
常见的变量转换包括标准化(平均值为0,方差为1)和中心化(减去平均值)。Patsy有内置的函数进行这样的工作:
![](https://img.haomeiwen.com/i10053166/0e2fcc93dc3ae757.png)
作为建模的一步,你可能拟合模型到一个数据集,然后用另一个数据集评估模型。另一个数据集可能是剩余的部分或是新数据。当执行中心化和标准化转变,用新数据进行预测要格外小心。因为你必须使用平均值或标准差转换新数据集,这也称作状态转换。
patsy.build_design_matrices函数可以使用原始样本数据集的保存信息,来转换新数据:
![](https://img.haomeiwen.com/i10053166/a525b4eb8801f341.png)
![](https://img.haomeiwen.com/i10053166/feef19c1bcf00c76.png)
![](https://img.haomeiwen.com/i10053166/4938bce595a948e7.png)
因为Patsy中的加号不是加法的意义,当你按照名称将数据集的列相加时,你必须用特殊I函数将它们封装起来:
![](https://img.haomeiwen.com/i10053166/25a9f5643a602b7a.png)
Patsy的patsy.builtins模块还有一些其它的内置转换。
2、分类数据和Patsy
非数值数据可以用多种方式转换为模型设计矩阵。
当你在Patsy公式中使用非数值数据,它们会默认转换为虚变量。如果有截距,会去掉一个,避免共线性:
![](https://img.haomeiwen.com/i10053166/c50bfed65e6e421a.png)
如果你从模型中忽略截距,每个分类值的列都会包括在设计矩阵的模型中:
![](https://img.haomeiwen.com/i10053166/36d6f013f790af3c.png)
使用C函数,数值列可以截取为分类量:
![](https://img.haomeiwen.com/i10053166/405de6d35bbe1ee3.png)
当你在模型中使用多个分类名,事情就会变复杂,因为会包括key1:key2形式的相交部分,它可以用在方差(ANOVA)模型分析中:
![](https://img.haomeiwen.com/i10053166/aa449a689d2f6fad.png)
![](https://img.haomeiwen.com/i10053166/50a0dfad50d32ef3.png)
Patsy提供转换分类数据的其它方法,包括以特定顺序转换。
三、statsmodels介绍
statsmodels是Python进行拟合多种统计模型、进行统计试验和数据探索可视化的库。Statsmodels包含许多经典的统计方法,但没有贝叶斯方法和机器学习模型。
statsmodels包含的模型有:
(1)线性模型,广义线性模型和健壮线性模型
(2)线性混合效应模型
(3)方差(ANOVA)方法分析
(4)时间序列过程和状态空间模型
(5)广义矩估计
估计线型模型
statsmodels有多种线性回归模型,包括从基本(比如普通最小二乘)到复杂(比如迭代加权最小二乘法)的。
statsmodels的线性模型有两种不同的接口:基于数组和基于公式。它们可以通过API模块引入:
![](https://img.haomeiwen.com/i10053166/038e54aa461a1ae2.png)
![](https://img.haomeiwen.com/i10053166/ee6634cf8817442c.png)
![](https://img.haomeiwen.com/i10053166/dbe86e3289764503.png)
![](https://img.haomeiwen.com/i10053166/11dd2449aeea40a7.png)
![](https://img.haomeiwen.com/i10053166/9d208619de602b9b.png)
我们从一些随机数据生成一个线性模型:
![](https://img.haomeiwen.com/i10053166/10ce514fcc80023b.png)
线性模型通常要拟合一个截距。sm.add_constant函数可以添加一个截距的列到现存的矩阵:
![](https://img.haomeiwen.com/i10053166/92d14a8ea5563edf.png)
sm.OLS类可以拟合一个普通最小二乘回归,这个模型的fit方法返回了一个回归结果对象,它包含估计的模型参数和其它内容:
![](https://img.haomeiwen.com/i10053166/d0f4ccaeb9744aca.png)
对结果使用summary方法可以打印模型的详细诊断结果:
![](https://img.haomeiwen.com/i10053166/177f4f7aa66f0480.png)
假设所有的模型参数都在一个DataFrame中:
![](https://img.haomeiwen.com/i10053166/0779d7c101b4f1d6.png)
现在,我们使用statsmodels的公式API和Patsy的公式字符串:
![](https://img.haomeiwen.com/i10053166/57959c9da84ebfe5.png)
观察下statsmodels是如何返回Series结果的,附带有DataFrame的列名。当使用公式和pandas对象时,我们不需要使用add_constant。
给出一个样本外数据,你可以根据估计的模型参数计算预测值:
![](https://img.haomeiwen.com/i10053166/60b0cbc3b68c96b3.png)
statsmodels的线性模型结果还有其它的分析、诊断和可视化工具。除了普通最小二乘模型,还有其它的线性模型。
四、scikit-learn介绍
scikit-learn是一个广泛使用、用途多样的Python机器学习库。它包含多种标准监督和非监督机器学习方法和模型选择和评估、数据转换、数据加载和模型持久化工具。这些模型可以用于分类、聚合、预测和其它任务。
举个例子,用一个Kaggle竞赛的经典数据集,关于泰坦尼克号乘客的生还率。我们用pandas加载测试和训练数据集:
![](https://img.haomeiwen.com/i10053166/5fba4e2f5500b2af.png)
statsmodels和scikit-learn通常不能接收缺失数据,因此我们要查看列是否包含缺失值:
![](https://img.haomeiwen.com/i10053166/bcb784ff6db9309a.png)
在统计和机器学习的例子中,根据数据中的特征,一个典型的任务是预测乘客能否生还。模型现在训练数据集中拟合,然后用样本外测试数据集评估。
用年龄作为预测值,但是它包含缺失值。缺失数据补全的方法有多种,我用的是一种简单方法,用训练数据集的中位数补全两个表的空值:
![](https://img.haomeiwen.com/i10053166/d56bccc950c1aecf.png)
现在我们需要指定模型。我增加了一个列IsFemale,作为“Sex”列的编码:
![](https://img.haomeiwen.com/i10053166/b07988fe953e9ad5.png)
然后,我们确定一些模型变量,并创建NumPy数组:
![](https://img.haomeiwen.com/i10053166/e8217ab79d11b650.png)
不能保证这是一个好模型,但它的特征都符合。我们用scikit-learn的LogisticRegression模型,创建一个模型实例。与statsmodels类似,我们可以用模型的fit方法,将它拟合到训练数据:
![](https://img.haomeiwen.com/i10053166/69df04385224faf4.png)
现在,我们可以用model.predict,对测试数据进行预测:
![](https://img.haomeiwen.com/i10053166/b9e46c4496673701.png)
如果有测试数据集的真是值,可以计算准确率或其它错误度量值:
![](https://img.haomeiwen.com/i10053166/f1278ed6afa764a5.png)
在实际中,模型训练经常有许多额外的复杂因素。许多模型有可以调节的参数,有些方法(比如交叉验证)可以用来进行参数调节,避免对训练数据过拟合。这通常可以提高预测性或对新数据的健壮性。
交叉验证通过分割训练数据来模拟样本外预测。基于模型的精度得分(比如均方差),可以对模型参数进行网格搜索。有些模型,如logistic回归,有内置的交叉验证的估计类。例如,logisticregressionCV类可以用一个参数指定网格搜索对模型的正则化参数C的粒度:
![](https://img.haomeiwen.com/i10053166/7284e17a810c2eab.png)
要手动进行交叉验证,你可以使用cross_val_score帮助函数,它可以处理数据分割。例如,要交叉验证我们的带有四个不重叠训练数据的模型,可以这样做:
![](https://img.haomeiwen.com/i10053166/d65e1488d7a0efe0.png)
默认的评分指标取决于模型本身,但是可以明确指定一个评分。交叉验证过的模型需要更长时间来训练,但会有更高的模型性能。
快速学习: