回归线

相关系数 $r$ 不仅度量散点图中点围绕一条直线的聚集程度,还有助于识别这些点所聚集的那条直线。在本节中,我们将重走高尔顿和皮尔逊发现那条直线的路径。

正如我们所见,关于父母身高及其成年子女身高的数据集表明两个变量之间存在线性关联。当我们基于父母中位身高对子女身高的预测大致呈一条直线时,这种线性关系得到了确认。

[In ]:
from datascience import *
import numpy as np
path_data = '../../../assets/data/'
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
[In ]:
original = Table.read_table(path_data + 'family_heights.csv')

heights = Table().with_columns(
    'MidParent', original.column('midparentHeight'),
    'Child', original.column('childHeight')
    )
[In ]:
def predict_child(mpht):
    """Return a prediction of the height of a child 
    whose parents have a midparent height of mpht.
    
    The prediction is the average height of the children 
    whose midparent height is in the range mpht plus or minus 0.5 inches.
    """
    
    close_points = heights.where('MidParent', are.between(mpht-0.5, mpht + 0.5))
    return close_points.column('Child').mean()   
[In ]:
heights_with_predictions = heights.with_column(
    'Prediction', heights.apply(predict_child, 'MidParent')
    )
[In ]:
heights_with_predictions.scatter('MidParent')
Scatterplot with 'MidParent' on the x-axis. The previous data points are shown again in dark blue and labeled 'Child.' These dark blue data points tend to have a positive correlation; as the x value increases so does the y value. There are additionally gold data points labeled 'Prediction.' The gold data points are in the center of the blue data points and also show a positive association. The x-axis ranges from 64 to 74. The y-axis ranges from 55 to 80.

以标准单位度量

让我们看看能否找到识别这条直线的方法。首先,注意到线性关联不依赖于度量单位——我们不妨将两个变量都以标准单位来度量。

[In ]:
def standard_units(xyz):
    "Convert any array of numbers to standard units."
    return (xyz - np.mean(xyz))/np.std(xyz)  
[In ]:
heights_SU = Table().with_columns(
    'MidParent SU', standard_units(heights.column('MidParent')),
    'Child SU', standard_units(heights.column('Child'))
)
heights_SU
MidParent SU | Child SU
3.45465      | 1.80416
3.45465      | 0.686005
3.45465      | 0.630097
3.45465      | 0.630097
2.47209      | 1.88802
2.47209      | 1.60848
2.47209      | -0.348285
2.47209      | -0.348285
1.58389      | 1.18917
1.58389      | 0.350559
... (924 rows omitted)

在这个尺度上,我们可以像之前一样精确地计算预测值。但首先,我们必须弄清楚如何将旧的“接近”点的定义转换为新尺度上的值。我们之前说过,如果父母中位身高相差在 0.5 英寸以内,就认为它们是“接近”的。由于标准单位以标准差为单位度量距离,我们必须计算出 0.5 英寸对应多少个父母中位身高的标准差。

父母中位身高的一个标准差约为 1.8 英寸。所以 0.5 英寸约为 0.28 个标准差。

[In ]:
sd_midparent = np.std(heights.column(0))
sd_midparent
1.8014050969207571
[In ]:
0.5/sd_midparent
0.277561110965367

我们现在准备修改预测函数,使其在标准单位尺度上进行预测。所有变化只是我们使用了标准单位的数值表,并如上所述定义“接近”。

[In ]:
def predict_child_su(mpht_su):
    """Return a prediction of the height (in standard units) of a child 
    whose parents have a midparent height of mpht_su in standard units.
    """
    close = 0.5/sd_midparent
    close_points = heights_SU.where('MidParent SU', are.between(mpht_su-close, mpht_su + close))
    return close_points.column('Child SU').mean()   
[In ]:
heights_with_su_predictions = heights_SU.with_column(
    'Prediction SU', heights_SU.apply(predict_child_su, 'MidParent SU')
    )
[In ]:
heights_with_su_predictions.scatter('MidParent SU')
Scatterplot with 'MidParent SU' on the x-axis. The shape of the data points is the same as before.In dark blue data points are labeled 'Child SU.' These dark blue data points tend to have a positive correlation; as the x value increases so does the y value. There are gold data points labeled 'Prediction SU.' The gold data points are in the center of the blue data points and also show a positive association. The x-axis ranges from -3 to 3. The y-axis ranges from -3 to 3.

