文章目录
- 1.基本术语
- 2.机器学习方法分类
- 3.建模流程
- 4.特征工程
- 5.模型评估和模型选择
- 6.模型求解算法
- [7. 模型评价指标](#7. 模型评价指标)
-
- 7.1回归模型评价指标
- 7.2分类模型评价指标
-
- 1)混淆矩阵
- 2)准确率(Accuracy)
- 3)精确率(Precision)
- 4)召回率(Recall)
- [5)F1分数(F1 Score)](#5)F1分数(F1 Score))
- 6)ROC曲线
- 7) 案例 案例)
- 8)AUC值
1.基本术语

数据集(Data Set):多条记录的集合。
训练集(Training Set):用于训练模型的数据。
验证集(Validation Set):用于调节超参数的数据。
测试集(Test Set):用于评估模型性能的数据。
-
样本(Sample):数据集中的一条记录是关于一个事件或对象的描述,称为一个样本。
-
特征(Feature):数据集中一列反映事件或对象在某方面的表现或性质的事项,称为特征或属性。
-
特征向量(Feature Vector):将样本的所有特征表示为向量的形式,输入到模型中。
-
标签(Label):监督学习中每个样本的结果信息,也称作目标值(target)。
-
模型(Model):一个机器学习算法与训练后的参数集合,用于进行预测或分类。
-
参数(Parameter):模型通过训练学习到的值,例如线性回归中的权重和偏置。
-
超参数(Hyper Parameter):由用户设置的参数,不能通过训练自动学习,例如学习率、正则化系数等。
2.机器学习方法分类
机器学习的方法种类繁多,并不存在一个统一的理论体系能够涵盖所有内容。从不同的角度,可以将机器学习的方法进行不同的分类:
通常分类:按照有无监督,机器学习可以分为 有监督学习 、无监督学习 和 半监督学习 ,除此之外还有 强化学习 。

各种类型的机器学习方法可以用下图汇总展示:
3.建模流程
以监督学习为例,考察一下机器学习的具体过程。
机器学习是由数据驱动的,核心是利用数据来"训练模型";模型训练的结果需要用一定的方法来进行评估、优化,最终得到一个成熟的学习模型;最后就可以用这个模型来进行预测和解决问题了。
总结监督学习建模的整体流程如下:

