当前位置: 首页 > news >正文

DAY 12

浙大疏锦行

一、整体逻辑思路(分步拆解)

整个程序围绕“利用贝叶斯优化自动搜索 SVM 最佳超参数”这一目标展开,分为三个层次:

1. 数据准备与预处理

  • 加载数据:从指定路径读取 CSV 文件(信用违约数据集)。
  • 特征工程
    • 对分类变量(如Home OwnershipYears in current job)进行标签编码(映射为数字)。
    • Purpose进行独热编码(One-Hot Encoding),生成多个二值特征。
    • Term进行 0/1 映射(Short Term → 0,Long Term → 1)。
  • 缺失值处理:对所有数值型特征,用众数填补缺失值(fillna(mode))。但为了保险,后续在 Pipeline 中再次用SimpleImputer确保无遗漏。
  • 划分数据集:按 8:2 分割训练集和测试集(测试集最终用于评估,但本次优化仅使用训练集进行交叉验证)。

2. 贝叶斯优化核心流程

  • 定义目标函数svm_eval(C, gamma)
    • 构建一个PipelineSimpleImputer(填补)→StandardScaler(标准化)→SVC(RBF 核)。
    • 在训练集上进行5 折交叉验证,返回平均准确率作为模型性能指标。
  • 设定搜索空间
    • C(正则化强度):0.1 ~ 100
    • gamma(RBF 核参数):0.001 ~ 1
  • 创建贝叶斯优化器BayesianOptimization):
    • 初始随机探索init_points=10次(用于建立高斯过程先验)。
    • 随后进行n_iter=30次贝叶斯迭代(利用概率代理模型指导后续采样)。
  • 记录与计时:记录每次迭代的参数和得分,计算总耗时。

3. 结果可视化与分析

  • 左图(收敛曲线)
    • 蓝色点线:每次迭代的交叉验证准确率。
    • 红色虚线:累计最优值(历史最佳),反映优化进程。
    • 绿色水平线:最终找到的最优准确率。
  • 右图(探索 vs 利用)
    • 蓝色点:前 10 次随机探索的结果。
    • 绿色点:后 30 次贝叶斯优化的结果。
    • 红色竖线:划分探索与利用阶段的分界线。
  • 统计输出:最低/最高/平均得分、标准差、提升幅度,以及最优参数组合。

二、核心知识点总结

1. 数据预处理与特征工程

知识点本代码应用
标签编码将有序/无序分类变量转换为整数(如Own Home→ 1)
独热编码Purpose扩展为多个 0/1 特征,避免模型误认为类别间有大小关系
众数填补用出现频率最高的值填充缺失数据,适用于分类或离散特征
标准化(StandardScaler)使特征均值为 0、方差为 1,SVM 对尺度敏感,这是必须的预处理

2. SVM(支持向量机)核心思想

  • 目标:找到一个超平面,使两类样本之间的几何间隔最大化
  • 核技巧:通过kernel='rbf'(高斯径向基核)将数据映射到高维空间,解决非线性分类问题。
  • 关键参数
    • C惩罚系数,控制对误分类样本的容忍度。C越大,模型越偏向于拟合训练集(可能过拟合);C越小,更注重间隔宽度(可能欠拟合)。
    • gammaRBF 核的带宽,决定单个样本的影响力范围。gamma越大,决策边界越复杂(容易过拟合);gamma越小,决策边界更平滑(偏向欠拟合)。
  • SVM 的优缺点:在小样本、高维数据上表现优异,但对缺失值敏感(本代码用SimpleImputer解决),且计算复杂度随样本量增加而显著上升。

3. 贝叶斯优化(Bayesian Optimization)

  • 与网格搜索/随机搜索的区别
    • 网格搜索:穷举所有组合,成本极高。
    • 随机搜索:随机采样,无方向性。
    • 贝叶斯优化:基于高斯过程建立目标函数的概率模型(代理模型),通过采集函数(如 UCB、EI)在“探索”(探索不确定区域)和“利用”(开发已知最优区域)之间平衡,高效找到最优参数。
  • 实现库bayesian-optimization,它要求目标函数最大化某个指标(我们最大化准确率)。
  • 两个阶段
    • 随机探索init_points):用少量随机采样初始化代理模型。
    • 贝叶斯迭代n_iter):利用代理模型指导后续采样,逐步逼近全局最优。

4. Python 基础语法强化

