使用 R 语言的线性回归预测葡萄酒价格





5.00/5 (3投票s)
通过分析葡萄酒定价,介绍线性回归及其在 R 中的应用。
1. 线性回归简介
20 世纪 90 年代初,普林斯顿大学经济学教授 Orley Ashenfelter 声称他发现了一种无需品尝一滴酒就能预测波尔多葡萄酒品质及其价格的方法。他使用线性回归方法,这是当今监督学习的一种方法。Ashenfelter 使用的数据可在网上获得。在本文中,我将使用这些数据来温和地介绍线性回归。为此,我们将使用 R 语言。
线性回归是一种用于通过使用一组自变量来预测一个变量(输出或因变量)结果的方法。顾名思义,预测方法是线性的,其中自变量的线性关系被用来预测结果变量的值。这在多变量线性回归的以下方程中得到了体现:
其中
- xij = 第 i 个观测值的第 j 个自变量,
- yi = 因变量,
- εi = 第 i 个观测值的误差项,也称为残差;此残差是因变量的实际值减去线性回归模型预测的值,
- β0 = 截距系数,
- βj = 第 j 个自变量的回归系数。
有一组称为训练集的数据,其中自变量和因变量的值是已知的——这些数据用于训练,用于学习线性回归的参数 β0 和 βj,这些参数将用于预测。还有另一组数据,称为测试集,其中自变量和因变量的值是已知的,但将用于测试我们线性回归模型的准确性和其他参数。大约两年前,我参加了由 MIT 在 edX 平台上提供的名为The Analytics Edge 的在线课程。他们使用一种不同的葡萄酒相关 CSV 文件(包含定价数据)来介绍 R 语言中的线性回归。我们利用这些学习来介绍线性回归。
在我们开始旅程之前,我将查看页面顶部可供下载的葡萄酒相关 CSV 文件内容。如我在上一篇文章中介绍的那样,我使用 R 命令 read.csv()
和 str()
分别读取 CSV 文件并查看其结构。数据文件的六个列是:
- Year:葡萄酒生产的年份。这是每个观测值的唯一标识符。
- LogPrice:葡萄酒价格的对数。这是我们要为测试数据预测的值。换句话说,这是因变量。
- WinterRain:波尔多地区冬季的降雨量(毫升),即 10 月至 3 月的降雨量。自变量。
- Temperature:该地区 4 月至 9 月的平均气温(摄氏度)。自变量。
- HarvestRain:该地区收获季的降雨量(毫升),即 8 月和 9 月的降雨量。自变量。
- TimeYears:自酿酒以来的年数。自变量。
此数据的结构显示在下面的屏幕截图中,如 R 控制台中所示,其中葡萄酒训练数据被读入一个名为 wineTrain
的数据框。
我们使用此训练数据集来学习该数据中的线性回归参数,并使用这些参数来预测测试集的(对数)价格值。我们注意到此数据框有 24 个观测值和上面列出的 6 个变量。
2. R 语言中的线性回归
在本节中,我们将提出一系列问题,并通过回答这些问题来介绍 R 语言中的线性回归。
- 葡萄酒数据的摘要是什么?
使用
summary()
命令可以看到这一点,该命令给出以下输出:
查看此输出,我们发现数据来自 1952 年至 1977 年。由于我们处理的是价格的对数,因此该值可能为负数。价格对数值确实为负数,最大值为 0.0。还可以从摘要中获得冬季降雨量、气温、收获季降雨量和年数等统计参数。 - 葡萄酒价格随气温如何变化?
使用
plot()
命令可以看到这一点,该命令给出以下输出:> plot(wineTrain$Temperature, wineTrain$LogPrice)
结果是一个如下所示的图:
查看此图,我们发现随着气温的升高,葡萄酒价格的对数通常会增加,并且可以拟合一条直线穿过数据。接下来,我们尝试使用仅气温(以度为单位)创建一个简单的线性回归模型来预测葡萄酒价格。 - 如何在 R 中进行线性回归计算,只使用一个自变量?
为此,我们考虑一个自变量
Temperature
,即该地区一年的平均气温。使用Temperature
作为自变量,LogPrice
作为因变量,让 R 进行线性回归的命令是:在此命令之后,使用summary
命令获取此模型的摘要。> modelReg1 = lm(LogPrice ~ Temperature, data=wineTrain) > summary(modelReg1)
在这里,~ 符号之前的变量名是因变量,~ 符号之后的变量名是自变量。运行这些命令后,R 控制台输出如下所示:
此摘要提供了大量信息。让我们通过提出以下一系列问题来了解此摘要。 - 误差平方和 (SSE) 是什么?
误差平方和是所有观测点的各个残差值之和。如果 N 个观测值,各个误差项为 ε1, ε2, ..., εN,则 SSE 为:
SSE = (ε1)2 + (ε2)2 + ... + (εN)2
给定两个线性回归模型,SSE 值较小者为更好的模型。理想情况下,我们希望有一个 SSE 值最小的线性回归模型。
- 均方根误差 (RMSE) 是什么?
误差平方和 (SSE) 可能难以解释,因为它取决于 N(观测值数量),并且其单位难以理解,因为 SSE 以因变量的平方单位表示。为了克服这一点,使用了均方根误差 (RMSE)。RMSE 定义为:
此 RMSE 值由 N 进行归一化,并且与因变量具有相同的单位。
- R2 误差度量是什么及其意义?
R2 误差度量将最佳模型与基线模型进行比较。基线模型不使用任何变量,并预测相同的输出(因变量),而与自变量的值无关。例如,基线模型可能预测因变量在所有观测值上的平均值。
基线模型的误差平方和也称为总平方和,记为 SST。R2 的公式为:
此 RMSE 值由 N 进行归一化,并且与因变量具有相同的单位。
R2 是一个很好的误差度量,因为它捕捉了使用线性回归模型与对每个数据点使用平均输出相比所带来的价值。如果 R2 的值为零,则意味着与基线模型相比没有改进。另一方面,如果 R2 的值等于 1,则意味着一个完美的预测模型,它完美地预测了训练集中因变量的所有值。R2 接近 1 意味着一个近乎完美的预测模型。R2 是无量纲的,因此是一个很好的误差度量。
SSE 和 SST 值都必须大于或等于零,因为它们是误差项的平方和。此外,SSE 必须小于或等于 SST。换句话说,线性回归模型永远不会比基线模型差。
掌握了 SSE、RMSE 和 R2 的知识后,我们现在可以解释上面显示的线性回归摘要。
- 如何解释上面显示的线性回归摘要?
查看上面显示的
summary(modelReg1)
命令的输出,我们看到输出中有以下部分:- Call 部分:输出用于构建模型的命令,以供参考。这是用于构建模型的函数描述。
- Residuals 部分:这是残差或误差项的摘要。显示了残差的最小值、第一和第三四分位数、中位数和最大值。
- Coefficients 部分:其中第一行对应于截距项,第二行对应于自变量
Temperature
。Estimates 列给出了我们模型 β 值的估计值。如果 Estimates 列中的系数为零或接近零,则其值不会显著改变因变量的值。其余列帮助我们确定是否应将变量包含在模型中。Standard Error 列指示了系数可能与估计值变化的程度。t-value 只是估计值除以标准误差。如果 t-value 的绝对值很大,则该系数更有可能显著。最后一列 Pr(>|t|) 给出了系数实际上为零的可能性度量。此概率数字越小,其系数估计为零的可能性就越小。Pr(>|t|) 列旁边有一些符号、星号、点。三个星号表示系数非常显著,星号数量减少表示显著性降低。句点表示系数几乎显著。星号编码方案的图例显示在 Coefficients 表的底部。 - 最后部分:在这里我们可以读出 Multiple R-squared 值,它与上面讨论的 R2 值相同。旁边是 Adjusted R-squared,它根据所使用的自变量数量相对于数据点数量来调整 R2。在添加更多自变量时,Multiple R-squared 通常会增加。
- 如何计算我们模型的残差和 SSE?
残差存储在向量
modelReg1$residuals
中。可以使用 R 命令计算 SSE:> SSE = sum(modelReg1$residuals^2)
我们的模型计算结果为 5.3942。
- 如何改进我们最初的线性回归模型?
我们可以向模型添加另一个自变量,让我们添加变量
HarvestRain
。相应的线性回归调用是:> modelReg2 = lm(LogPrice ~ Temperature + HarvestRain, data=wineTrain) > summary(modelReg2)
summary
命令的结果如图所示:
我们看到,通过向线性回归计算添加另一个自变量,R2 值增加到 0.7079。因此,modelReg2
可能比modelReg1
更好。如果我们按照上面的方法计算modelReg2
的 SSE,我们会发现该值为 2.9607,这比modelReg1
的 SSE 值要好;因此,该模型确实比前一个模型更好。我们注意到Temperature
和HarvestRain
都是显著变量,如这些行对应的三个星号所示。 - 我们能否进一步改进模型?
我们将所有自变量添加到模型中。相应的线性回归调用是:
> modelReg3 = lm(LogPrice ~ Temperature + HarvestRain + WinterRain + TimeYears, data=wineTrain) > summary(modelReg3)
summary
命令的结果如图所示:
我们注意到 Coefficients 表有五行,一行用于截距,一行用于每个自变量。我们还看到,通过将所有自变量添加到线性回归计算中,R2 值增加到 0.8383,几乎是我们第一个线性回归模型的 R2 值的一倍。此外,SSE 计算显示为 1.6387,小于前两个线性回归模型的值。我们注意到Temperature
和HarvestRain
都是显著变量,如这些行对应的三个星号所示,而TimeYears
的显著性较低,由两个星号表示。变量WinterRain
仅为显著,由其行末尾的句点表示。 - 我们的模型是否存在多重共线性问题?
相关性是衡量变量之间线性关系的一种度量。如果模型中的两个自变量相关,那么模型很可能存在多重共线性问题。为了检查我们的模型是否存在此类问题,我们使用 R 中的
cor()
命令计算wineTrain
数据框所有变量之间的相关性。> cor(wineTrain)
cor()
命令的结果如图所示:
我们注意到,在此表中输出的相关系数对于任何两对自变量都不接近 +1 或 -1。因此,我们的模型不存在多重共线性问题。 - 模型在新数据上的表现如何?
用于构建模型的数据是训练数据,而此数据集之外的任何数据,又称新数据,是测试数据。问题是该模型在测试数据上的表现如何。此类测试数据也可在上面的
wine_test.csv
文件中下载。> wineTest = read.csv("wine_test.csv") > str(wineTest)
这表明文件中存在 3 个与wine_train.csv
文件中相同的 6 个变量的观测值。我们现在检查第三个模型modelReg3
在测试数据上的表现。 - 如何在测试数据上进行预测?
R 中的预测命令如下:
> predictTest = predict(modelReg3, newdata=wineTest) > predictTest
这显示了模型modelReg3
预测的价格。如果我们查看str(wineTest)
的结果,我们的模型预测为 -1.677749,而 1978 年的实际值为 -1.31。对于 1979 年和 1980 年的其他两年,也可以进行类似的比较。这些预测相差不大,但也不算太近,我们尝试通过查看 R2 值来量化这些预测。接下来我们就是这样做。 - 如何量化我们预测的结果?
标准方法是计算 SSE 和 SST 值,并使用它们来计算 R2。
> SSE = sum((wineTest$LogPrice - predictTest)^2) > SST = sum((wineTest$LogPrice - mean(wineTrain$LogPrice))^2) > 1 - SSE / SST
这给出了一个相当低的 R2 值 0.37。我们可以将此低值归因于训练数据和测试数据的点数较少。如果我们有更多的训练数据点和更多的数据点,那么我们在测试数据上的 R2 值可能会更好。
3. 结语
本文就使用线性回归进行葡萄酒定价的简短文章到此结束。在本文中,我们通过观察葡萄酒定价问题,在 R 中学习了线性回归。我们了解了加载数据以及运行单个变量的线性回归。我们理解了 R 语言的输出。然后,我们将线性回归模型扩展为包含另一个变量,然后进一步扩展到包含更多变量。我们理解了线性回归计算输出的 SSE 和 R2 值的含义。然后,我们使用线性回归的输出预测测试集中的价格值,从而了解了模型的准确性。
我们敦促您加载自己的训练和测试 CSV 文件,使用上面列出的命令尝试线性回归,并告知我们您的反馈。
历史
- 版本 1.0:2017 年 2 月 22 日。