4.特征工程
4.1什么是特征工程
特征工程 (Feature Engineering)是机器学习过程中非常重要的一步,指的是通过对
原始数据的处理、转换和构造,生成新的特征或选择有效的特征,从而提高模型的性能。简单来说,特征工程是将原始数据转换为可以更好地表示问题的特征形式,帮助模型更好地理解和学习数据中的规律。
优秀的特征工程可以显著提高模型的表现;反之,忽视特征工程可能导致模型性能欠佳。
4.2特征工程的内容
4.2.1特征选择
从原始特征中挑选出与目标变量关系最密切的特征,剔除冗余、无关或噪声特征。这样可以减少模型的复杂度、加速训练过程、并减少过拟合的风险。
特征选择不会创建新特征,也不会改变数据结构。
(1)过滤法(Filter Method)
基于统计测试(如卡方检验、相关系数、信息增益等)来评估特征与目标变量之间的关系,选择最相关的特征。
(2)包裹法(Wrapper Method)
使用模型(如递归特征消除 RFE)来评估特征的重要性,并根据模型的表现进行特征选择。
(3)嵌入法(Embedded Method)
使用模型本身的特征选择机制(如决策树的特征重要性,L1正则化的特征选择)来选择最重要的特征。
4.2.2特征转换
对数据进行数学或统计处理,使其变得更加适合模型的输入要求。
(1)归一化(Normalization)
将特征缩放到特定的范围(通常是0到1之间)。适用于对尺度敏感的模型(如KNN、SVM)。
(2)标准化(Standardization)
通过减去均值并除以标准差,使特征的分布具有均值0,标准差1。
(3)对数变换
对于有偏态的分布(如收入、价格等),对数变换可以将其转化为更接近正态分布的形式。
(4)类别变量的编码
独热编码(One-Hot Encoding):将类别型变量转换为二进制列,常用于无序类别特征。
标签编码(Label Encoding):将类别型变量映射为整数,常用于有序类别特征。
目标编码(Target Encoding):将类别变量的每个类别替换为其对应目标变量的平均值或其他统计量。
频率编码(Frequency Encoding):将类别变量的每个类别替换为该类别在数据集中的出现频率。
4.2.3特征构造
特征构造是基于现有的特征创造出新的、更有代表性的特征。通过组合、转换、或者聚合现有的特征,形成能够更好反映数据规律的特征。
(1)交互特征
将两个特征组合起来,形成新的特征。例如,两个特征的乘积、和或差等。
例如,将年龄与收入结合创建新的特征,可能能更好地反映某些模式。
(2)统计特征
从原始特征中提取统计值,例如求某个时间窗口的平均值、最大值、最小值、标准差等。
例如,在时间序列数据中,你可以从原始数据中提取每个小时、每日的平均值。
(3)日期和时间特征
从日期时间数据中提取如星期几、月份、年份、季度等特征。
例如,将"2000-01-01"转换为"星期几"、"是否节假日"、"月初或月末"等特征。
4.2.4特征降维
当数据集的特征数量非常大时,特征降维可以帮助减少计算复杂度并避免过拟合。通过降维方法,可以在保持数据本质的情况下减少特征的数量。
(1)主成分分析(PCA)
通过线性变换将原始特征映射到一个新的空间,使得新的特征(主成分)尽可能地保留数据的方差。
(2)线性判别分析(LDA)
一种监督学习的降维方法,通过最大化类间距离与类内距离的比率来降维。
(3)t-SNE(t-Distributed Stochastic Neighbor Embedding,t分布随机近邻嵌入)
一种非线性的降维技术,特别适合可视化高维数据。
(4)自编码器(Auto Encoder)
一种神经网络模型,通过压缩编码器来实现数据的降维。
4.3常用方法
4.3.1特征数值缩放
对于不同的特征,单位和量纲不同,可能导致数值差距较大,影响机器学习模型的性能和稳定性。因此,对特征数值进行缩放转换是一个重要的预处理步骤,常见的方法就是 归一化 和 标准化。
归一化
(1)定义
将数据按比例缩放到一个固定范围 x m i n , x m a x x_{{min}},x_{max} xmin,xmax,(通常是 0 , 1 0,1 0,1或者 − 1 , 1 -1,1 −1,1)。。
(2)目的
- 消除量纲差异:不同特征的单位或量纲可能差异巨大(例如身高以米为单位,体重以千克为单位),归一化可消除这种差异,避免模型被大范围特征主导。
- 加速模型收敛:对于梯度下降等优化算法,归一化后特征处于相近的尺度,优化路径更平滑,收敛速度更快。
- 适配特定模型需求:某些模型(如神经网络、K近邻、SVM)对输入数据的范围敏感,归一化能显著提升其性能。
(3)场景
归一化不改变原始分布形状,但对异常值比较敏感。当数据分布有明显边界(如图像像素值、文本词频),或模型对输入范围敏感时可以优先考虑归一化。
代码示例
python
from sklearn.preprocessing import MinMaxScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
# 归一化,区间设置为(-1,1)
X = MinMaxScaler(feature_range=(-1, 1)).fit_transform(X)
print(X)
标准化
(1)定义
将数据调整为均值为0、标准差为1的标准分布。

(2)目的
-
适应数据分布:将数据转换为均值为0、标准差为1的分布,适合假设数据服从正态分布的模型(如线性回归、逻辑回归)。
-
稳定模型训练:标准化后的数据对异常值的敏感度较低(相比归一化),鲁棒性更强。
-
统一特征尺度:与归一化类似,标准化也能消除量纲差异,但更关注数据的统计分布而非固定范围。
(3)场景
大多数场景下标准化更通用,尤其是数据分布未知或存在轻微异常值时。
代码示例
python
from sklearn.preprocessing import StandardScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
# 标准化
X = StandardScaler().fit_transform(X)
print(X)
4.3.2解决维度灾难
在训练模型时有时会遇到 维度灾难 ,即特征数量过多,随着维数的增加,计算量呈指数倍增长的一种现象。我们希望能在确保不丢失重要特征的前提下减少维度的数量,来降低训练模型的难度。
对于一个模型来说,有些特征可能很关键,而有些特征可能用处不大。
例如:
某个特征取值较接近,变化很小,可能与结果无关。某几个特征相关性较高,可能包含冗余信息。
因此,特征选择 在特征工程中是最基本、也最常见的操作。另外,也经常会用到 特征降维 方法。
低方差过滤法
对于特征的选择,可以直接基于方差来判断,这是最简单的。低方差的特征意味着该特征的所有样本值几乎相同,对预测影响极小,可以将其去掉。
python
from sklearn.feature_selection import VarianceThreshold
# 低方差过滤:删除方差低于 0.01 的特征
var_thresh = VarianceThreshold(threshold=0.01)
X_filtered = var_thresh.fit_transform(X)
相关系数法
通过计算特征与目标变量或特征之间的相关性,筛选出高相关性特征(与目标相关)或剔除冗余特征(特征间高度相关)。

