一个简单的模型
本课程将介绍预测建模,并重点讲解如何使用损失函数构建一个简单的模型。
在本课程的前几章中,我们学习了数据清洗、数据探索和统计推断。现在,是时候进入数据科学生命周期的最后阶段——通过预测来辅助决策。到目前为止,我们已经发现了数据中一些有意义的模式,但如何利用这些模式来预测未来事件呢?为此,我们将使用模型来进行预测。
建模
一个模型是对某个系统的抽象表示,旨在近似现实世界的现象。例如,艾萨克·牛顿提出了一个关于重力的模型,我们可以用这个模型预测:如果以一定的力度抛出一个球,它会飞多远或多高。在这个重力模型中,影响结果的因素包括球被抛出的力度、球的质量等。同样地,我们也可以建立模型来预测某位客户下个月是否会拖欠信用卡还款,其中客户的还款历史及其他因素可能会影响模型的结果。
建模的方法有很多,衡量模型效果的方式也多种多样。但首先,让我们从一个非常简单的模型开始。
预测服务员小费
我们拥有顾客在餐厅支付小费的数据。我们将尝试建立一个模型,用于预测顾客会支付多少小费。首先加载数据并查看其内容。
1# 小费数据集 2# total_bill: 总账单金额(餐费,含税),单位为美元 3# tip: 小费金额,单位为美元 4# gender: 付款人性别(男、女) 5# smoker: 同行中有吸烟者吗?(0=否,1=是) 6# day: 到店日期 7# time: 到店时间(午餐、晚餐) 8# people: 用餐人数 9 10import pandas as pd 11df = pd.read_csv('tips.csv') 12 13print(df.head()) 14print(df.describe())
现在,一个非常简单的模型可以是:顾客总是按总账单金额的 15% 支付小费。数学上表示为:
这里的 0.15 称为模型的参数。如果我们用 表示模型参数,用 表示总账单金额,用 表示预测的小费,则上述公式可写为:
因此,我们的简单模型变成一个数学函数 ,输入为 ,输出为预测的小费。
接下来,我们先创建一列来检查实际的小费占比。
1import pandas as pd 2import matplotlib.pyplot as plt 3df = pd.read_csv('tips.csv') 4 5# 计算小费百分比 6df['percent_tip'] = df['tip'] * 100.0 / df['total_bill'] 7df['percent_tip'] = df['percent_tip'].round() 8 9# 绘制小费百分比的频数分布图 10df['percent_tip'].value_counts().plot(kind = 'bar')
在第6行,我们通过将 tip 乘以 100.0 再除以 total_bill 来计算小费的百分比。随后在第7行对结果进行四舍五入,以便于在第10行的图表中更清晰地区分数值。我们首先使用 value_counts 函数获取 percent_tip 各值的出现次数,然后用 plot 函数绘制柱状图。
从图表可以看出,我们之前设定的固定 15% 的预测模型并不能准确预测所有情况。因此可以说,该模型表现不佳。此时,我们需要一种方法来衡量预测值与真实值之间的偏差程度。这正是损失函数的作用。
损失函数
损失函数是一个数学函数,它接收由模型参数预测出的值以及一组真实值(记作 ),并告诉我们模型在整个输入数据集(记作 )上的表现如何。损失函数输出一个单一数值,称为损失,它反映了使用某一模型参数时产生的误差或损失大小。由于损失函数输出的是损失值,因此损失越小,说明模型性能越好。
因此,我们可以通过使用不同的模型参数进行预测,将预测结果输入损失函数,比较不同参数对应的损失值,最终选择使损失函数值最小的那个参数作为最优模型参数。
换句话说,我们选择能够最小化损失函数的模型。
那么,损失函数是如何计算损失的呢?计算损失的方式有很多,针对不同问题设计了多种损失函数,但最常见且最直观的是均方误差损失函数。
均方误差
顾名思义,该损失函数计算的是平方误差的平均值。这是一种非常直观的损失计算方式。下面我们通过一个例子来说明原因。
假设我们仍选择 。在我们的“小费”数据集中,第一条记录的 total_bill 值为 16.99。
如果用 表示第一条记录的真实小费值,则预测误差为:
我们可以对所有输入值 () 重复这一过程,计算出所有的误差。由于误差可能为正也可能为负,因此我们取误差的平方。得到所有平方误差后,再求它们的平均值,即可得到当前 下预测的平均误差。
这就是损失函数的基本原理。在下一节课中,我们将用 Python 实现这一损失函数,以找出最适合预测小费的最佳模型。