修改了机器学习部分文档

This commit is contained in:
jackfrued 2025-01-15 22:39:14 +08:00
parent 5423003f54
commit 291577f78e
3 changed files with 32 additions and 32 deletions

View File

@ -197,7 +197,7 @@
9. **模型维护**。机器学习模型不是一成不变的,随着时间的推移,模型可能需要通过重新训练、增量学习等方式来维持其性能。
> **说明**:如果对上面出现的一些概念不是很理解,可以先跳过去,我们会在遇到这些问题的时候展开讲解。
> **说明**:如果对上面出现的概念不是很理解,可以先跳过去,我们会在遇到这些问题的时候展开讲解。
### 第一次机器学习
@ -376,7 +376,7 @@ $$
b = \bar{y} - a\bar{x}
$$
需要说明的是,如果回归模型本身比较复杂,不像线性模型$\small{Y = aX + b}$这么简单,可能没有办法像上面那样直接求解方程,而是要通过不断的迭代去逼近极值点,这个我们会在后续的内容中为大家讲解。回到刚才的问题,我们可以通过上面的公式计算出$\small{a}$和$\small{b}$的值,为了运算方便,下面直接使用了 NumPy 中的函数,因为 NumPy 中的运算都是矢量化的,通常不需要我们自己写循环结构,对 NumPy 不熟悉的小伙伴,可以移步到我的[《基于Python的数据分析》](https://www.zhihu.com/column/c_1217746527315496960)专栏。
需要说明的是,如果回归模型本身比较复杂,不像线性模型$\small{Y = aX + b}$这么简单,可能没有办法像上面那样直接求解方程,而是要通过其他的方式来找寻极值点,这个我们会在后续的内容中会为大家讲解。回到刚才的问题,我们可以通过上面的公式计算出$\small{a}$和$\small{b}$的值,为了运算方便,下面直接使用了 NumPy 中的函数,因为 NumPy 中的运算都是矢量化的,通常不需要我们自己写循环结构,对 NumPy 不熟悉的小伙伴,可以移步到我的[《基于Python的数据分析》](https://www.zhihu.com/column/c_1217746527315496960)专栏。
```python
import numpy as np

View File

@ -234,34 +234,34 @@ model.score(X_test, y_test)
1. **准确率**Accuracy
$$
准确率 = \frac{TP + TN}{TP + FP + FN + TN}
\text{准确率} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{FP} + \text{FN} + \text{TN}}
$$
上面的例子,模型预测的准确率为:$\small{\frac{80 + 870}{80 + 30 + 20 + 870} = \frac{950}{1000} = 95\%}$。
2. **精确率**Precesion。精确率用于衡量在所有被预测为正类的样本中实际上属于正类的比例通常也被称为查准率。
$$
精确率 = \frac{TP}{TP+FP}
精确率 = \frac{\text{TP}}{\text{TP} + \text{FP}}
$$
上面的例子,模型预测的精确率为:$\small{\frac{80}{80 + 30} = \frac{80}{110} = 72.73\%}$。
3. **召回率**Recall。召回率用于衡量在所有实际为正类的样本中被模型正确预测为正类的比例通常也被称为查全率或真正例率True Positive Rate
$$
召回率 = \frac{TP}{TP + FN}
召回率 = \frac{\text{TP}}{\text{TP} + \text{FN}}
$$
上面的例子,模型预测的召回率为:$\small{\frac{80}{80 + 20} = \frac{80}{100} = 80\%}$。
4. **F1 分数**F1 Score。F1 分数是精确率和召回率的调和平均数,它在精确率和召回率之间寻求一个平衡,尤其适用于在两者之间有权衡的情况。
$$
F1分数 = \frac{2}{\frac{1}{精确率} + \frac{1}{召回率}} = 2 \times \frac{精确率 \times 召回率}{精确率 + 召回率}
\text{F1分数} = \frac{2}{\frac{1}{\text{精确率}} + \frac{1}{\text{召回率}}} = 2 \times \frac{\text{精确率} \times \text{召回率}}{\text{精确率} + \text{召回率}}
$$
上面的例子模型预测的F1 分数为:$\small{2 \times \frac{0.7273 * 0.8}{0.7273 + 0.8} = 76.19\%}$。
5. **特异度**Specificity和**假正例率**False Positive Rate。特异度用于衡量的是在所有实际为负类的样本中被模型正确预测为负类的比例类似于召回率只不过针对的是负类样本。
$$
特异度 = \frac{TN}{TN + FP}
\text{特异度} = \frac{\text{TN}}{\text{TN} + \text{FP}}
$$
$$
假正例率 = 1 - 特异度
\text{假正例率} = 1 - \text{特异度}
$$
上面的例子,模型预测的特异度为:$\small{\frac{870}{870 + 30} = \frac{870}{900} = 96.67\%}$。
@ -383,7 +383,7 @@ from sklearn.model_selection import GridSearchCV
# 网格搜索交叉验证
gs = GridSearchCV(
KNeighborsClassifier(),
estimator=KNeighborsClassifier(),
param_grid={
'n_neighbors': [1, 3, 5, 7, 9, 11, 13, 15],
'weights': ['uniform', 'distance'],

View File

@ -29,9 +29,9 @@
$$
上面的公式也可以用向量的形式简化表示为:
$$
y = \bf{x}^{T} \bf{\beta} + \varepsilon
y = \mathbf{x}^{T} \mathbf{\beta} + \varepsilon
$$
其中,$\small{\bf{x} = [1, x_{1}, x_{2}, \dots, x_{n}]^{T}}$ 是包含截距的输入向量,$\small{\bf{\beta} = [\beta_{0}, \beta_{1}, \beta_{2}, \dots, \beta_{n}]^{T}}$ 是模型参数(包括截距 $\small{\beta_{0}}$ 和回归系数 $\small{\beta_{1}, \beta_{2}, \cdots, \beta_{n}}$$\small{\varepsilon}$ 是误差项。
其中,$\small{\mathbf{x} = [1, x_{1}, x_{2}, \dots, x_{n}]^{T}}$ 是包含截距的输入向量,$\small{\mathbf{\beta} = [\beta_{0}, \beta_{1}, \beta_{2}, \dots, \beta_{n}]^{T}}$ 是模型参数(包括截距 $\small{\beta_{0}}$ 和回归系数 $\small{\beta_{1}, \beta_{2}, \cdots, \beta_{n}}$$\small{\varepsilon}$ 是误差项。
2. **多项式回归**Polynomial Regression引入高阶特征使模型能拟合更复杂的非线性关系属于线性模型的扩展因为因为它对参数 $\small{\beta}$ 的求解仍然是线性形式,如下面所示的二次关系:
$$
@ -49,42 +49,42 @@
### 回归系数的计算
建立回归模型的关键是找到最佳的回归系数 $\small{\bf{\beta}}$,所谓最佳回归系数是指让模型对数据的拟合效果达到最好的模型参数,即能够最小化模型的预测值 $\small{\hat{y}_{i}}$ 与实际观测值 $\small{y_{i}}$ 之间差异的模型参数。为此,我们先定义如下所示的损失函数。
建立回归模型的关键是找到最佳的回归系数 $\small{\mathbf{\beta}}$,所谓最佳回归系数是指让模型对数据的拟合效果达到最好的模型参数,即能够最小化模型的预测值 $\small{\hat{y}_{i}}$ 与实际观测值 $\small{y_{i}}$ 之间差异的模型参数。为此,我们先定义如下所示的损失函数。
$$
L(\bf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2}
L(\mathbf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2}
$$
其中,$\small{m}$表示样本容量,代入回归模型,有:
$$
L(\bf{\beta}) = \sum_{i=1}^{m}(y_{i} - \bf{x}_{i}^{T}\bf{\beta})^{2}
L(\mathbf{\beta}) = \sum_{i=1}^{m}(y_{i} - \mathbf{x}_{i}^{T}\mathbf{\beta})^{2}
$$
如果用矩阵形式表示,有:
$$
L(\bf{\beta}) = (\bf{y} - \bf{X\beta})^{T}(\bf{y} - \bf{X\beta})
L(\mathbf{\beta}) = (\mathbf{y} - \mathbf{X\beta})^{T}(\mathbf{y} - \mathbf{X\beta})
$$
其中,$\bf{y}$ 是目标值的向量,大小为 $\small{m \times 1}$$\bf{X}$ 是特征矩阵,大小为 $\small{m \times n}$$\small{\bf{\beta}}$ 是回归系数的向量,大小为 $\small{n \times 1}$。
其中,$\mathbf{y}$ 是目标值的向量,大小为 $\small{m \times 1}$$\mathbf{X}$ 是特征矩阵,大小为 $\small{m \times n}$$\small{\mathbf{\beta}}$ 是回归系数的向量,大小为 $\small{n \times 1}$。
通过最小化损失函数 $\small{L(\bf{\beta})}$,我们可以得到线性回归模型的解析解。对 $\small{L(\bf{\beta})}$ 求导并令其为 0
通过最小化损失函数 $\small{L(\mathbf{\beta})}$,我们可以得到线性回归模型的解析解。对 $\small{L(\mathbf{\beta})}$ 求导并令其为 0
$$
\frac{\partial{L(\bf{\beta})}}{\partial{\bf{\beta}}} = -2\bf{X}^{T}(\bf{y} - \bf{X\beta}) = 0
\frac{\partial{L(\mathbf{\beta})}}{\partial{\mathbf{\beta}}} = -2\mathbf{X}^{T}(\mathbf{y} - \mathbf{X\beta}) = 0
$$
整理后得到:
$$
\bf{\beta} = (\bf{X}^{T}\bf{X})^{-1}\bf{X}^{T}\bf{y}
\mathbf{\beta} = (\mathbf{X}^{T}\mathbf{X})^{-1}\mathbf{X}^{T}\mathbf{y}
$$
对于矩阵 $\small{\bf{X}^{T}\bf{X}}$ 不满秩的情况,可以通过添加正则化项的方式使得矩阵可逆,如下所示,这个就是线性回归的解析解。
对于矩阵 $\small{\mathbf{X}^{T}\mathbf{X}}$ 不满秩的情况,可以通过添加正则化项的方式使得矩阵可逆,如下所示,这个就是线性回归的解析解。
$$
\bf{\beta} = (\bf{X}^{T}\bf{X} + \bf{\lambda \mit{I}})^{-1}\bf{X}^{T}\bf{y}
\mathbf{\beta} = (\mathbf{X}^{T}\mathbf{X} + \mathbf{\lambda \mit{I}})^{-1}\mathbf{X}^{T}\mathbf{y}
$$
> **说明**:如果你对这里提到的正则化不理解可以先放放,后面我们再来讨论这个问题。
上述方法适用于小规模数据集,当数据体量不大(样本和特征数量较少)时,计算效率是没有问题的。对于大规模数据集或更为复杂的优化问题,我们可以使用**梯度下降法**,通过迭代更新参数来逐步逼近最优解。梯度下降法的目标也是最小化损失函数,该方法通过计算梯度方向进行参数更新。梯度是一个向量,包含了目标函数在各个参数方向上的偏导数。对于上面的损失函数 $\small{L(\bf{\beta})}$,梯度可以表示为:
上述方法适用于小规模数据集,当数据体量不大(样本和特征数量较少)时,计算效率是没有问题的。对于大规模数据集或更为复杂的优化问题,我们可以使用**梯度下降法**,通过迭代更新参数来逐步逼近最优解。梯度下降法的目标也是最小化损失函数,该方法通过计算梯度方向进行参数更新。梯度是一个向量,包含了目标函数在各个参数方向上的偏导数。对于上面的损失函数 $\small{L(\mathbf{\beta})}$,梯度可以表示为:
$$
\nabla L(\bf{\beta}) = \left[ \frac{\partial{L}}{\partial{\beta_{1}}}, \frac{\partial{L}}{\partial{\beta_{2}}}, \cdots, \frac{\partial{L}}{\partial{\beta_{n}}} \right]
\nabla L(\mathbf{\beta}) = \left[ \frac{\partial{L}}{\partial{\beta_{1}}}, \frac{\partial{L}}{\partial{\beta_{2}}}, \cdots, \frac{\partial{L}}{\partial{\beta_{n}}} \right]
$$
梯度下降法通过以下更新规则来更新参数 $\small{\bf{\beta}}$
梯度下降法通过以下更新规则来更新参数 $\small{\mathbf{\beta}}$
$$
\bf{\beta}^{\prime} = \bf{\beta} - \alpha \nabla L(\bf{\beta}) \\
\bf{\beta} = \bf{\beta^{\prime}}
\mathbf{\beta}^{\prime} = \mathbf{\beta} - \alpha \nabla L(\mathbf{\beta}) \\
\mathbf{\beta} = \mathbf{\beta^{\prime}}
$$
其中,$\small{\alpha}$ 是学习率step size通常是一个较小的正数用于控制每次更新的幅度。如果学习率 $\small{\alpha}$ 选择得当,梯度下降法将收敛到目标函数的局部最小值。如果学习率过大,可能导致震荡不收敛;如果学习率过小,则收敛的速度缓慢,需要更多次的迭代。
@ -253,7 +253,7 @@ print('截距:', model.intercept_)
$$
R^{2} = 1 - \frac{\text{SS}_{\text{res}}}{\text{SS}_{\text{tot}}}
$$
其中,$\text{SS}_{\text{res}} = \sum_{i=1}^{m}(y_i - \hat{y}_i)^2$ 为残差平方和,$\text{SS}_{\text{tot}} = \sum_{i=1}^{m} (y_i - \bar{y})^{2}$ 为总平方和,如下图所示。下图左边红色正方形的面积之和代表总平方和,右边蓝色正方形的面积之和代表残差的平方和,很显然,模型拟合的效果越好,$\small{\frac{\text{SS}_{\text{res}}}{\text{SS}_{\text{tot}}}}$的值就越接近 0$\small{R^{2}}$的值就越接近 1。通常$\small{R^{2} \ge 0.8}$时,我们认为模型的拟合效果已经很不错了。
其中,$\small{\text{SS}_{\text{res}} = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^2}$ 为残差平方和,$\small{\text{SS}_{\text{tot}} = \sum_{i=1}^{m} (y_{i} - \bar{y})^{2}}$ 为总平方和,如下图所示。下图左边红色正方形的面积之和代表总平方和,右边蓝色正方形的面积之和代表残差的平方和,很显然,模型拟合的效果越好,$\small{\frac{\text{SS}_{\text{res}}}{\text{SS}_{\text{tot}}}}$的值就越接近 0$\small{R^{2}}$的值就越接近 1。通常$\small{R^{2} \ge 0.8}$时,我们认为模型的拟合效果已经很不错了。
<img src="res/05_regression_r2.png" style="zoom:40%;">
@ -283,7 +283,7 @@ print(f'决定系数: {r2:.4f}')
岭回归是在线性回归的基础上引入 $\small{L2}$ 正则化项,目的是防止模型过拟合,尤其是当特征数较多或特征之间存在共线性时。岭回归的损失函数如下所示:
$$
L(\bf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \lambda \sum_{j=1}^{n}\beta_{j}^{2}
L(\mathbf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \lambda \sum_{j=1}^{n}\beta_{j}^{2}
$$
其中,$\small{L2}$ 正则化项 $\small{\lambda \sum_{j=1}^{n} \beta_{j}^{2}}$ 会惩罚较大的回归系数,相当于缩小了回归系数的大小,但不会使系数为 0即不会进行特征选择。可以通过 scikit-learn 库`linear_model`模块的`Ridge`类实现岭回归,代码如下所示。
@ -313,9 +313,9 @@ print(f'决定系数: {r2:.4f}')
套索回归引入 $\small{L1}$ 正则化项,不仅防止过拟合,还具有特征选择的功,特别适用于高维数据。套索回归的损失函数如下所示:
$$
L(\bf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \lambda \sum_{j=1}^{n}|\beta_{j}|
L(\mathbf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \lambda \sum_{j=1}^{n}|\beta_{j}|
$$
其中,$\small{L1}$ 正则化项 $\small{\lambda \sum_{j=1}^{n}|\beta_{j}|}$ 会将某些不重要的回归系数缩减为 0从而实现特征选择。可以通过 scikit-learn 库`linear_model`模块的`Lasso`类实现回归,代码如下所示。
其中,$\small{L1}$ 正则化项 $\small{\lambda \sum_{j=1}^{n}|\beta_{j}|}$ 会将某些不重要的回归系数缩减为 0从而实现特征选择。可以通过 scikit-learn 库`linear_model`模块的`Lasso`类实现套索回归,代码如下所示。
```python
from sklearn.linear_model import Lasso
@ -345,7 +345,7 @@ print(f'决定系数: {r2:.4f}')
弹性网络回归结合了岭回归和套索回归的优点,通过同时引入 $\small{L1}$ 和 $\small{L2}$ 正则化项,适用于高维数据且特征之间存在相关的情况,其损失函数如下所示:
$$
L(\bf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \alpha \lambda \sum_{j=1}^{n}|\beta_{j}| + (1 - \alpha) \lambda \sum_{j=1}^{n}\beta_{j}^{2}
L(\mathbf{\beta}) = \sum_{i=1}^{m}(y_{i} - \hat{y}_{i})^{2} + \alpha \lambda \sum_{j=1}^{n}|\beta_{j}| + (1 - \alpha) \lambda \sum_{j=1}^{n}\beta_{j}^{2}
$$
其中,$\small{\alpha}$ 是控制 $\small{L1}$ 和 $\small{L2}$ 正则化的权重比例。
@ -447,7 +447,7 @@ plt.show()
<img src="res/05_polynomial_line_fit.png" style="zoom:50%;">
我们再看看 $\small{R^{2}}$ 的值:
很显然,这是一个欠拟合的结果。我们再看看 $\small{R^{2}}$ 的值:
```python
r2 = r2_score(y, y_pred)