- 正相关:值接近1,说明特征随目标变量增加而增加。
- 负相关:值接近-1,说明特征随目标变量增加而减少。
- 无关:值接近0,说明特征和目标变量无明显关系。
使用pandas.DataFrame.corrwith(method="pearson")计算各个特征与标签间的皮尔逊相关系数。
python
import pandas as pd
advertising = pd.read_csv("data/advertising.csv")
advertising.drop(advertising.columns[0], axis=1, inplace=True)
advertising.dropna(inplace=True)
X = advertising.drop("Sales", axis=1)
y = advertising["Sales"]
# 计算皮尔逊相关系数
print(X.corrwith(y, method="pearson"))
# TV 0.782224
# Radio 0.576223
# Newspaper 0.228299
# dtype: float64
使用pandas.DataFrame.corr(method="pearson")计算皮尔逊相关系数矩阵
python
import seaborn as sns
import matplotlib.pyplot as plt
# 计算皮尔逊相关系数矩阵
corr_matrix = advertising.corr(method="pearson")
# 可视化热力图
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", fmt=".2f")
plt.title("Feature Correlation Matrix")
plt.show()

主成分分析(PCA)
主成分分析(Principal Component Analysis,PCA)是一种常用的降维技术,通过线性变换将高维数据投影到低维空间,同时保留数据的主要变化模式。

使用sklearn.decomposition.PCA进行主成分分析。参数n_components若为小数则表示保留多少比例的信息,为整数则表示保留多少个维度。
python
import numpy as np
from sklearn.decomposition import PCA
n_samples = 1000
# 构造3维数据
X = np.random.randn(n_samples, 3)
# 应用PCA,将3维数据降维到2维
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
print(X_pca.shape)
5.模型评估和模型选择
5.1损失函数
对于模型一次预测结果的好坏,需要有一个度量标准。
对于监督学习而言,给定一个输入_X_,选取的模型就相当于一个"决策函数"f,它可以输出一个预测结果_f(X),而真实的结果(标签)记为 Y。f(X) 和Y之间可能会有偏差,我们就用一个损失函数 (loss function)来度量预测偏差的程度,记作
L(Y,f(X))。
- 损失函数用来衡量模型预测误差的大小;损失函数值越小,模型就越好;
- 损失函数是f(X)和Y的非负实值函数;
常见的损失函数有:

5.2经验误差(测试误差)
给定一个训练数据集,数据个数为n。根据选取的损失函数,就可以计算出模型f(X)在训练集上的平均误差,称为训练误差,也被称作 经验误差 (empirical error) 或 经验风险 (empirical risk)。
类似地,在测试数据集上平均误差,被称为测试误差 或者 泛化误差 (generalization error)。
一般情况下对模型评估的策略,就是考察经验误差;当经验风险最小时,就认为取到了最优的模型。这种策略被称为 经验风险最小化(empirical risk minimization,ERM)。
5.3欠拟合与过拟合
拟合 (Fitting)是指机器学习模型在训练数据上学习到规律并生成预测结果的过程。理想情况下,模型能够准确地捕捉训练数据的模式,并且在未见过的新数据(测试数据)上也有良好的表现;即模型具有良好的 泛化能力 。

欠拟合 (Underfitting):是指模型在训练数据上表现不佳,无法很好地捕捉数据中的规律。这样的模型不仅在训练集上表现不好,在测试集上也同样表现差。

过拟合 (Overfitting):是指模型在训练数据上表现得很好,但在测试数据或新数据上表现较差的情况。过拟合的模型对训练数据中的噪声或细节过度敏感,把训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质,从而失去了泛化能力。

产生欠拟合和过拟合的根本原因 ,是模型的复杂度过低或过高,从而导致测试误差(泛化误差)偏大。
- 欠拟合:模型在训练集和测试集上误差都比较大。模型过于简单,高偏差。
- 过拟合:模型在训练集上误差较小,但在测试集上误差较大。模型过于复杂,高方差。

产生原因与解决办法
(1)欠拟合
产生原因:
- 模型复杂度不足:模型过于简单,无法捕捉数据中的复杂关系。
- 特征不足:输入特征不充分,或者特征选择不恰当,导致模型无法充分学习数据的模式。
- 训练不充分:训练过程中迭代次数太少,模型没有足够的时间学习数据的规律。
- 过强的正则化:正则化项设置过大,强制模型过于简单,导致模型无法充分拟合数据。
解决办法: - 增加模型复杂度:选择更复杂的模型。
- 增加特征或改进特征工程:添加更多的特征或通过特征工程来创造更有信息量的特征。
- 增加训练时间:增加训练的迭代次数,让模型有更多机会去学习。
- 减少正则化强度:如果使用了正则化,尝试减小正则化的权重,以让模型更灵活。
(2)过拟合
产生原因:
- 模型复杂度过高:模型过于复杂,参数太多。
- 训练数据不足:数据集太小,模型能记住训练数据的细节,但无法泛化到新数据。
- 特征过多:特征太多,模型可能会"记住"数据中的噪声,而不是学到真正的规律。
- 训练过长:训练时间过长,导致模型学习到训练数据中的噪声,而非数据的真正规律。
解决办法: - 减少模型复杂度:降低模型的参数数量、使用简化的模型或降维来减小模型复杂度。
- 增加训练数据:收集更多数据,或通过数据增强来增加训练数据的多样性。
- 使用正则化:引入L1、L2正则化,避免过度拟合训练数据。
- 交叉验证:使用交叉验证技术评估模型在不同数据集上的表现,以减少过拟合的风险。
- 早停:训练时,当模型的验证损失不再下降时,提前停止训练,避免过度拟合训练集。
代码演示

