欠拟合、过拟合、正则化、学习曲线

1.欠拟合、过拟合、正则化、学习曲线

1.1 欠拟合、过拟合

欠拟合:模型相对于要解决的问题来说太简单了,模型并没有拟合训练数据的状态
过拟合:模型相对于要解决的问题来说太复杂了,模型只能拟合训练数据的状态

下图来自:数据分析中的插值与拟合(2) —— 拟合

如何避免过拟合呢?

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

1.2 正则化

正则化有L1正则化、L2正则化等

L1正则化、L2正则化区别

L1 正则化的特征是被判定为不需要的参数会变为 0,从而减少变量个数。而 L2 正则化不会把参数变为 0
L2 正则化会抑制参数,使变量的影响不会过大,而 L1 会直接去除不要的变量。

使用哪个正则化取决于要解决什么问题,不能一概而论

1.2.1 回归的L2正则化

新目标函数 = 目标函数 + 正则项
m m m为参数个数、 λ \lambda λ 是决定正则化项影响程度的正的常数
注意: θ 0 \theta_0 θ0这种只有参数的项称为偏置项,一般不对它进行正则化

通过目标函数、正则项、新目标函数的图像来看看正则化到底怎么起作用的

这就是正则化的效果。它可以防止参数变得过大,有助于参数接近较小的值。虽然我们只考虑了 θ 1 \theta_1 θ1,但其他 θ j \theta_j θj 参数的情况也是类似的。
参数的值变小,意味着该参数的影响也会相应地变小,通过减小不需要的参数的影响,将复杂模型替换为简单模型来防止过拟合的方式
为了防止参数的影响过大,在训练时要对参数施加一些惩罚,而 λ \lambda λ 可以控制正则化惩罚的强度, λ \lambda λ越大,惩罚越严厉

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





扫描二维码关注公众号,回复: 15424381 查看本文章

1.2.3 回归的正则化的实现

import numpy as np
import matplotlib.pyplot as plt
# 真正的函数
def g(x):
    return 0.1 * (x ** 3 + x ** 2 + x)

x = np.linspace(-2, 2, 100)
plt.plot(train_x, train_y, 'o')
plt.plot(x, g(x), linestyle = 'dashed', color= 'm')
plt.ylim(-1, 2)
plt.show()


向函数 g ( x ) g(x) g(x)中加入一些自己造的训练数据

# 随意准备一些向真正的函数加入了一点噪声的训练数据
train_x = np.linspace(-2, 2, 8)
train_y = g(train_x) + np.random.randn(train_x.size) * 0.05

标准化变量x

# 标准化
mu = train_x.mean()
sigma = train_x.std()
def standardize(x):
    return (x - mu) / sigma

train_z = standardize(train_x)

假设我们用 10 次多项式来学习这个训练数据

# 创建训练数据的矩阵
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()

下图中绿色线为添加了正则项的,橙色线为未添加正则项的

1.2.4 逻辑回归的L2正则化



为什么突然添加负号?
反转符号是为了将最大化问题替换为最小化问题
对数似然函数本来以最大化为目标。但是,这次我想让它变成和回归的目标函数一样的最小化问题,所以加了负号。这样就可以像处理回归一样处理它,所以只要加上正则化项就可以了

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



1.3 学习曲线(区分欠拟合和过拟合)

先来看一个例子,有10个训练数据

若我们随机挑选2个训练数据,选择一次函数模型对其进行拟合,可以看到一次函数完美拟合,误差为0

我们用这10个训练数据,选择一次函数模型对其进行拟合,可以看到一次函数并不能很好的拟合这些数据,误差已经无法为0了

模型选的太简单了,随着数据量的增加,误差逐渐变大,精度逐渐下降

用测试数据对上面这个简单模型进行评估

使用少量训练数据来训练模型,然后用测试数据评估该模型精度
然后增加训练数据来训练模型,随后用测试数据对模型进行评估,重复这样的步骤,最终能绘制出数据数量和精度的关系曲线图,展示了数据数量和精度的图称为学习曲线

欠拟合状态

图中上方曲线为使用训练数据时,数据数量与其精度的关系曲线
数据量少时,由于只有几个数据,模型可以很好的拟合这些少量数据,误差会很小,精度会很大,但由于模型过于简单,那么随着数据量的增加,误差也会一点点变大。换句话说就是精度会一点点下降

图中下方曲线为使用测试数据时,数据数量与其精度的关系曲线
训练数据较少时训练好的模型难以预测未知的数据,所以精度很低;反过来说,训练数据变多时,预测精度就会一点点地变高。

过拟合状态

随着数据量的增加,使用训练数据时的精度一直很高,而使用测试数据时的精度一直没有上升到它的水准。只对训练数据拟合得较好,这就是过拟合的特征

高偏差为欠拟合
下图来自:2022吴恩达机器学习Deeplearning.ai课程:学习曲线

高方差为过拟合
下图来自:2022吴恩达机器学习Deeplearning.ai课程:学习曲线

通过学习曲线判断出是过拟合还是欠拟合之后,就可以采取相应的对策以便改进模型了。

猜你喜欢

转载自blog.csdn.net/weixin_48524215/article/details/131366833