机器学习实战_线性回归&逻辑回归(二)

线性模型的正则化

正如咱们在第一和第二章看到的那样,下降模型的过拟合的好方法是正则化这个模型(即限制它):模型有越少的自由度,就越难以拟合数据。例如,正则化一个多项式模型,一个简单的方法就是减小多项式的阶数。git

对于一个线性模型,正则化的典型实现就是约束模型中参数的权重。 接下来咱们将介绍三种不一样约束权重的方法:Ridge回归,Lasso回归和Elastic Net。算法

岭回归(Ridge):(L2正则)

岭回归(也称为Tikhonov正则化)是线性回归的正则化版:注意到这个正则项只有在训练过程当中才会被加到代价函数。当获得完成训练的模型后,咱们应该使用没有正则化的测量方法去评价模型的表现网络

通常状况下,训练过程使用的代价函数和测试过程使用的评价函数不同样的。除了正则化,还有一个不一样:训练时的代价函数应该在优化过程当中易于求导,而在测试过程当中,评价函数更应该接近最后的客观表现。一个好的例子:在分类训练中咱们使用对数损失(立刻咱们会讨论它)做为代价函数,可是咱们却使用精确率/召回率来做为它的评价函数。

岭回归(L2正则)代价函数:
$$J(\theta)=MSE(\theta)+\alpha\frac{1}{2}\sum\limits_{i=1}^n\theta_i^2$$函数

超参数$\alpha$ 决定了你想正则化这个模型的强度,正则化强度越大,模型会越简单。若是$\alpha$=0 那此时的岭回归便变为了线性回归。若是alpha很是的大,全部的权重最后都接近与零,最后结果将是一条穿过数据平均值的水平直线学习

(公式4-6:代价函数的梯度向量,加上$\alpha w$是$1/2*\alpha*w^2$求偏导的结果 )
clipboard.png测试

在使用岭回归前,对 数据进行放缩(可使用StandardScaler)是很是重要的,算法对于输入特征的数值尺度(scale)很是敏感。 大多数的正则化模型都是这样的

下图展现了在相同线性数据上使用不一样$\alpha$ 值的岭回归模型最后的表现。左图中,使用简单的岭回归模型,最后获得了线性的预测。右图中的数据首先使用10 阶的PolynomialFearuresj进行扩展,而后使用StandardScaler进行缩放,最后将岭模型应用在处理事后的特征上。这就是带有岭正则项的多项式回归。注意当$\alpha$ 增大的时候,致使预测曲线变得扁平(即少了极端值,多了通常值),这样减小了模型的方差,去增长了模型的误差优化

clipboard.png

对线性回归来讲,对于岭回归,咱们可使用封闭方程去计算,也可使用梯度降低去处理。它们的缺点和优势是同样的。公式4-9表示封闭方程的解(矩阵$\mathbf{A}$ 是一个除了左上角有一个0的$n \times n$的单位矩,这个0表明误差项。译者注:误差$\theta_0$ 不被正则化的)。编码

岭回归的封闭方程的解(公式4-6:代价函数的梯度向量,加上$\alpha w$是$1/2*\alpha*w^2$求偏导的结果 ):
$$\hat{\theta} =({\mathbf{X}}^T\cdot\mathbf{X}+\alpha\mathbf{A})^{-1}\cdot{\mathbf{X}}^T\cdot\mathbf{y}$$spa

下面是如何使用Scikit-Learn来进行封闭方程的求解(使用Cholesky法进行矩阵分解对上面公式行变形)code