python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
plt.rcParams["font.sans-serif"] = ["KaiTi"]
plt.rcParams["axes.unicode_minus"] = False
def polynomial(x, degree):
"""构成多项式,返回 [x^1,x^2,x^3,...,x^n]"""
return np.hstack([x**i for i in range(1, degree + 1)])
# 生成随机数据
X = np.linspace(-3, 3, 300).reshape(-1, 1)
y = np.sin(X) + np.random.uniform(-0.5, 0.5, 300).reshape(-1, 1)
fig, ax = plt.subplots(1, 3, figsize=(15, 4))
ax[0].plot(X, y, "yo")
ax[1].plot(X, y, "yo")
ax[2].plot(X, y, "yo")
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建线性回归模型
model = LinearRegression()
# 欠拟合
x_train1 = x_train
x_test1 = x_test
model.fit(x_train1, y_train) # 模型训练
y_pred1 = model.predict(x_test1) # 预测
ax[0].plot(np.array([[-3], [3]]), model.predict(np.array([[-3], [3]])), "c") # 绘制曲线
ax[0].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred1):.4f}")
ax[0].text(-3, 1.3, f"训练集均方误差:{mean_squared_error(y_train, model.predict(x_train1)):.4f}")
# 恰好拟合
x_train2 = polynomial(x_train, 5)
x_test2 = polynomial(x_test, 5)
model.fit(x_train2, y_train) # 模型训练
y_pred2 = model.predict(x_test2) # 预测
ax[1].plot(X, model.predict(polynomial(X, 5)), "k") # 绘制曲线
ax[1].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred2):.4f}")
ax[1].text(-3, 1.3, f"训练集均方误差:{mean_squared_error(y_train, model.predict(x_train2)):.4f}")
# 过拟合
x_train3 = polynomial(x_train, 20)
x_test3 = polynomial(x_test, 20)
model.fit(x_train3, y_train) # 模型训练
y_pred3 = model.predict(x_test3) # 预测
ax[2].plot(X, model.predict(polynomial(X, 20)), "r") # 绘制曲线
ax[2].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[2].text(-3, 1.3, f"训练集均方误差:{mean_squared_error(y_train, model.predict(x_train3)):.4f}")
plt.show()

- 当多项式次数较低时,模型过于简单,拟合效果较差。
- 当多项式次数增加后,模型复杂度适中,拟合效果较好,训练误差和测试误差均较低。
- 当多项式次数继续增加,模型变得过于复杂,过度学习了噪声,导致训练误差较低而测试误差较高。
5.4正则化
正则化(Regularization)是一种在训练机器学习模型时,在损失函数中添加额外项,来惩罚过大的参数,进而限制模型复杂度、避免过拟合,提高模型泛化能力的技术。

这里的 是 **正则化系数**,用来表示惩罚项的权重。正则化系数不属于模型的参数,无法通过训练学习得到,需要在模型训练开始之前手动设置,这种参数被称为"**超参数**"。
两者相互平衡,在模型的拟合能力(偏差)和复杂度之间找到最佳折中。
常见的正则化技术有L1正则化和L2正则化。
1)L1正则化(Lasso回归)
L1正则化在损失函数中加入参数的绝对值之和:

L1正则化通过惩罚模型参数的绝对值,使得部分权重趋近0甚至变为0。这会导致特征选择,即模型会自动"丢弃"一些不重要的特征。L1正则化有助于创建稀疏模型(即许多参数为0)。在解决回归问题时,使用L1正则化也被称为"Lasso回归"。
λ超参数控制着正则化的强度。较大的 值意味着强烈的正则化,会使模型更简单,可能导致欠拟合。而较小的λ 值则会使模型更复杂,可能导致过拟合。
2)L2正则化(Ridge回归,岭回归)
L2正则化在损失函数中加入参数的平方之和:

L2正则化通过惩罚模型参数的平方,使得所有参数都变得更小,但不会将参数强行压缩为0。它会使得模型尽量平滑,从而防止过拟合。在解决回归问题时,使用L2正则化也被称为"岭回归"。
3)ElasticNet正则化(弹性网络回归)
ElasticNet正则化结合了L1和L2正则化,通过调整两个正则化项的比例来取得平衡,从而同时具备稀疏性和稳定性的优点。

