吴恩达机器学习笔记
监督学习
定义
监督学习是一种机器学习方法,其中模型从输入数据(特征)和相应的输出标签(目标)中学习,目的是能够预测或决定新实例的输出标签。
监督学习机器学习中的核心概念之一,它涉及到从标记的训练数据中学习,以便对新的、未见过的数据进行预测或分类。
基本流程
- 数据收集:收集包含输入特征和对应输出标签的数据集。
- 数据预处理:清洗数据,处理缺失值,进行特征工程等。
- 选择模型:根据问题的性质(回归或分类)选择合适的算法。
- 训练模型:使用训练数据集来训练模型,使其学习输入和输出之间的关系。
- 模型评估:使用验证集或测试集来评估模型的性能。
- 参数调优:根据评估结果调整模型参数以优化性能。
- 模型部署:将训练好的模型部署到生产环境中,用于预测新数据。
常见算法
- 回归算法:线性回归、多项式回归、决策树回归、随机森林回归、支持向量回归等。
- 分类算法:逻辑回归、K最近邻(KNN)、决策树、随机森林、支持向量机(SVM)、神经网络等。
评估指标
- 回归问题:均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)、R平方值等。
- 分类问题:准确率、精确率、召回率、F1分数、ROC曲线、AUC值等。
过拟合与欠拟合
- 过拟合:模型在训练数据上表现很好,但在未见过的数据上表现差,即泛化能力差。
- 欠拟合:模型在训练数据上表现就不好,没有捕捉到数据的基本模式。
无监督学习
定义
无监督学习是一种机器学习方法,它从没有标签的数据中学习,目的是发现数据的内在结构或分布。
无监督学习(Unsupervised Learning)是机器学习中的一种方法,它处理的数据没有标签或标记。
基本流程
- 数据收集:收集数据,这些数据通常没有标签。
- 数据预处理:清洗数据,处理缺失值,进行特征工程等。
- 选择算法:根据数据的特性和目标选择合适的无监督学习算法。
- 模型训练:使用数据训练模型,以发现数据中的模式或结构。
- 结果解释:解释模型的输出,以理解数据中的模式。
常见算法
- 聚类算法:K-means、层次聚类、DBSCAN、高斯混合模型(GMM)等。
- 降维算法:主成分分析(PCA)、线性判别分析(LDA)、t-SNE、自编码器等。
- 关联规则学习:Apriori算法、FP-Growth算法等。
- 异常检测:基于统计的方法、基于邻近度的方法、基于聚类的方法等。
线性回归
线性回归(Linear Regression)是统计学中的一种基本预测模型,用于建立一个或多个自变量(解释变量)与因变量(响应变量)之间的线性关系。
线性回归模型的目的是找到最佳拟合线,使得模型预测值与实际观测值之间的差异最小化。
简单线性回归(Simple Linear Regression)
- 定义:简单线性回归涉及一个自变量和一个因变量,它们之间的关系可以用一条直线来近似表示。
- 模型形式:
y
=
β
0
+
β
1
x
+
ϵ
y = \beta_0 + \beta_1 x + \epsilon
y=β0+β1x+ϵ
- y y y 是因变量(响应变量)。
- x x x 是自变量(解释变量)。
- β 0 \beta_0 β0 是截距项。
- β 1 \beta_1 β1 是斜率,表示 x x x 每变化一个单位, y y y 的预期变化量。
- ϵ \epsilon ϵ 是误差项,表示模型无法解释的随机变异。
多元线性回归(Multiple Linear Regression)
- 定义:多元线性回归涉及两个或多个自变量和一个因变量,它们之间的关系可以用一个超平面来近似表示。
- 模型形式:
y
=
β
0
+
β
1
x
1
+
β
2
x
2
+
…
+
β
n
x
n
+
ϵ
y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \ldots + \beta_n x_n + \epsilon
y=β0+β1x1+β2x2+…+βnxn+ϵ
- y y y 是因变量。
- x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,…,xn 是自变量。
- β 0 , β 1 , β 2 , … , β n \beta_0, \beta_1, \beta_2, \ldots, \beta_n β0,β1,β2,…,βn 是模型参数。
模型训练
-
目标:找到参数 β \beta β 的值,使得模型预测值与实际观测值之间的差异最小化。这通常通过最小二乘法(Least Squares Method)实现。
最小二乘法(Least Squares Method)是一种数学优化技术,它通过最小化误差的平方和来寻找数据的最佳函数匹配。在统计学中,这种方法被广泛用于估计线性回归模型的参数。
原理
最小二乘法的目标是找到一组参数,使得模型预测值与实际观测值之间的残差(误差)平方和最小。残差是指实际观测值与模型预测值之间的差异。
数学表达
对于一个简单的线性回归模型 y = β 0 + β 1 x y = \beta_0 + \beta_1 x y=β0+β1x,我们希望找到 β 0 \beta_0 β0 和 β 1 \beta_1 β1 的值,使得残差平方和 S S S 最小:
S = ∑ i = 1 n ( y i − ( β 0 + β 1 x i ) ) 2 S = \sum_{i=1}^{n} (y_i - (\beta_0 + \beta_1 x_i))^2 S=∑i=1n(yi−(β0+β1xi))2
其中:
- y i y_i yi 是第 i i i 个观测值的实际值。
- x i x_i xi 是第 i i i 个观测值的自变量值。
- β 0 \beta_0 β0 是截距项。
- β 1 \beta_1 β1 是斜率系数。
- n n n 是观测值的总数。
参数估计
为了找到使 S S S 最小的 β 0 \beta_0 β0 和 β 1 \beta_1 β1,我们对 S S S 分别对 β 0 \beta_0 β0 和 β 1 \beta_1 β1 求偏导数,并令它们等于零:
∂
S
∂
β
0
=
−
2
∑
i
=
1
n
(
y
i
−
(
β
0
+
β
1
x
i
)
)
=
0
\frac{\partial S}{\partial \beta_0} = -2 \sum_{i=1}^{n} (y_i - (\beta_0 + \beta_1 x_i)) = 0
∂β0∂S=−2∑i=1n(yi−(β0+β1xi))=0
∂
S
∂
β
1
=
−
2
∑
i
=
1
n
(
y
i
−
(
β
0
+
β
1
x
i
)
)
x
i
=
0
\frac{\partial S}{\partial \beta_1} = -2 \sum_{i=1}^{n} (y_i - (\beta_0 + \beta_1 x_i)) x_i = 0
∂β1∂S=−2∑i=1n(yi−(β0+β1xi))xi=0
解这个方程组可以得到 β 0 \beta_0 β0 和 β 1 \beta_1 β1 的估计值:
β
1
=
∑
i
=
1
n
(
x
i
−
x
ˉ
)
(
y
i
−
y
ˉ
)
∑
i
=
1
n
(
x
i
−
x
ˉ
)
2
\beta_1 = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^{n} (x_i - \bar{x})^2}
β1=∑i=1n(xi−xˉ)2∑i=1n(xi−xˉ)(yi−yˉ)
β
0
=
y
ˉ
−
β
1
x
ˉ
\beta_0 = \bar{y} - \beta_1 \bar{x}
β0=yˉ−β1xˉ
其中:
- x ˉ \bar{x} xˉ 是 x x x 值的平均数。
- y ˉ \bar{y} yˉ 是 y y y 值的平均数。
特点
- 简单直观:最小二乘法的计算相对简单,直观上容易理解。
- 广泛适用:适用于各种线性模型,包括简单线性回归和多元线性回归。
- 敏感性:对异常值敏感,因为误差的平方放大了大误差的影响。
局限性
- 非线性关系:如果数据之间的关系是非线性的,最小二乘法可能不会提供好的拟合。
- 同方差性假设:假设误差具有恒定的方差,这在某些情况下可能不成立。
模型评估
1. 均方误差(Mean Squared Error, MSE)
均方误差是预测值与实际值之间差异的平方的平均值。它衡量模型预测的准确性,值越小表示模型预测越准确。
MSE = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 \text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 MSE=n1∑i=1n(yi−y^i)2
- y i y_i yi 是第 i i i 个观测值的实际值。
- y ^ i \hat{y}_i y^i 是第 i i i 个观测值的预测值。
- n n n 是观测值的总数。
2. 均方根误差(Root Mean Squared Error, RMSE)
均方根误差是MSE的平方根,与原始数据具有相同的单位,因此更容易解释。它衡量预测值与实际值之间差异的标准差。
RMSE = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 \text{RMSE} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2} RMSE=n1∑i=1n(yi−y^i)2
3. 平均绝对误差(Mean Absolute Error, MAE)
平均绝对误差是预测值与实际值之间差异的绝对值的平均值。与MSE相比,MAE对异常值的敏感度较低。
MAE = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ \text{MAE} = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| MAE=n1∑i=1n∣yi−y^i∣
4. R平方值(R-squared, R²)
R平方值,也称为决定系数,衡量模型解释的变异量占总变异量的比例。它的值范围从0到1,值越接近1表示模型的解释能力越强。
R 2 = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ˉ ) 2 R^2 = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2} R2=1−∑i=1n(yi−yˉ)2∑i=1n(yi−y^i)2
- y ˉ \bar{y} yˉ 是实际值的平均值。
解释
- MSE和RMSE:这两个指标对异常值非常敏感,因为它们基于平方误差。一个非常大的误差可以使MSE和RMSE显著增加。
- MAE:这个指标对异常值的敏感度较低,因为它基于绝对误差。
- R²:这个指标提供了模型解释数据变异的能力的度量。然而,一个高的R²值并不一定意味着模型是好的,因为它可能受到模型复杂度的影响。
假设
线性回归模型的有效性依赖于几个基本假设:
- 线性:自变量与因变量之间存在线性关系。
- 独立性:自变量之间相互独立,没有多重共线性。
- 同方差性:对于所有的观测值,误差项具有恒定的方差。
- 正态分布:误差项呈正态分布。
代价函数
代价函数是机器学习中用于衡量模型预测值与实际值之间差异的函数,其目的是通过最小化代价函数来找到最优的模型参数。
代价函数(Cost Function)在机器学习中扮演着核心角色,它用于衡量模型预测值与真实值之间的差异,从而指导模型参数的优化。
与损失函数的区别:尽管代价函数和损失函数是同义词并且可以互换使用,但它们是不同的。损失函数用于单个训练样本,而代价函数是整个训练数据集的平均损失。
代价函数公式
在线性回归中,最常用的代价函数是均方误差代价函数,其公式为:
J ( w , b ) = 1 2 m ∑ i = 1 m ( h w ( x ( i ) ) − y ( i ) ) 2 J(w, b) = \frac{1}{2m} \sum_{i=1}^{m} (h_w(x^{(i)}) - y^{(i)})^2 J(w,b)=2m1∑i=1m(hw(x(i))−y(i))2
其中:
- J ( w , b ) J(w, b) J(w,b) 是代价函数, w w w 和 b b b 是模型参数。
- m m m 是训练样本的数量。
- h w ( x ( i ) ) h_w(x^{(i)}) hw(x(i)) 是模型预测值, y ( i ) y^{(i)} y(i) 是实际值。
- ∑ \sum ∑ 表示求和符号,对所有训练样本求和。
- 1 2 m \frac{1}{2m} 2m1 是为了使代价函数的规模与训练样本数量无关,并且简化梯度计算中的常数因子。
代价函数可视化
代价函数的可视化通常涉及到三维图形,其中两个轴表示模型参数(如 w w w 和 b b b),第三个轴表示代价函数的值。通过这种可视化,我们可以直观地看到代价函数的形状,以及如何通过调整参数来最小化代价函数。
-
三维可视化:在三维空间中,我们可以将 w w w 和 b b b 作为两个坐标轴,代价函数 J ( w , b ) J(w, b) J(w,b) 的值作为高度轴。这样,我们可以看到一个类似碗状的曲面,其最低点对应于代价函数的最小值,即模型参数的最优解。
-
等高线可视化:等高线图是一种二维表示方法,它显示了不同代价函数值对应的等值线。每条线代表一个特定的代价函数值,最中心的点代表代价函数的最小值。这种表示方法有助于我们理解参数空间中代价函数的变化情况。
梯度下降
梯度下降(Gradient Descent)是一种常用的优化算法,用于最小化一个函数,特别在机器学习中用于最小化代价函数以找到模型参数的最优值。
基本思想
梯度下降算法通过迭代地更新参数来最小化代价函数。在每一步迭代中,算法计算代价函数关于每个参数的梯度(即偏导数),然后沿着梯度的反方向更新参数,因为梯度指示了函数增长最快的方向,其反方向则是下降最快的方向。
算法步骤
- 初始化参数:随机选择一个参数的初始值,通常接近于零或一个小的随机数。
- 计算梯度:对于每一个参数,计算代价函数关于该参数的梯度。
- 更新参数:使用梯度和学习率(步长)来更新每个参数:
θ j : = θ j − α ∂ J ∂ θ j \theta_j := \theta_j - \alpha \frac{\partial J}{\partial \theta_j} θj:=θj−α∂θj∂J
其中, θ j \theta_j θj 是第 j j j 个参数, α \alpha α 是学习率, ∂ J ∂ θ j \frac{\partial J}{\partial \theta_j} ∂θj∂J 是代价函数 J J J 关于 θ j \theta_j θj 的偏导数。 - 重复:重复步骤2和3,直到满足停止条件,比如梯度足够小、达到最大迭代次数或代价函数值的变化低于某个阈值。
梯度下降的实现
1. 初始化参数
首先,我们需要随机初始化模型的参数。对于线性回归,我们有两个参数:斜率(权重) w w w 和截距(偏置) b b b。
import numpy as np
# 随机初始化参数
w = np.random.randn()
b = np.random.randn()
# 学习率
alpha = 0.01
2. 定义模型和代价函数
对于线性回归,模型预测是 h w ( x ) = w ⋅ x + b h_w(x) = w \cdot x + b hw(x)=w⋅x+b,代价函数是均方误差:
def compute_cost(X, y, w, b):
"""
计算代价函数
:param X: 特征矩阵
:param y: 实际结果
:param w: 权重
:param b: 偏置
:return: 代价函数的值
"""
m = len(y)
predictions = w * X + b
cost = (1 / (2 * m)) * np.sum(np.square(predictions - y))
return cost
def gradient_descent(X, y, w, b, alpha, iterations):
"""
梯度下降算法
:param X: 特征矩阵
:param y: 实际结果
:param w: 权重
:param b: 偏置
:param alpha: 学习率
:param iterations: 迭代次数
:return: 最优的权重和偏置
"""
m = len(y)
for i in range(iterations):
# 计算预测值
predictions = w * X + b
# 计算误差
errors = predictions - y
# 计算梯度
dw = (1 / m) * np.sum(errors * X)
db = (1 / m) * np.sum(errors)
# 更新权重和偏置
w -= alpha * dw
b -= alpha * db
return w, b
3. 准备数据
假设我们有一些数据点,我们可以将它们表示为 X
(特征)和 y
(标签)。
# 示例数据
X = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
4. 运行梯度下降
现在,我们可以运行梯度下降算法来找到最优的参数。
iterations = 1000
w, b = gradient_descent(X, y, w, b, alpha, iterations)
# 打印最终的代价函数值
print("最终的代价函数值:", compute_cost(X, y, w, b))
5. 可视化结果
我们可以绘制数据点和拟合的直线来可视化结果。
import matplotlib.pyplot as plt
# 绘制数据点
plt.scatter(X, y, color='red', label='数据点')
# 绘制拟合的直线
plt.plot(X, w * X + b, label='拟合直线')
plt.legend()
plt.show()
梯度下降的变体
- 批量梯度下降(Batch Gradient Descent):每次更新参数时使用全部数据集。
- 随机梯度下降(Stochastic Gradient Descent, SGD):每次更新参数时只使用一个训练样本。
- 小批量梯度下降(Mini-batch Gradient Descent):每次更新参数时使用一个小批量的训练样本。
梯度下降算法陷阱
-
局部最小值点陷阱:在非凸函数中,梯度下降可能会陷入局部最小值点,而不是全局最小值点。这意味着算法可能会在一个区域内找到最小值,但这个最小值并不是整个搜索空间中的最小值。
-
鞍点陷阱:鞍点是指那些不是极值点但梯度为0的点。在鞍点处,梯度在一个方向上是极小值,在另一个方向上是极大值。梯度下降可能会在鞍点附近振荡,导致难以收敛。
-
梯度悬崖:在多层神经网络中,可能会遇到极度陡峭的区域,类似于悬崖。在这些区域,梯度变化很大,可能导致参数更新时“跳过”最优区域,从而无法收敛到最小值。
-
梯度消失和梯度爆炸:在深度神经网络中,梯度可能会随着网络层的增加而变得非常小(梯度消失)或者非常大(梯度爆炸),这会导致训练过程不稳定。
学习率
定义
学习率(通常表示为 α \alpha α)决定了在梯度下降中,我们沿着梯度方向(即最陡下降方向)更新参数时的步长。如果步长太大,可能会跳过最小值;如果步长太小,收敛会非常缓慢。
影响
- 太大的学习率:可能导致算法在最小值附近震荡,甚至发散,无法收敛。
- 太小的学习率:可能导致算法收敛速度非常慢,需要更多的迭代次数才能达到最小值。
选择学习率
1. 经验法则
- 初始猜测:通常从一个较小的学习率开始,如0.01或0.001,然后根据训练过程的表现进行调整。
2. 调参
- 网格搜索:尝试一系列不同的学习率值,通过交叉验证来找到最佳的学习率。
- 随机搜索:随机选择不同的学习率值进行尝试,这种方法通常比网格搜索更高效。
3. 学习率衰减
- 时间衰减:随着训练的进行,逐渐减小学习率。例如,每过一定的epoch数,学习率减半。
- 步长衰减:每经过一定的迭代次数,学习率减小一定的比例。
4. 性能衰减
- 早停法:当验证集上的性能不再提升时,减小学习率或停止训练。
5. 自适应学习率算法
- 使用自适应学习率算法:如AdaGrad、RMSProp、Adam等,这些算法可以根据参数的更新历史自动调整学习率。
6. 学习率范围测试
- 从大到小:从一个较大的学习率开始,逐渐减小,观察训练过程中代价函数的变化。如果代价函数在下降,说明学习率过大;如果代价函数在震荡或上升,说明学习率可能过小。
7. 可视化方法
- 损失曲线:绘制训练和验证损失随epoch变化的曲线,如果损失下降太快,可能需要减小学习率;如果下降太慢,可能需要增大学习率。
自适应学习率
自适应学习率算法是一类优化算法,它们能够根据参数更新的历史自动调整每个参数的学习率。这些算法特别适用于处理不同参数需要不同学习率的情况,以及在训练过程中动态调整学习率以加速收敛。
AdaGrad(Adaptive Gradient Algorithm)
原理:
AdaGrad通过累积所有梯度的平方来调整学习率。对于每个参数,AdaGrad会维护一个累积梯度平方和的变量,然后用这个变量的平方根的倒数来调整该参数的学习率。
优点:
- 自适应地调整每个参数的学习率,对于稀疏数据特别有效。
缺点:
- 累积梯度平方和可能会导致学习率过快减小,特别是当训练数据量大时。
公式:
r
t
=
r
t
−
1
+
g
t
⊙
g
t
\mathbf{r}_t = \mathbf{r}_{t-1} + \mathbf{g}_t \odot \mathbf{g}_t
rt=rt−1+gt⊙gt
w
t
+
1
=
w
t
−
η
r
t
+
ϵ
⊙
g
t
\mathbf{w}_{t+1} = \mathbf{w}_t - \frac{\eta}{\sqrt{\mathbf{r}_t + \epsilon}} \odot \mathbf{g}_t
wt+1=wt−rt+ϵη⊙gt
其中,
r
t
\mathbf{r}_t
rt 是累积梯度平方和,
g
t
\mathbf{g}_t
gt 是当前梯度,
η
\eta
η 是初始学习率,
ϵ
\epsilon
ϵ 是为了避免除以零的小常数,
⊙
\odot
⊙ 表示逐元素乘法。
RMSProp(Root Mean Square Propagation)
原理:
RMSProp通过计算梯度的指数衰减平均来调整学习率,解决了AdaGrad学习率过快减小的问题。它使用一个衰减率(通常表示为
ρ
\rho
ρ)来控制历史梯度的影响。
优点:
- 缓解了AdaGrad学习率过快减小的问题。
- 适用于非平稳目标和有噪声的梯度。
缺点:
- 需要调整额外的超参数(衰减率 ρ \rho ρ)。
公式:
s
t
=
ρ
s
t
−
1
+
(
1
−
ρ
)
g
t
⊙
g
t
\mathbf{s}_t = \rho \mathbf{s}_{t-1} + (1 - \rho) \mathbf{g}_t \odot \mathbf{g}_t
st=ρst−1+(1−ρ)gt⊙gt
w
t
+
1
=
w
t
−
η
s
t
+
ϵ
⊙
g
t
\mathbf{w}_{t+1} = \mathbf{w}_t - \frac{\eta}{\sqrt{\mathbf{s}_t + \epsilon}} \odot \mathbf{g}_t
wt+1=wt−st+ϵη⊙gt
其中,
s
t
\mathbf{s}_t
st 是梯度平方的指数衰减平均,
ρ
\rho
ρ 是衰减率。
Adam(Adaptive Moment Estimation)
原理:
Adam结合了RMSProp和动量(Momentum)的概念。它维护了梯度的一阶矩估计(类似于动量)和二阶矩估计(类似于RMSProp),并使用这两个估计值来调整学习率。
优点:
- 结合了动量和RMSProp的优点,通常具有较好的性能和稳定性。
- 自适应地调整每个参数的学习率。
缺点:
- 需要调整更多的超参数(初始学习率、衰减率、 ϵ \epsilon ϵ)。
公式:
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
\mathbf{m}_t = \beta_1 \mathbf{m}_{t-1} + (1 - \beta_1) \mathbf{g}_t
mt=β1mt−1+(1−β1)gt
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
⊙
g
t
\mathbf{v}_t = \beta_2 \mathbf{v}_{t-1} + (1 - \beta_2) \mathbf{g}_t \odot \mathbf{g}_t
vt=β2vt−1+(1−β2)gt⊙gt
m
^
t
=
m
t
1
−
β
1
t
\hat{\mathbf{m}}_t = \frac{\mathbf{m}_t}{1 - \beta_1^t}
m^t=1−β1tmt
v
^
t
=
v
t
1
−
β
2
t
\hat{\mathbf{v}}_t = \frac{\mathbf{v}_t}{1 - \beta_2^t}
v^t=1−β2tvt
w
t
+
1
=
w
t
−
η
m
^
t
v
^
t
+
ϵ
\mathbf{w}_{t+1} = \mathbf{w}_t - \eta \frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t + \epsilon}}
wt+1=wt−ηv^t+ϵm^t
其中, m t \mathbf{m}_t mt 是梯度的一阶矩估计, v t \mathbf{v}_t vt 是梯度的二阶矩估计, β 1 \beta_1 β1 和 β 2 \beta_2 β2 是衰减率, m ^ t \hat{\mathbf{m}}_t m^t 和 v ^ t \hat{\mathbf{v}}_t v^t 是偏差校正后的一阶和二阶矩估计。
实践中的考虑
- 批量大小:对于小批量梯度下降,通常需要更大的学习率。
- 问题规模:对于大规模问题,可能需要更小的学习率。
- 数据分布:如果数据分布不均匀,可能需要对不同特征使用不同的学习率。
线性回归的梯度下降
在线性回归中使用梯度下降是为了找到最小化代价函数(通常是均方误差)的参数(权重和偏置)。以下是用于线性回归的梯度下降算法的详细步骤:
1. 代价函数
对于线性回归,代价函数 J ( w , b ) J(w, b) J(w,b) 通常是均方误差:
J ( w , b ) = 1 2 m ∑ i = 1 m ( h w ( x ( i ) ) − y ( i ) ) 2 J(w, b) = \frac{1}{2m} \sum_{i=1}^{m} (h_w(x^{(i)}) - y^{(i)})^2 J(w,b)=2m1∑i=1m(hw(x(i))−y(i))2
其中:
- m m m 是训练样本的数量。
- h w ( x ( i ) ) = w ⋅ x ( i ) + b h_w(x^{(i)}) = w \cdot x^{(i)} + b hw(x(i))=w⋅x(i)+b 是模型的预测值。
- y ( i ) y^{(i)} y(i) 是实际值。
2. 梯度计算
为了进行梯度下降,我们需要计算代价函数相对于参数 w w w 和 b b b 的梯度。
∂ J ∂ w = 1 m ∑ i = 1 m ( w ⋅ x ( i ) + b − y ( i ) ) ⋅ x ( i ) \frac{\partial J}{\partial w} = \frac{1}{m} \sum_{i=1}^{m} (w \cdot x^{(i)} + b - y^{(i)}) \cdot x^{(i)} ∂w∂J=m1∑i=1m(w⋅x(i)+b−y(i))⋅x(i)
∂ J ∂ b = 1 m ∑ i = 1 m ( w ⋅ x ( i ) + b − y ( i ) ) \frac{\partial J}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} (w \cdot x^{(i)} + b - y^{(i)}) ∂b∂J=m1∑i=1m(w⋅x(i)+b−y(i))
3. 参数更新
使用计算出的梯度来更新参数 w w w 和 b b b:
w : = w − α ∂ J ∂ w w := w - \alpha \frac{\partial J}{\partial w} w:=w−α∂w∂J
b : = b − α ∂ J ∂ b b := b - \alpha \frac{\partial J}{\partial b} b:=b−α∂b∂J
其中 α \alpha α 是学习率。
4. 梯度下降算法
将上述步骤整合到一个循环中,直到满足停止条件(例如,达到最大迭代次数或梯度足够小):
import numpy as np
# 初始化参数
w = np.random.randn()
b = np.random.randn()
# 设置学习率和迭代次数
alpha = 0.01
iterations = 1000
# 训练数据
X = np.array([1, 2, 3, 4, 5]).reshape(-1, 1) # 特征值
y = np.array([2, 4, 6, 8, 10]) # 实际结果
# 梯度下降
for i in range(iterations):
# 预测值
predictions = X.dot(w) + b
# 计算梯度
dw = (1 / len(X)) * np.sum((X * (predictions - y)))
db = (1 / len(X)) * np.sum(predictions - y)
# 更新参数
w -= alpha * dw
b -= alpha * db
# 输出最终参数
print(f"学习后的 w: {w}, b: {b}")
多维特征
多维特征,也称为多变量特征或高维特征,指的是在数据分析和机器学习任务中,每个数据点由多个特征(变量、属性或维度)描述的情况。
特征向量
每个数据点可以表示为一个特征向量,其中包含多个特征值。例如,一个数据点可以由其长度、宽度、高度和重量等特征描述。
数据表示
在多维特征空间中,数据可以被表示为一个矩阵,其中每一行代表一个数据点,每一列代表一个特征。
特征选择
在多维特征中,特征选择(Feature Selection)是一个重要步骤,它涉及从现有特征中选择最相关的子集以提高模型的性能。
特征工程
特征工程(Feature Engineering)是创建新特征或修改现有特征以提高模型性能的过程。在多维特征中,这可能涉及特征组合、多项式特征、交互特征等。
维度诅咒
随着特征维度的增加,数据点之间的距离趋向于变得相似,这可能导致模型性能下降,这种现象称为维度诅咒。
特征缩放
在多维特征空间中,特征缩放(Feature Scaling)变得尤为重要,因为它可以防止某些特征由于数值范围大而在模型训练中占主导地位。
降维
降维(Dimensionality Reduction)是减少数据集中特征数量的过程,它可以提高计算效率并减少过拟合的风险。常见的降维技术包括主成分分析(PCA)、线性判别分析(LDA)和t-SNE。
向量化
向量化是一种编程技术,它允许我们以更高效、更简洁的方式执行数组或矩阵上的操作。以下是向量化的详细教学,包括其基本原理、优势、实践应用以及在机器学习领域的深度实践。
1. 向量化的基本原理
向量化技术涉及将数据操作从标量级别提升到向量级别,利用现代计算机架构的并行处理能力,大幅提升机器学习模型的训练和推理效率。
通过向量化操作,多个标量操作可以合并成一个单一的向量操作,减少内存访问次数、提高缓存命中率,并充分利用多核处理器的并行计算能力。
2. 向量化的优势
- 提高计算效率:向量化操作可以显著提高数据处理和机器学习模型训练的效率,因为它减少了循环的使用,使得代码更接近于数学表达式,从而利用库的优化实现来加速计算过程。
- 简化代码:向量化代码通常更短,减少了编程错误的机会,并且更易于理解和维护。
- 促进数据交互:向量化技术使得不同类型的数据可以更容易地在不同的模型和任务之间共享和迁移知识。
3. 实现向量化的实践应用
3.1 常规计算的向量化
在MATLAB中,可以通过向量化代码来提高计算效率。例如,计算一系列值的正弦函数,非向量化的方法需要使用循环,而向量化的方法可以直接应用矩阵运算,大大简化了代码。
t = 0:.01:10;
y = sin(t);
3.2 机器学习中的向量化
在机器学习中,向量化技术可以应用于矩阵运算和数据处理。例如,在训练神经网络模型时,向量化技术可以将矩阵乘法和反向传播算法中的梯度计算并行化,从而显著提升训练速度。
import numpy as np
# 假设我们有一些数据
X = np.array([1, 2, 3, 4, 5]).reshape(-1, 1) # 特征值
y = np.array([2, 4, 6, 8, 10]) # 实际结果
# 向量化的参数更新
w = np.random.randn()
b = np.random.randn()
alpha = 0.01
# 预测值
predictions = X.dot(w) + b
errors = predictions - y
dw = (1 / len(X)) * np.sum(errors * X)
db = (1 / len(X)) * np.sum(errors)
# 更新参数
w -= alpha * dw
b -= alpha * db
4. 向量化技术在机器学习领域的深度实践
- 文本分类:通过将文本数据向量化,可以用于文档相似性分析、智能问答系统、文本分类等任务。
- 图像识别:通过图像特征向量进行相似度计算,可以快速找到与查询图像相似的图片或视频,支持基于内容的图像检索(CBIR)系统。
- 推荐系统:通过用户和物品的特征向量计算相似度,实现个性化推荐。
使用梯度下降算法进行多元线性回归
1. 定义模型
多元线性回归模型可以表示为:
y
=
β
0
+
β
1
x
1
+
β
2
x
2
+
…
+
β
n
x
n
+
ϵ
y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \ldots + \beta_n x_n + \epsilon
y=β0+β1x1+β2x2+…+βnxn+ϵ
其中,
y
y
y 是因变量,
x
1
,
x
2
,
…
,
x
n
x_1, x_2, \ldots, x_n
x1,x2,…,xn 是自变量,
β
0
\beta_0
β0 是截距项,
β
1
,
β
2
,
…
,
β
n
\beta_1, \beta_2, \ldots, \beta_n
β1,β2,…,βn 是回归系数,
ϵ
\epsilon
ϵ 是误差项。
2. 成本函数
通常使用均方误差(MSE)作为成本函数:
J
(
β
)
=
1
m
∑
i
=
1
m
(
h
β
(
x
(
i
)
)
−
y
(
i
)
)
2
J(\beta) = \frac{1}{m} \sum_{i=1}^{m} (h_\beta(x^{(i)}) - y^{(i)})^2
J(β)=m1i=1∑m(hβ(x(i))−y(i))2
其中,
m
m
m 是样本数量,
h
β
(
x
(
i
)
)
h_\beta(x^{(i)})
hβ(x(i)) 是模型的预测值。
3. 梯度计算
对于每个参数
β
j
\beta_j
βj, 梯度的计算为:
∂
J
(
β
)
∂
β
j
=
2
m
∑
i
=
1
m
(
h
β
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
\frac{\partial J(\beta)}{\partial \beta_j} = \frac{2}{m} \sum_{i=1}^{m} (h_\beta(x^{(i)}) - y^{(i)}) x_j^{(i)}
∂βj∂J(β)=m2i=1∑m(hβ(x(i))−y(i))xj(i)
4. 更新参数
使用学习率
α
\alpha
α 更新参数:
β
j
:
=
β
j
−
α
∂
J
(
β
)
∂
β
j
\beta_j := \beta_j - \alpha \frac{\partial J(\beta)}{\partial \beta_j}
βj:=βj−α∂βj∂J(β)
5. 循环迭代
重复执行梯度计算和参数更新,直到满足停止条件(如,损失函数的变化小于某个阈值或达到最大迭代次数)。
代码示例
import numpy as np
# 生成一些示例数据
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]]) # 自变量 (包含常数项)
y = np.array([1, 2, 2, 3]) # 因变量
# 初始化参数
m, n = X.shape
beta = np.zeros(n) # 初始化参数为0
alpha = 0.01 # 学习率
iterations = 1000 # 迭代次数
# 梯度下降
for _ in range(iterations):
predictions = X.dot(beta)
errors = predictions - y
gradients = (2/m) * X.T.dot(errors)
beta -= alpha * gradients
print("Learned parameters:", beta)
特征放缩
特征缩放是机器学习中的一个重要预处理步骤,它涉及将数据集中的特征值缩放到一个特定的范围,以提高模型的性能和预测能力。
1. 定义
特征缩放(Feature Scaling)是将输入特征缩放到一个共同的范围,例如0到1之间,以避免特征量级上的巨大差异。
2. 目的
- 防止特征主导模型:当特征的量纲差异很大时,某些特征可能会主导模型,从而影响模型的性能。
- 加速优化算法:某些优化算法(如梯度下降)在处理特征缩放的数据时可以更快地收敛。
3. 常用方法
-
最小-最大缩放(Min-Max Scaling):将特征缩放到指定最小值和最大值之间(通常是0到1)。公式为:
x ′ = x − min ( x ) max ( x ) − min ( x ) x' = \frac{x - \min(x)}{\max(x) - \min(x)} x′=max(x)−min(x)x−min(x) -
标准化(Standardization):将特征转换为均值为0、标准差为1的正态分布。公式为:
z = x − μ σ z = \frac{x - \mu}{\sigma} z=σx−μ
其中, μ \mu μ 是均值, σ \sigma σ 是标准差。 -
最大绝对标准化(MaxAbs Scaling):将特征缩放到[-1, 1]范围,特别适用于稀疏数据。公式为:
x ′ = x max ( ∣ x ∣ ) x' = \frac{x}{\max(|x|)} x′=max(∣x∣)x -
Robust Scaling:使用中位数和四分位间距进行缩放,适合存在离群值的数据。公式为:
x ′ = x − median ( x ) IQR ( x ) x' = \frac{x - \text{median}(x)}{\text{IQR}(x)} x′=IQR(x)x−median(x)
其中, IQR ( x ) \text{IQR}(x) IQR(x) 是四分位间距。
4. 实际应用
- 在数据预处理中,特征缩放可以使模型训练更加高效,尤其是在深度学习中,对于加速训练过程、减少梯度消失或梯度爆炸现象具有重要意义。
5. 与正则化的关系
- 特征缩放和正则化在机器学习中都起到重要作用,但它们的目的不同。特征缩放确保特征在相同尺度上,而正则化旨在防止模型过拟合。
6. 是否所有机器学习算法都需要特征缩放
- 并不是所有算法都需要特征缩放,例如,决策树算法对特征的量级不敏感,因此不需要特征缩放。
7. 缩放后特征的单位和物理意义
- 缩放后特征的单位和物理意义会发生变化。Min-Max Scaling将特征缩放到一个特定的范围 (如0到1),而标准化则使得生成的特征在均值为0和标准差为1的分布中。
8. 如何在Pipeline中实现特征缩放
- 使用机器学习Pipeline时可以通过
sklearn.preprocessing
中的StandardScaler
或MinMaxScaler
来实现特征缩放,确保它与模型训练过程的一致性。
代码示例
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 示例数据
data = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
# 标准化
standard_scaler = StandardScaler()
data_standardized = standard_scaler.fit_transform(data)
print("Standardized Data:\n", data_standardized)
# 归一化
minmax_scaler = MinMaxScaler()
data_normalized = minmax_scaler.fit_transform(data)
print("Normalized Data:\n", data_normalized)
判断梯度下降是否收敛
在机器学习中,梯度下降算法是一种常用的优化方法,用于最小化目标函数。判断梯度下降是否收敛是实现有效模型训练的重要环节,通常可以通过以下几种方式:
1. 梯度值的大小
如果目标函数的梯度(即导数)接近于零,通常可以认为算法已经收敛。这是因为在最小值点,函数的梯度为零。
2. 损失函数的变化
观察损失函数值的变化。如果损失函数值的变化非常小,或者在一定数量的迭代后不再显著变化,这通常意味着算法已经收敛。可以用以下公式来判断:
∣
J
(
β
(
t
)
)
−
J
(
β
(
t
−
1
)
)
∣
<
ϵ
|J(\beta^{(t)}) - J(\beta^{(t-1)})| < \epsilon
∣J(β(t))−J(β(t−1))∣<ϵ
其中,
J
(
β
(
t
)
)
J(\beta^{(t)})
J(β(t)) 是第
t
t
t 次迭代的损失值。
3. 迭代次数
设置一个最大迭代次数。如果达到这个迭代次数,即使算法没有完全收敛,也会停止迭代,以避免无限循环。
4. 容忍度(Tolerance)
设置一个容忍度阈值,当连续几次迭代的损失函数值变化小于这个阈值时,可以认为算法已经收敛。
5. 梯度的范数
计算梯度向量的范数(如L2范数)。如果梯度的范数小于某个预设的阈值,可以认为算法已经收敛:
∣
∣
∇
J
(
β
)
∣
∣
<
ϵ
||\nabla J(\beta)|| < \epsilon
∣∣∇J(β)∣∣<ϵ
6. 参数更新的变化
观察每次迭代中参数的更新量。如果参数的更新量非常小,这可能意味着算法已经接近收敛。
7. 可视化
通过绘制损失函数值随迭代次数变化的曲线图,可以直观地观察算法是否收敛。
8. 使用二阶导数(Hessian矩阵)
对于二次可微的目标函数,可以计算Hessian矩阵的正定性来判断。如果Hessian矩阵是正定的,当前点可能是局部最小值,梯度下降算法可以认为已经收敛。
9. 线搜索
在每次迭代中使用线搜索方法来确定步长。如果步长非常小,这可能意味着算法已经接近收敛。
10. 早停法(Early Stopping)
在训练过程中,如果验证集上的性能在连续多个epoch后没有改善,可以提前停止训练,这也是一种判断收敛的方法。
示例代码
import numpy as np
# 成本函数
def cost_function(X, y, beta):
m = len(y)
return (1/(2*m)) * np.sum((X.dot(beta) - y) ** 2)
# 梯度下降
def gradient_descent(X, y, alpha, max_iterations, epsilon):
m, n = X.shape
beta = np.zeros(n)
previous_cost = float('inf')
for iteration in range(max_iterations):
predictions = X.dot(beta)
errors = predictions - y
gradients = (1/m) * X.T.dot(errors)
beta -= alpha * gradients
# 当前损失
current_cost = cost_function(X, y, beta)
# 判断收敛
if np.abs(previous_cost - current_cost) < epsilon or np.linalg.norm(gradients) < epsilon:
print(f"收敛于迭代次数: {iteration}")
break
previous_cost = current_cost
return beta
# 示例数据
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
y = np.array([1, 2, 2, 3])
alpha = 0.01
max_iterations = 1000
epsilon = 1e-6
# 运行梯度下降
beta = gradient_descent(X, y, alpha, max_iterations, epsilon)
print("学习到的参数:", beta)
多项式回归
多项式回归是一种扩展线性回归的方法,通过将输入特征进行多项式变换,以捕捉特征之间的非线性关系。
1. 定义
多项式回归是一种回归技术,其形式为输入变量的多项式组合,用于建立因变量与自变量之间的关系。例如,二次回归模型可以表示为:
y
=
β
0
+
β
1
x
+
β
2
x
2
+
ϵ
y = \beta_0 + \beta_1 x + \beta_2 x^2 + \epsilon
y=β0+β1x+β2x2+ϵ
其中,
y
y
y 是因变量,
x
x
x 是自变量,
β
0
\beta_0
β0、
β
1
\beta_1
β1、
β
2
\beta_2
β2 是模型参数,
ϵ
\epsilon
ϵ 是误差项。
2. 模型形式
多项式回归的目标是寻找最佳拟合的多项式函数,其通用形式为:
y
=
β
0
+
β
1
x
+
β
2
x
2
+
…
+
β
n
x
n
+
ϵ
y = \beta_0 + \beta_1 x + \beta_2 x^2 + \ldots + \beta_n x^n + \epsilon
y=β0+β1x+β2x2+…+βnxn+ϵ
其中,
n
n
n 是多项式的阶数。
3. 目的
- 捕捉非线性关系:多项式回归能够有效捕捉输入变量与目标变量之间的非线性关系。
- 提高模型拟合能力:通过增加多项式的阶数,可以提高模型对复杂模式的拟合能力,但也要防止过拟合。
4. 实际应用
- 在实际应用中,多项式回归常用于曲线拟合,比如预测非线性趋势的数据集,或者在需要理解变量之间复杂关系的情况下使用。
5. 优缺点
-
优点:
- 能够捕捉复杂的非线性关系。
- 比简单线性回归更灵活。
-
缺点:
- 可能导致过拟合,尤其是在高阶多项式的情况下。
- 高阶多项式模型的解释性较差。
6. 特征缩放
特征缩放在多项式回归中尤为重要,尤其是高阶多项式可能导致数值范围的巨大差异。常用的特征缩放方法包括标准化和归一化,以加速模型训练和提高数值稳定性。
7. 如何实现多项式回归
在 Python 中,使用 Scikit-Learn 库可以方便地实现多项式回归。首先,需要将特征转换为多项式形式,然后使用线性回归模型进行训练。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
# 创建示例数据
X = np.array([[1], [2], [3], [4], [5]])
y = np.array([1, 4, 9, 16, 25]) # y = x^2
# 将特征转换为多项式特征
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
# 训练线性回归模型
model = LinearRegression()
model.fit(X_poly, y)
# 进行预测
y_pred = model.predict(X_poly)
# 可视化结果
plt.scatter(X, y, color='red', label='Actual data')
plt.plot(X, y_pred, color='blue', label='Polynomial regression model')
plt.title('Polynomial Regression Example')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()
# 输出模型参数
print(f"模型参数: {model.intercept_}, {model.coef_[1:]}")
逻辑回归
逻辑回归(Logistic Regression)是一种广泛应用于分类问题的统计模型。尽管其名称中包含“回归”,但逻辑回归实际上是一种分类算法,特别适合处理二分类问题(例如,响应变量为0或1)。
1. 基本概念
逻辑回归用于预测二元结果,通常使用sigmoid(逻辑)函数将线性组合的输入特征映射到0和1之间的概率值。其形式为:
P
(
Y
=
1
∣
X
)
=
σ
(
Z
)
=
1
1
+
e
−
Z
P(Y=1 | X) = \sigma(Z) = \frac{1}{1 + e^{-Z}}
P(Y=1∣X)=σ(Z)=1+e−Z1
这里,
- Z = β 0 + β 1 x 1 + β 2 x 2 + … + β n x n Z = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \ldots + \beta_n x_n Z=β0+β1x1+β2x2+…+βnxn,表示线性组合;
- σ ( Z ) \sigma(Z) σ(Z) 是sigmoid函数。
2. 模型输出
逻辑回归将输出理解为某个类别的概率,通常通过阈值(如0.5)决定最终的分类:
- 如果 P ( Y = 1 ∣ X ) ≥ 0.5 P(Y=1 | X) \geq 0.5 P(Y=1∣X)≥0.5,则预测结果为1;
- 如果 P ( Y = 1 ∣ X ) < 0.5 P(Y=1 | X) < 0.5 P(Y=1∣X)<0.5,则预测结果为0。
3. 训练逻辑回归
3.1 成本函数
逻辑回归使用交叉熵损失(或对数损失)作为成本函数来评估模型的预测效果。公式为:
J
(
β
)
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
log
(
h
β
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
β
(
x
(
i
)
)
)
]
J(\beta) = -\frac{1}{m} \sum_{i=1}^{m} [y^{(i)} \log(h_{\beta}(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_{\beta}(x^{(i)}))]
J(β)=−m1i=1∑m[y(i)log(hβ(x(i)))+(1−y(i))log(1−hβ(x(i)))]
其中:
- h β ( x ( i ) ) = σ ( Z ) h_{\beta}(x^{(i)}) = \sigma(Z) hβ(x(i))=σ(Z) 是模型的预测值;
- y ( i ) y^{(i)} y(i) 是实际标签。
3.2 优化方法
逻辑回归通常使用梯度下降法或其变体(例如随机梯度下降)来最小化成本函数,更新参数:
β
j
:
=
β
j
−
α
∂
J
(
β
)
∂
β
j
\beta_j := \beta_j - \alpha \frac{\partial J(\beta)}{\partial \beta_j}
βj:=βj−α∂βj∂J(β)
4. 示例代码
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score, classification_report
# 加载示例数据集
data = load_iris()
X, y = data.data, data.target
# 只使用前两类来进行二分类
X = X[y != 2]
y = y[y != 2]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 初始化并训练逻辑回归模型
model = LogisticRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率: {accuracy:.2f}")
print("分类报告:\n", classification_report(y_test, y_pred))
5. 应用场景
逻辑回归广泛应用于多个领域,如:
- 医学:预测患者是否患病。
- 金融:信用风险评估。
- 市场营销:客户是否会购买某产品。
- 社交媒体:用户行为预测。
6. 优缺点
优点:
- 简单且易于实现。
- 结果易于解释。
- 适合线性可分的数据。
缺点:
- 假设特征与目标变量之间存在线性关系。
- 不适合复杂关系的数据。
- 对于特征间的多重共线性敏感。
决策边界
决策边界是在机器学习和统计分类中用于区分不同类别的边界。它是一个重要的概念,尤其是在分类任务中,因为它影响模型的分类性能。
1. 定义
决策边界是一个函数,用于划分输入特征空间中的不同类别。假设我们有一个二分类问题,决策边界将特征空间分成两个区域,每个区域对应于一个类别。
2. 决策边界的形式
- 线性决策边界:例如,支持向量机和线性回归的线性模型可以生成线性决策边界,通常表示为 $w^T x + b = 0 $,其中 w w w 是权重向量, x x x 是输入特征, b b b 是偏置。
- 非线性决策边界:例如,使用决策树、支持向量机(使用非线性核)、神经网络等模型时,可以生成复杂的非线性决策边界。
3. 决策边界的可视化
在二维特征空间中,决策边界可以用图形直观地表示出来。通过绘制各类样本点和决策边界,可以清晰地看到模型如何划分特征空间。
4. 应用场景
- 分类任务:在分类模型中,决策边界用来决定输入数据的类别。
- 模型评估:通过分析决策边界的形状和位置,可以了解模型的性能,并发现潜在的改进方向(例如,过拟合或欠拟合)。
5. 决策边界的例子
- 线性分类器(如逻辑回归)在特征空间中生成一条直线(或超平面),将类分开。对于二维数据集,决策边界是一条直线,对于三维数据集,是一个平面。
- 非线性分类器(如核支持向量机或神经网络)能够生成弯曲或复杂的边界,以更好地适应数据的分布。
代码示例:可视化决策边界
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
# 生成样本数据
X, y = make_moons(n_samples=100, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 使用支持向量机进行训练
model = SVC(kernel='rbf')
model.fit(X_train, y_train)
# 可视化决策边界
def plot_decision_boundary(model, X, y):
# 创建网格以评估模型
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np.linspace(y_min, y_max, 100))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 绘制决策边界和数据点
plt.contourf(xx, yy, Z, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', marker='o')
plt.title("决策边界")
plt.xlabel("特征1")
plt.ylabel("特征2")
plt.show()
plot_decision_boundary(model, X_train, y_train)
逻辑回归中的代价函数
逻辑回归是一种用于分类任务的统计模型,通常用于二元分类问题。在逻辑回归中,我们使用的是 sigmoid 函数来预测某一类的概率。代价函数(Cost Function)用于评估模型的预测效果,并指导模型的训练过程。
1. Sigmoid 函数
逻辑回归中的 Sigmoid 函数定义为:
h
θ
(
x
)
=
1
1
+
e
−
θ
T
x
h_\theta(x) = \frac{1}{1 + e^{-\theta^T x}}
hθ(x)=1+e−θTx1
其中,$h_\theta(x) $ 是给定输入 $x $ 的预测概率,$\theta $ 是模型参数。
2. 代价函数
在逻辑回归中,我们使用的是对数损失(Log Loss)或称为交叉熵代价函数(Cross-Entropy Cost Function)。代价函数的主要目的是量化模型预测值与实际标签之间的差异。对于一个数据集包含 $m $ 个样本,代价函数定义为:
J ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) log ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) log ( 1 − h θ ( x ( i ) ) ) ] J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log(h_\theta(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right] J(θ)=−m1i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
其中:
- $y^{(i)} $ 是样本 $i $ 的真实标签(0 或 1)。
- $h_\theta(x^{(i)}) $ 是模型输出的预测概率。
3. 代价函数的推导
代价函数的推导基于最大似然估计。假设每个样本的标签是独立的,我们希望最大化所有样本标签的似然函数:
L
(
θ
)
=
∏
i
=
1
m
h
θ
(
x
(
i
)
)
y
(
i
)
(
1
−
h
θ
(
x
(
i
)
)
)
(
1
−
y
(
i
)
)
L(\theta) = \prod_{i=1}^{m} h_\theta(x^{(i)})^{y^{(i)}} (1 - h_\theta(x^{(i)}))^{(1 - y^{(i)})}
L(θ)=i=1∏mhθ(x(i))y(i)(1−hθ(x(i)))(1−y(i))
然后取对数,得到对数似然函数:
log
L
(
θ
)
=
∑
i
=
1
m
[
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
\log L(\theta) = \sum_{i=1}^{m} \left[ y^{(i)} \log(h_\theta(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right]
logL(θ)=i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
为了最大化对数似然函数,我们通常最小化负对数似然函数,即代价函数 $J(\theta) $。
4. 代价函数的性质
- 非负性:代价函数的值总是非负的($J(\theta) \geq 0 $)。
- 最小化目标:代价函数值越小,模型的预测效果越好。
- 连续可导:代价函数是连续可导的,这使得我们可以使用梯度下降等优化算法进行参数更新。
5. 代码示例
import numpy as np
# Sigmoid函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 代价函数
def compute_cost(X, y, theta):
m = len(y)
h = sigmoid(X @ theta) # X @ theta 是矩阵乘法
cost = - (1/m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
return cost
# 示例数据
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]]) # 特征矩阵(加入常数1的偏置项)
y = np.array([0, 0, 1, 1]) # 标签
theta = np.array([0.5, -0.5]) # 假设的参数
# 计算代价
cost = compute_cost(X, y, theta)
print("代价函数的值:", cost)
简化逻辑回归代价函数
1. 逻辑回归模型
首先,逻辑回归模型的预测函数为:
h
θ
(
x
)
=
σ
(
θ
T
x
)
=
1
1
+
e
−
θ
T
x
h_\theta(x) = \sigma(\theta^T x) = \frac{1}{1 + e^{-\theta^T x}}
hθ(x)=σ(θTx)=1+e−θTx1
这里,
σ
(
z
)
\sigma(z)
σ(z) 是sigmoid函数。结果
h
θ
(
x
)
h_\theta(x)
hθ(x) 表示样本
x
x
x 属于正类的概率。
2. 代价函数定义
对于二分类问题,逻辑回归的代价函数
J
(
θ
)
J(\theta)
J(θ) 定义为:
J
(
θ
)
=
−
1
m
∑
i
=
1
m
(
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
)
J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} \left( y^{(i)} \log(h_\theta(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right)
J(θ)=−m1i=1∑m(y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i))))
其中:
- m m m 是样本的总数。
- y ( i ) y^{(i)} y(i) 是样本 i i i 的真实标签(0或1)。
- h θ ( x ( i ) ) h_\theta(x^{(i)}) hθ(x(i)) 是对样本 i i i 的预测概率。
3. 代价函数的逻辑
- 对于正类( y ( i ) = 1 y^{(i)} = 1 y(i)=1),代价为 − log ( h θ ( x ( i ) ) ) -\log(h_\theta(x^{(i)})) −log(hθ(x(i)))。当模型预测的概率接近1时,代价接近0;当概率接近0时,代价趋向于无穷大。
- 对于负类( y ( i ) = 0 y^{(i)} = 0 y(i)=0),代价为 − log ( 1 − h θ ( x ( i ) ) ) -\log(1 - h_\theta(x^{(i)})) −log(1−hθ(x(i)))。同样,当预测的概率接近0时,代价接近0;当概率接近1时,代价趋向于无穷大。
4. 优化代价函数
逻辑回归的目标是选择参数 θ \theta θ 以最小化代价函数 J ( θ ) J(\theta) J(θ)。通常使用梯度下降算法来实现这一目标。
代价函数简化
通过将正类和负类的代价合并,可以得到简化后的形式:
J
(
θ
)
=
−
1
m
∑
i
=
1
m
(
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
)
J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} \left( y^{(i)} \log(h_\theta(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right)
J(θ)=−m1i=1∑m(y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i))))
这一形式直观地展示了模型对每个样本的预测与真实标签之间的关系,是逻辑回归模型的核心。通过最小化这个代价函数,我们能够得到最优的模型参数 θ \theta θ。
示例代码
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def cost_function(X, y, theta):
m = len(y)
h = sigmoid(X.dot(theta)) # 预测值
# 代价函数
J = (-1/m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
return J
# 示例数据
X = np.array([[1, 2], [1, 3], [1, 4], [1, 5]]) # 特征矩阵,包含偏置项
y = np.array([0, 0, 1, 1]) # 标签
theta = np.array([0.5, 0.5]) # 初始化参数
# 计算代价
cost = cost_function(X, y, theta)
print("代价函数值:", cost)
实现梯度下降
实现梯度下降算法的基本流程可以分为几个步骤:初始化参数、计算损失值及梯度、更新参数,并重复这一过程直到满足停止条件。
示例:线性回归的梯度下降实现
1. 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
2. 生成示例数据
# 生成线性数据 y = 2x + 1 加上一些噪声
np.random.seed(42) # 为了结果可重复
X = 2 * np.random.rand(100, 1) # 100个样本,特征范围在[0, 2]
y = 4 + 3 * X + np.random.randn(100, 1) # 线性关系加噪声
3. 定义成本函数
def cost_function(X, y, beta):
m = len(y) # 样本数量
return (1/(2*m)) * np.sum((X.dot(beta) - y) ** 2) # 均方损失
4. 实现梯度下降
def gradient_descent(X, y, alpha, max_iterations, epsilon):
m, n = X.shape # m: 样本数量, n: 特征数量
beta = np.zeros((n, 1)) # 初始化参数为0
previous_cost = float('inf') # 用于存储上一个成本值
for iteration in range(max_iterations):
predictions = X.dot(beta) # 用当前参数预测
errors = predictions - y # 计算误差
gradients = (1/m) * X.T.dot(errors) # 计算梯度
beta -= alpha * gradients # 更新参数
# 当前损失
current_cost = cost_function(X, y, beta)
# 判断收敛
if np.abs(previous_cost - current_cost) < epsilon:
print(f"收敛于迭代次数: {iteration}")
break
previous_cost = current_cost # 更新上一个成本值
return beta
5. 执行梯度下降
# 在输入数据上添加一列常数项,用于截距
X_b = np.c_[np.ones((X.shape[0], 1)), X] # 在X前加一个1,形成X的扩展 (m, n) -> (m, n+1)
alpha = 0.1 # 学习率
max_iterations = 1000 # 最大迭代次数
epsilon = 1e-6 # 收敛阈值
# 运行梯度下降
beta = gradient_descent(X_b, y, alpha, max_iterations, epsilon)
print("学习到的参数:", beta)
6. 绘制结果
# 绘制最终回归线
plt.scatter(X, y, color='blue', label='数据点')
plt.plot(X, X_b.dot(beta), color='red', label='回归线')
plt.xlabel('X')
plt.ylabel('y')
plt.title('线性回归与梯度下降')
plt.legend()
plt.show()
代码总结
这个示例展示了如何使用梯度下降法来拟合线性回归模型。在代码中:
- 我们使用随机生成的数据模拟线性关系。
- 通过
cost_function
计算损失,通过gradient_descent
更新模型参数。 - 最后绘制出数据点与拟合的回归线。
过拟合问题
过拟合是机器学习中一个常见的现象,指的是模型在训练数据上表现良好,但在测试数据或验证集上表现不佳的情况。这表示模型过于复杂,以至于捕捉到了训练数据中的噪声或随机波动,而不是学习到数据的真实模式。
1. 过拟合的原因
- 模型复杂度过高:当模型的参数数量过多时,模型可能会学习到训练数据中不重要的细节和噪音。
- 训练数据不足:当可用的训练数据集较小,模型将更容易过拟合训练数据。
- 特征数量过多:如果特征数量远大于样本数量,模型可能会过拟合训练数据。
- 数据噪声:训练数据中存在的噪声或异常值也可能导致模型学习到错误的模式。
2. 过拟合的影响
- 模型在训练数据上的精度非常高,但在新的、未见过的数据上表现不佳。
- 可能导致模型生成不稳定的预测,从而影响实际应用的可靠性。
3. 判断过拟合的方法
- 训练与测试集表现对比:通过比较模型在训练集和测试集上的性能(如准确率、F1分数等)来判断。如果在训练集上的性能显著高于测试集,可能存在过拟合。
- 学习曲线:绘制训练集和验证集的学习曲线,查看两个曲线在训练过程中是如何变化的。如果训练集表现持续上升而验证集表现趋于平稳或下降,很可能面对过拟合。
4. 解决过拟合的方法
-
使用更多的数据:增加训练样本的数量,可以通过收集更多数据,或采用数据增强技术(例如旋转、翻转图片等)来增加样本。
-
简化模型:
- 使用更简单的模型,降低模型的复杂度,例如选择较少的特征或使用较少的层和神经元(如果是深度学习模型)。
-
正则化:在损失函数中加入惩罚项,通过正则化技术(如L1和L2正则化)来抑制模型参数的过度学习。
- L1正则化(Lasso):增加模型的稀疏性,通过对权重的绝对值求和施加惩罚。
- L2正则化(Ridge):增加权重平方和的惩罚,抑制权重的大小。
-
使用 dropout:特别在深度学习中,dropout是一种常用的技术,在训练过程中随机地将部分神经元的输出置为零,以防止过拟合。
-
早停法(Early Stopping):在验证集性能不再提升时提前停止训练,防止模型在训练集上训练过度。
-
交叉验证:通过k折交叉验证等方法,评估模型的稳定性和泛化能力,以发现潜在的过拟合问题。
-
集成学习:采用Bagging(如随机森林)或Boosting(如AdaBoost、XGBoost)等集成学习方法,将多个模型组合,提高模型的泛化能力。
5. 示例代码
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error
# 加载数据
data = load_boston()
X, y = data.data, data.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用L2正则化的岭回归
ridge_model = Ridge(alpha=1.0)
ridge_model.fit(X_train, y_train)
# 预测
y_pred = ridge_model.predict(X_test)
# 评估模型
mse = mean_squared_error(y_test, y_pred)
print(f"测试集均方误差: {mse:.2f}")
正则化
正则化是机器学习中过拟合问题的常见解决方案,通过在损失函数中加入额外的约束来减少模型的复杂性。
1. 定义
正则化是一种技术,通过引入对模型参数的惩罚项(也称为正则项),来控制模型的复杂性,从而避免过拟合。过拟合是指模型在训练数据上表现良好,但在未见数据上表现不佳。
2. 常用正则化方法
A. L1 正则化(Lasso 回归)
L1 正则化通过添加参数绝对值的和作为惩罚项,对模型参数施加限制。其损失函数形式为:
J
(
θ
)
=
MSE
+
λ
∑
j
=
1
n
∣
θ
j
∣
J(\theta) = \text{MSE} + \lambda \sum_{j=1}^{n} |\theta_j|
J(θ)=MSE+λj=1∑n∣θj∣
其中:
- MSE \text{MSE} MSE 是均方误差(Mean Squared Error)。
- λ \lambda λ 是正则化强度的超参数(控制惩罚的大小)。
- θ j \theta_j θj 是模型参数。
特点:
- L1 正则化可以导致一些参数变为零,从而实现特征选择,具有简化模型的效果。
B. L2 正则化(Ridge 回归)
L2 正则化通过添加参数平方和的惩罚项,约束模型的复杂度。其损失函数为:
J
(
θ
)
=
MSE
+
λ
∑
j
=
1
n
θ
j
2
J(\theta) = \text{MSE} + \lambda \sum_{j=1}^{n} \theta_j^2
J(θ)=MSE+λj=1∑nθj2
特点:
- L2 正则化不会将参数压缩为零,而是使它们的绝对值保持较小,从而降低模型的复杂性,没有特征选择的效果。
C. Elastic Net
Elastic Net 是 L1 和 L2 正则化的结合,损失函数为:
J
(
θ
)
=
MSE
+
λ
1
∑
j
=
1
n
∣
θ
j
∣
+
λ
2
∑
j
=
1
n
θ
j
2
J(\theta) = \text{MSE} + \lambda_1 \sum_{j=1}^{n} |\theta_j| + \lambda_2 \sum_{j=1}^{n} \theta_j^2
J(θ)=MSE+λ1j=1∑n∣θj∣+λ2j=1∑nθj2
特点:
- 特别适用于特征数量远大于样本数量的高维数据集,能够结合 L1 和 L2 的优点。
3. 正则化的优势
- 防止过拟合:通过限制模型的复杂度,提高模型对未见数据的泛化能力。
- 特征选择:尤其是 L1 正则化,可以自动选择最重要的特征,剔除不重要的特征。
- 提高模型的稳定性:正则化有助于缓解小数据集中的噪声影响,减少因数据波动导致的预测不稳定性。
4. 超参数的选择
正则化强度( λ \lambda λ)是正则化的重要超参数。通常可以使用交叉验证来选择合适的 λ \lambda λ 值,确保模型在训练集和验证集上的性能平衡。
5. 实现示例
以下是使用 Python 和 Scikit-Learn 进行 Lasso 和 Ridge 回归的示例:
import numpy as np
from sklearn.linear_model import Lasso, Ridge
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_regression
# 生成示例数据
X, y = make_regression(n_samples=100, n_features=20, noise=0.1, random_state=42)
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Lasso 回归
lasso = Lasso(alpha=0.1) # alpha 是正则化强度
lasso.fit(X_train, y_train)
lasso_score = lasso.score(X_test, y_test)
print("Lasso 回归的 R^2 得分:", lasso_score)
# Ridge 回归
ridge = Ridge(alpha=0.1)
ridge.fit(X_train, y_train)
ridge_score = ridge.score(X_test, y_test)
print("Ridge 回归的 R^2 得分:", ridge_score)
用于线性回的正则化
在机器学习中,正则化是防止模型过拟合的一种技术,尤其在处理线性回归模型时非常重要。正则化通过在损失函数中添加一个惩罚项来影响模型的复杂度。常用的正则化方法有 L1 正则化(Lasso 回归)和 L2 正则化(Ridge 回归)。
1. L2 正则化(Ridge Regression)
L2 正则化通过添加每个参数的平方和作为惩罚项来控制模型的复杂度。其目标函数为:
J
(
β
)
=
1
m
∑
i
=
1
m
(
h
β
(
x
(
i
)
)
−
y
(
i
)
)
2
+
λ
∑
j
=
1
n
β
j
2
J(\beta) = \frac{1}{m} \sum_{i=1}^{m} (h_\beta(x^{(i)}) - y^{(i)})^2 + \lambda \sum_{j=1}^{n} \beta_j^2
J(β)=m1i=1∑m(hβ(x(i))−y(i))2+λj=1∑nβj2
其中:
- h β ( x ( i ) ) h_\beta(x^{(i)}) hβ(x(i)) 是线性回归的预测值。
- y ( i ) y^{(i)} y(i) 是真实值。
- m m m 是样本数量。
- n n n 是特征数量。
- λ \lambda λ 是正则化参数,控制惩罚项的强度。
L2 正则化的优点是能够减小模型的复杂度,同时不会使参数完全变为零。它可以解决共线性问题,提高模型的稳定性。
2. L1 正则化(Lasso Regression)
L1 正则化通过添加每个参数的绝对值和作为惩罚项,其定义的目标函数为:
J
(
β
)
=
1
m
∑
i
=
1
m
(
h
β
(
x
(
i
)
)
−
y
(
i
)
)
2
+
λ
∑
j
=
1
n
∣
β
j
∣
J(\beta) = \frac{1}{m} \sum_{i=1}^{m} (h_\beta(x^{(i)}) - y^{(i)})^2 + \lambda \sum_{j=1}^{n} |\beta_j|
J(β)=m1i=1∑m(hβ(x(i))−y(i))2+λj=1∑n∣βj∣
L1 正则化具有特征选择的效果,因为它会将某些参数压缩为零,从而有效地选择出重要特征。这使得 Lasso 回归在高维数据中尤其有用。
3. 弹性网(Elastic Net)
弹性网结合了 L1 和 L2 正则化的优势,其目标函数为:
J
(
β
)
=
1
m
∑
i
=
1
m
(
h
β
(
x
(
i
)
)
−
y
(
i
)
)
2
+
λ
1
∑
j
=
1
n
∣
β
j
∣
+
λ
2
∑
j
=
1
n
β
j
2
J(\beta) = \frac{1}{m} \sum_{i=1}^{m} (h_\beta(x^{(i)}) - y^{(i)})^2 + \lambda_1 \sum_{j=1}^{n} |\beta_j| + \lambda_2 \sum_{j=1}^{n} \beta_j^2
J(β)=m1i=1∑m(hβ(x(i))−y(i))2+λ1j=1∑n∣βj∣+λ2j=1∑nβj2
在弹性网中,
λ
1
\lambda_1
λ1 和
λ
2
\lambda_2
λ2 是控制 L1 和 L2 惩罚的参数。
4. 代码示例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge, Lasso
from sklearn.model_selection import train_test_split
# 生成示例数据
np.random.seed(0)
X = np.random.rand(100, 1) * 10 # 100个随机特征
y = 2.5 * X.squeeze() + np.random.randn(100) * 2 # 添加一些噪声
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# L2 正则化(Ridge)
ridge_reg = Ridge(alpha=1.0)
ridge_reg.fit(X_train, y_train)
ridge_pred = ridge_reg.predict(X_test)
# L1 正则化(Lasso)
lasso_reg = Lasso(alpha=1.0)
lasso_reg.fit(X_train, y_train)
lasso_pred = lasso_reg.predict(X_test)
# 可视化结果
plt.scatter(X_test, y_test, color='black', label='Actual data')
plt.scatter(X_test, ridge_pred, color='blue', label='Ridge prediction')
plt.scatter(X_test, lasso_pred, color='red', label='Lasso prediction')
plt.title('Ridge vs Lasso Regression')
plt.xlabel('Feature')
plt.ylabel('Target')
plt.legend()
plt.show()
用于逻辑回归的正则化
在逻辑回归中,正则化是一种用于防止模型过拟合的技术。逻辑回归,作为一种分类算法,通过最大化似然函数来学习模型参数,而正则化则在这一过程中引入了惩罚项,从而帮助模型在复杂数据中更好地泛化。
1. L1正则化(Lasso正则化)
L1正则化通过向损失函数中添加绝对值参数的惩罚项来工作。优化目标变为:
Loss
L
1
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
+
λ
∑
j
=
1
n
∣
θ
j
∣
\text{Loss}_{L1} = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log(h_\theta(x^{(i)}) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right] + \lambda \sum_{j=1}^{n} |\theta_j|
LossL1=−m1i=1∑m[y(i)log(hθ(x(i))+(1−y(i))log(1−hθ(x(i)))]+λj=1∑n∣θj∣
其中,
h
θ
(
x
)
h_\theta(x)
hθ(x) 是模型的预测输出,$\lambda $ 是正则化参数。
- 优点:
- 可以导致稀疏模型,使某些特征的权重变为0,从而实现特征选择。
2. L2正则化(Ridge正则化)
L2正则化通过向损失函数中添加参数平方的惩罚项来工作。优化目标变为:
Loss
L
2
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
+
λ
2
∑
j
=
1
n
θ
j
2
\text{Loss}_{L2} = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log(h_\theta(x^{(i)}) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right] + \frac{\lambda}{2} \sum_{j=1}^{n} \theta_j^2
LossL2=−m1i=1∑m[y(i)log(hθ(x(i))+(1−y(i))log(1−hθ(x(i)))]+2λj=1∑nθj2
- 优点:
- 可以减小参数的绝对值,防止模型过拟合,尤其在特征数量大于样本数量时。
3. Elastic Net正则化
Elastic Net正则化结合了L1和L2正则化,通过惩罚项同时包含绝对值和平方项:
Loss
E
N
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
log
(
h
θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
+
λ
1
∑
j
=
1
n
∣
θ
j
∣
+
λ
2
2
∑
j
=
1
n
θ
j
2
\text{Loss}_{EN} = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log(h_\theta(x^{(i)}) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)})) \right] + \lambda_1 \sum_{j=1}^{n} |\theta_j| + \frac{\lambda_2}{2} \sum_{j=1}^{n} \theta_j^2
LossEN=−m1i=1∑m[y(i)log(hθ(x(i))+(1−y(i))log(1−hθ(x(i)))]+λ1j=1∑n∣θj∣+2λ2j=1∑nθj2
其中,
λ
1
\lambda_1
λ1 和
λ
2
\lambda_2
λ2 分别是L1和L2的正则化参数。
- 优点:
- 结合了L1和L2的优点,既可以进行特征选择,又可以保持小权重,有效处理多重共线性。
如何选择正则化参数
选择合适的正则化参数(如λ)非常重要。常用的方法包括:
- 交叉验证:使用交叉验证方法来评估不同λ值下模型的性能,并选择最优的λ。
- 学习曲线:绘制训练集和验证集的学习曲线,可以直观展示过拟合和欠拟合的情况。
代码示例
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 生成示例数据
X, y = make_classification(n_samples=100, n_features=20, n_informative=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# L2正则化逻辑回归
model = LogisticRegression(penalty='l2', C=1.0) # C是正则化强度的倒数
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"L2正则化模型准确率: {accuracy_score(y_test, y_pred)}")
# L1正则化逻辑回归
model_l1 = LogisticRegression(penalty='l1', solver='liblinear', C=1.0)
model_l1.fit(X_train, y_train)
y_pred_l1 = model_l1.predict(X_test)
print(f"L1正则化模型准确率: {accuracy_score(y_test, y_pred_l1)}")
😊