对《机器学习》这门课程的回顾,系列文章的目的是希望能够把原理和代码实现统一起来,增进理解,所以对一些我认为简单的知识,可能会一笔带过。
前言
这里对第一周的内容做一些简单的回顾:
线性回归-单变量(one variable)
基本内容
假设函数
(1)公式:$h_{\theta}(x)=\theta_{0}+\theta_{1}x$
(2)原理:输入一个单变量x,输出预测值
$\theta_{0}$又叫偏置项,也就是截距。如果没有偏置的话,直线必须经过原点,这就导致很多情况下根本没法拟合。
很显然,我们的目标就是要确定$\theta_{0}$和$\theta_{1}$,但是如何确定呢?
关键在于衡量$h_{\theta}(x)$和$y$之间的差别。
代价函数
(1)公式:$J(\theta_{0},\theta_{1})=\frac{1}{2m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})^{2}$,又称“平方误差函数”,这里的1/2是方便后面求导时约掉平方。计算出参数$\theta_{0}$和$\theta_{1}$需要用迭代的方法,而每次迭代都会代入所有的x和y,因此用向量化的方式来代替循环。
(2)原理:最小二乘法判断误差。
由于代价函数是衡量$h_{\theta}(x)$和$y$之间的误差,因此我们的目标就是要找到能使代价函数值最小的$\theta_{0}$和$\theta_{1}$。
梯度下降法
在线性回归问题中,代价函数的图像是凸函数(convex-function),如下图。只要你学过高中数学,你就应该明白黄点处的代价值是最小的(极小值点),也就是说,在黄点处需要满足$\frac{\partial J(\theta_{0}, \theta_{1})}{\partial \theta_{0} }=0$和$\frac{\partial J(\theta_{0}, \theta_{1})}{\partial \theta_{1} }=0$。
直观来说,就是如何解决从初始值“走”到黄点处。
(1)公式:
一项项来看:
导数项$\frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) \cdot x_{j}^{(i)}$
当时我有一个理解不了的地方:
结合图像来看,我们Random initial value的点在左侧,导数小于0,那么似乎公式中就变成减去一个负值
其实这么理解是错误的,梯度看起来像是导数在高维的推广,但二者应该有本质上的区别。梯度是矢量而某点的导数是常量,梯度指向了数值最大增大方向,而导数并不指向方向,它仅仅表示了切线的斜率。
实际应用中一般$\theta_{j},j>=2$,我们不会单独对$\theta_{0}$和$\theta_{1}$求值,把他们向量化是更明智的选择,
$\left( \begin{array}{c}{\frac{\partial}{\partial \theta_{0}} \operatorname{J}(\theta)} \\ {\frac{\partial}{\partial \theta_{1}} \operatorname{J}(\theta)} \\ {\vdots} \\ {\frac{\partial}{\partial \theta_{n}} \operatorname{J}(\theta)}\end{array}\right)=\frac{1}{m} \mathbf{X}^{T} \cdot(\mathbf{X} \cdot \theta-\mathbf{y})$
这也就保证了这一项的值必然是个矢量,换句话说,就是求得的一定是梯度。而取负号,意思就是取和数值最大增大方向相反。
$\alpha$
学习速率,直观叫法“步长”。表示的是你每次迭代时移动的位置大小。如果过大,可能会导致函数越过最优点发散;如果过小,将会导致时间开销变大。
最后重复直到收敛。
代码
在实际代码中,数据都是用矩阵的方式来表示。
1.导入几个常用库
1 | import numpy as np |
数据处理
1.导入csv
文件,用DataFrame
结构存储。
(1)关于csv
文件:简单来说就是纯文本,以行为一条记录,每条记录被分隔符分隔。CSV文件
(2)pandas中的DataFrame
:官方手册
(3)关于.describe()
返回值中的分位数:浅谈分为数
1 | '''导入数据''' |
2.对得到的数据进行加工,方便计算
1 | ''' |
初始化数据矩阵,这里转化成了np.matrix
,但建议使用np.ndarray
1 | ''' |
计算函数
1.代价函数
公式:$J(\theta_{0},\theta_{1})=\frac{1}{2m}\sum_{i=1}^{m}(h_{\theta}(x_{i})-y_{i})^{2}$,其中主要矩阵化:假设函数$h_{\theta}(x_{i})=\theta^{T}X$和$y_{(i)}$
(1)向量化:计算过程中注意矩阵乘法或是向量乘法的合法性。
(2)数据可以用np.matrix
存储,但更建议使用np.ndarray
(3)np.matrix
和np.ndarray
在乘法上有所区别:Numpy中的矩阵乘法
1 | ''' |
2.批量梯度下降:
(1)公式:
(2)作用:通过迭代的方式来寻找代价函数最小时的参数($\theta_{j}$)
(3)学习速率:如果过大,会导致无法到达代价值最小点(函数发散或震荡);如果过小,则会使得迭代时间过长。
1 | ''' |
2*.正规方程法(Normal Equation)
(1)同样也可以用于寻找代价函数最小时候的参数取值,与梯度下降法(Gradient Descent)比较
(2)公式:$\theta=(X^{T}X)^{-1}X^{T}y$
1 | '''特征方程''' |
画图函数
1 | x = np.linspace( |
结果图:
可以看出拟合效果还可以。
1 | ''' |
结果图:
随着迭代次数的增加,代价函数值单调递减。
1 | ''' |
结果图:
关于3D图中的Numpy中的Meshgrid
1 | ''' |
结果图:
线性回归-多变量(multiple variables)
特征缩放(Feature scaling)
也叫均值归一化
(1)公式:$x=\frac{x-\mu}{s_{1}}$,其中$\mu$为$x$的均值,$s_{1}$为$x$的最大值减去最小值,或者使用标准差。
(2)作用:在多个特征值情况下,如果某个特征值$x_{i}$的取值范围和另一个特征值$x_{j}$的取值范围相差太大,会减慢梯度下降的速度,因此需要用特征缩放,将不同特征值的取值限定在差不多的范围内。
e.g. $x_{1}$为房子的面积,取值范围0~2000;$x_{2}$为卧室的数量,取值0-5;那么对二者使用特征缩放,可得:
(3)代码:
1 | data = (data - data.mean()) / data.std() |
参考资料
[2] 机器学习 | 吴恩达机器学习第二周编程作业(Python版)