α∈0,1,决定L1和L2的权重。
代码示范
同样以使用多项式在 上拟合 为例,分别不使用正则化、使用L1正则化、使用L2正则化进行拟合。
python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso, Ridge
from sklearn.metrics import mean_squared_error
plt.rcParams["font.sans-serif"] = ["KaiTi"]
plt.rcParams["axes.unicode_minus"] = False
def polynomial(x, degree):
"""构成多项式,返回 [x^1,x^2,x^3,...,x^n]"""
return np.hstack([x**i for i in range(1, degree + 1)])
# 生成随机数据
X = np.linspace(-3, 3, 300).reshape(-1, 1)
y = np.sin(X) + np.random.uniform(-0.5, 0.5, X.size).reshape(-1, 1)
fig, ax = plt.subplots(2, 3, figsize=(15, 8))
ax[0, 0].plot(X, y, "yo")
ax[0, 1].plot(X, y, "yo")
ax[0, 2].plot(X, y, "yo")
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
x_train1 = polynomial(x_train, 20)
x_test1 = polynomial(x_test, 20)
# 拟合
model = LinearRegression()
model.fit(x_train1, y_train) # 模型训练
y_pred3 = model.predict(x_test1) # 预测
ax[0, 0].plot(X, model.predict(polynomial(X, 20)), "r") # 绘制曲线
ax[0, 0].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[1, 0].bar(np.arange(20), model.coef_.reshape(-1)) # 绘制所有系数
# L1正则化-Lasso回归
lasso = Lasso(alpha=0.01)
lasso.fit(x_train1, y_train) # 模型训练
y_pred3 = lasso.predict(x_test1) # 预测
ax[0, 1].plot(X, lasso.predict(polynomial(X, 20)), "r") # 绘制曲线
ax[0, 1].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[0, 1].text(-3, 1.2, "Lasso回归")
ax[1, 1].bar(np.arange(20), lasso.coef_) # 绘制所有系数
# L2正则化-岭回归
ridge = Ridge(alpha=1)
ridge.fit(x_train1, y_train) # 模型训练
y_pred3 = ridge.predict(x_test1) # 预测
ax[0, 2].plot(X, ridge.predict(polynomial(X, 20)), "r") # 绘制曲线
ax[0, 2].text(-3, 1, f"测试集均方误差:{mean_squared_error(y_test, y_pred3):.4f}")
ax[0, 2].text(-3, 1.2, "岭回归")
ax[1, 2].bar(np.arange(20), ridge.coef_) # 绘制所有系数
plt.show()

5.5交叉验证
交叉验证(Cross-Validation)是一种评估模型泛化能力的方法,通过将数据集划分为多个子集,反复进行训练和验证,以减少因单次数据划分带来的随机性误差。通过交叉验证能更可靠地估计模型在未知数据上的表现,亦能避免因单次数据划分不合理导致的模型过拟合或欠拟合。
1)简单交叉验证(Hold-Out Validation)
将数据划分为训练集和验证集(如70%训练,30%验证)。结果受单次划分影响较大,可能高估或低估模型性能。
2)k折交叉验证(k-Fold Cross-Validation)
将数据均匀分为k个子集(称为"折"),每次用k−1折训练,剩余1折验证,重复k次后取平均性能。充分利用数据,结果更稳定。

