coursera的机器学习课程
10 Oct 2019断断续续学完了这个经典课程,记录下。
概念
机器学习:一个程序,从经验E中学习,解决问题T,性能度量为P,当有了E之后,经过P评判,处理T的性能得到提升。
简化: 利用经验改善系统自身的性能。
其中:
- 从经验(数据)中产生模型的的算法即学习算法。
- 有了算法,我们再把经验数据传给它,称为学习或者训练(Training)。
- 产生的模型就可以对新的数据进行预测(判断),这个过程称为测试(Testing)。
机器学习从输入来看可以分为:
- 监督学习:学习数据是有正确答案的,比如预测肿瘤等,这里的答案通常也称为标签。
- 无监督学习:学习数据并没有标签,比如google的新闻分类。
如果从输出角度来看,可以分:
- 回归问题(regression),输出是一个连续值。
- 分类问题(classification),输出是一个离散值,常见的一种是二元分类问题,输出就是二选一。
- 聚类(clustering),就比如上方的新闻分类。
通常来说回归问题,分类问题是属于监督学习,聚类问题属于无监督学习。
线性回归
代价函数:
梯度下降
线性回归问题可以使用梯度下降算法,算法核心是每一轮迭代时同时修改参数:
对于两个参数的线性回归问题,可以等价为:
梯度下降因为涉及多步迭代,参数的选择非常重要,如果参数差异非常大,迭代效果不佳(甚至不能收敛),这时需要做参数正规化处理,结果是需要保证参数在-0.5~0.5范围,最常用的方法就是减去平均值再除以range。
多元线性回归
对于多个特征值的线性回归问题,我们称为多元线性回归,使用线性代数得方程,可以大大简化h函数的写法。
注意右上角的T为转置。
正规方程
对于线性回归算法,也可以用正规方程直接求解参数,无需梯度下降
注意上方的-1为求逆矩阵。
正规方程 vs 梯度下降:
- 正规方程一步求解,比较方便,也不需要做参数的缩放。但正规方程的算法涉及矩阵求逆,是个O(n^3)算法,所以参数少时,正规方程很快,但参数达到10000以上,要考虑性能问题,n太大时,还是梯度下降更快。
- 正规方程只能用于特征变量少的线性回归算法,在其他算法里,梯度下降算法仍可以用,但却不能使用正规方程了。
分类问题
y等于0或者1,称之为二元分类问题,但直接输出0或1的h函数不是那么有意义,更常见的场景是,h函数的输出是y为1的概率,也就是说我们将h函数仍然定义为一个连续量(从0到1),比如把预测肿瘤是良性还是恶性(二元分类问题)改变为预测肿瘤为恶性的概率。这样基本上把一个分类问题转换为了一个回归问题,我们称之为逻辑回归。
于是这个h函数可以使用概率论中的P表达式
对于这样的h函数,比较好的拟合算法不再是线性方程,而是S函数,或者说逻辑函数,如下图
S函数在x大于0时,输出0.5以上的值,在x小于0时,输出0.5以下的值,同时可以引出一个概念,决策边界,就是h函数等于0.5的区域。
逻辑回归
对于上述逻辑回归的h函数定义,cost函数不能使用原先线性回归的定义,那样会导致cost函数有大量局部优化解,不利于梯度下降等算法的求解,所以我们为逻辑回归问题定义新的cost函数
选择这个cost函数,是因为这个函数是凸函数,便于参数的求解,我们依然可以使用梯度下降来求解参数,并且神奇的是,这个公式和线性回归一模一样。
当然,可以使用向量来简化公式:
除了梯度下降,还有一些更高级或者说复杂的算法来计算θ,可以不需要选择alpha,但是这些算法复杂的多,通常不需要了解实现细节,一些函数库将他们封装好,直接使用。
多元分类
当y取值大于2个,这种分类问题称为多元分类,可以将多元分类,分解为多个二元分类来求解,这样:
神经网络
对于复杂的非线性分类问题,上述的算法都不再适用,因为非线性问题导致的输入参数过多,n个特征值的二次函数,总参数为O(n^2),计算量过大,如果用三次函数则为O(n^3),更多了。比如图像识别等,因此神经网络更为适合。
神经网络中的基本元素是神经元,神经元做的事情很简单,一个线性变换加一个激活变换(非线性)。
之所以加激活函数,这个是神经网络的灵魂,没这个函数,再多层的神经网络叠加后本质上还是只是一个线性变换,当然为了梯度下降算法能够应用,我们需要激活函数可以连续微分。激活函数到目前为止,常用的有:
之所以最早使用sigmoid函数,因为它的输出是0~1,符合很多分类预测问题概率输出的需要。但实际情况中,sigmoid并非最佳。
- sigmoid 现在常用在二元分类网络的输出层,输出0~1间的概率分布。
- relu函数的梯度更大,更适合梯段下降算法,常用于hidden layer,tanh也还不错。
softmax layer 常用在多分类网络的输出层,它很简单,把上一层的每个分类的可能性输出转换为0~1的概率。
训练神经网络的方法通常为梯度下降法, Loss函数可以用最大似然估计来求解,可以得到三个函数(求解过程略):
- Binary Cross entropy
- Cross entropy
- Squared loss function
线性回归的python实现
可以用线性回归来作机器学习的入门,因为它最简单,但揭示了很多机器学习的概念。简单的线性回归问题是可以有解析解的,但问了演示,我们还是通过数值方式来解。
它的代价函数通常为RMSE - 均方根误差,也可以用MSE-均方误差, 下面是一个最小二乘法(Least Squares)实现的回归例子(最小二乘可以直接用方程推导)。
import pylab
import numpy
pylab.ion()
x = numpy.linspace(-1,1,100)
signal = 2 + x + 2 * x * x
noise = numpy.random.normal(0, 0.1, 100)
y = signal + noise
x_train = x[0:80]
y_train = y[0:80]
degree = 9
X_train = numpy.column_stack([numpy.power(x_train,i) for i in xrange(0,degree)])
model = numpy.dot(numpy.dot(numpy.linalg.inv(numpy.dot(X_train.transpose(),X_train)),X_train.transpose()),y_train)
pylab.plot(x,y,'g')
pylab.xlabel("x")
pylab.ylabel("y")
predicted = numpy.dot(model, [numpy.power(x,i) for i in xrange(0,degree)])
pylab.plot(x, predicted,'r')
pylab.legend(["Actual", "Predicted"], loc = 2)
train_rmse1 = numpy.sqrt(numpy.sum(numpy.dot(y[0:80] - predicted[0:80], y_train - predicted[0:80])))
test_rmse1 = numpy.sqrt(numpy.sum(numpy.dot(y[80:] - predicted[80:], y[80:] - predicted[80:])))
解释一下numpy的几个api:
- numpy.column_stack
- numpy.dot 点积/点乘/内积
这是一个典型的欠拟合,将degree改为3和9,分别可以得到2阶和8阶多项式拟合的结果,结果分别对应比较好的拟合和过拟合,因为实验数据解来自于二阶多项式加噪声,可以理解为什么二阶拟合最佳,但实际情况中很难知道实验数据是几阶的,所以调节模型的阶数并不容易。另外,如果学习数据量很小,也不能用过高的阶数的拟合,比如50个学习数据,如果用50阶来拟合,就100%过拟合,没有任何意义。
为了解决过拟合问题,一种方法当然是提高训练集数量,另一个方法是引入正则化概念,在模型上引入一个正则项,用于惩罚过多的阶数,正则后的模型可以更好的防止过拟合。