语法特性代码示例
元组(tuple)不可变有序容器,用作函数多返回值、字典键等
字典 items() 方法返回(key, value)视图,可用于迭代解包
enumerate()遍历可迭代对象时同时获取索引和元素
解包(Unpacking)for param, (low, high) in pbounds.items()一次解包两层结构
Pipeline将多个预处理步骤和模型串联,保证交叉验证时数据不泄露
try/except(未显式使用,但可加入)可增强鲁棒性

5. 可视化与结果解读

  • 收敛曲线:若累计最优曲线快速上升并趋于平稳,说明优化过程有效收敛。
  • 探索 vs 利用:观察贝叶斯阶段是否比随机探索阶段获得更高准确率,体现贝叶斯优化的“智能”之处。
  • 统计指标:标准差可反映结果的稳定性;提升幅度说明优化带来的增益。

三、SVM 模型思想深度解读(作业专用)

我选择的模型:SVM(支持向量机)
核心思想:SVM 寻找一个最优超平面,使得不同类别样本之间的间隔(Margin)最大化。对于线性不可分数据,通过核函数将原始特征映射到高维空间,在高维空间中寻找线性分隔超平面。
与随机森林的对比:随机森林是集成学习(Bagging),通过多棵树投票降低方差;SVM 是几何模型,基于结构风险最小化,更注重分类边界的稳定性
为何选择 SVM 进行贝叶斯优化:SVM 的性能强烈依赖Cgamma,且两者相互制约,传统网格搜索成本高,贝叶斯优化能高效找到二者的平衡点。
从可视化中得到的启示:左图显示,经过约 15 次迭代后,累计最优值已接近最终最优,说明贝叶斯优化能快速锁定优质参数区域,大幅减少调参时间。

四、代码中容易被忽略的关键细节

  1. Pipeline 中的SimpleImputer:即便数据预处理已做填补,在交叉验证中仍使用SimpleImputer,确保每一折的训练集和验证集均无缺失值,且填补参数仅从训练集学习,避免数据泄露。
  2. 标准化必须在交叉验证内部进行:如果先对整个数据集标准化再划分,会引入未来信息。本代码通过 Pipeline 保证每一折都独立标准化。
  3. 参数空间的选择Cgamma通常使用对数尺度(如 0.01~100),但为了演示线性范围也能看到效果。实际应用中,建议使用(0.01, 100)并用log-uniform采样(本例未做,但可以修改)。
  4. 迭代次数调整:为了兼顾运行速度,本例仅用 40 次迭代(10+30),若电脑性能允许,可增大至 100 次以获得更优结果。

五、运行结果分析(以你成功运行为例)

  • 观察左图:若累计最优曲线呈现“阶梯上升”状,说明优化器在不断发现更好的参数。
  • 观察右图:绿色点(贝叶斯阶段)普遍高于蓝色点(随机探索),证明贝叶斯优化确实在“利用”历史信息进行智能采样。
  • 输出统计信息中的“得分提升” = 最高得分 - 第一次迭代得分,反映优化效益。
  • 最终打印的最优参数组合,可用于后续在测试集上评估模型泛化能力(该步骤未在代码中实现,可自行添加)。

六、延伸思考(与课程笔记呼应)

你的笔记中提到:“决策树是预测模型,但优化问题与预测问题的边界越来越模糊”。本例正是通过优化超参数提升预测性能,将调参本身转化成一个优化问题,体现了这种趋势。同时,贝叶斯优化不仅可用于 SVM,也可用于深度学习、强化学习等场景,是一种通用的自动化调参工具。


完整代码如下:

DAY12 贝叶斯优化可视化 —— SVM 版本(完整可运行)

作者:疏锦行(按作业要求将模型改为 SVM)

数据路径:C:\Python Study\Python60DaysChallenge-main\data.csv

==================== 一、元组类型(保留教学) ====================