3)留一交叉验证(Leave-One-Out,LOO)
每次仅留一个样本作为验证集,其余全部用于训练,重复直到所有样本都被验证一次。适用于小数据集,计算成本极高。
6.模型求解算法
正则化可以有效防止过拟合,增强模型的泛化能力。这时模型的评估策略,就是让结构化的经验风险最小,即增加了正则化项的损失函数最小,称为 结构风险最小化 (Structural Risk Minimization,SRM)。
min 1 n ( ∑ i = 1 n L ( y i , f ( x i ) ) + λ J ( θ ) ) \min{\frac{1}{n}\left(\ \sum_{i=1}^{n} L\left(y_{i},f\left(x_{i}\right)\right)+\lambda J\left(\theta \right)\ \right)} minn1( ∑i=1nL(yi,f(xi))+λJ(θ) )
这其实就是求解一个 最优化问题 。代入训练集所有数据( x i , y i x{i},y{i} xi,yi),要求最小值的目标函数就是模型中参数 θ θ θ的函数。
具体求解的算法,可以利用数学公式直接计算解析解,也可以使用迭代算法。
6.1解析法
如果模型损失函数的最小值可以通过数学公式进行严格推导,得到一个解析解,那么就直接得到了最优模型的全部参数。这种方法称作解析法。
1)特点
- 适用条件:目标函数必须可导,且导数方程有解析解。
- 优点:直接且精确;计算高效;
- 缺点:适用条件较为苛刻;特征维度较大时,矩阵求逆计算复杂度极高。
1)应用示例
- 线性回归问题:可以采用"最小二乘法"求得解析解。
L o s s M S E = 1 n ( X β − y ) T ( X β − y ) {Loss}_{MSE}={\frac{1}{n}\left(\boldsymbol{X\beta }-\boldsymbol{y}\right)}^{T}\left(\boldsymbol{X\beta }-\boldsymbol{y}\right) LossMSE=n1(Xβ−y)T(Xβ−y)
∇ L o s s M S E = 2 n X T ( X β − y ) = 0 \mathrm{\nabla }{Loss}_{MSE}=\frac{2}{n}{\boldsymbol{X}}^{T}\left(\boldsymbol{X\beta }-\boldsymbol{y}\right)=0 ∇LossMSE=n2XT(Xβ−y)=0
β = ( X T X ) − 1 X T y \boldsymbol{\beta }={({\boldsymbol{X}}^{T}\boldsymbol{X})}^{-1}{\boldsymbol{X}}^{T}\boldsymbol{y} β=(XTX)−1XTy
这里用 β 表示线性回归模型的参数。
- 线性回归L2正则化(Ridge回归,岭回归)
可以得到解析解如下:
L o s s L 2 = 1 n ( X β − y ) T ( X β − y ) + 1 n λ β T β {Loss}_{L2}=\frac{1}{n}{\left(\boldsymbol{X\beta }-\boldsymbol{y}\right)}^{T}\left(\boldsymbol{X\beta }-\boldsymbol{y}\right)+\frac{1}{n}\lambda {\boldsymbol{\beta }}^{T}\boldsymbol{\beta } LossL2=n1(Xβ−y)T(Xβ−y)+n1λβTβ
∇ L o s s L 2 = 2 n X T ( X β − y ) + 2 n λ β = 0 \mathrm{\nabla }{Loss}_{L2}=\frac{2}{n}{\boldsymbol{X}}^{T}\left(\boldsymbol{X\beta }-\boldsymbol{y}\right)+\frac{2}{n}\lambda \boldsymbol{\beta }=0 ∇LossL2=n2XT(Xβ−y)+n2λβ=0
β = ( X T X + λ I ) − 1 X T y \boldsymbol{\beta }={({\boldsymbol{X}}^{T}\boldsymbol{X}+\lambda \boldsymbol{I})}^{-1}{\boldsymbol{X}}^{T}\boldsymbol{y} β=(XTX+λI)−1XTy
由于加入的对角矩阵 就像一条"山岭",因此L2正则化也称作"岭回归"。
6.2梯度下降法
梯度下降法 (gradient descent)是一种常用的一阶优化方法,是求解无约束优化问题最简单、最经典的方法之一。梯度下降法是迭代算法,基本思路就是先选取一个适当的初始值 ,然后沿着梯度方向或者负梯度方向,不停地更新参数,最终取到极小值。

- 梯度方向:函数变化增长最快的方向(变量沿此方向变化时函数增长最快)
- 负梯度方向:函数变化减少最快的方向(变量沿此方向变化时函数减少最快)
因为损失函数是系数的函数,那么如果系数沿着损失函数的负梯度方向变化,此时损失函数减少最快,能够以最快速度下降到极小值。
公式为: θ ( k + 1 ) = θ ( k ) − α ⋅ ▽ L ( θ ( k ) ) {\boldsymbol{\theta }}^{(k+1)}={\boldsymbol{\theta }}^{(k)}-\ \alpha ·\triangledown L({\boldsymbol{\theta }}^{(k)}) θ(k+1)=θ(k)− α⋅▽L(θ(k))
这里的 θ ( k ) {\boldsymbol{\theta }}^{(k)} θ(k)代表第k次迭代时的参数值,而 ▽ L ( θ ( k ) ) \triangledown L({\boldsymbol{\theta }}^{(k)}) ▽L(θ(k))是参数取值为 θ ( k ) {\boldsymbol{\theta }}^{(k)} θ(k)时损失函数 的梯度; α 是每次迭代的"步长",被称为"学习率 "。学习率也是一个常见的超参数,需要手动设置,选择不当会导致收敛失败。
1)特点 - 梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解。
- 优点:适用性广;计算简单;
- 缺点:收敛速度慢;可能陷入局部最优。
2)分类
(1)批量梯度下降(Batch Gradient Descent,BGD)
每次迭代使用全部训练数据计算梯度。 - 优点:稳定收敛。
- 缺点:计算开销大。
(2)随机梯度下降(Stochastic Gradient Descent,SGD)
每次迭代随机选取一个样本计算梯度。 - 优点:速度快,适合大规模数据。
- 缺点:梯度更新方向不稳定,优化过程震荡较大,可能难以收敛。
(3)小批量梯度下降(Mini-batch Gradient Descent,MBGD)
每次迭代使用一小批样本(如32、64个)计算梯度。
平衡了BGD的稳定性和SGD的速度,是最常用的方法。
3)梯度下降法计算步骤
(1)初始化参数:随机选择初始参数
(2)计算梯度:在当前参数下,计算损失函数的梯度
(3)更新参数:沿负梯度方向调整参数
(4)重复迭代:直到满足停止条件(如梯度接近零、达到最大迭代次数等)
4)代码实现
我们以一个单变量函数为例,介绍梯度下降法的代码实现。
设 f ( x ) = x 2 f\left(x\right)=x^{2} f(x)=x2,求 x x x为何值时, f ( x ) = 2 f\left(x\right)=2 f(x)=2 。

