@toc
1 预测数值型数据:回归
1.1 什么是回归?
- 大自然让我们回归到一定的区间范围之内;反过来说就是,有一个平均的水平,可以让突出的事物能向他靠拢。
- 回归是由达尔文(Charles Darwin)的表兄弟Francis Galton发明的。 Galton于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌豆种子(孩子)的尺寸。Galton在大量对象上应用了回归分析,甚至包括人的身高。他注意到,如果双亲的高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲。孩子的高度向着平均高度回退(回归)。Galton在多项研究上都注意到这个现象,所以尽管这个英文单词跟数值预测没有任何关系,但这种研究方法仍被称作回归 2 。
- 那些高个子的后代的身高,有种回归到大众身高的趋势。 eg: 姚明身高2米26,叶莉身高1米90, 但是他们后代的身高是会逐渐回归到正常的身高水平。
1.2 回归的目的是预测数值型的目标值。
1.3 回归可以做什么事?
回归可以做任何事情。然而大多数公司常常使用回归法做一些比较沉闷的事情,例如:
- 销售量预测
- 制造缺陷预测。
当然也可以做有新意的应用,例如:
- 预测名人的离婚率。
- 预测所在地区的房价。
2 线性回归模型表示
2.1 线性回归的基本概念
- 回归,一般都是指线性回归(linear regression).
从我们最熟悉的开始, 已知两点,求直线公式设 y = ax+b, 带入两点,求得解析解为 y = 3x-60
- 回归方程 (regression equation): y = 3x-60
- 回归系数 (regression weights): 3和-60可以称为回归系数
- 回归: 求这些回归系数的过程
2.2 西安高新区房价预测
这个例子是预测住房价格的,我们要使用一个数据集,数据集包含西安市的住房价格。在这里,我要根据不同房屋尺寸所售出的价格,画出我的数据集。比方说,如果你朋友的房子是40平方米大小,你要告诉他们这房子能卖多少钱。那么,你可以做的一件事就是构建一个模型,也许是条直线,从这个数据模型上来看,也许你可以告诉你的朋友,他能以大约78万(人民币)左右的价格卖掉这个房子。这就是监督学习算法的一个例子。
m:表示训练集数据的总量
x:表示输入变量
y:表示输出变量
(x,y): 表示一个训练样本
(x(i),y(i)): 表示第i个训练样本
3 回归的一般方法
3.1 线性回归的一般步骤
对于一元线性回归(单变量线性回归)来说,学习算法为 y = ax + b
我们换一种写法: hθ(x) = θ0 + θ1x1
3.2 利用Sklearn做线性回归的预测
- 实现步骤
1). 模拟数据
2). 调用sklearn拟合数据, 把theta0 theta1求出来
3). 预测
from sklearn.linear_model import LinearRegression
import numpy as np
# 1).模拟数据
X = np.random.rand(100, 1)
Y = 4 + 2 * X + np.random.randn(100, 1)
# 2). 调用sklearn拟合数据, 把theta0 theta1求出来
# 导入线性回归类
lin_reg = LinearRegression()
# 让线性回归类做训练
lin_reg.fit(X, Y)
# 输出theta0 theta1; intercept_是截距, coef_是斜率系数;
print("\ntheat0, theta1:", lin_reg.intercept_, lin_reg.coef_)
# 3). 预测
X_new = np.array([[0], [1]])
print("\nx=0, x=1预测结果:\n", lin_reg.predict(X_new))
- 测试结果:
3 损失/代价函数
3.1 拟合
- 线性回归实际上要做的事情就是: 选择合适的参数(θ0, θ1),使得hθ(x)方程,很好的拟合训练集。实现如何把最有可能的直线与我们的数据相拟合。
- 拟合就是把平面上一系列的点,用一条光滑的曲线连接起来。因为这条曲线有无数种可能,从而有各种拟合方法。拟合的曲线一般可以用函数表示.
下面的三张图, 展示了拟合的三种状态:
- 图一是部分拟合
- 图二是完全不拟合
- 图三是完全拟合
3.2 损失函数: 均方误差MSE
- 拟合过程中因为theta0和theta1的取值准确度, 预测的结果与训练集中的实际值有差距。
我们选择的参数决定了我们得到的直线相对于我们的训练集的准确程度,模型所预测的值与训练集中实际值之间的差距(下图中蓝线所指)就是建模误差(modeling error)。
- 我们的目标便是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得损函数最小。
3.3 均方误差MSE最小化
- 二维空间求均方差
上图是参考吴恩达视频的图片, 我们会发现随着theta1的不断变化, 均方误差MSE会找到一个最小值。 如果从数学角度来看, 就是求解函数的导数,计算函数的最小值。
- 三维空间求均方差
上图是参考吴恩达视频的图片, 我们会发现随着theta0和theta1的不断变化, 均方误差MSE会找到一个最小值。为了通过图形化看到最小的均方差, 三维图片并不直观。 通常使用等高线实现。如下图:
- 更高维空间
我们会遇到更复杂、更高维度、更多参数的情况,而这些情况是很难画出图的,因此更无法将其可视化,因此我们真正需要的是编写程序来找出这些最小化代价函数的和的值,而梯度下降算法就是能够自动地找出能使代价函数最小化的参数和的值。
4 梯度下降
4.1 梯度下降的思想
梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数的最小值。
梯度下降背后的思想是:开始时我们随机选择一个参数的组合,计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到到到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。
4.2 梯度下降的分类
想象一下你正站立在山的这一点上,站立在你想象的公园这座红色山上,在梯度下降算法中,我们要做的就是旋转360度,看看我们的周围,并问自己要在某个方向上,用小碎步尽快下山。这些小碎步需要朝什么方向?如果我们站在山坡上的这一点,你看一下周围,你会发现最佳的下山方向,你再看看周围,然后再一次想想,我应该从什么方向迈着小碎步下山?然后你按照自己的判断又迈出一步,重复上面的步骤,从这个新的点,你环顾四周,并决定从什么方向将会最快下山,然后又迈进了一小步,并依此类推,直到你接近局部最低点的位置。
- 公式:
-
理解
- a是学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大;
- 如果α太小的话,梯度下降会很慢
- 如果α太大的话,梯度下降越过最小值,不仅不会收敛,而且有可能发散
- 不论斜率正或负,梯度下降都会逐渐趋向最小值
- 即使学习率α是固定不变的,梯度下降也会收敛到一个最低点
- 梯度下降的两种更新方式:
4.2.1 “Batch” Gradient Descent 批梯度下降
批梯度下降:指的是每下降一步,使用所有的训练集来计算梯度值
- 在梯度下降中,在计算微分求导项时,我们需要进行求和运算,所以,在每一个单独的梯度下降中,我们最终都要计算这样一个东西,这个项需要对所有个训练样本求和。因此,批量梯度下降法这个名字说明了我们需要考虑所有这一"批"训练样本,
- 代码实现
"""
线性回归实现梯度下降的批处理(batch_gradient_descent )
"""
import numpy as np
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# print(X_b)
learning_rate = 0.1
# 通常在做机器学习的时候,一般不会等到他收敛,因为太浪费时间,所以会设置一个收敛次数
n_iterations = 100000
m = 100
# 1.初始化theta, w0...wn
theta = np.random.randn(2, 1)
count = 0
# 4. 不会设置阈值,之间设置超参数,迭代次数,迭代次数到了,我们就认为收敛了
for iteration in range(n_iterations):
count += 1
# 2. 接着求梯度gradient
gradients = 1/m * X_b.T.dot(X_b.dot(theta)-y)
# 3. 应用公式调整theta值, theta_t + 1 = theta_t - grad * learning_rate
theta = theta - learning_rate * gradients
print(count)
print(theta)
- 执行结果
4.2.2 “Stochastic” Gradient Descent 随机梯度下降
随机梯度下降:指的是每下降一步,使用一条训练集来计算梯度值
4.2.3 “Mini-Batch” Gradient Descent “Mini-Batch”梯度下降
“Mini-Batch”梯度下降:指的是每下降一步,使用一部分的训练集来计算梯度值
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。