点击上方“进修编程”,选择“星标”公众号
超级无敌干货,第一时间送达!!!
支持向量机 (SVM) 的性能在很大程度上取决于超参数,例如正则化参数 (C) 和核参数(RBF 核的伽马)。遗传算法 (GA) 利用进化原理来搜索最佳超参数值。
本文探讨了使用遗传算法优化 SVM 参数,并讨论了其实现和优点。
支持向量机 (SVM) 的超参数
支持向量机 (SVM)是用于分类和回归任务的监督学习模型。它们的工作原理是找到最能将数据划分为不同类别的超平面,从而最大化它们之间的差距。
SVM 的关键超参数包括:
C(正则化参数):控制实现低训练误差和低测试误差之间的权衡。
核参数:这些包括特定于所选核函数的参数,例如 RBF 核的伽马。
遗传算法 (GA) 用于超参数调整 SVM 参数
对于 SVM,超参数(C 和 gamma)被编码为染色体。染色体中的每个基因代表一个特定的超参数。
适应度函数使用给定的一组超参数来评估 SVM 模型的性能,通常使用交叉验证来衡量准确性或其他相关指标。
超参数调整的 GA 工作流程
初始化:生成潜在超参数集的初始群体。
选择:根据适应度得分选择解决方案。
交叉:结合父母解决方案来产生具有父母双方特征的后代。
突变:向后代引入随机变异以保持多样性。
评估:评估新解决方案的适用性。
迭代:重复该过程多次,直到收敛或满足停止标准。
伪代码
Initialize population with random hyperparameter sets
Evaluate fitness of each individual in the population
while (termination criteria not met) do:
Select parents based on fitness
Apply crossover to produce offspring
Apply mutation to offspring
Evaluate fitness of offspring
Select individuals for the next generation
end while
Return the best hyperparameter set
使用遗传算法优化 SVM 超参数
步骤 1:安装必要的软件包
此步骤将安装所需的 Python 包deap并scikit-learn使用pip。这些包分别是运行遗传算法和机器学习任务所必需的。
pip install deap
第 2 步:导入库
在此步骤中,我们导入实现遗传算法和机器学习功能所需的库。random用于随机数生成、数值运算、、和分别用于加载数据集、交叉验证和 SVM 分类器。该库提供了遗传算法所需的工具。
import random
import np
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
from deap import base, creator, tools, algorithms
步骤3:加载数据集
在这里,我们从 scikit-learn 加载数字数据集。此数据集是手写数字的集合,是展示机器学习分类器用法的一个很好的例子。然后我们将数据分为特征 (X) 和目标标签 (y)。
# Load dataset
data = datasets.load_digits()
X = data.data
y = data.target
步骤 4:定义具有错误处理的评估函数
我们定义一个函数evaluate,用于评估遗传算法中个体的表现。个体代表 SVM 分类器的一组超参数(C 和 gamma)。我们确保 C 和 gamma 的值至少为 0.1,以避免无效的参数值。使用交叉验证对 SVM 分类器进行训练和评估,并返回平均分数。如果在评估过程中出现任何错误,则会分配一个较差的分数。
# Define evaluation function with error handling
def evaluate(individual):
C = max(0.1, individual[0])
gamma = max(0.1, individual[1])
try:
clf = SVC(C=C, gamma=gamma)
score = cross_val_score(clf, X, y, cv=5).mean()
except Exception as e:
score = -1 # Assign a poor score if there's an error
return score,
步骤 5:设置遗传算法工具箱
此步骤涉及为遗传算法设置 DEAP 工具箱。我们定义要最大化的适应度函数和个体的结构(具有适应度属性的列表)。然后,我们注册用于创建属性(随机浮点)、个体(重复属性)和种群(重复个体)的函数。还注册了用于交叉、变异、选择和评估的遗传算子。
# Genetic Algorithm setup
toolbox = base.Toolbox()
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
toolbox.register("attr_float", random.uniform, 0.1, 10)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, 2)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("mate", tools.cxBlend, alpha=0.5)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.2)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)
步骤 6:定义主函数来运行遗传算法
我们定义了主函数,用于初始化随机种子以实现可重复性并创建初始种群。我们设置了在遗传算法运行期间要记录的统计数据,包括平均值、标准差、最小和最大适应度。然后使用 执行遗传算法eaSimple,该算法以给定的交叉和突变概率运行指定数量的代数。
# 遗传算法执行
def main():
random.seed(42)
# 创建初始种群
population = toolbox.population(n=50)
# 定义要记录的统计数据
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("std", np.std)
stats.register("min", np.min)
stats.register("max", np.max)
# 运行遗传算法
population, logbook = algorithm.eaSimple(population, toolbox, cxpb=0.5, mutpb=0.2, ngen=40, stats=stats, verbose=True)
returnpopulation, logbook
第七步:执行Main函数并输出结果
在最后一步中,我们执行主函数并从最终种群中检索最佳个体。然后,我们提取最佳超参数(C 和 gamma),并打印最佳个体及其适应度得分和超参数。
if __name__ == "__main__":
population, logbook = main()
# Get the best individual
best_individual = tools.selBest(population, 1)[0]
best_C = max(0.1, best_individual[0])
best_gamma = max(0.1, best_individual[1])
print(f"Best individual: {best_individual}")
print(f"Best fitness: {best_individual.fitness.values[0]}")
print(f"Best hyperparameters: C={best_C}, gamma={best_gamma}")
完整代码
# Install necessary packages
!pip install deap scikit-learn
import random
import numpy as np
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
from deap import base, creator, tools, algorithms
# Load dataset
data = datasets.load_digits()
X = data.data
y = data.target
# Define evaluation function with error handling
def evaluate(individual):
C = max(0.1, individual[0])
gamma = max(0.1, individual[1])
try:
clf = SVC(C=C, gamma=gamma)
score = cross_val_score(clf, X, y, cv=5).mean()
except Exception as e:
score = -1 # Assign a poor score if there's an error
return score,
# Genetic Algorithm setup
toolbox = base.Toolbox()
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
toolbox.register("attr_float", random.uniform, 0.1, 10)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, 2)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("mate", tools.cxBlend, alpha=0.5)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.2)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)
# Genetic Algorithm execution
def main():
random.seed(42)
# Create initial population
population = toolbox.population(n=50)
# Define statistics to be recorded
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("std", np.std)
stats.register("min", np.min)
stats.register("max", np.max)
# Run genetic algorithm
population, logbook = algorithms.eaSimple(population, toolbox, cxpb=0.5, mutpb=0.2, ngen=40, stats=stats, verbose=True)
return population, logbook
if __name__ == "__main__":
population, logbook = main()
# Get the best individual
best_individual = tools.selBest(population, 1)[0]
best_C = max(0.1, best_individual[0])
best_gamma = max(0.1, best_individual[1])
print(f"Best individual: {best_individual}")
print(f"Best fitness: {best_individual.fitness.values[0]}")
print(f"Best hyperparameters: C={best_C}, gamma={best_gamma}")
# Train and test the final model
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
final_model = SVC(C=best_individual[0], gamma=best_individual[1])
final_model.fit(X_train, y_train)
print(f'Test accuracy: {final_model.score(X_test, y_test)}')
输出:
gen nevals avg std min max
0 50 0.107677 0.00987644 0.101281 0.139164
1 33 0.113994 0.0121825 0.101281 0.140279
2 30 0.124992 0.0120814 0.101838 0.153649
3 32 0.132813 0.00799749 0.110752 0.150864
4 32 0.134774 0.0107546 0.101838 0.154206
5 29 0.139799 0.00769207 0.107409 0.154206
6 23 0.142953 0.0092506 0.101838 0.155877
7 24 0.147688 0.00616172 0.136379 0.155877
8 20 0.151276 0.00503346 0.135822 0.155877
9 34 0.151811 0.00685508 0.121894 0.155877
10 28 0.152724 0.00622722 0.134708 0.155877
11 21 0.154084 0.0080811 0.101281 0.155877
12 31 0.155454 0.00280674 0.135822 0.155877
13 38 0.154763 0.00440217 0.135822 0.155877
14 28 0.155309 0.00301966 0.135822 0.155877
15 27 0.154017 0.00824709 0.101838 0.155877
16 25 0.154072 0.00547047 0.135822 0.155877
17 25 0.155811 0.000467967 0.152535 0.155877
18 33 0.15288 0.00929871 0.101838 0.155877
19 22 0.154752 0.00447696 0.135822 0.155877
20 31 0.15454 0.00458452 0.135822 0.155877
21 40 0.154373 0.00513775 0.135822 0.155877
22 29 0.155265 0.003148 0.135822 0.155877
23 30 0.154396 0.00801579 0.101838 0.155877
24 32 0.152813 0.00940053 0.101838 0.155877
25 32 0.153627 0.00872855 0.101838 0.155877
26 33 0.154295 0.00536714 0.135822 0.155877
27 27 0.155476 0.0028078 0.135822 0.155877
28 30 0.154641 0.00471836 0.135822 0.155877
29 32 0.154396 0.00801579 0.101838 0.155877
30 35 0.154072 0.00531391 0.135822 0.155877
31 31 0.154173 0.00517646 0.135822 0.155877
32 24 0.154429 0.0061524 0.119109 0.155877
33 30 0.153404 0.0107497 0.101838 0.155877
34 32 0.155298 0.00304926 0.135822 0.155877
35 36 0.154674 0.00476297 0.135822 0.155877
36 35 0.154507 0.00768577 0.101838 0.155877
37 21 0.155877 2.77556e-17 0.155877 0.155877
38 27 0.154184 0.00576914 0.131365 0.155877
39 36 0.154474 0.0055802 0.126351 0.155877
40 26 0.155153 0.0034742 0.135822 0.155877
Best individual: [-6.96604485823403, 1.256273035647874]
Best fitness: 0.15587743732590528
Best hyperparameters: C=0.1, gamma=1.256273035647874
提供的输出代表了 40 代遗传算法的进度和结果。以下是关键部分的详细解释:
统计
该表显示了每一代的统计数据:
gen:代数。
nevals:该代中评估的个体数量。
avg:该代种群的平均适应度值。
std:适应度值的标准差,表示群体内的变异性。
min:种群中的最小适应度值。
max:种群中的最大适应度值。
该表有助于追踪遗传算法的进度,显示种群的适应性在几代过程中如何提高(或没有提高)。
遗传算法找到的最优个体表示为:
Best individual:
最优个体的适应度值为:
Best fitness: 0.15587743732590528
该值表示遗传算法运行期间具有最佳超参数的 SVM 分类器所获得的最高交叉验证分数。
使用 GA 进行超参数调整的优势
有效探索搜索空间: GA 专注于有前景的区域,从而减少寻找最佳超参数所需的时间。
摆脱局部最优的能力: GA 的随机性有助于其避免陷入次优解决方案。
可扩展至复杂模型:即使在大型、复杂的超参数空间中,GA 仍然有效。
平衡探索和利用: GA 在改进良好解决方案的同时保持多样性。
结论
超参数调整对于优化机器学习模型至关重要,而遗传算法提供了一种高效且有效的解决方案。GA 在探索和利用之间实现了平衡,使其适用于复杂的超参数空间。虽然它们面临着计算挑战,但它们的优点往往大于缺点。随着机器学习的不断发展,GA 可能会在超参数优化中发挥越来越重要的作用。
python、matlab程序设计找我
— 完 —