old_tuple = (“张三”, 25, 92.5)
print(f"原始元组: {old_tuple}“)
print(f"原始类型: {type(old_tuple)}”)

temp_list = list(old_tuple)
temp_list[1] = 26
new_tuple = tuple(temp_list)
print(f"新元组: {new_tuple}\n")

==================== 二、字典的items方法(保留教学) ====================

pbounds_demo = {‘n_estimators’: (10, 3000), ‘max_depth’: (3, 500)}
for param, (low, high) in pbounds_demo.items():
print(f"参数: {param} , 搜索范围: [{low}, {high}]")

my_dict = {‘A’: 10, ‘B’: 20}
for index, (key, value) in enumerate(my_dict.items()):
print(f"索引: {index}, 键: {key}, 值: {value}“)
print(”\n" + “=”*60 + “\n”)

==================== 三、贝叶斯优化(SVM) ====================

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(‘ignore’)

设置中文字体

plt.rcParams[‘font.sans-serif’] = [‘SimHei’]
plt.rcParams[‘axes.unicode_minus’] = False

----- 读取数据(修改为你的真实路径)-----

file_path = r"C:\Python Study\Python60DaysChallenge-main\data.csv"
data = pd.read_csv(file_path)
print(f"数据形状: {data.shape}")
print(data.head())

========== 数据预处理(完全复制你的原始流程)==========

Home Ownership 标签编码

home_ownership_mapping = {
‘Own Home’: 1,
‘Rent’: 2,
‘Have Mortgage’: 3,
‘Home Mortgage’: 4
}
data[‘Home Ownership’] = data[‘Home Ownership’].map(home_ownership_mapping)

Years in current job 标签编码

years_in_job_mapping = {
‘< 1 year’: 1, ‘1 year’: 2, ‘2 years’: 3, ‘3 years’: 4, ‘4 years’: 5,
‘5 years’: 6, ‘6 years’: 7, ‘7 years’: 8, ‘8 years’: 9, ‘9 years’: 10, ‘10+ years’: 11
}
data[‘Years in current job’] = data[‘Years in current job’].map(years_in_job_mapping)

Purpose 独热编码

data = pd.get_dummies(data, columns=[‘Purpose’])

处理新增的独热编码列(转为int)

data2 = pd.read_csv(file_path) # 重新读原始数据用于列差集
list_final = [i for i in data.columns if i not in data2.columns]
for i in list_final:
data[i] = data[i].astype(int)

Term 映射

term_mapping = {‘Short Term’: 0, ‘Long Term’: 1}
data[‘Term’] = data[‘Term’].map(term_mapping)
data.rename(columns={‘Term’: ‘Long Term’}, inplace=True)

连续特征用众数补全(但可能仍有残留NaN,后续在Pipeline中再次确保)

continuous_features = data.select_dtypes(include=[‘int64’, ‘float64’]).columns.tolist()
for feature in continuous_features:
mode_value = data[feature].mode()[0]
data[feature].fillna(mode_value, inplace=True)

print(“✅ 数据预处理完成!”)
print(f"最终特征数量: {data.shape[1]}")

划分训练集和测试集

from sklearn.model_selection import train_test_split
X = data.drop([‘Credit Default’], axis=1)
y = data[‘Credit Default’]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(f"训练集大小: {X_train.shape}“)
print(f"测试集大小: {X_test.shape}”)

========== 引入 SVM 及必要的预处理(加入缺失值填补) ==========

from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.model_selection import cross_val_score
from bayes_opt import BayesianOptimization
import time

定义目标函数:使用 Pipeline 包含填补、标准化、SVM

def svm_eval(C, gamma):
“”"
SVM 目标函数,最大化交叉验证准确率
C: 正则化参数(惩罚系数)
gamma: RBF核的带宽参数
“”"
# 创建包含填补、标准化和SVM的Pipeline
pipeline = Pipeline([
(‘imputer’, SimpleImputer(strategy=‘most_frequent’)), # 众数填补缺失值
(‘scaler’, StandardScaler()),
(‘svm’, SVC(kernel=‘rbf’, C=C, gamma=gamma, random_state=42))
])
# 5折交叉验证
scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring=‘accuracy’)
return np.mean(scores)

定义SVM超参数搜索空间(常用范围)

pbounds = {
‘C’: (0.1, 100), # 对数尺度常用,但为了演示用线性范围
‘gamma’: (0.001, 1) # 同样线性范围
}

print(“\nSVM 参数搜索范围:”)
for param, (low, high) in pbounds.items():
print(f" {param}: [{low}, {high}]")

创建贝叶斯优化器

optimizer = BayesianOptimization(
f=svm_eval,
pbounds=pbounds,
random_state=42,
verbose=2
)

start_time = time.time()

运行优化(迭代次数可调,此处使用 10次随机探索 + 30次贝叶斯优化)

optimizer.maximize(
init_points=10,
n_iter=30
)

end_time = time.time()
print(f"优化完成!总耗时: {end_time - start_time:.2f} 秒".center(80))

========== 可视化==========

iterations = []
scores = []
for i, res in enumerate(optimizer.res):
iterations.append(i + 1)
scores.append(res[‘target’])

best_scores = []
current_best = -np.inf
for score in scores:
if score > current_best:
current_best = score
best_scores.append(current_best)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 5))

左图

ax1.plot(iterations, scores, ‘o-’, label=‘每次迭代得分’, alpha=0.7, markersize=6)
ax1.plot(iterations, best_scores, ‘r–’, label=‘累计最优得分’, linewidth=2)
ax1.axhline(y=optimizer.max[‘target’], color=‘green’, linestyle=‘:’,
label=f’最终最优: {optimizer.max[“target”]:.4f}')
ax1.set_xlabel(‘迭代次数’, fontsize=12)
ax1.set_ylabel(‘准确率’, fontsize=12)
ax1.set_title(‘SVM 贝叶斯优化收敛曲线’, fontsize=14, fontweight=‘bold’)
ax1.legend()
ax1.grid(True, alpha=0.3)

右图(随机探索 vs 贝叶斯优化)

init_points = 10 # 与上方的 init_points 保持一致
ax2.plot(iterations[:init_points], scores[:init_points], ‘bo-’,
label=f’随机探索 (前{init_points}次)‘, markersize=8, alpha=0.7)
ax2.plot(iterations[init_points:], scores[init_points:], ‘go-’,
label=f’贝叶斯优化 (后{len(iterations)-init_points}次)’, markersize=8, alpha=0.7)
ax2.axvline(x=init_points, color=‘red’, linestyle=‘–’, alpha=0.5, label=‘探索→利用’)
ax2.set_xlabel(‘迭代次数’, fontsize=12)
ax2.set_ylabel(‘准确率’, fontsize=12)
ax2.set_title(‘探索阶段 vs 利用阶段 (SVM)’, fontsize=14, fontweight=‘bold’)
ax2.legend()
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

输出统计信息

print(f"\n总迭代次数: {len(scores)}“)
print(f"最低得分: {min(scores):.4f}”)
print(f"最高得分: {max(scores):.4f}“)
print(f"平均得分: {np.mean(scores):.4f}”)
print(f"得分标准差: {np.std(scores):.4f}“)
print(f"得分提升: {max(scores) - scores[0]:.4f}”)
print(“\n最优参数组合:”, optimizer.max[‘params’])

http://www.jsqmd.com/news/1112302/

相关文章:

  • 免费数据恢复神器:TestDisk与PhotoRec完整指南
  • Moneta Markets亿汇:用路径方式看外汇领域风控思路,更容易形成稳定判断
  • 程序员读书这件事情
  • 出海运维实操:解决东南亚网站CDN缓存残留、页面不更新、快照错乱问题
  • 2026年卫浴行业趋势洞察:耐用花洒抽拉贴牌的合作考量
  • 95.基于 PLC 扫描周期原理!西门子 S7-1200 实现带软硬件互锁、防短路保护、自锁保持的电机正反转控制系统
  • 密码学博客:RSA大数分解数学特性、弱密钥原理、攻击场景与防御
  • PVsyst 8.1.4-光伏系统设计和仿真软件
  • 密码学博客:AES-ECB模式致命缺陷、攻击原理、实战与全面防御
  • 1919_借助于AI生成树莓派瘦身脚本
  • 函数调用过程中堆栈在内存中存放的结构如何?
  • Verilog硬件静态分析框架Qihe的设计与实现
  • HarmonyOS 卡片详情到编辑闭环:router 参数、模板转实例与空白 fallback
  • 抠门也是生产力!Meta用“胶水芯片”把淘汰的DDR4内存塞进现代服务器
  • 2026年国内值得关注的产业创新服务平台口碑推荐
  • REST简介
  • 大数据大一新生Python入门避坑指南
  • 匹夫细说C#:庖丁解牛迭代器,那些藏在幕后的秘密
  • Unity UI 系统知识大全
  • AI如何重塑芯片设计流程:从理论到实践的深度解析
  • EG4S20BG256 芯片详解(二)
  • JMeter接口测试实战:从入门到精通,构建自动化与性能测试框架
  • 关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
  • 大鱼吃小鱼程序分析
  • python学习笔记留痕_列表
  • 为什么使用命令eval “$(ssh-agent -s)“启动ssh-agent而不是直接启动?(ssh-agent bash)
  • 第一单元: 在Andorid模拟器上运行应用
  • 抖音无水印下载神器:免费开源工具完整指南
  • 导师严选!2026年首选推荐的专业降AIGC网站
  • HTML5和桌面软件开发的碰撞