python
def J(x):
"""目标函数"""
return (x**2 - 2) ** 2
def gradient(x):
"""梯度"""
return 4 * x**3 - 8 * x
x = 1 # x的初始值
alpha = 0.1 # 学习率
while (j := J(x)) > 1e-30: # 当目标函数的值小于10的-30次幂时停止计算
print(f"x={x}\tJ={j}")
grad = gradient(x) # 求解梯度
x = x - alpha * grad # 更新参数
6.3牛顿法和拟牛顿法
牛顿法也是求解无约束最优化问题的常用方法,核心思想是利用目标函数的二阶导数信息,通过迭代逐渐逼近极值点。

7. 模型评价指标
对学习的泛化性能进行评估,不仅需要有效可行的实验估计方法,还需要有衡量模型泛化能力的评价指标,也叫做性能度量(performance measure)。
7.1回归模型评价指标
模型的评价指标用于衡量模型在训练集或测试集上的性能,评估结果反映了模型预测的准确性和泛化能力。
对于回归问题,最常用的性能度量是"均方误差" (Mean Squared Error,MSE)。
1)平均绝对误差(MAE)
M A E = 1 n ∑ i = 1 n ∣ f ( x i ) − y i ∣ MAE=\frac{1}{n}\sum_{i=1}^{n} \left|f({\boldsymbol{x}}{\boldsymbol{i}})-y{i}\right| MAE=n1∑i=1n∣f(xi)−yi∣
- MAE对异常值不敏感,解释直观。适用于数据包含异常值的场景
2)均方误差(MSE)
M S E = 1 n ∑ i = 1 n ( f ( x i ) − y i ) 2 MSE=\frac{1}{n}\sum_{i=1}^{n} {(f({\boldsymbol{x}}{\boldsymbol{i}})-y{i})}^{2} MSE=n1∑i=1n(f(xi)−yi)2
- MSE会放大较大误差,对异常值敏感。适用于需要惩罚大误差的场景。
3)均方根误差(RMSE)
R M S E = 1 n ∑ i = 1 n ( f ( x i ) − y i ) 2 RMSE=\sqrt{\frac{1}{n}\sum_{i=1}^{n} {(f({\boldsymbol{x}}{\boldsymbol{i}})-y{i})}^{2}} RMSE=n1∑i=1n(f(xi)−yi)2
- 与MSE类似,但量纲与目标变量一致。适用于需要直观误差量纲的场景。如果一味地试图降低RMSE,可能会导致模型对异常值也拟合度很高,容易过拟合。
4)R²(决定系数)
R 2 = 1 − ∑ i = 1 n ( f ( x i ) − y i ) 2 ∑ i = 1 n ( y i − y ˉ ) 2 R^{2}=1-\frac{\sum_{i=1}^{n} {\left(f\left({\boldsymbol{x}}{\boldsymbol{i}}\right)-y{i}\right)}^{2}}{\sum_{i=1}^{n} {\left(y_{i}-\bar{y}\right)}^{2}} R2=1−∑i=1n(yi−yˉ)2∑i=1n(f(xi)−yi)2
- 衡量模型对目标变量的解释能力,越接近1越好,对异常值敏感。
7.2分类模型评价指标
对于分类问题,最常用的指标就是"准确率"(Accuracy),它定义为分类器对测试集正确分类的样本数与总样本数之比。此外还有一系列常用的评价指标。
1)混淆矩阵
混淆矩阵(Confusion Matrix)是用于评估分类模型性能的工具,展示了模型预测结果与实际标签的对比情况。
对于二分类问题,混淆矩阵是一个2×2矩阵:

例如,有10个样本。6个是猫,4个是狗。假设以猫为正例,模型预测对了5个猫,2个狗。

