提交 f4ef2c26 编写于 作者: W wizardforcel

2021-01-01 17:16:48

上级 fe506231
......@@ -8,11 +8,11 @@
# 13.1 pandas 与模型代码的接口
模型开发的通常工作流是使用 pandas 进行数据加载和清洗,然后切换到建模库进行建模。开发模型的重要一环是机器学习中的“特征工程”。它可以描述从原始数据集中提取信息的任何数据转换或分析,这些数据集可能在建模中有用。本书中学习的数据聚合和 GroupBy 工具常用于特征工程中。
模型开发的通常工作流是使用 pandas 进行数据加载和清洗,然后切换到建模库进行建模。开发模型的重要一环是机器学习中的“特征工程”。它可以描述从原始数据集中提取信息的任何数据转换或分析,这些数据集可能在建模中有用。本书中学习的数据聚合和`GroupBy`工具常用于特征工程中。
优秀的特征工程超出了本书的范围,我会尽量直白地介绍一些用于数据操作和建模切换的方法。
pandas 与其它分析库通常是靠 NumPy 的数组联系起来的。将`DataFrame`转换为 NumPy 数组,可以使用.values 属性:
pandas 与其它分析库通常是靠 NumPy 的数组联系起来的。将`DataFrame`转换为 NumPy 数组,可以使用`.values`属性:
```python
In [10]: import pandas as pd
......@@ -44,7 +44,7 @@ array([[ 1. , 0.01, -1.5 ],
[ 5. , 0. , -2. ]])
```
要转换回`DataFrame`,可以传递一个二维 ndarray,可带有列名:
要转换回`DataFrame`,可以传递一个二维`ndarray`,可带有列名:
```python
In [16]: df2 = pd.DataFrame(data.values, columns=['one', 'two', 'three'])
......@@ -58,7 +58,7 @@ Out[17]:
4 5.0 0.00 -2.0
```
> 笔记:最好当数据是均匀的时候使用.values 属性。例如,全是数值类型。如果数据是不均匀的,结果会是 Python 对象的 ndarray
> 笔记:最好当数据是均匀的时候使用`.values`属性。例如,全是数值类型。如果数据是不均匀的,结果会是 Python 对象的`ndarray`
>```python
>In [18]: df3 = data.copy()
>
......@@ -82,7 +82,7 @@ Out[17]:
> [5, 0.0, -2.0, 'e']], dtype=object)
>```
对于一些模型,你可能只想使用列的子集。我建议你使用 loc,用 values 作索引:
对于一些模型,你可能只想使用列的子集。我建议你使用`loc`,用`values`作索引:
```python
In [22]: model_cols = ['x0', 'x1']
......@@ -97,7 +97,7 @@ array([[ 1. , 0.01],
一些库原生支持 pandas,会自动完成工作:从`DataFrame`转换到 NumPy,将模型的参数名添加到输出表的列或`Series`。其它情况,你可以手工进行“元数据管理”。
在第 12 章,我们学习了 pandas 的 Categorical 类型和`pandas.get_dummies`函数。假设数据集中有一个非数值列:
在第 12 章,我们学习了 pandas 的`Categorical`类型和`pandas.get_dummies`函数。假设数据集中有一个非数值列:
```python
In [24]: data['category'] = pd.Categorical(['a', 'b', 'a', 'a', 'b'],
....: categories=['a', 'b'])
......@@ -112,7 +112,7 @@ Out[25]:
4 5 0.00 -2.0 b
```
如果我们想替换 category 列为虚变量,我们可以创建虚变量,删除 category 列,然后添加到结果:
如果我们想替换`category`列为虚变量,我们可以创建虚变量,删除`category`列,然后添加到结果:
```python
In [26]: dummies = pd.get_dummies(data.category, prefix='category')
......@@ -139,7 +139,7 @@ Patsy 适合描述 statsmodels 的线性模型,因此我会关注于它的主
y ~ x0 + x1
```
a+b 不是将 a 与 b 相加的意思,而是为模型创建的设计矩阵。patsy.dmatrices 函数接收一个公式字符串和一个数据集(可以是`DataFrame`或数组的字典),为线性模型创建设计矩阵:
`a+b`不是将`a``b`相加的意思,而是为模型创建的设计矩阵。`patsy.dmatrices`函数接收一个公式字符串和一个数据集(可以是`DataFrame`或数组的字典),为线性模型创建设计矩阵:
```python
In [29]: data = pd.DataFrame({
....: 'x0': [1, 2, 3, 4, 5],
......@@ -189,7 +189,7 @@ DesignMatrix with shape (5, 3)
'x1' (column 2)
```
这些 Patsy 的 DesignMatrix 实例是 NumPy 的 ndarray,带有附加元数据:
这些 Patsy 的`DesignMatrix`实例是 NumPy 的`ndarray`,带有附加元数据:
```python
In [35]: np.asarray(y)
Out[35]:
......@@ -208,7 +208,7 @@ array([[ 1. , 1. , 0.01],
[ 1. , 5. , 0. ]])
```
你可能想 Intercept 是哪里来的。这是线性模型(比如普通最小二乘回归)的惯例用法。添加 +0 到模型可以不显示 intercept
你可能想`Intercept`是哪里来的。这是线性模型(比如普通最小二乘回归)的惯例用法。添加 +0 到模型可以不显示`intercept`
```python
In [37]: patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
Out[37]:
......@@ -229,7 +229,7 @@ Patsy 对象可以直接传递到算法(比如`numpy.linalg.lstsq`)中,它
In [38]: coef, resid, _, _ = np.linalg.lstsq(X, y)
```
模型的元数据保留在 design_info 属性中,因此你可以重新附加列名到拟合系数,以获得一个`Series`,例如:
模型的元数据保留在`design_info`属性中,因此你可以重新附加列名到拟合系数,以获得一个`Series`,例如:
```python
In [39]: coef
Out[39]:
......@@ -289,7 +289,7 @@ DesignMatrix with shape (5, 3)
作为建模的一步,你可能拟合模型到一个数据集,然后用另一个数据集评估模型。另一个数据集可能是剩余的部分或是新数据。当执行中心化和标准化转变,用新数据进行预测要格外小心。因为你必须使用平均值或标准差转换新数据集,这也称作状态转换。
patsy.build_design_matrices 函数可以使用原始样本数据集的保存信息,来转换新数据,:
`patsy.build_design_matrices`函数可以使用原始样本数据集的保存信息,来转换新数据,:
```python
In [46]: new_data = pd.DataFrame({
....: 'x0': [6, 7, 8, 9],
......@@ -312,7 +312,7 @@ Out[48]:
'center(x1)' (column 2)]
```
因为 Patsy 中的加号不是加法的意义,当你按照名称将数据集的列相加时,你必须用特殊 I 函数将它们封装起来:
因为 Patsy 中的加号不是加法的意义,当你按照名称将数据集的列相加时,你必须用特殊`I`函数将它们封装起来:
```python
In [49]: y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)
......@@ -330,7 +330,7 @@ DesignMatrix with shape (5, 2)
'I(x0 + x1)' (column 1)
```
Patsy 的 patsy.builtins 模块还有一些其它的内置转换。请查看线上文档。
Patsy 的`patsy.builtins`模块还有一些其它的内置转换。请查看线上文档。
分类数据有一个特殊的转换类,下面进行讲解。
......@@ -407,7 +407,7 @@ DesignMatrix with shape (8, 2)
'C(key2)' (column 1)
```
当你在模型中使用多个分类名,事情就会变复杂,因为会包括 key1:key2 形式的相交部分,它可以用在方差(ANOVA)模型分析中:
当你在模型中使用多个分类名,事情就会变复杂,因为会包括`key1:key2`形式的相交部分,它可以用在方差(ANOVA)模型分析中:
```python
In [58]: data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})
......@@ -510,7 +510,7 @@ beta = [0.1, 0.3, 0.5]
y = np.dot(X, beta) + eps
```
这里,我使用了“真实”模型和可知参数 beta。此时,dnorm 可用来生成正态分布数据,带有特定均值和方差。现在有:
这里,我使用了“真实”模型和可知参数`beta`。此时,`dnorm`可用来生成正态分布数据,带有特定均值和方差。现在有:
```python
In [66]: X[:5]
Out[66]:
......@@ -524,7 +524,7 @@ In [67]: y[:5]
Out[67]: array([ 0.4279, -0.6735, -0.0909, -0.4895,-0.1289])
```
像之前 Patsy 看到的,线性模型通常要拟合一个截距。sm.add_constant 函数可以添加一个截距的列到现存的矩阵:
像之前 Patsy 看到的,线性模型通常要拟合一个截距。`sm.add_constant`函数可以添加一个截距的列到现存的矩阵:
```python
In [68]: X_model = sm.add_constant(X)
......@@ -537,12 +537,12 @@ array([[ 1. , -0.1295, -1.2128, 0.5042],
[ 1. , 1.2433, -0.3738, -0.5226]])
```
sm.OLS 类可以拟合一个普通最小二乘回归:
`sm.OLS`类可以拟合一个普通最小二乘回归:
```python
In [70]: model = sm.OLS(y, X)
```
这个模型的 fit 方法返回了一个回归结果对象,它包含估计的模型参数和其它内容:
这个模型的`fit`方法返回了一个回归结果对象,它包含估计的模型参数和其它内容:
```python
In [71]: results = model.fit()
......@@ -550,7 +550,7 @@ In [72]: results.params
Out[72]: array([ 0.1783, 0.223 , 0.501 ])
```
对结果使用 summary 方法可以打印模型的详细诊断结果:
对结果使用`summary`方法可以打印模型的详细诊断结果:
```python
In [73]: print(results.summary())
OLS Regression Results
......@@ -582,7 +582,7 @@ Warnings:
specified.
```
这里的参数名为通用名 x1, x2 等等。假设所有的模型参数都在一个`DataFrame`中:
这里的参数名为通用名`x1``x2`等等。假设所有的模型参数都在一个`DataFrame`中:
```python
In [74]: data = pd.DataFrame(X, columns=['col0', 'col1', 'col2'])
......@@ -619,7 +619,7 @@ col2 6.303971
dtype: float64
```
观察下 statsmodels 是如何返回`Series`结果的,附带有`DataFrame`的列名。当使用公式和 pandas 对象时,我们不需要使用 add_constant
观察下 statsmodels 是如何返回`Series`结果的,附带有`DataFrame`的列名。当使用公式和 pandas 对象时,我们不需要使用`add_constant`
给出一个样本外数据,你可以根据估计的模型参数计算预测值:
```python
......@@ -655,7 +655,7 @@ for i in range(N):
values.append(new_x)
```
这个数据有 AR(2)结构(两个延迟),参数是 0.8 和-0.4。拟合 AR 模型时,你可能不知道滞后项的个数,因此可以用较多的滞后量来拟合这个模型:
这个数据有`AR(2)`结构(两个延迟),参数是 0.8 和 -0.4。拟合 AR 模型时,你可能不知道滞后项的个数,因此可以用较多的滞后量来拟合这个模型:
```python
In [82]: MAXLAGS = 5
......@@ -750,7 +750,7 @@ In [92]: train['Age'] = train['Age'].fillna(impute_value)
In [93]: test['Age'] = test['Age'].fillna(impute_value)
```
现在我们需要指定模型。我增加了一个列 IsFemale,作为“Sex”列的编码:
现在我们需要指定模型。我增加了一个列`IsFemale`,作为`Sex`列的编码:
```python
In [94]: train['IsFemale'] = (train['Sex'] == 'female').astype(int)
......@@ -779,14 +779,14 @@ In [101]: y_train[:5]
Out[101]: array([0, 1, 1, 1, 0])
```
我不能保证这是一个好模型,但它的特征都符合。我们用 scikit-learn 的 LogisticRegression 模型,创建一个模型实例:
我不能保证这是一个好模型,但它的特征都符合。我们用 scikit-learn 的`LogisticRegression`模型,创建一个模型实例:
```python
In [102]: from sklearn.linear_model import LogisticRegression
In [103]: model = LogisticRegression()
```
与 statsmodels 类似,我们可以用模型的 fit 方法,将它拟合到训练数据:
与 statsmodels 类似,我们可以用模型的`fit`方法,将它拟合到训练数据:
```python
In [104]: model.fit(X_train, y_train)
Out[104]:
......@@ -796,7 +796,7 @@ LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
verbose=0, warm_start=False)
```
现在,我们可以用 model.predict,对测试数据进行预测:
现在,我们可以用`model.predict`,对测试数据进行预测:
```python
In [105]: y_predict = model.predict(X_test)
......@@ -811,7 +811,7 @@ Out[106]: array([0, 0, 0, 0, 1, 0, 1, 0, 1, 0])
在实际中,模型训练经常有许多额外的复杂因素。许多模型有可以调节的参数,有些方法(比如交叉验证)可以用来进行参数调节,避免对训练数据过拟合。这通常可以提高预测性或对新数据的健壮性。
交叉验证通过分割训练数据来模拟样本外预测。基于模型的精度得分(比如均方差),可以对模型参数进行网格搜索。有些模型,如 logistic 回归,有内置的交叉验证的估计类。例如,logisticregressioncv 类可以用一个参数指定网格搜索对模型的正则化参数 C 的粒度:
交叉验证通过分割训练数据来模拟样本外预测。基于模型的精度得分(比如均方差),可以对模型参数进行网格搜索。有些模型,如 logistic 回归,有内置的交叉验证的估计类。例如,`LogisticRegressionCV`类可以用一个参数指定网格搜索对模型的正则化参数`C`的粒度:
```python
In [107]: from sklearn.linear_model import LogisticRegressionCV
......@@ -825,7 +825,7 @@ LogisticRegressionCV(Cs=10, class_weight=None, cv=None, dual=False,
refit=True, scoring=None, solver='lbfgs', tol=0.0001, verbose=0)
```
要手动进行交叉验证,你可以使用 cross_val_score 帮助函数,它可以处理数据分割。例如,要交叉验证我们的带有四个不重叠训练数据的模型,可以这样做:
要手动进行交叉验证,你可以使用`cross_val_score`帮助函数,它可以处理数据分割。例如,要交叉验证我们的带有四个不重叠训练数据的模型,可以这样做:
```python
In [110]: from sklearn.model_selection import cross_val_score
......@@ -845,10 +845,10 @@ Out[113]: array([ 0.7723, 0.8027, 0.7703, 0.7883])
这本书的重点是数据规整,有其它的书是关注建模和数据科学工具的。其中优秀的有:
- Andreas Mueller and Sarah Guido (OReilly)的 《Introduction to Machine Learning with Python》
- Jake VanderPlas (OReilly)的 《Python Data Science Handbook》
- Joel Grus (OReilly) 的 《Data Science from Scratch: First Principles》
- 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 (OReilly) 的《Hands-On Machine Learning with Scikit-Learn and TensorFlow》
- Aurélien Géron (O'Reilly) 的《Hands-On Machine Learning with Scikit-Learn and TensorFlow》
虽然书是学习的好资源,但是随着底层开源软件的发展,书的内容会过时。最好是不断熟悉各种统计和机器学习框架的文档,学习最新的功能和 API。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册