这个图看起来与在原始尺度上绘制的图完全一样。只是轴上的数字发生了变化。这证实了我们只需在标准单位下工作就可以理解预测过程。

在标准单位下识别直线

上方的散点图呈现“橄榄球”形状——即大致呈椭圆形,像美式橄榄球。并非所有散点图都是橄榄球形,即使是那些显示线性关联的散点图也不一定。但在本节中,我们只处理橄榄球形的散点图。在下一节中,我们将把分析推广到其他形状的图。

这是一个橄榄球形的散点图,两个变量均以标准单位度量。45 度线以红色显示。

[In ]:
r = 0.5
x_demo = np.random.normal(0, 1, 10000)
z_demo = np.random.normal(0, 1, 10000)
y_demo = r*x_demo + np.sqrt(1 - r**2)*z_demo
plots.figure(figsize=(6,6))
plots.xlim(-4, 4)
plots.ylim(-4, 4)
plots.scatter(x_demo, y_demo, s=10)
#plots.plot([-4, 4], [-4*0.6,4*0.6], color='g', lw=2)
plots.plot([-4,4],[-4,4], color='r', lw=2)
#plots.plot([1.5,1.5], [-4,4], color='k', lw=2)
plots.xlabel('x in standard units')
plots.ylabel('y in standard units');
Scatterplot with 'x in standard units' on the x-axis and 'y in standard units' on the y-axis. Both axes range from -4 to 4. The data points show a moderately strong positive correlation; as the x value increases so does the y value. A red line y=x is drawn and sits roughly in the middle of the data points.

但 45 度线并不是穿过垂直条带中心的直线。你可以在下图中看到这一点,其中位于 1.5 标准单位处的垂直线以黑色显示。黑色线附近散点图上的点的高度大致在 -2 到 3 的范围内。红色线太高,无法穿过中心。

[In ]:
r = 0.5
x_demo = np.random.normal(0, 1, 10000)
z_demo = np.random.normal(0, 1, 10000)
y_demo = r*x_demo + np.sqrt(1 - r**2)*z_demo
plots.figure(figsize=(6,6))
plots.xlim(-4, 4)
plots.ylim(-4, 4)
plots.scatter(x_demo, y_demo, s=10)
#plots.plot([-4, 4], [-4*0.6,4*0.6], color='g', lw=2)
plots.plot([-4,4],[-4,4], color='r', lw=2)
plots.plot([1.5,1.5], [-4,4], color='k', lw=2)
plots.xlabel('x in standard units')
plots.ylabel('y in standard units');
The previous graph is reproduced with the addition of a black vertical line y=1.5. The previous graph description: Scatterplot with 'x in standard units' on the x-axis and 'y in standard units' on the y-axis. Both axes range from -4 to 4. The data points show a moderately strong positive correlation; as the x value increases so does the y value. A red line y=x is drawn and sits roughly in the middle of the data points.

所以 45 度线并不是“平均值图”。那条线是下面所示的绿色线。

[In ]:
r = 0.5
x_demo = np.random.normal(0, 1, 10000)
z_demo = np.random.normal(0, 1, 10000)
y_demo = r*x_demo + np.sqrt(1 - r**2)*z_demo
plots.figure(figsize=(6,6))
plots.xlim(-4, 4)
plots.ylim(-4, 4)
plots.scatter(x_demo, y_demo, s=10)
plots.plot([-4, 4], [-4*0.6,4*0.6], color='g', lw=2)
plots.plot([-4,4],[-4,4], color='r', lw=2)
plots.plot([1.5,1.5], [-4,4], color='k', lw=2)
plots.xlabel('x in standard units')
plots.ylabel('y in standard units');
The previous graph is reproduced, including the black vertical line at y=1.5, with the addition of a green line that truly sits in the center of the data. Previous description: Scatterplot with 'x in standard units' on the x-axis and 'y in standard units' on the y-axis. Both axes range from -4 to 4. The data points show a moderately strong positive correlation; as the x value increases so does the y value. A red line y=x is drawn and sits roughly in the middle of the data points.

两条线都经过原点 (0, 0)。绿色线穿过垂直条带的中心(至少大致如此),并且比红色 45 度线“更平缓”。

