方法:回归。
回归可以用来做实证研究,研究自变量和因变量之间的内在联系和规律,这在社会科学研究中是常见的。回归也可以用来做预测,根据已知的信息准确预测未知的事物。
1. 回归(regression)
1.1 起源与定义
回归最早是由高尔顿.提出的通过研究,他发现如果父母双方都比较高,他们孩子的身高就会低于父母的平均身高。相反,如果父母双方都比较矮,出生的孩子身高会高于父母的平均身高。他认为自然界存在一种约束力,使得身高的分布不发展到身高和身高的极端,而是趋向于回归中心,所以称之为回归。
目前从使用角度定义为数值(标量)预测技术,不同于分类(类别预测技术)。
1.2 不同的用法
1.2.1 解释(Explanation)
回归可以用来做实证研究,研究自变量和因变量之间的内在联系和规律,这在社会科学研究中是常见的。
互联网的普及是否降低了教育不平等的程度?
大学生就业选择的影响因素有哪些?
医疗电商场景下顾客满意度的影响因素有哪些?
1.2.2 预测(Prediction)
回归也可以用来做预测,根据已知的信息准确预测未知的事物。
股市预测:根据股票变动、新闻咨询、公司合并咨询等预测明天股市的平均值。在过去的十年里。
产品推荐:根据用户过去的购买记录和候选产品信息,预测用户购买某一产品的可能性。
自动驾驶:根据汽车各传感器的数据,如路况、车距等,预测正确的方向盘角度。
1.3 模型的构建
无论目的是解释还是预测,都需要掌握与任务相关的规律(认识世界),即建立合理的模型。
不同的是,解释模型只需要建立在训练集的基础上,一般有解析解(计量经济模型)。预测模型必须在测试集上进行测试和调整。一般没有解析解,需要通过机器学习来调整参数。因此,在相同的模型框架和数据集下,最优解释模型和预测模型很可能是不同的。
本文主要侧重于预测模型的构建,并未进一步涉及解释模型的相关内容。
2. 基于机器学习的模型构建
我们以Pokemon精灵攻击力预测(Combat Power of a pokemon)的任务为例,梳理机器学习三步走的细节。
输入:进化前的CP值、物种(妙蛙种子)、血量(HP)、体重(体重)和身高(身高)
输出:进化的CP值
2.1 模型假设 - 线性模型
为了方便,我们选择最简单的线性模型作为模型框架来完成回归任务。我们可以使用单特征或多特征的线性回归模型,后者会更复杂,模型集会更大。
为了选择合理的模型框架,提前探索数据集,需要观察变量之间的关系,这将决定哪些变量最终被放入模型中,以及变量是否需要再次处理(二次项、倒数等)。).
可以看出横轴和纵轴主要是线性的,有一些二次关系(可以考虑二次项)。
框架(预设)参数(待估计)=模型(目标)
当前模型的参数包括每个特征的权重和偏移量。
2.2 模型评价 - 损失函数
本文描述的回归任务属于监督学习场景,因此需要收集足够的输入输出对来指导模型的构建。
有了这些真实的数据,我们如何衡量模型?从数学上讲,我们使用损失函数来衡量模型。损失函数是根据模型的预测值和实际值之间的差异设置的。
本文选择常用的均方误差作为损失函数。
2.3 模型调优 - 梯度下降
当模型不凸时,没有解析解,只能用启发式方法迭代优化,常用的方法是梯度下降。
首先,我们随机选择一个\ (w 0 \),然后计算微分确定移动方向,然后更新相应的参数,重复直到找到最低点(两次更新的差值小于阈值或预设的迭代次数)。
对于需要更新多个参数的模型,步骤基本相同,只是做了部分微分。
在梯度下降过程中,会遇到一些问题,导致无法达到最优点。
如何解决这些问题,后面会涉及。
3. 模型构建中的问题和解决
3.1 评价模型的泛用性(Generalization)
一个好的模型不仅要在训练集中表现良好,还要在未知的数据集(测试集,真实的应用场景)中表现良好。
因此,我们必须在测试机上计算模型。
性能,理想情况下不能有较大的下滑。
3.2 提高模型的拟合度
若模型过于简单,则模型集合较小,可能无法包含真实的模型,即出现欠拟合问题。
我们可以选择更复杂的模型去优化性能。以使用1元2次方程举例,显著提高了预测性能。
我们还可以在模型中增加调节项(Pokemon种类)来改进模型。
模型在训练集和测试集的性能表现如下所示:
3.3 防止过拟合(Overfiting)的出现
如果我们继续使用更高次的模型,可能会出现过拟合问题。
我们可以通过加入正则项来防止过拟合问题的出现。
正则项权重变化对模型性能的影响如下所示:
4. 回归 - 代码演示
现在假设有10个x_data和y_data,x和y之间的关系是y_data=b+w*x_data。b,w都是参数,是需要学习出来的。现在我们来练习用梯度下降找到b和w。
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
# matplotlib没有中文字体,动态解决
plt.rcParams['font.sans-serif'] = ['Simhei'] # 显示中文
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 生成实验数据
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]
x_d = np.asarray(x_data)
y_d = np.asarray(y_data)
x = np.arange(-200, -100, 1) # 参数的候选项,指偏移项b
y = np.arange(-5, 5, 0.1) # 参数的候选项,指权重w
Z = np.zeros((len(x), len(y)))
X, Y = np.meshgrid(x, y)
# 得出每种可能组合下的loss,共需要计算100*100=10000次
for i in range(len(x)):
for j in range(len(y)):
b = x[i]
w = y[j]
Z[j][i] = 0 # meshgrid吐出结果:y为行,x为列
for n in range(len(x_data)):
Z[j][i] += (y_data[n] - b - w * x_data[n]) ** 2
Z[j][i] /= len(x_data)
以上代码生成了实验数据,并用穷举法计算出了所有可能组合的loss,其中最小值为10216。
接下来我们尝试使用梯度下降法来快速寻找到较小的loss值。
# linear regression
b=-120
w=-4
lr = 0.000005
iteration = 10000 #先设置为10000
b_history = [b]
w_history = [w]
loss_history = []
import time
start = time.time()
for i in range(iteration):
m = float(len(x_d))
y_hat = w * x_d +b
loss = np.dot(y_d - y_hat, y_d - y_hat) / m
grad_b = -2.0 * np.sum(y_d - y_hat) / m
grad_w = -2.0 * np.dot(y_d - y_hat, x_d) / m
# update param
b -= lr * grad_b
w -= lr * grad_w
b_history.append(b)
w_history.append(w)
loss_history.append(loss)
if i % 1000 == 0:
print("Step %i, w: %0.4f, b: %.4f, Loss: %.4f" % (i, w, b, loss))
end = time.time()
print("大约需要时间:",end-start)
# Step 0, w: 1.6534, b: -119.9839, Loss: 3670819.0000
# Step 1000, w: 2.4733, b: -120.1721, Loss: 11492.1941
# Step 9000, w: 2.4776, b: -121.6771, Loss: 11435.5676
可以发现,梯度下降法可以快速从初始值迭代到合适的参数组合,接近最优参数。但我们发现,达到最优值的过程却非常缓慢。使用下面的代码可以对寻优过程进行可视化。
# plot the figure
plt.contourf(x, y, Z, 50, alpha=0.5, cmap=plt.get_cmap('jet')) # 填充等高线
plt.plot([-188.4], [2.67], 'x', ms=12, mew=3, color="orange") # 最优参数
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
plt.xlim(-200, -100)
plt.ylim(-5, 5)
plt.xlabel(r'$b$')
plt.ylabel(r'$w$')
plt.title("线性回归")
plt.show()
如下图所示,参数最终寻优的方向是正确的,但是因为迭代次数不够所以提前停止。
我们将迭代次数更改为10万次,结果如下所示:
迭代次数仍然不足,我们继续将迭代次数更改为100万次,结果接近最优,如下所示:
迭代次数太多会消耗过多的计算资源,我们可以通过调整学习率来加快速度。当我们将学习率设置为之前的两倍(0.00001)时,迭代10万次即可达到接近最优的结果,如下所示;
但需要注意的是,学习率如果设置得太高,可能会发生振荡,无法收敛。下图是我们将学习率设置为0.00005时的情况。
总而言之,我们要清楚机器学习的强大能力以及不稳定性,然后学习相关原理进而熟练使用。
参考文献
- Datawhale 开源学习资料 李宏毅机器学习
- 到底什么是实证研究
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/79564.html