超参数调整专题2
- 三种启发式算法的示例代码:遗传算法、粒子群算法、退火算法
- 学习优化算法的思路(避免浪费无效时间)
作业:今天以自由探索的思路为主,尝试检索资料、视频、文档,用尽可能简短但是清晰的语言看是否能说清楚这三种算法每种算法的实现逻辑,帮助更深入的理解。
启发式算法
启发式算法是一种基于经验规则或直觉来寻找问题近似解的方法,特别适用于那些传统算法难以快速找到最优解的复杂问题。简单来说,它是一种 “用策略换时间” 的智慧解题思路。
一、核心思想:不求完美,但求满意
想象你在一个巨大的迷宫中找出口:
- 传统算法(如穷举法):会尝试每一条可能的路径,确保找到最短的出口,但在超复杂迷宫中可能要花一辈子。
- 启发式算法:会根据 “出口通常在边缘” 或 “跟着阳光走” 等经验规则,优先尝试更可能的路径,虽然不一定是最短路径,但能快速找到一个可行解。
适用场景:
- 问题规模太大,精确求解时间成本过高(如旅行商问题、调度问题)。
- 问题本身没有精确解(如天气预报、股票预测)。
二、生活化比喻:找钥匙
假设你在家里丢了钥匙,有两种找法:
- 精确算法:把整个房子按顺序一格一格地毯式搜索,确保找到钥匙,但可能要翻遍所有角落。
- 启发式算法:
- 先去 “常放钥匙的地方”(如玄关)找。
- 如果没找到,去 “最近活动过的地方”(如沙发、餐桌)找。
- 最后才扩大搜索范围。
这种基于经验的搜索策略,就是启发式算法的核心思想 ——用有限的时间和资源,找到足够好的解。
三、启发式算法在 AI 中的应用
- 游戏 AI:AlphaGo 通过蒙特卡洛树搜索(一种启发式算法)评估落子位置。
- 自然语言处理:在机器翻译中,通过启发式规则快速生成候选翻译。
- 计算机视觉:在目标检测中,用启发式规则筛选可能包含物体的区域。
总结
启发式算法是解决复杂问题的一把 “瑞士军刀”,它不追求完美,但强调实用。当面对 “找不到最优解” 或 “找最优解成本太高” 的问题时,启发式算法是你的最佳选择。
模拟退火
可以把机器学习中的 “退火算法” 理解成一个 “聪明试错” 的过程,就像我们找东西时,从一开始大范围摸索,慢慢聚焦到精准位置,既不会错过可能的好地方,又能高效找到目标。
用生活化的例子理解核心思路
想象你在一座大雾笼罩的山上,想找到最低的山谷(类似算法要找的 “最优解”),但看不清周围全貌,只能凭脚下的感觉摸索:
- 一开始你可能站在某个坡上,脚下有点陡(比如向左走会变高,向右走会变低)。这时候你会本能地向右走(找更低的地方)。
- 但走着走着,你可能来到一个小平台(局部最低点),周围几步之内都是上坡。这时候如果只看眼前,你会以为这就是山谷了,但其实不远处可能有更深的山谷,只是被小坡挡住了。
- 退火算法的 “聪明” 之处在于:一开始允许自己 “冒险”—— 哪怕眼前是上坡,也偶尔往上走几步(接受暂时变差的选择),避免困在小平台;但随着时间推移(类似 “温度降低”),这种冒险会越来越少,最后专注于在当前区域里找最低点。
为什么叫 “退火”?
这个名字来自金属加工中的 “退火工艺”:金属加热后慢慢冷却,原子会从混乱状态逐渐排列成更稳定的结构(能量更低)。算法模仿了这个过程:
- “高温” 阶段:像加热的金属原子一样活跃,允许尝试各种可能性(哪怕暂时变差),避免错过全局最优解。
- “降温” 阶段:像金属冷却一样,逐渐收敛,越来越倾向于接受更好的选择,最终稳定在一个好的结果上。
机器学习中的作用
在机器学习里,退火算法常用来解决那些 “答案不唯一、容易陷入局部最优” 的问题,比如:
- 神经网络调参:避免模型卡在一个不好的局部最优解(比如训练精度不高但无法提升)。
- 特征选择:从大量特征中找到一组最优组合(比如选 10 个特征比选 5 个效果更好,但试错成本高)。
举例来说,假设你要给模型选 3 个最有用的特征:
- 普通方法可能试了 “特征 A+B+C” 效果不错,就停下了,但可能 “特征 D+E+F” 效果更好,只是一开始没试到。
- 退火算法会先随机试很多组合(哪怕中间选到效果差的),随着过程推进,逐渐聚焦到那些表现好的组合上,最后找到更优的结果。
关键特点总结
- 允许 “暂时变差”:避免被眼前的小利益困住(跳出局部最优)。
- 逐渐收敛:随着过程推进,越来越谨慎,最终稳定在一个好结果上。
- 像 “聪明的摸索”:比盲目试错高效,又比 “一条道走到黑” 灵活。
简单说,退火算法就是通过 “先大胆尝试,再慢慢聚焦” 的策略,高效找到复杂问题的最优解,就像找山谷时既敢走远点看看,又不会一直瞎逛浪费力气~
# --- 2. 模拟退火算法优化随机森林 ---
print("\n--- 2. 模拟退火算法优化随机森林 (训练集 -> 测试集) ---")
# 定义适应度函数
def fitness_function(params):
n_estimators, max_depth, min_samples_split, min_samples_leaf = params
model = RandomForestClassifier(n_estimators=int(n_estimators),
max_depth=int(max_depth),
min_samples_split=int(min_samples_split),
min_samples_leaf=int(min_samples_leaf),
random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
return accuracy
# 模拟退火算法实现
def simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha):
current_solution = initial_solution
current_fitness = fitness_function(current_solution)
best_solution = current_solution
best_fitness = current_fitness
temp = initial_temp
while temp > final_temp:
# 生成邻域解
neighbor_solution = []
for i in range(len(current_solution)):
new_val = current_solution[i] + random.uniform(-1, 1) * (bounds[i][1] - bounds[i][0]) * 0.1
new_val = max(bounds[i][0], min(bounds[i][1], new_val))
neighbor_solution.append(new_val)
neighbor_fitness = fitness_function(neighbor_solution)
delta_fitness = neighbor_fitness - current_fitness
if delta_fitness > 0 or random.random() < np.exp(delta_fitness / temp):
current_solution = neighbor_solution
current_fitness = neighbor_fitness
if current_fitness > best_fitness:
best_solution = current_solution
best_fitness = current_fitness
temp *= alpha
return best_solution, best_fitness
# 超参数范围
bounds = [(50, 200), (10, 30), (2, 10), (1, 4)] # n_estimators, max_depth, min_samples_split, min_samples_leaf
# 模拟退火算法参数
initial_temp = 100 # 初始温度
final_temp = 0.1 # 终止温度
alpha = 0.95 # 温度衰减系数
# 初始化初始解
initial_solution = [random.uniform(bounds[i][0], bounds[i][1]) for i in range(len(bounds))]
start_time = time.time()
best_params, best_fitness = simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha)
end_time = time.time()
print(f"模拟退火算法优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", {
'n_estimators': int(best_params[0]),
'max_depth': int(best_params[1]),
'min_samples_split': int(best_params[2]),
'min_samples_leaf': int(best_params[3])
})
# 使用最佳参数的模型进行预测
best_model = RandomForestClassifier(n_estimators=int(best_params[0]),
max_depth=int(best_params[1]),
min_samples_split=int(best_params[2]),
min_samples_leaf=int(best_params[3]),
random_state=42)
best_model.fit(X_train, y_train)
best_pred = best_model.predict(X_test)
print("\n模拟退火算法优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("模拟退火算法优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))