45 度线的斜率为 1。因此绿色“平均值图”线的斜率是一个正值但小于 1。

这个值可能是多少?你已经猜到了——它就是 $r$。

标准单位下的回归线

绿色的“平均值图”线被称为“回归线”,其原因我们稍后将解释。但首先,让我们模拟一些具有不同 $r$ 值的橄榄球形散点图,观察这条线如何变化。在每种情况下,红色 45 度线都已绘制以作比较。

执行模拟的函数称为 regression_line,以 $r$ 作为其参数。

[In ]:

def regression_line(r):
    x = np.random.normal(0, 1, 10000)
    z = np.random.normal(0, 1, 10000)
    y = r*x + (np.sqrt(1-r**2))*z
    plots.figure(figsize=(6, 6))
    plots.xlim(-4, 4)
    plots.ylim(-4, 4)
    plots.scatter(x, y)
    plots.plot([-4, 4], [-4*r,4*r], color='g', lw=2)
    if r >= 0:
        plots.plot([-4,4],[-4,4], lw=2, color='r')
    else:
        plots.plot([-4,4], [4,-4], lw=2, color='r')
[In ]:
regression_line(0.95)
Scatterplot where both axes extend from -4 to 4. The data is highly strongly positively correlated; as the x values increase so do the y values. Two lines are drawn. A red line starts a little lower than the green line and ends a little higher than the green line. Both lines stay within the shape of the data. The red line is y=x.
[In ]:
regression_line(0.6)
Scatterplot where both axes extend from -4 to 4. The data points are moderately potively correlated; as the x values increase do the y avlues. The line y=x is drawn in red. There is also a green line with a smaller slope that better aligns with the data points.

当 $r$ 接近 1 时,散点图、45 度线和回归线都非常接近。但对于更适中的 $r$ 值,回归线明显更平缓。

回归效应

在预测方面,这意味着对于父母中位身高为 1.5 标准单位的父母,我们对子女身高的预测会“略低于”1.5 标准单位。如果父母中位身高为 2 标准单位,我们预测子女的身高将略低于 2 标准单位。

换句话说,我们预测子女会比其父母更接近平均值。这被称为“均值回归”,这也是“回归”这一名称的由来。

当父母中位身高低于平均值时,均值回归同样适用。父母中位身高低于平均值的子女,平均而言比他们那一代人的平均身高略高。

一般来说,在一个变量上偏离平均值的个体,预计在另一个变量上不会偏离得那么远。这被称为“回归效应”。

请记住,回归效应是关于平均值的陈述。例如,它指出:如果你取所有父母中位身高为 1.5 标准单位的子女,那么这些子女的平均身高略低于 1.5 标准单位。这并不意味着所有这些子女的身高都略低于 1.5 标准单位。有些会更高,有些会更矮。这些身高的“平均值”将低于 1.5 标准单位。

回归线的方程

在回归中,我们使用一个变量(称为 $x$)的值来预测另一个变量(称为 $y$)的值。当变量 $x$ 和 $y$ 以标准单位度量时,用于基于 $x$ 预测 $y$ 的回归线的斜率为 $r$ 且经过原点。因此,回归线的方程可以写为:

$$ \mbox{estimate of }y ~=~ r \cdot x ~~~ \mbox{when both variables are measured in standard units} $$

在数据的原始单位下,这变为

$$ \frac{\mbox{estimate of}~y ~-~\mbox{average of}~y}{\mbox{SD of}~y} ~=~ r \times \frac{\mbox{the given}~x ~-~\mbox{average of}~x}{\mbox{SD of}~x} $$

Two figures are shown. The first is labeled "Regression Line in Standard Units." We see the point (0,0) with a horizontal line extending to the right. The length of the horizontal line is 1. From the end of that horizontal line is a veritcal line that extends upward with length r. The regression line is a sloping line that connects (and extends beyond in both directions) from (0,0) to the top of the vertical line. The second figure is labeled "Regression Line in Original Units." A similar figure is shown with different annotations. (0,0) is now (average of x, average of y), the horizontal length is now "SD of x" and the vertical length is now "r SD of y"

原始单位下回归线的斜率和截距可以从上图推导出来。

$$ \mathbf{\mbox{slope of the regression line}} ~=~ r \cdot \frac{\mbox{SD of }y}{\mbox{SD of }x} $$