>>> from sklearn.linear_model import Ridge
>>> ridge_reg = Ridge(alpha=1, solver="cholesky")
>>> ridge_reg.fit(X, y)
>>> ridge_reg.predict([[1.5]])
array([[ 1.55071465]]

使用随机梯度法进行求解:

>>> sgd_reg = SGDRegressor(penalty="l2")
>>> sgd_reg.fit(X, y.ravel())
>>> sgd_reg.predict([[1.5]])
array([[ 1.13500145]])

penalty参数指的是正则项的惩罚类型。指定“l2”代表你要在代价函数上添加一项:权重向量$\ell_2$ 范数平方的一半,这就是简单的岭回归。

Lasso回归(L1正则)

Lasso回归(也称Least Absolute Shrinkage,或者Selection Operator Regression)是另外一种正则化版的线性回归:就像岭回归那样,它也在代价函数上添加了一个正则化项,可是它使用权重向量的$\ell_1$ 范数而不是权重向量$\ell_2$ 范数平方的一半。

Lasso回归的代价函数:
$$J(\theta)=MSE(\theta)+\alpha\sum\limits_{i=1}^n\left|\theta_i \right|$$

下图展现了和以前相同的事情,仅仅是用Lasso模型代替了Ridge模型,同时调小了$\alpha$ 的值

clipboard.png

Lasso回归的一个重要特征是它倾向于彻底消除最不重要的特征的权重(即将它们设置为零)。例如,右图中的虚线所示($\alpha=10^{-7}$ ),曲线看起来像一条二次曲线,并且几乎是线性的,这是由于全部的高阶多项特征都被设置为零

下面是一个使用Lasso类的小Scikit-Learn示例。你也可使用SGDRegressor(penalty="l1")来代替它

>>> from sklearn.linear_model import Lasso
>>> lasso_reg = Lasso(alpha=0.1)
>>> lasso_reg.fit(X, y)
>>> lasso_reg.predict([[1.5]])
array([ 1.53788174]

弹性网络(ElasticNet)

弹性网络介于Ridge回归和Lasso回归之间。它的正则项是Ridge回归和Lasso回归正则项的简单混合,同时你能够控制它们的混合率r,当r=0时,弹性网络就是Ridge回归,当r=1时,其就是Lasso回归

弹性网络代价函数:

$$J(\theta)=MSE(\theta)+r\alpha\sum\limits_{i=1}^n\left|\theta_i \right|+\frac{1-r}{2}\alpha\sum\limits_{i=1}^n\theta_i^2$$

那么咱们该如何选择线性回归,岭回归,Lasso回归,弹性网络呢?通常来讲有一点正则项的表现更好,所以一般你应该避免使用简单的线性回归。岭回归是一个很好的首选项,可是若是你的特征仅有少数是真正有用的,你应该选择Lasso和弹性网络。就像咱们讨论的那样,它两可以将无用特征的权重降为零。通常来讲,弹性网络的表现要比Lasso好,由于当特征数量比样例的数量大的时候,或者特征之间有很强的相关性时,Lasso可能会表现的不规律。下面是一个使用Scikit-Learn 弹性网络ElasticNet(l1_ratio指的就是混合率r)的简单样例:

>>> from sklearn.linear_model import ElasticNet
>>> elastic_net = ElasticNet(alpha=0.1, l1_ratio=0.5)
>>> elastic_net.fit(X, y)
>>> elastic_net.predict([[1.5]])
array([ 1.54333232])

早期中止法(Early Stopping)

随着训练的进行,算法一直学习,它在训练集上的预测偏差(RMSE)天然而然的降低。然而一段时间后,验证偏差中止降低,并开始上升。这意味着模型在训练集上开始出现过拟合。一旦验证错误达到最小值,便提前中止训练.

随机梯度和小批量梯度降低不是平滑曲线,你可能很难知道它是否达到最小值。 一种解决方案是,只有在验证偏差高于最小值一段时间后(你确信该模型不会变得更好了),才中止以后将模型参数回滚到验证偏差最小值

clipboard.png

下面是一个早期中止法的基础应用

from sklearn.base import clone
sgd_reg = SGDRegressor(n_iter=1, warm_start=True, penalty=None,learning_rate="constant", eta0=0.0005)

minimum_val_error = float("inf")
best_epoch = None
best_model = None
for epoch in range(1000):
    sgd_reg.fit(X_train_poly_scaled, y_train)    # 训练多项式的新特征,拟合非线性
    y_val_predict = sgd_reg.predict(X_val_poly_scaled)
    val_error = mean_squared_error(y_val_predict, y_val)
    if val_error < minimum_val_error:
        minimum_val_error = val_error
        best_epoch = epoch
        best_model = clone(sgd_reg)
注意:当warm_start=True时,调用fit()方法后,训练会从停下来的地方继续,而不是从头从新开始

逻辑回归(几率估计)

Logistic回归模型计算输入特征的加权和(加上误差项),但它不像线性回归模型那样直接输出结果,而是把结果输入logistic()函数进行二次加工后进行输出

逻辑回归模型的几率估计(向量形式):

$$\hat{p}=h_\theta(\mathbf{x})=\sigma(\theta^T \cdot \mathbf{x})$$

Logistic函数(也称为logit),用$\sigma()$ 表示,其是一个sigmoid函数(图像呈S型),它的输出是一个介于0和1之间的数字
逻辑函数(S函数)

$$\sigma(t)=\frac{1}{1+exp(-t)}$$

clipboard.png

逻辑回归预测模型($\sigma()$ 几率输出以0.5做为二分类门槛):

clipboard.png

单个样例的代价函数:

clipboard.png

这个代价函数是合理的,由于当t接近0时,-log(t)变得很是大,因此若是模型估计一个正例几率接近于0,那么代价函数将会很大,同时若是模型估计一个负例的几率接近1,那么代价函数一样会很大。 另外一方面,当t接近于1时, -log(t)接近0,因此若是模型估计一个正例几率接近于0,那么代价函数接近于0,同时若是模型估计一个负例的几率接近0,那么代价函数一样会接近于0, 这正是咱们想的.(简单来讲,y=1时,几率p越接近1损失越小;相反y=0时,几率p越接近0时损失越小)

整个训练集的代价函数只是全部训练实例的平均值。能够用一个表达式(你能够很容易证实)来统一表示,称为对数损失

逻辑回归的代价函数(对数损失):

$$J(\theta)=-\frac{1}{m}\sum\limits_{i=1}^m\left[y^{(i)}log\left(\hat{p}^{(i)}\right)+\left(1-y^{(i)}\right)log\left(1-\hat{p}^{(i)}\right)\right]$$

可是这个代价函数对于求解最小化代价函数的$\theta$ 是没有公式解的(没有等价的正态方程)。 但好消息是,这个代价函数是凸的,因此梯度降低(或任何其余优化算法)必定可以找到全局最小值(若是学习速率不是太大,而且你等待足够长的时间)。下面公式给出了代价函数关于第j个模型参数$\theta_j$ 的偏导数

逻辑回归代价函数的偏导数:

$$\frac{\partial}{\partial \theta_j}J(\theta_j)=\frac{1}{m} \sum\limits_{i=1}^m{\left(\sigma\left(\theta^T \cdot \mathbf{x}^{(i)}\right)-y^{(i)}\right)}{x_j}^{(i)}$$

这个公式首先计算每一个样例的预测偏差,而后偏差项乘以第j项特征值,最后求出全部训练样例的平均值。 一旦你有了包含全部的偏导数的梯度向量,你即可以在梯度向量上使用批量梯度降低算法。 也就是说:你已经知道如何训练Logistic回归模型。 对于随机梯度降低,你固然只须要每一次使用一个实例,对于小批量梯度降低,你将每一次使用一个小型实例集。

决策边界

咱们使用鸢尾花数据集来分析Logistic回归。 这是一个著名的数据集,其中包含150朵三种不一样的鸢尾花的萼片和花瓣的长度和宽度。这三种鸢尾花为:Setosa,Versicolor,Virginica

clipboard.png

让咱们尝试创建一个分类器,仅仅使用花瓣的宽度特征来识别Virginica,首先让咱们加载数据:

>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> list(iris.keys())
['data', 'target_names', 'feature_names', 'target', 'DESCR']
>>> X = iris["data"][:, 3:] # petal width
>>> y = (iris["target"] == 2).astype(np.int)

接下来,咱们训练一个逻辑回归模型:

from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()
log_reg.fit(X, y) # 训练模型

咱们来看看模型估计的花瓣宽度从0到3厘米的几率估计

X_new = np.linspace(0, 3, 1000).reshape(-1, 1)    # 构造花瓣宽度从0到3厘米的全部特征
y_proba = log_reg.predict_proba(X_new)    # 预测几率
plt.plot(X_new, y_proba[:, 1], "g-", label="Iris-Virginica")
plt.plot(X_new, y_proba[:, 0], "b--", label="Not Iris-Virginica"

clipboard.png

Virginica花的花瓣宽度(用三角形表示)在1.4厘米到2.5厘米之间,而其余种类的花(由正方形表示)一般具备较小的花瓣宽度,范围从0.1厘米到1.8厘米。注意,它们之间会有一些重叠。在大约2厘米以上时,分类器很是确定这朵花是Virginica花(分类器此时输出一个很是高的几率值),而在1厘米如下时,它很是确定这朵花不是Virginica花(不是Virginica花有很是高的几率)。在这两个极端之间,分类器是不肯定的。可是,若是你使用它进行预测(使用predict()方法而不是predict_proba()方法),它将返回一个最可能的结果。所以,在1.6厘米左右存在一个决策边界,这时两类状况出现的几率都等于50%:若是花瓣宽度大于1.6厘米,则分类器将预测该花是Virginica,不然预测它不是(即便它有可能错了):

>>> log_reg.predict([[1.7], [1.5]])
array([1, 0])

下图的线性决策边界表示相同的数据集,可是此次使用了两个特征进行判断:花瓣的宽度和长度。 一旦训练完毕,Logistic回归分类器就能够根据这两个特征来估计一朵花是Virginica的可能性。 虚线表示这时两类状况出现的几率都等于50%:这是模型的决策边界。 请注意,它是一个线性边界。每条平行线都表明一个分类标准下的两两个不一样类的几率,从15%(左下角)到90%(右上角)。越过右上角分界线的点都有超过90%的几率是Virginica花

clipboard.png

就像其余线性模型,逻辑回归模型也能够$\ell_1$或者$\ell_2$ 惩罚使用进行正则化。Scikit-Learn默认添加了$\ell_2$ 惩罚

在Scikit-Learn的LogisticRegression模型中控制正则化强度的超参数不是$\alpha$ (与其余线性模型同样),而是是它的逆:C. C的值越大,模型正则化强度越低

Softmax回归:

Logistic回归模型能够直接推广到支持多类别分类,没必要组合和训练多个二分类器, 其称为Softmax回归或多类别Logistic回归.

这个想法很简单:当给定一个实例$\mathbf{x}$ 时,Softmax回归模型首先计算k类的分数$s_k(\mathbf{x})$ ,而后将分数应用在Softmax函数(也称为归一化指数)上,估计出每类的几率。 计算$s_k(\mathbf{x})$ 的公式看起来很熟悉,由于它就像线性回归预测的公式同样

k类的Softmax得分: $s_k(\mathbf{x})= \theta^T \cdot \mathbf{x}$

注意,每一个类都有本身独一无二的参数向量$\theta_k$ 。 全部这些向量一般做为行放在参数矩阵$\Theta$ 中

一旦你计算了样例$\mathbf{x}$ 的每一类的得分,你即可以经过Softmax函数估计出样例属于第k类的几率$\hat{p}_k$ :经过计算e的$s_k(\mathbf{x})$ 次方,而后对它们进行归一化(除以全部分子的总和)

clipboard.png

和Logistic回归分类器同样,Softmax回归分类器将估计几率最高(它只是得分最高的类)的那类做为预测结果,如公式4-21所示

clipboard.png

Softmax回归分类器一次只能预测一个类(即它是多类的,但不是多输出的),所以它只能用于判断互斥的类别,如不一样类型的植物。 你不能用它来识别一张照片中的多我的。

如今咱们知道这个模型如何估计几率并进行预测,接下来将介绍如何训练。咱们的目标是创建一个模型在目标类别上有着较高的几率(所以其余类别的几率较低),最小化公式4-22能够达到这个目标,其表示了当前模型的代价函数,称为交叉熵,当模型对目标类得出了一个较低的几率,其会惩罚这个模型。 交叉熵一般用于衡量待测类别与目标类别的匹配程度(咱们将在后面的章节中屡次使用它)

clipboard.png

交叉熵

交叉熵源于信息论。假设你想要高效地传输天天的天气信息。若是有八个选项(晴天,雨天等),则可使用3位对每一个选项进行编码,由于2^3=8。可是,若是你认为几乎天天都是晴天,更高效的编码“晴天”的方式是:只用一位(0)。剩下的七项使用四位(从1开始)。交叉熵度量每一个选项实际发送的平均比特数。 若是你对天气的假设是完美的,交叉熵就等于天气自己的熵(即其内部的不肯定性)。 可是,若是你的假设是错误的(例如,若是常常下雨)交叉熵将会更大,称为Kullback-Leibler散度(KL散度)。

clipboard.png

如今你能够计算每一类的梯度向量,而后使用梯度降低(或者其余的优化算法)找到使得代价函数达到最小值的参数矩阵$\Theta$

让咱们使用Softmax回归对三种鸢尾花进行分类。当你使用LogisticRregression对模型进行训练时,Scikit_Learn默认使用的是一对多模型,可是你能够设置multi_class参数为“multinomial”来把它改变为Softmax回归。你还必须指定一个支持Softmax回归的求解器,例如“lbfgs”求解器(有关更多详细信息,请参阅Scikit-Learn的文档)。其默认使用$\ell_12$ 正则化,你可使用超参数C控制它。

X = iris["data"][:, (2, 3)] # petal length, petal width
y = iris["target"]

softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10)
softmax_reg.fit(X, y)

因此下次你发现一个花瓣长为5厘米,宽为2厘米的鸢尾花时,你能够问你的模型你它是哪一类鸢尾花,它会回答94.2%是Virginica花(第二类),或者5.8%是其余鸢尾花

>>> softmax_reg.predict([[5, 2]])
array([2])
>>> softmax_reg.predict_proba([[5, 2]])
array([[ 6.33134078e-07, 5.75276067e-02, 9.42471760e-01]])是

clipboard.png

图4-25用不一样背景色表示告终果的决策边界。注意,任何两个类之间的决策边界是线性的。 该图的曲线表示Versicolor类的几率(例如,用0.450标记的曲线表示45%的几率边界)。注意模型也能够预测一个几率低于50%的类。 例如,在全部决策边界相遇的地方,全部类的估计几率相等,分别为33%。

相关文章
相关标签/搜索