机器学习-正则化

本文介绍了机器学习中的正则化方法,用于防止过拟合。正则化通过对模型参数施加惩罚,限制其大小,从而简化模型并提高泛化能力。文章详细阐述了L2正则化在回归和分类问题中的应用,并展示了正则化如何影响目标函数,通过代码实例对比了使用和不使用正则化的预测效果。
摘要由CSDN通过智能技术生成

5.7正则化

上次我们提到模型对训练数据过度的优化拟合,使模型能够很好的对训练数据进行拟合,但却对测试数据的预测或者分类效果很差,这种状态被称为过拟合。一般过度增加函数的次数会导致过拟合的情况。我们有哪些方法可以避免过拟合的情况呢?一般情况下:

  1. 增加全部训练数据的训练量
  2. 使用简单的模型
  3. 正则化

我们知道机器学习是从数据中学习的,所以足够的训练数据最重要。其次简单的模型也有助于防止过拟合的情况。我们现在需要着重介绍的是正则化的方法:

首先我们要理解使用正则化产生的效果。我们知道无论回归还是分类,参数θ是对模型的拟合产生影响的最主要因素,一般模型的过拟合就是由于参数的影响过大。而正则化的效果就是防止参数的影响过大,在训练时对参数施加的一些“惩罚”,让参数对模型的影响变小一点,从而达到防止过拟合的效果。

5.7.1回归的正则化

我们现在对这个新的目标函数进行最小化,这种方法称为正则化。正则项里的m表示正则化的对象参数的个数,θ0被称为偏置项,一般不对θ0正则化,所以j的取值是从1开始的。举个例子,假设预测函数的表达式为f(x)=θ0+θ1x+θ2x2,那么m=2就是表示正则化的对象参数为θ1和θ2。而λ是决定正则化影响程度的正的常数,这个值需要我们根据情况自己决定,后面会再提及。

只看表达式不容易理解正则化是如何防止过拟合的,我们可以结合图来理解:

我们首先把新组合成的目标函数拆开:

我们将这两个函数分别画出来后再加起来看看,不过参数过多的话就画不出图来了,所以假设f(x)=θ0+θ1x,而且为了方便理解,先不考虑λ,或令λ=1。在将回归的时候我们提到过这个目标函数C(θ)开口向上,所以我们假设一个开口向上的函数即可,R(θ)是一个标准的二次函数表达式1/2*θ12。则将两个函数的图形画出,如图5-7-2所示:

 

图5-7-2

新的目标函数是这两个函数之和E(θ)=C(θ)+R(θ),如何画出E(θ)的图形呢?我们这里只需要将C(θ)和R(θ)在横坐标θ1上各点的值相加映射到坐标轴上即可,如图5-7-3所示:

 

图5-7-3

本来目标函数在θ1=4.5处最小,加上正则项后,现在θ1=0.9处最小,我们可以发现θ1跟接近0了。这个就是正则化的效果,它可以防止参数变得过大,有助于参数接近最小的值。虽然我们只考虑了θ1,但是其它θj参数的情况也是类似的。参数的值变小了,那么意味着该参数的影响也会相应的变小。比如有这样的一个预测函数f(x)=θ0+θ1x+θ2x2。极端一点,假设θ2=0了,那么表达式就从二次变成了一次了。这正是通过减小不需要的参数的影响,将复杂的模型替换为简单的模型来防止过拟合的方式。之前提到的λ就是控制正则化惩罚强度的一个正的常数,是根据实际情况来决定的,如λ=0时相当于不使用正则化,反过来λ越大正则化的惩罚就越厉害。

5.7.2分类的正则化

分类的正则化与回归的正则化类似,就是在目标函数的基础上增加正则项。我们之前提到过逻辑回归的目标函数是对数似然函数:

 

我们只需要在这个目标函数的基础上增加正则项就可以了,但是对数似然函数是以最大化为目标,我们要把它变成和回归的目标函数一样处理最小化问题,所以前面加一个负号即可:

5.7.3 包含正则项表达式的微分

刚才我们把回归的目标函数分成C(θ)和R(θ)。这是新的目标函数的形式,我们要对它进行微分:E(θ)=C(θ)+R(θ)。由于是加法,所以我们对各部分进行偏微分:

 

首先对第一部分进行微分,具体微分步骤如下图5-7-4。

图5-7-4

所以,第一部分微分表达式如下:

先对第一个部分即原目标函数进行微分,微分具体步骤如图5-7-5:

图5-7-5

之前提到考虑的是最小化问题,所以在前面加上负号,所以将括号内的数进行反转:

 

刚才我们已经求过R(θ)的微分了,直接使用即可。与回归的正则化一样,θ0不参与正则化,所以要将参数的更新表达式“分段”:

 

这就是我们要求的逻辑回归正则化的参数更新表达式了。

我们这里讲的正则化方法其实叫L2正则化,除了L2正则化,还有一个叫L1正则化,L1正则化项是这样的:

 

虽然有两种正则化方法,但是我们可以根据实际情况来进行选择。L1正则化的特征是被判定为不需要的参数会变为0,从而减少变量的个数,而L2正则化不会把参数变为0。换句话说,L2正则化会抑制参数,使变量影响不会太大,而L1会直接去除不要的变量。

既然知道了正则化的表达式,我们就很好理解代码了,下面是应用正则化和没有使用正则化的对比:

import numpy as np

import matplotlib.pyplot as plt

# 真正的函数

def g(x):

    return 0.1 * (x ** 3 + x ** 2 + x)

# 随意准备一些向真正的函数加入了一点噪声的训练数据

train_x = np.linspace(-2, 2, 8)

train_y = g(train_x) + np.random.randn(train_x.size) * 0.05

# 标准化

mu = train_x.mean()

sigma = train_x.std()

def standardize(x):

    return (x - mu) / sigma

train_z = standardize(train_x)

# 创建训练数据的矩阵

def to_matrix(x):

    return np.vstack([

        np.ones(x.size),

        x,

        x ** 2,

        x ** 3,

        x ** 4,

        x ** 5,

        x ** 6,

        x ** 7,

        x ** 8,

        x ** 9,

        x ** 10

    ]).T

X = to_matrix(train_z)

# 参数初始化

theta = np.random.randn(X.shape[1])

# 预测函数

def f(x):

    return np.dot(x, theta)

# 目标函数

def E(x, y):

    return 0.5 * np.sum((y - f(x)) ** 2)

# 正则化常量

LAMBDA = 0.5

# 学习率

ETA = 1e-4

# 误差

diff = 1

# 重复学习(不应用正则化)

error = E(X, train_y)

while diff > 1e-6:

    theta = theta - ETA * (np.dot(f(X) - train_y, X))

    current_error = E(X, train_y)

    diff = error - current_error

    error = current_error

theta1 = theta

# 重复学习(应用正则化)

theta = np.random.randn(X.shape[1])

diff = 1

error = E(X, train_y)

while diff > 1e-6:

    reg_term = LAMBDA * np.hstack([0, theta[1:]])

    theta = theta - ETA * (np.dot(f(X) - train_y, X) + reg_term)

    current_error = E(X, train_y)

    diff = error - current_error

    error = current_error

theta2 = theta

# 绘图确认

plt.plot(train_z, train_y, 'o')

z = standardize(np.linspace(-2, 2, 100))

theta = theta1 # 未应用正则化

plt.plot(z, f(to_matrix(z)), linestyle='dashed')

theta = theta2 # 应用正则化

plt.plot(z, f(to_matrix(z)))

plt.show()

运行结果如下:

 

截图和代码引自《白话机器学习的数学》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值