$$ \mathbf{\mbox{intercept of the regression line}} ~=~ \mbox{average of }y ~-~ \mbox{slope} \cdot \mbox{average of }x $$

下面的三个函数用于计算相关性、斜率和截距。它们都接受三个参数:表的名称、包含 $x$ 的列标签以及包含 $y$ 的列标签。

[In ]:
def correlation(t, label_x, label_y):
    return np.mean(standard_units(t.column(label_x))*standard_units(t.column(label_y)))

def slope(t, label_x, label_y):
    r = correlation(t, label_x, label_y)
    return r*np.std(t.column(label_y))/np.std(t.column(label_x))

def intercept(t, label_x, label_y):
    return np.mean(t.column(label_y)) - slope(t, label_x, label_y)*np.mean(t.column(label_x))

数据单位下的回归线

父母中位身高与子女身高之间的相关性为 0.32:

[In ]:
family_r = correlation(heights, 'MidParent', 'Child')
family_r
0.32094989606395924

我们还可以找到基于父母中位身高预测子女身高的回归线方程。

[In ]:
family_slope = slope(heights, 'MidParent', 'Child')
family_intercept = intercept(heights, 'MidParent', 'Child')
family_slope, family_intercept
(0.637360896969479, 22.63624054958975)

回归线的方程为

