系列文章目录
监督学习:参数方法
【学习笔记】 陈强-机器学习-Python-Ch4 线性回归
【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归
【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv)
【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析
【学习笔记】 陈强-机器学习-Python-Ch8 朴素贝叶斯
【学习笔记】 陈强-机器学习-Python-Ch9 惩罚回归
【课后题练习】 陈强-机器学习-Python-Ch9 惩罚回归(student-mat.csv)
监督学习:非参数方法
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch10 KNN法
【学习笔记】 陈强-机器学习-Python-Ch11 决策树(Decision Tree)
监督学习:集成学习
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch12 随机森林(Random Forest)
【学习笔记】 陈强-机器学习-Python-Ch13 提升法
监督学习:支持向量机
【学习笔记】 陈强-机器学习-Python-Ch14 支持向量机
监督学习:人工神经网络
文章目录
- 系列文章目录
- 监督学习:参数方法
- 监督学习:非参数方法
- 监督学习:集成学习
- 监督学习:支持向量机
- 监督学习:人工神经网络
- 前言
- 一、人工神经网络(Artificial Neural Networks, ANN)
- 正则化
- 二、ANN回归 (使用sklearn)
- 1. 载入、处理数据
- 2. ANN 模型 估计:单一隐藏层(包含5个神经元)
- `笔记:MLPRegressor()`
- 【参数介绍】
- 属性
- 3. 画 神经网络系数矩阵的热图
- 4.特征变量的置换重要性
- 1)计算 置换重要性
- 2)画 置换重要性的水平箱型图
- 解读
- 3)查看 置换重要性的具体取值
- 4)画 偏依赖图
- 5. 最优神经元数目(拟合优度)
- 1)使用 f o r for for循环找出最优神经元个数(最高 R 2 R^2 R2 )
- 2)画图展示
- 3)最优模型
- 4)画偏依赖图
- 5. ANN:2个隐藏层
- 6. 2个隐藏层的最优神经元数目
- 三、ANN分类 (使用sklearn)
- 1. 载入、处理数据
- 2. ANN 模型 估计
- 1)单一隐藏层(包含100个神经元)
- `笔记:MLPClassifier()`
- 2)2个隐藏层,神经元都是500个
- 3. 正则化
- 1)早停(Early Stopping)
- 2)权重衰减(Weight Decay)
- 4. 选出 最优惩罚参数
- 1)计算 混淆矩阵
- 2)生成月亮形状的模型数据
- `笔记:make_moons()`
- 3)加入随机噪音
- 4)生成1000个观测值,构建测试集
- 5)计算测试集的预测准确率
- 6) f o r for for 循环考察惩罚参数的正则化作用(决策边界)
- `笔记:enumerate()`
前言
本学习笔记 仅为以防自己忘记了,顺便分享给一起学习的网友们参考。如有不同意见/建议,可以友好讨论。
本学习笔记 所有的代码和数据都可以从 陈强老师的个人主页 上下载
参考书目:陈强.机器学习及Python应用. 北京:高等教育出版社, 2021.
数学原理等 详见陈强老师的 PPT
参考了:网友阡之尘埃的Python机器学习12——神经网络
一、人工神经网络(Artificial Neural Networks, ANN)
人工神经网络(Artificial Neural Networks, ANN) 是一种模仿生物神经网络结构和功能的计算模型,广泛应用于机器学习和人工智能领域。它由多个神经元(或节点)组成,通过连接(或权重)形成层次结构,用于处理复杂的输入数据并进行预测、分类等任务。
激活函数决定每个神经元的输出值,增加了网络的非线性能力。常见的激活函数包括:
· Sigmoid:
σ
(
x
)
=
11
+
e
x
p
(
−
x
)
σ
(
x
)
=
1
+
e
x
p
(
−
x
)
1
σ(x)=11+exp(−x)σ(x)=1+exp(−x)1
σ(x)=11+exp(−x)σ(x)=1+exp(−x)1
· ReLU (Rectified Linear Unit):
R
e
L
U
(
x
)
=
m
a
x
(
0
,
x
)
ReLU(x)=max(0,x)
ReLU(x)=max(0,x)
· Tanh (Hyperbolic Tangent):
t
a
n
h
(
x
)
=
e
x
p
(
x
)
−
e
x
p
(
−
x
)
e
x
p
(
x
)
+
e
x
p
(
−
x
)
tanh(x)=\frac{exp(x)−exp(−x)}{exp(x)+exp(−x)}
tanh(x)=exp(x)+exp(−x)exp(x)−exp(−x)
· Softmax: 通常用于分类问题,将输出转换为概率分布。
优化算法用于调整权重和偏置,以最小化损失函数。常见的优化算法包括:
- 梯度下降(Gradient Descent): 基本优化算法,通过计算损失函数的梯度来更新权重。
- Adam(Adaptive Moment Estimation): 自适应学习率的优化算法,结合了梯度下降的优点。
正则化
提前停止(Early Stopping):在训练过程中监控验证集上的性能,当性能不再提升时停止训练。有助于防止训练过程中过拟合。
- 实现方法: 记录训练过程中验证集的损失或准确率。当验证集性能不再改善(或恶化)时,停止训练。
权重衰减(Weight Decay):与L2正则化类似,通过在损失函数中添加权重的平方和来实现。主要用于控制权重的大小,防止模型过于复杂。
噪声注入: 在输入数据、权重更新或激活层中加入噪声,以提高模型的鲁棒性。可以防止模型对训练数据的过度拟合。
二、ANN回归 (使用sklearn)
以波士顿房价数据 boston为例(参见【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 )
1. 载入、处理数据
import numpy as np
import pandas as pd
#读取CSV文件的路径
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\spam.csv'
spam = pd.read_csv(csv_path)
#定义X与y
X = spam.iloc[:, :-1]
y = spam.iloc[:, -1]
#全样本随机分20%测试集和80%训练集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
stratify=y,
random_state=0)
#特征变量 标准化
from sklearn.preprocessing import StandardScaler
#生成一个实例scaler
scaler = StandardScaler()
#进行估计
scaler.fit(X_train)
#使用transform()分别将 训练集、测试集的特征变量进行标准化
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)
2. ANN 模型 估计:单一隐藏层(包含5个神经元)
from sklearn.neural_network import MLPRegressor
model = MLPRegressor(
solver='lbfgs', #L-BFGS算法,一种准牛顿算法
hidden_layer_sizes=(5,), #单一隐藏层,包含5个神经元
random_state=123,
max_iter=10000)
model.fit(X_train_s, y_train)
model.score(X_test_s, y_test)
结果输出: 0.8570418638979551
#查看迭代次数
model.n_iter_
结果输出: 326
笔记:MLPRegressor()
MLPRegressor 是 scikit-learn 中的一个多层感知器(MLP)回归器,用于通过使用一个或多个隐藏层的神经网络模型来实现回归任务。这是一个非常灵活的工具,能够拟合非线性模型。
#基本语法和参数
from sklearn.neural_network import MLPClassifier
#创建模型
model = MLPRegressor(
hidden_layer_sizes=(100, ), #元组,表示每个隐藏层的神经元数目。默认 (100,)。例如 (50, 50) 表示两层,每层50个神经元。
activation='relu', #激活函数的选择,可选 'identity', 'logistic', 'tanh', 'relu'。默认:'relu'
solver='adam', #优化器的选择,可选 'lbfgs', 'sgd', 'adam'。默认:'adam'
alpha=0.0001, #L2惩罚(正则化项)的系数。默认:0.0001
batch_size='auto', #每次优化的小批量样本大小,默认:'auto' 表示 min(200, n_samples)。
learning_rate='constant', #学习率的调整策略,可选 'constant', 'invscaling', 'adaptive'。默认:'constant'
learning_rate_init=0.001, #初始学习率。默认:0.001
power_t=0.5, #逆扩展学习率的指数。默认:0.5
max_iter=200, #最大迭代次数。默认:200
shuffle=True, #是否在每次迭代前打乱样本。默认:True
random_state=None,
tol=0.0001, #优化的容忍度。默认:0.0001
verbose=False, #是否打印进度消息。默认:False
warm_start=False, #是否使用前一次训练结果继续训练。默认:False
momentum=0.9, #动量的值,【仅当 solver='sgd' 时使用】。默认:0.9
nesterovs_momentum=True, #是否使用 Nesterov 动量。默认:True
early_stopping=False, #是否提前停止训练以防止过拟合。默认:False
validation_fraction=0.1, #用于早停的验证集的比例。默认:0.1
beta_1=0.9, #用于计算梯度及其平方的指数衰减率,【仅在 solver='adam' 时使用】。默认:0.9
beta_2=0.999, #用于计算梯度及其平方的指数衰减率,【仅在 solver='adam' 时使用,用于梯度平方的计算】。默认:0.999
epsilon=1e-8, #数值稳定性参数,【仅在 solver='adam' 时使用】。默认:1e-8
n_iter_no_change=10, #用于早停的连续迭代次数,无改进时停止。默认:10
max_fun=15000) #【lbfgs 求解器】的最大函数求值次数。默认:15000
【参数介绍】
activation
用于定义神经网络每个隐藏层中的激活函数。激活函数的作用是在神经元的输出上应用一个非线性变换,这是神经网络能够学习和执行更复杂任务的关键。identity
:无激活函数,输出等于输入。也就是说,激活函数 f ( x ) = x f(x)=x f(x)=x。logistic
逻辑S型激活函数,表达式为 f ( x ) = 1 1 + e − x f(x)=\frac{1}{1+e^{−x}} f(x)=1+e−x1。- 此激活函数可以输出介于 0 和 1 之间的值,适用于需要输出概率或者需要强烈非线性的场景。因为它容易产生梯度消失,所以在深层网络中较少使用。
tanh
双曲正切激活函数,表达式为 f ( x ) = t a n h ( x ) f(x)=tanh(x) f(x)=tanh(x)。- 此激活函数的输出介于 -1 和 1 之间。它比逻辑激活函数表现出更好的性能,因为其输出以 0 为中心,通常用于隐藏层。
relu
线性整流单元(Rectified Linear Unit),表达式为 f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x)。- ReLU 函数是最常用的激活函数之一,因为它在正区间内梯度恒定,避免了梯度消失问题,且计算简单。适用于大多数问题,尤其是深度学习网络。
solver
用于选择用于权重优化的算法。adam
Adam(Adaptive Moment Estimation)是一个相对较新的优化算法,它结合了 AdaGrad 和 RMSProp 算法的优点。- 它可以自适应地调整每个参数的学习率,并且通常表现出较快的收敛速度,在很多情况下都工作得很好。
- 适合处理大规模的数据和参数量,因为它在每次迭代中有效地调整学习率,也适用于不是很平滑的数据。
- 相对于其他求解器,它更加健壮,尤其是在模型结构较复杂或数据规模较大的情况下。
- 大数据集和/或复杂模型:通常推荐使用 ‘adam’,因为它能够有效地处理大规模问题并且默认设置通常表现良好。
sgd
SGD(Stochastic Gradient Descent)是最传统的优化算法,通过随机选择样本来更新权重。- 它使用固定的学习率进行权重更新,也可以通过设置
learning_rate
参数为 ‘invscaling’ 来逐渐减小学习率。 - SGD 的优点在于简单,但它可能需要更多的迭代次数才能收敛,特别是在学习率选择不恰当的情况下。
- 可以通过参数如
momentum
和nesterovs_momentum
来增强其性能,这些参数可以帮助克服局部极小值的问题和加速收敛。 - 对收敛速度有特殊要求:如果需要更细粒度的控制或想要尝试不同的学习率调整策略,'sgd’可能是一个不错的选择,特别是当加入动量等参数优化时。
- 它使用固定的学习率进行权重更新,也可以通过设置
lbfgs
L-BFGS(Limited-memory Broyden–Fletcher–Goldfarb–Shanno Algorithm)是一个基于拟牛顿方法的优化器,适合处理小到中等规模的数据集。- 它是一种二阶优化算法,相较于 SGD,它在每次迭代中利用更多的历史信息来更新权重,从而通常能更快地收敛。
- L-BFGS 适用于数据较少、特征较少的场景,因为它在内存使用上更为高效,但在非常大的数据集上可能会遇到性能问题。
- 小到中等数据集:可以考虑 ‘lbfgs’,尤其是当模型相对简单且数据量不是很大时。
learning_rate
用于指定用于权重更新的学习率的调整策略。学习率是控制模型学习速度的关键参数,选择合适的学习率调整策略可以帮助模型更好地收敛。constant
学习率在整个训练过程中保持不变。这适用于数据规模不是特别大,或者训练不需要过分精细调整的情况。invscaling
逆缩放调整,学习率随着时间 t t t 的增加按某种功能规模逐渐减小,通常按照 1 t p o w e r t \frac{1}{t^ {power _t} } tpowert1 减少,其中power_t
是一个用户定义的指数。- 适用于需要随着训练的进行逐步减小学习率以细致调整模型参数的场景。这种策略有助于在训练初期快速收敛,并在训练后期通过较小的步长提高模型的稳定性和性能。
adaptive
如果在设置的迭代次数内,训练集的损失没有改善,学习率将会被减少。- 当模型的训练过程中出现停滞或者损失不再减少时,这种策略可以动态调整学习率,尝试摆脱局部最小值或促进进一步的收敛。这适用于那些对初始学习率比较敏感,或者训练过程中需要自适应调整以优化性能的复杂模型。
属性
coefs_: 网络中每个层的权重矩阵。
intercepts_: 网络中每个层的偏差向量。
n_iter_: 训练时的迭代次数。
loss_: 最终的损失函数值。
n_layers_: 网络的总层数。
n_outputs_: 输出层的单元数。
out_activation_: 输出层的激活函数。
3. 画 神经网络系数矩阵的热图
import matplotlib.pyplot as plt
import seaborn as sns
table = pd.DataFrame(
model.coefs_[0],
index=columns,
columns=[1,2,3,4,5])
sns.heatmap(abs(table), #abs 绝对值
cmap='Blues', annot=True)
plt.xlabel('Neuron')
plt.title('Neural Network Weights (Absolute Values)')
plt.tight_layout()
由图可见,第二个神经元、第四个神经元的权重绝对值最大
4.特征变量的置换重要性
对于神经网络模型,无法像决策树模型(决策树、随机森林或提升法)那样计算每个变量的重要性。替代方法之一:计算每个变量的置换重要性(permutation importance)。
1)计算 置换重要性
**置换重要性(Permutation Importance)**是一种用于评估特征对模型预测影响的技术。它通过打乱特征的值来测量模型性能的下降,从而判断该特征的重要性。
步骤:
1)训练模型:使用完整的数据集训练模型。
2)计算基准分数:在未打乱特征之前,计算模型的性能指标(如准确率、AUC等)。
3)打乱特征:对一个特征进行随机打乱,使其与目标变量的关系被破坏。
重新计算分数:在打乱后的数据上评估模型性能。
4)计算重要性:重要性等于基准分数与打乱后分数的差异,差异越大,说明特征的重要性越高。
#特征变量的置换重要性 permutation_importance()
from sklearn.inspection import permutation_importance
result = permutation_importance(
model,
X_test_s,
y_test,
n_repeats=20, #重复20次
random_state=42)
dir(result) #查看result的组成
结果输出: [‘importances’, ‘importances_mean’, ‘importances_std’] result 对象包含三个主要属性:importances 每个特征在每次置换中重要性的值;importances_mean 每个特征的重要性的平均值;importances_std 每个特征重要性的标准差,显示该特征重要性估计的变异性。
2)画 置换重要性的水平箱型图
置换重要性的水平箱型图(Horizontal Box Plot for Permutation Importance)是一种用于可视化特征重要性分布的图形方法。它可以帮助我们理解每个特征对模型性能的影响,以及各特征在多次置换中的表现波动情况。
#画 置换重要性的水平箱型图
index = result.importances_mean.argsort()
plt.boxplot(result.importances[index].T,
vert=False, #水平箱型图
labels=X_test.columns[index])
plt.title('Permutation Importances')
解读
箱体(Box):表示特征重要性的四分位数范围(从 25% 到 75%),中间的线为中位数。箱体的长度显示了该特征重要性值的集中程度。
须(Whiskers):伸展至箱体的上下边缘,表示数据的范围(通常为 1.5 倍四分位距)。须外的点表示异常值。
中位数线(Median Line):箱体中的水平线表示该特征的重要性中位数,提供了该特征的重要性的中心趋势。
异常值(Outliers):箱体须之外的点表示异常值,显示了特征重要性估计中的极端变化。
3)查看 置换重要性的具体取值
pd.DataFrame(
result.importances_mean[index],
index=X_test.columns[index],
columns=['mean_importance'])
结果输出:
由置换重要性的水平箱型图和取值 可知,LASTAT和RM是最重要的两个变量,与决策树、随机森林、提升法所得结果一致。
4)画 偏依赖图
# 画偏依赖图
from sklearn.inspection import PartialDependenceDisplay
PartialDependenceDisplay.from_estimator(model, X_train_s, ['LSTAT', 'RM'])
结果输出:
5. 最优神经元数目(拟合优度)
1)使用 f o r for for循环找出最优神经元个数(最高 R 2 R^2 R2 )
'''寻找最优神经元个数:R^2'''
#for循环
scores = []
for n_neurons in range(1, 41): #神经元取值范围1-41
model = MLPRegressor(
solver='lbfgs',
hidden_layer_sizes=(n_neurons,),
random_state=123, max_iter=10000)
model.fit(X_train_s, y_train)
score = model.score(X_test_s, y_test)
scores.append(score)
index = np.argmax(scores)
range(1, 41)[index]
结果输出: 8
2)画图展示
#画出 折线图
plt.plot(range(1, 41), scores, 'o-')
plt.axvline(range(1, 101)[index],
linestyle='--', color='k', linewidth=1)
plt.axhline(max(scores),
linewidth=1, linestyle='--', color='r')
# 标记交点
best_n_nodes = range(1, 41)[index]
best_score = max(scores)
plt.scatter(best_n_nodes, best_score, color='b', zorder=5)
plt.text(best_n_nodes,
best_score, f'({best_n_nodes}, {best_score:.6f})',
horizontalalignment='right',
verticalalignment='bottom', fontsize=11, color='b')
plt.xlabel('Number of Nodes')
plt.ylabel('R2')
plt.title('Test Set R2 vs Number of Nodes')
3)最优模型
model = MLPRegressor(
solver='lbfgs',
hidden_layer_sizes=(8,),
random_state=123,
max_iter=10000)
model.fit(X_train_s, y_train)
model.score(X_test_s, y_test)
结果输出: 0.9029614612418355
4)画偏依赖图
PartialDependenceDisplay.from_estimator(
model, X_train_s, ['LSTAT', 'RM'])
结果输出:
RM对响应变量的MEDV的偏作用不再是先降后升的非单调关系了。
5. ANN:2个隐藏层
model = MLPRegressor(
solver='lbfgs',
hidden_layer_sizes=(5,5), #2隐藏层,包含5个神经元
random_state=123,
max_iter=10000)
model.fit(X_train_s, y_train)
model.score(X_test_s, y_test)
结果输出: 0.8826157510840963
6. 2个隐藏层的最优神经元数目
#双重for循环:同时选出第1、第2层的最优神经元数目
best_score = 0
best_sizes = (1, 1)
for i in range(1, 11):
for j in range(1, 11):
model = MLPRegressor(solver='lbfgs', hidden_layer_sizes=(i, j), random_state=123, max_iter=10000)
model.fit(X_train_s, y_train)
score = model.score(X_test_s, y_test)
if best_score < score:
best_score = score
best_sizes = (i, j)
best_score
结果输出: 0.9088351462167137
#展示最优模型的网络结构
best_sizes
结果输出: (8, 10) 第一层8个,第二层10个
三、ANN分类 (使用sklearn)
使用过滤垃圾邮件的spam数据( 参见【学习笔记】 陈强-机器学习-Python-Ch8 朴素贝叶斯 )
1. 载入、处理数据
import numpy as np
import pandas as pd
#读取CSV文件的路径
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\spam.csv'
spam = pd.read_csv(csv_path)
#定义X与y
X = spam.iloc[:, :-1]
y = spam.iloc[:, -1]
#全样本随机分20%测试集和80%训练集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
stratify=y,
random_state=0)
#特征变量 标准化
from sklearn.preprocessing import StandardScaler
#生成一个实例scaler
scaler = StandardScaler()
#进行估计
scaler.fit(X_train)
#使用transform()分别将 训练集、测试集的特征变量进行标准化
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)
2. ANN 模型 估计
1)单一隐藏层(包含100个神经元)
from sklearn.neural_network import MLPClassifier
model = MLPClassifier( #默认solver= 'adam'。
hidden_layer_sizes=(100,), #单隐藏层,100个神经元
random_state=123, max_iter=10000)
model.fit(X_train_s, y_train)
model.score(X_test_s, y_test)
结果输出: 0.9489685124864278
#查看迭代次数
model.n_iter_
结果输出: 283
笔记:MLPClassifier()
MLPClassifier() 是 Scikit-Learn 库中的一个类,用于实现多层感知器(MLP)算法,这是一种监督学习算法,通过训练数据来进行分类。MLP 属于神经网络的一种,可以用于解决复杂的模式识别和分类问题。
#基本语法和参数
from sklearn.neural_network import MLPClassifier
#创建模型
model = MLPClassifier(
hidden_layer_sizes=(100,), #元组,表示每个隐藏层的神经元数目。默认 (100,)
activation='relu', #激活函数的类型:'identity', 'logistic', 'tanh', 或 'relu'。默认为 'relu'。
solver='adam', #用于优化权重的求解器:'lbfgs', 'sgd', 或 'adam'。默认为 'adam'。
alpha=0.0001, #L2 正则化参数,用于控制过拟合。默认值为 0.0001。
batch_size='auto', #每次迭代用于训练网络的最小样本数。默认为 'auto',即 min(200, n_samples)。
learning_rate='constant', #学习率调度策略,可选 'constant', 'invscaling' 或 'adaptive'。默认为 'constant'。
learning_rate_init=0.001, #初始学习率。默认:0.001
power_t=0.5, #逆扩展学习率的指数。默认:0.5
max_iter=200, #最大迭代次数。默认:200
shuffle=True, #是否在每次迭代前打乱样本。默认:True
random_state=None,
tol=0.0001, #优化的容忍度。默认:0.0001
verbose=False, #是否打印进度消息。默认:False
warm_start=False, #是否使用前一次训练结果继续训练。默认:False
momentum=0.9, #动量的值,【仅当 solver='sgd' 时使用】。默认:0.9
nesterovs_momentum=True, #是否使用 Nesterov 动量。默认:True
early_stopping=False, #是否提前停止训练以防止过拟合。默认:False
validation_fraction=0.1, #用于早停的验证集的比例。默认:0.1
beta_1=0.9, #用于计算梯度及其平方的指数衰减率,【仅在 solver='adam' 时使用】。默认:0.9
beta_2=0.999, #用于计算梯度及其平方的指数衰减率,【仅在 solver='adam' 时使用,用于梯度平方的计算】。默认:0.999
epsilon=1e-8, #数值稳定性参数,【仅在 solver='adam' 时使用】。默认:1e-8
n_iter_no_change=10, #用于早停的连续迭代次数,无改进时停止。默认:10
max_fun=15000) #【lbfgs 求解器】的最大函数求值次数。默认:15000
2)2个隐藏层,神经元都是500个
model = MLPClassifier(
hidden_layer_sizes=(500, 500), #2个隐藏层,神经元都是500个
random_state=123, max_iter=10000)
model.fit(X_train_s, y_train)
model.score(X_test_s, y_test)
结果输出: 0.9391965255157437
#查看迭代次数
model.n_iter_
结果输出: 44
3. 正则化
以上结果显示,模型可能已经过拟合。
**正则化(Regularization)**是一种用于防止机器学习模型过拟合(overfitting)的方法。它通过在模型训练过程中加入额外的惩罚项来限制模型的复杂度,从而使模型在面对新数据时具有更好的泛化能力。
1)早停(Early Stopping)
#采用 早停的方法进行正则化
model_es = MLPClassifier(
hidden_layer_sizes=(500, 500),
early_stopping=True, #早停
validation_fraction=0.25, #随机选取25%的训练集作为验证集
random_state=123, max_iter=10000)
model_es.fit(X_train_s, y_train)
model_es.score(X_test_s, y_test)
结果输出: 0.9457111834961998 提高了一点
#查看迭代次数
model_es.n_iter_
结果输出: 30 迭代次数下降
2)权重衰减(Weight Decay)
#采用 权重衰退的方法进行正则化
model_wd = MLPClassifier(
hidden_layer_sizes=(500,500),
alpha=0.1, #将L_2惩罚参数设为0.1
random_state=123,max_iter=10000)
model_wd.fit(X_train_s, y_train)
model_wd.score(X_test_s, y_test)
结果输出: 0.9467969598262758 提高了一点
#查看迭代次数
model_wd.n_iter_
结果输出: 65迭代次数有所增加
4. 选出 最优惩罚参数
1)计算 混淆矩阵
pred = model_wd.predict(X_test_s)
from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_predictions(
y_test, pred)
结果输出:
2)生成月亮形状的模型数据
from sklearn.datasets import make_moons
X,y = make_moons(n_samples=100)
#画图展示
import matplotlib.pyplot as plt
import seaborn as sns
data = pd.DataFrame(X, columns=['x1','x2'])
sns.scatterplot(x='x1', y ='x2',
data=data,
hue=y, palette=['blue','black'])
结果输出:
make_moons()默认生产确定性的两类数据。
笔记:make_moons()
make_moons() 是一个用于生成二分类数据集的函数,常用于测试分类算法。它生成两个半月形状的分类数据点,通常用于演示机器学习模型的性能,尤其是在具有非线性决策边界的任务中。
#基本语法和参数
from sklearn.datasets import make_moons
# 生成数据
X, y = make_moons(
n_samples=100, #生成的数据点的总数。如果是单个整数,则生成相同数量的正负样本。默认:100
noise=0.2, #数据点的噪声水平。这个值表示添加到数据中的高斯噪声的标准差,较大的值会使数据点分布更加模糊。默认:0.2
random_state=None)
#返回值
# X (array of shape [n_samples, 2]):生成的特征数据,形状为 (n_samples, 2)。
# y (array of shape [n_samples]):生成的目标标签,包含 0 和 1 两个类别。
3)加入随机噪音
X,y = make_moons(n_samples=100,
noise=0.3, #加入标准差=0.3的正态随机变量
random_state=0)
#画图展示
data = pd.DataFrame(X, columns=['x1','x2'])
sns.scatterplot(x='x1', y ='x2',
data=data,
hue=y, palette=['blue','black'])
结果输出:
4)生成1000个观测值,构建测试集
X_test, y_test = make_moons(
n_samples=1100,
noise=0.3,
random_state=0)
X_test = X_test[100:, :]
y_test = y_test[100:]
5)计算测试集的预测准确率
#估计双隐藏测模型
model = MLPClassifier(
hidden_layer_sizes=(100, 100),
random_state=123, max_iter=10000)
model.fit(X, y)
#计算 测试集的预测准确率
model.score(X_test, y_test)
结果输出: 0.895
6) f o r for for 循环考察惩罚参数的正则化作用(决策边界)
from mlxtend.plotting import plot_decision_regions
plt.figure(figsize=(9, 6)) #设定画布尺寸
for i, alpha in enumerate([0.01, 0.1, 1, 10]): #alpha取值分布为0.01, 0.1, 1, 10
model = MLPClassifier(
hidden_layer_sizes=(100, 100),
alpha=alpha,
random_state=123, max_iter=10000)
model.fit(X, y)
plt.subplot(2, 2, i + 1)
accuracy = model.score(X_test, y_test)
plot_decision_regions(X, y, model, legend=0)
plt.xlabel('x1')
plt.ylabel('x2')
plt.title(f'alpha = {alpha}')
plt.text(-2, 2, f'Accuracy = {accuracy}')
plt.subplots_adjust(hspace=0.5, wspace=0.3)
plt.tight_layout()
由上图可见, alpha=0.01(惩罚极小),决策边界不光滑,存在过拟合。 alpha=10(惩罚大),决策边界过于光滑,存在千拟合,预测准确度也较低(0.831) 相较而言,alpha=1时,决策边界比较能捕捉数据特征,预测准确度相对最好(0.916)。
笔记:enumerate()
enumerate() 是 Python 内置的一个函数,用于在遍历序列时同时获取元素的索引和值。它非常适合于需要同时获取元素及其位置的场景,如在循环中需要知道当前元素的索引时。
#基本语法和参数
enumerate(
iterable, #一个可迭代对象,如列表、元组、字符串等。
start=0) #索引的起始值,默认为 0。