- 使用sklearn.metrics.confusion_matrix查看混淆矩阵:
python
import pandas as pd
import seaborn as sns
from sklearn.metrics import confusion_matrix
label = ["猫", "狗"] # 标签
y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值
y_pred1 = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"] # 预测值
matrix1 = confusion_matrix(y_true, y_pred1, labels=label) # 混淆矩阵
print(pd.DataFrame(matrix1, columns=label, index=label))
sns.heatmap(matrix1, annot=True, fmt='d', cmap='Greens')
2)准确率(Accuracy)
正确预测的比例。
A c c u r a c y = T P + T N T P + T N + F P + F N Accuracy=\frac{TP+TN}{TP+TN+FP+FN} Accuracy=TP+TN+FP+FNTP+TN

python
from sklearn.metrics import accuracy_score
label = ["猫", "狗"] # 标签
y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值
y_pred1 = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"] # 预测值
accuracy = accuracy_score(y_true, y_pred1)
print(accuracy)
3)精确率(Precision)
预测为正例的样本中实际为正例的比例,也叫查准率。
P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP+FP} Precision=TP+FPTP

python
from sklearn.metrics import precision_score
label = ["猫", "狗"] # 标签
y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值
y_pred1 = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"] # 预测值
precision = precision_score(y_true, y_pred1, pos_label="猫") # pos_label指定正例
print(precision)
4)召回率(Recall)
实际为正类的样本中预测为正类的比例,也叫查全率。
R e c a l l = T P T P + F N Recall=\frac{TP}{TP+FN} Recall=TP+FNTP

python
from sklearn.metrics import recall_score
label = ["猫", "狗"] # 标签
y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值
y_pred1 = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"] # 预测值
recall = recall_score(y_true, y_pred1, pos_label="猫") # pos_label指定正例
print(recall)
5)F1分数(F1 Score)
精确率和召回率的调和平均。
F 1 S c o r e = 2 × P r e c i s i o n × R e c a l l P r e c i s i o n + R e c a l l F1\ Score=\frac{2\times Precision\times Recall}{Precision+Recall} F1 Score=Precision+Recall2×Precision×Recall
python
from sklearn.metrics import f1_score
label = ["猫", "狗"] # 标签
y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值
y_pred1 = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"] # 预测值
f1 = f1_score(y_true, y_pred1, pos_label="猫") # pos_label指定正例
print(f1)
在代码中,我们可通过sklearn.metrics.classification_report生成分类任务的评估报告,包括精确率、召回率、F1分数等。
python
from sklearn.metrics import classification_report
report = classification_report(y_true, y_pred, labels=[], target_names=None)
# y_true:真实标签
# y_pred:预测的标签
# labels:可选,指定需要计算的类别列表(默认计算所有出现过的类别)
# target_names:可选,类别名称(默认使用 labels 指定的类别号)
python
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
# 生成一个二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=100)
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
# 训练一个逻辑回归模型
model = LogisticRegression()
model.fit(x_train, y_train)
# 预测
y_pred = model.predict(x_test)
# 生成分类报告
report = classification_report(y_test, y_pred)
print(report)
6)ROC曲线
-
真正例率(TPR):实际为正例,被预测为正例的比例,即召回率。
- T P R = T P 实际正例数 = T P T P + F N TPR=\frac{TP}{实际正例数}=\frac{TP}{TP+FN} TPR=实际正例数TP=TP+FNTP
-
假正例率(FPR):实际为负例,被预测为正例的比例。
- F P R = F P 实际负例数 = F P F P + T N FPR=\frac{FP}{实际负例数}=\frac{FP}{FP+TN} FPR=实际负例数FP=FP+TNFP
-
阈值(Threshold):根据阈值将概率转换为类别标签。
ROC曲线(Receiver Operating Characteristic Curve,受试者工作特征)是
评估二分类模型性能的工具,以假正例率(FPR)为横轴,以真正例率(TPR)为纵轴,展示不同阈值下模型的表现。绘制ROC曲线时,从高到低调整阈值,计算每个阈值的TPR和FPR并绘制所有阈值的点,形成ROC曲线。
7) 案例
假设一个二分类模型的真实标签和模型输出概率如下:


8)AUC值
AUC值代表ROC曲线下的面积,用于量化模型性能。AUC值越大,模型区分正负类的能力越强,模型性能越好。AUC值=0.5表示模型接近随机猜测,AUC值=1代表完美模型。
可通过sklearn.metrics.roc_auc_score计算AUC值。
python
from sklearn.metrics import roc_auc_score
auc_score = roc_auc_score(y_true, y_score)
# y_true: 真实标签(0 或 1)
# y_score: 正例的概率值或置信度
例如:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
# 生成一个二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=100)
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=100)
# 训练一个逻辑回归模型
model = LogisticRegression()
model.fit(x_train, y_train)
# 预测概率值(取正类的概率)
y_pred_proba = model.predict_proba(x_test)[:, 1]
# 计算AUC
auc_score = roc_auc_score(y_test, y_pred_proba)
print(auc_score)