$$ \mbox{estimate of child's height} ~=~ 0.64 \cdot \mbox{midparent height} ~+~ 22.64 $$

这也被称为“回归方程”。回归方程的主要用途是基于 $x$ 预测 $y$。

例如,对于父母中位身高 70.48 英寸,回归方程预测子女身高为 67.56 英寸。

[In ]:
family_slope * 70.48 + family_intercept
67.55743656799862

我们最初的预测(通过取所有父母中位身高接近 70.48 英寸的子女的平均身高得到)与回归线的预测非常接近:67.63 英寸对比回归线的 67.55 英寸。

[In ]:
heights_with_predictions.where('MidParent', are.equal_to(70.48)).show(3)
<IPython.core.display.HTML object>

以下是表的所有行,以及我们最初的预测和新的回归预测的子女身高。

[In ]:
heights_with_predictions = heights_with_predictions.with_column(
    'Regression Prediction', family_slope * heights.column('MidParent') + family_intercept
)
heights_with_predictions
MidParent | Child | Prediction | Regression Prediction
75.43     | 73.2  | 70.1       | 70.7124
75.43     | 69.2  | 70.1       | 70.7124
75.43     | 69    | 70.1       | 70.7124
75.43     | 69    | 70.1       | 70.7124
73.66     | 73.5  | 70.4158    | 69.5842
73.66     | 72.5  | 70.4158    | 69.5842
73.66     | 65.5  | 70.4158    | 69.5842
73.66     | 65.5  | 70.4158    | 69.5842
72.06     | 71    | 68.5025    | 68.5645
72.06     | 68    | 68.5025    | 68.5645
... (924 rows omitted)
[In ]:
heights_with_predictions.scatter('MidParent')
Scatterplot with 'MidParent' on the x-axis. Three colors of data points are present. In dark blue is 'Child.' These data points have a moderate positive correlation and are clearly blob-like, with multiple points possible per x-value. The gold data points are labeled 'Prediction' and the light blue data points are labeled 'Regression Prediction.' Each of the gold and light blue data points have one point per possible x value. The light blue and gold data points are very close together, but we see the regression prediction data points falling along a straight line, where the gold data points have some wavy-ness to them.

浅蓝色点显示回归预测值,全部位于回归线上。注意这条线非常接近金色的平均值图。对于这些数据,回归线很好地近似了垂直条带的中心。

拟合值

所有预测值都位于线上,称为“拟合值”。函数 fit 接受表的名称以及 $x$ 和 $y$ 的标签,返回一个拟合值数组,散点图中每个点对应一个拟合值。

[In ]:
def fit(table, x, y):
    """Return the height of the regression line at each x value."""
    a = slope(table, x, y)
    b = intercept(table, x, y)
    return a * table.column(x) + b

在下面的图中比在上面的图中更容易看到这条线。

[In ]:
heights.with_column('Fitted', fit(heights, 'MidParent', 'Child')).scatter('MidParent')
The previous scatterplot is reproduced without the light blue data points. The 'Fitted' data is now in gold and 'Child' data remains in dark blue.

另一种绘制该线的方法是使用 Table 方法 scatterfit_line=True 选项。

[In ]:
heights.scatter('MidParent', fit_line=True)
The previous scatterplot is reproduced with the gold data points replaced by a dark blue line. The line cuts through the center of the data points.

斜率的度量单位

斜率是一个比值,值得花点时间研究它的度量单位。我们的示例来自关于在医院系统分娩的母亲的熟悉数据集。孕期体重对身高的散点图看起来像一个用得有点久的橄榄球,但它足够接近橄榄球形,我们可以证明将拟合线穿过它是合理的。在后面的章节中,我们将看到如何使这种论证更加正式。

[In ]:
baby = Table.read_table(path_data + 'baby.csv')
[In ]:
baby.scatter('Maternal Height', 'Maternal Pregnancy Weight', fit_line=True)
Scatterplot with 'Maternal Height' on the x-axis and 'Maternal Pregnancy Weight' on the y-axis. Data points have discrete x values, and we see many possible y values for the majority of each x value. But generally, as x values increase so do y values. There are some notable outliers with higher y values than the other data points with the same x value. A blue line with a positive slope is drawn through the data.
[In ]:
slope(baby, 'Maternal Height', 'Maternal Pregnancy Weight')
3.572846259275056

回归线的斜率为 3.57 磅/英寸。这意味着对于身高相差 1 英寸的两名女性,我们对孕期体重的预测将相差 3.57 磅。对于一名比另一名高 2 英寸的女性,我们对孕期体重的预测将比我们对较矮女性的预测多

$$ 2 \times 3.57 ~=~ 7.14 $$

磅。

注意散点图中连续的垂直条带相距 1 英寸,因为身高已四舍五入到最接近的英寸。另一种理解斜率的方法是取任意两个连续的条带(它们必然相距 1 英寸),对应于身高相差 1 英寸的两组女性。3.57 磅/英寸的斜率意味着较高组的平均孕期体重比较矮组多约 3.57 磅。

示例

假设我们的目标是使用回归来根据巴吉度猎犬的体重估算其身高,使用的样本看起来与回归模型一致。假设观察到的相关性 $r$ 为 0.5,两个变量的汇总统计如下表所示:

average SD
height 14 inches 2 inches
weight 50 pounds 5 pounds

要计算回归线的方程,我们需要斜率和截距。

$$ \mbox{slope} ~=~ \frac{r \cdot \mbox{SD of }y}{\mbox{SD of }x} ~=~ \frac{0.5 \cdot 2 \mbox{ inches}}{5 \mbox{ pounds}} ~=~ 0.2 ~\mbox{inches per pound} $$

$$ \mbox{intercept} ~=~ \mbox{average of }y - \mbox{slope}\cdot \mbox{average of } x ~=~ 14 \mbox{ inches} ~-~ 0.2 \mbox{ inches per pound} \cdot 50 \mbox{ pounds} ~=~ 4 \mbox{ inches} $$

回归线的方程使我们能够根据给定的体重(以磅为单位)计算估计身高(以英寸为单位):

$$ \mbox{estimated height} ~=~ 0.2 \cdot \mbox{given weight} ~+~ 4 $$

该线的斜率衡量估计身高每单位体重增长的平均增加量。斜率为正,但需要注意,这并不意味着我们认为巴吉度猎犬增加体重会变得更高。斜率反映的是体重相差 1 磅的两组狗的平均身高差异。具体来说,考虑一组体重为 $w$ 磅的狗和一组体重为 $w+1$ 磅的狗。第二组平均估计身高高出 0.2 英寸。这对于样本中的所有 $w$ 值都成立。

一般来说,回归线的斜率可以解释为 $y$ 每单位 $x$ 增加的平均增加量。注意,如果斜率为负,则 $x$ 每增加一个单位,$y$ 的平均值就会减少。

结语

尽管我们不会建立回归方程的数学基础,但我们可以看到,当散点图为橄榄球形时,它能给出相当好的预测。一个令人惊讶的数学事实是:无论散点图的形状如何,同一个方程在所有直线中给出了“最佳”的拟合。这是下一节的主题。