目录html
更新、更全的《机器学习》的更新网站,更有python、go、数据结构与算法、爬虫、人工智能教学等着你:http://www.javashuo.com/article/p-vozphyqp-cm.htmlpython
相信咱们不少人可能都有去售楼处买房而无奈回家的行为,就算你没去过售楼处,相信你也应该据说过那使人叹而惊止的房价吧?对于高房价你没有想过这房价是怎么算出来的呢?难道就是房地产商拍拍脑门,北京的一律1000万,上海的一律800万,杭州的一律600万吗?看到这相信你应该有动力想要学好机器学习走向人生巅峰了。算法
其实仔细想一想这房价大有来头,首先房价不可能只和地区有关,北京有1000万的房子,又会有800万、600万的房子,那这些房价不和地区有关还和什么有关呢?若是你真的买过房就知道,房子的价格首先和地区是有着比较大的联系的,北京五环外的房子可能都高于杭州任何地区的房子,在同一个地区内,房子的价格大多和房子的占地面积、户型、采光度等等因素有关系。数组
这个时候就有某位聪明的投机者想到了,我是否是能够找到一个方法来预测房价呢?若是这个房子的房价明显小于这所房子该有的房价(注:房价可能在某段时间因为某种鲜为人知的因素有小幅波动),就把那所买过来了,等房价涨回去了再卖出去,这样看起来也是生财之道。(注:纯属虚构)数据结构
但是若是去预测房价呢?上面讲到了房价和房子所在地区\(x_1\)、占地面积\(x_2\)、户型\(x_3\)和采光度\(x_4\)有关,那么我是否是能够把这些因素假想成房子的特征,而后给这些每一个特征都加上一个相应的权重\(\omega\),既能够获得以下的决策函数
\[ \hat{Y} = \omega_1x_1 + \omega_2x_2 + \omega_3x_3 + \omega_4x_4 + b \]
其中\(b\)能够理解为误差,你也能够想成房子的这些特征再差也可能会有一个底价。dom
基于上述给出房价的决策函数,咱们就能够对一个某个不知名的房子输入它的这些特征,而后就能够获得这所房子的预测价格了。机器学习
理想老是美好的,即一条生财之道就在眼前,可是咱们如何去获得这个决策函数呢?咱们能够获得这个特征值,可是这个\(\omega\)怎么获得呢?这就是咱们的线性回归须要解决的问题,下面让咱们一块儿走向这条生财之道吧!函数
你能够简单的认为线性回归就是找到一条曲线去拟合全部样本点,上面说起买房的问题有四个特征,所以咱们获得的决策函数为
\[ \hat{Y} = \omega_1x_1 + \omega_2x_2 + \omega_3x_3 + \omega_4x_4 + b \]工具
对于\(n\)个特征的线性回归模型,你可能须要找到一条曲线,也能够说成是一个决策函数
\[ \hat{Y}=f_\theta(X)=\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n+b=\theta^TX+b \]
拟合全部样本点。其中\(b\)为未知参数偏置(bias);\(\theta\)为未知参数向量\([\theta_1,\theta_2,\cdots,\theta_n]\);\(X\)为样本在各个特征上的特征值,用向量表示为\([x_1,x_2,\cdots,x_n]\);\(\theta^T\)为向量\(\theta\)的转置
\[ \begin{bmatrix} \theta_1 \\ \theta_2 \\ \vdots \\ \theta_n \end{bmatrix} \]
;
\[ \theta^TX= \begin{bmatrix} \theta_1 \\ \theta_2 \\ \vdots \\ \theta_n \end{bmatrix} * [x_1,x_2,\cdots,x_n] = \theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n \]
若是你对矩阵运算不熟悉,牢记\(f_\theta(X)=\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n+b=\theta^TX+b\)便可。性能
若是把未知参数\(b\)当作\(\theta_0\),曲线为
\[ \hat{Y}=f_\theta(X)=\theta_0x_0+\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n+b=\theta^TX \]
其中\(x_0=1\)。
虽然其余机器学习算法的决策函数不必定是线性回归的\(f_\theta(X)=\theta^T{X}\),可是决策函数中通常都会有一个未知参数\(\theta\),之后对于全部的机器学习算法都会逐一讲解为何会有这个参数。
# 损失函数图例 import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn.datasets.samples_generator import make_regression %matplotlib inline font = FontProperties(fname='/Library/Fonts/Heiti.ttc') # 生成随机数据 # X为样本特征,y为样本输出,coef为回归系数,共100个样本,5个噪声,每一个样本1个特征,数据集随机种子为1 X, y, coef = make_regression( n_samples=100, n_features=1, noise=50, coef=True, random_state=1) # 散点图+直线 plt.scatter(X, y, color='g', s=50, label='房子信息') plt.plot(X, X*coef, color='r', linewidth=2) plt.xlabel('房子面积', fontproperties=font, fontsize=15) plt.ylabel('房价', fontproperties=font, fontsize=15) plt.title('房子面积-房价', fontproperties=font, fontsize=20) # 去掉x,y轴尺度 plt.xticks(()) plt.yticks(()) plt.legend(prop=font) plt.show()
如上图所示,上图假设每个绿点表示一所房子的信息,红色的直线为咱们经过某种方法获得一个决策函数\(\hat{Y}=f_\theta(X)=\theta^T{X}+b=\theta_1x+b\)。对于监督模型中的经过房子面积预测房价例子,咱们是假设已知\(\theta_1=10,b=0\)。
可是若是你眼力劲还不错,你可能会发现咱们的这个决策函数并无彻底通过这些数据点,也能够说是没有彻底拟合这些数据点。通常咱们的决策函数都是没法通过全部点的,你要知道机器学习是不可能作到预言的,而只能作到预测,预言有时候都会不许确,更别说预测了,也就是说机器学习对新数据的预测是有偏差的。一般咱们使用一个损失函数(loss function)或代价函数(cost function)度量模型预测错误的程度
\[ L(Y-\hat{Y})=L(Y-f_\theta(X)) \]
其中\(Y\)为样本的真实值,\(\hat{Y}\)为样本的预测值。
四种经常使用的损失函数:
损失函数通常是对某个样本损失的计算,可是咱们的模型很明显不是由一个样本生成的,而是由一组样本生成的。因为\(X\)和\(Y\)咱们能够经过数据得到,可是未知参数\(\theta\)是未知的,所以咱们在这里给出关于\(\theta\)的目标函数(objective function),即全部样本的偏差加和取平均
\[ J(\theta)= \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) \]
其中\(m\)是样本总数,\(\sum_{i=1}^m L(y_i,f_{\theta_i}(x_i))= L(y_1,f_{\theta_1}(x_1))+L(y_2,f_{\theta_2}(x_2))+\cdots+L(y_m,f_{\theta_m}(x_m))\)
假设咱们获得了目标函数,那么咱们接下来要干什么呢?目标函数是全部样本的偏差加和取平均,那么是否是这个偏差越小越好呢?对,你暂时能够这样想,偏差越小,则咱们的预测值会愈来愈接近真实值,接下来咱们就是须要最小化目标函数,因为目标函数在统计学中被称为经验风险(empirical risk),因此有时候也会最小化目标函数也会被称为经验风险最小化(empirical risk minimization)。
\[ \min{J(\theta)} = \min \frac{1}{m}\sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) \]
其中\(\min{J(\theta)}\)表示最小化\(J(\theta)\)函数。
经过线性回归举例,因为\(f_{\theta}(X)=\theta^TX\),则它的损失函数是
\[ L(Y,f_\theta(X)) = L(Y,\theta^TX) \]
它的目标函数是
\[ J(\theta)=\frac{1}{m} \sum_{i=1}^m L(y_i,\theta_i{x_i}) \]
假设上述目标函数使用了平方损失函数,则目标函数变成
\[ J(\theta) = \frac{1}{m} \sum_{i=1}^m (y_i-\theta_i{x_i})^2 \]
最小化目标函数为
\[ \begin{align} \min{J(\theta)} & = \min \frac{1}{m} \sum_{i=1}^m (y_i-\theta_i{x_i})^2 \\ & = \min \frac{1}{m} [(y_1-\theta_1{x_1})^2+(y_2-\theta_2{x_2})^2+\cdots+(y_m-\theta_m{x_m})^2] \end{align} \]
其中\(\{x_1,x_2,\cdots,x_m\}\)、\(\{y_1,y_2,\cdots,y_m\}\)、\(m\)都是已知的,即咱们能够把他们当作一个常数。
若是咱们考虑一个极端状况,即假设\(x_i=1,\,(i=1,2,\cdots,m)\)、\(y_i=2,\,(y=1,2,\cdots,m)\)、\(m=100\)、\(\theta_1=\theta_2=\cdots=\theta_m=\theta_j\),则最小化目标函数变为
\[ \begin{align} \min{J(\theta)} & = \min \frac{1}{100} \underbrace{[(2-\theta_j*1)^2+(2-\theta_j*1)^2+\cdots+(2-\theta_j*1)^2]}_{100} \\ & = \min \frac{1}{100} 100*[(2-\theta_j*1)^2] \\ & = \min (2-\theta_j*1)^2 \end{align} \]
# 目标函数最小化图例 import numpy as np import matplotlib.pyplot as plt %matplotlib inline # 生成一个数组(-4.98,-4.96,...,4.98,5) theta_j = np.arange(-5, 5, 0.02) # 构造J_theta曲线 J_theta_j = (2-theta_j)**2 # 描绘曲线 plt.plot(theta_j, J_theta_j, color='r', linewidth=2) plt.xlabel('$θ$', fontproperties=font, fontsize=15) plt.ylabel('$min{J(θ)}$', fontproperties=font, fontsize=15) plt.title('$\min{J(θ)}=(2-θ_j*1)^2$', fontproperties=font, fontsize=20) plt.show()
上图即咱们假设的目标函数的图像,从上图能够看出,若是要最小化目标函数则须要找到能使目标函数最小化的参数向量\(\theta\),经过公式能够表示为
\[ \underbrace{arg\,\min}_\theta{J(\theta)}=\frac{1}{m}\sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) \]
其中\(\underbrace{arg\,\min}_\theta{J(\theta)}\)表示找到能使\(J(\theta)\)最小化的参数向量\(\theta\)。
因为这里只介绍目标函和目标函数最小化问题,怎么找能使得目标函数最小化的\(\theta\)不在此处介绍范围,之后会详细介绍。相信你对目标函数的构造、目标函数最小化(目标函数优化问题)有了一个明确的认知,至于目标函数中埋下的几处伏笔,之后都会详细介绍,目前的你只须要了解这个流程,之后咱们会经过具体的机器学习算法来再一次解释这个过程。而且之后你会发现其实咱们接下来要介绍的全部机器学习算法都是基于这个流程,因此你会反复再反复接触这个流程,若是如今能有个明确的认知很好,若是不能够等把这个流程与某个机器学习算法联系在一块儿的时候相信你能理解他。
在这里我必须得明确告诉你,理论上模型多是越小越好,可是在工业上模型并非偏差越小越好。你能够这样想一想,假设咱们有一个数据集,这个数据集难道不会有噪音(noise)或噪声吗?首先我能够很明确的告诉你,通常的工业上的数据都会有噪声,若是咱们的模型通过了包括噪声的全部样本点,也就是说模型对咱们的训练集作到了完美拟合,这就是咱们常说的过拟合(over-fitting),而且过拟合时模型也会变得相对复杂。
产生噪声的缘由:
# 过拟合图例 import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression font = FontProperties(fname='/Library/Fonts/Heiti.ttc') %matplotlib inline # 自定义数据并处理数据 data_frame = {'x': [2, 1.5, 3, 3.2, 4.22, 5.2, 6, 6.7], 'y': [0.5, 3.5, 5.5, 5.2, 5.5, 5.7, 5.5, 6.25]} df = pd.DataFrame(data_frame) X, y = df.iloc[:, 0].values.reshape(-1, 1), df.iloc[:, 1].values.reshape(-1, 1) # 线性回归 lr = LinearRegression() lr.fit(X, y) def poly_lr(degree): """多项式回归""" poly = PolynomialFeatures(degree=degree) X_poly = poly.fit_transform(X) lr_poly = LinearRegression() lr_poly.fit(X_poly, y) y_pred_poly = lr_poly.predict(X_poly) return y_pred_poly def plot_lr(): """对线性回归生成的图线画图""" plt.scatter(X, y, c='k', edgecolors='white', s=50) plt.plot(X, lr.predict(X), color='r', label='lr') # 噪声 plt.scatter(2, 0.5, c='r') plt.text(2, 0.5, s='$(2,0.5)$') plt.xlim(0, 7) plt.ylim(0, 8) plt.xlabel('x') plt.ylabel('y') plt.legend() def plot_poly(degree, color): """对多项式回归生成的图线画图""" plt.scatter(X, y, c='k', edgecolors='white', s=50) plt.plot(X, poly_lr(degree), color=color, label='m={}'.format(degree)) # 噪声 plt.scatter(2, 0.5, c='r') plt.text(2, 0.5, s='$(2,0.5)$') plt.xlim(0, 7) plt.ylim(0, 8) plt.xlabel('x') plt.ylabel('y') plt.legend() def run(): plt.figure() plt.subplot(231) plt.title('图1(线性回归)', fontproperties=font, color='r', fontsize=12) plot_lr() plt.subplot(232) plt.title('图2(一阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(1, 'orange') plt.subplot(233) plt.title('图3(三阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(3, 'gold') plt.subplot(234) plt.title('图4(五阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(5, 'green') plt.subplot(235) plt.title('图5(七阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(7, 'blue') plt.subplot(236) plt.title('图6(十阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(10, 'violet') plt.show() run()
如上图所示每张图都有相同分布的8个样本点,红点明显是一个噪声点,接下来将讲解上述8张图。暂时不用太关心线性回归和多项式回归是什么,这两个之后你都会学习到,此处引用只是为了方便举例。
从上图能够看出,过拟合模型将会变得复杂,对于线性回归而言,它可能须要更高阶的多项式去拟合样本点,对于其余机器学习算法,也是如此。这个时候你也能够想象,过拟合虽然对拟合的样本点的偏差接近0,可是对于将来新数据而言,若是新数据的\(x=2\),若是使用过拟合的曲线进行拟合新数据,那么会给出\(y=0.5\)的预测值,也就是说把噪声的值给了新数据,这样明显是不合理的。
上面给你们介绍了机器学习中避不开的一个话题,即模型颇有可能出现过拟合现象,出现了问题就应该解决,我讲讲机器学习中最经常使用的解决过拟合问题的方法——正则化(regularization)。给目标函数加上正则化项(regularizer)或惩罚项(penalty term),即新的目标函数变成
\[ J(\theta)=\frac{1}{m} \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) + \lambda(R(f)) \]
其中\(\lambda\geq0\)为超参数,相似于参数,可是参数能够经过算法求解,超参数须要人工手动调整;\(\lambda(R(f))\)为正则化项。
这个时候你可能在想为何加上正则化项就能够解决过拟合问题呢?对于线性回归而言,因为涉及线性回归、梯度降低法、最小角回归法等概念,此处很少赘述,讲线性回归时会详细讲述。下面将经过线性回归中正则化的两种形式L1正则化和L2正则化作简单解释。
L1正则化(Lasso)是在目标函数上加上L1正则化项,即新的目标函数为
\[ J(\theta) =\frac{1}{m} \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) + \lambda||\theta||_1 \]
其中\(||\theta||_1\)为参数向量\(\theta\)的1范数。
假设样本有\(n\)特征,则\(\theta\)为\(n\)维向量,1范数为
\[ ||\theta||_1=\sum_{j=1}^n|\theta_j| \]
L2正则化(Ridge)是在目标函数上加上L2正则化项,即新的目标函数为
\[ J(\theta)=\frac{1}{m} \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) + \frac{\lambda}{2}||\theta||_2^2 \]
其中\(||\theta||_2^2\)为参数向量\(\theta\)的2范数的平方。
假设样本有\(n\)特征,则\(\theta\)为\(n\)维向量,2范数为
\[ ||\theta||_2=\sqrt{\sum_{j=1}^n{\theta_j}^2} \]
多说一嘴,假设样本有\(n\)特征,则\(\theta\)为\(n\)维向量,p范数为
\[ ||\theta||_p=\sqrt[p]{\sum_{j=1}^n{\theta_j}^p} \]
一般状况下咱们不会使用数据集中的全部数据做为训练数据训练模型,而是会按照某种比例,将数据集中的数据随机分红训练集、验证集、测试集学得一个较优模型,如能够把数据集按照7:2:1的比例分红训练集、验证集、测试集,对于不一样的问题通常分配的比例不一样,下面将介绍这三者各自的做用。
通常状况下咱们都会使用带有正则项的目标函数去构建模型,即咱们的目标函数为
\[ J(\theta)=\frac{1}{m} \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) + \lambda(R(f)) \]
通常会经过训练集获得参数\(\theta\)。如线性回归的目标函数中有两个参数\(\theta\)和\(b\),通常会经过训练集获得这两个参数\(\theta\)和\(b\)。
通常状况下咱们都会使用带有正则项的目标函数去构建模型,即咱们的目标函数为
\[ J(\theta)=\frac{1}{m} \sum_{i=1}^m L(y_i,f_{\theta_i}(x_i)) + \lambda(R(f)) \]
通常会经过给定一组超参数,而后经过验证集获得最优超参数\(\lambda\),有时候会把验证集获得超参数的步骤划分到训练集中。如线性回归的目标函数有一个超参数\(\lambda\),通常会经过验证集获得该超参数\(\lambda\)。
测试集通常被当作将来新数据集,而后经过度量模型性能的工具测试模型的偏差大小。
本章主要经过线性回归介绍了决策函数、四种损失函数、目标函数及目标函数的问题,其实其余的机器学习算法也是这样的套路,在在一部分算法原理时咱们会细讲,此处你有一个大概的概念便可。
最小化目标函数咱们假设偏差越小越好,然而工业上数据老是会有噪声,也就是说\(0\)偏差也许并非最好的,所以引出了咱们的过拟合问题,以后讲解了解决过拟合问题的两个方法,一个是在目标函数上加上正则化项,另外一个则把训练集分红训练集、验证集和测试集。