相关文章:
1 GlobalBestPSO() 函数简介
PSO 超参数调优采用的是 pyswarm 包中的 GlobalBestPSO():
class pyswarms.single.global_best.GlobalBestPSO(n_particles, dimensions, options, bounds=None, oh_strategy=None, bh_strategy=‘periodic’, velocity_clamp=None, vh_strategy=‘unmodified’, center=1.0, ftol=-inf, ftol_iter=1, init_pos=None)
输入参数:
- n_particles:整数,粒子群中的粒子数量
- dimension:整数,空间维度,或特征维度
- options:系数,字典形式 {‘c1’=2, ‘c2’=2, ‘w’=0.3}
- bounds:数组,可选,行数为 2,第一行是边界的最小值,第二行是边界的最大值
- oh_strategy:字典,可选,每个 option 的选择策略
- bh_strategy:字符串,处理超出边界的粒子的策略
- velocity_clamp:元组,可选,一个大小为2的元组,其中第一个条目是最小速度,第二个条目是最大速度。它设定了速度的限制
- vh_strategy:字符串,处理超出边界的粒子速度的策略
- ftol:列表(默认为None),
GlobalBestPSO()的优化方法:
optimize(objective_func, iters, n_processes=None, verbose=True, **kwargs)
输入参数:
- objective_func (function):自适应函数或损失函数
- iters (int):迭代次数
- kwargs (dict) :目标函数的参数
返回:
- tuple:目标函数最优值和最优位置
2 定义PSO优化器
import numpy as np
import pyswarms as ps
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.model_selection import cross_val_score
n_particles = 10
cv = 5
options = {'c1': 0.5, 'c2': 0.5, 'w': 0.9}
optimizer = ps.single.GlobalBestPSO(n_particles=n_particles, dimensions=dims,
options=options, bounds=bounds)
3 定义参数和边界
这里选择逻辑回归模型的超参数:C 和 penalty。
# 超参数 C 和 penalty
C = [0., 1.]
penalty = ['l1', 'l2', 'elasticnet', 'none']
penalty_bound = [0, len(penalty)] # 把这个看作索引
dims = 2
# bounds表示所有参数的界限
max_ = np.zeros(dims)
min_ = np.zeros(dims)
for i, param in enumerate([C, penalty_bound]):
min_[i] = param[0]
max_[i] = param[1]
bounds = (min_, max_)
print(bounds)
输出:
(array([0., 0.]), array([1., 4.]))
4 得到最优模型
# 这里目标函数的输入为需要优化的参数
best_cost, best_pos = optimizer.optimize(objective, iters=25)
print(best_pos, penalty[int(best_pos[1])])
best_model = LogisticRegression(C=best_pos[0], penalty=penalty[int(best_pos[1])])
best_model = best_model.fit(X_train, y_train)
输出:
[0.01806252 1.430832 ] l2
5 定义目标函数
在定义目标函数时,需要将每个粒子的值带入模型中训练,然后返回模型的指标值。这个指标值可以是分类中的准确率。
具体如下:
def objective(param):
"""计算每个粒子的适应度,param表示输入的参数(n_particles, n_dims)"""
scores = np.zeros((n_particles, cv))
clf = LogisticRegression
for i in range(n_particles):
"""计算每个粒子的得分"""
scores[i, :] = cross_val_score(clf(C=param[i][0], penalty=penalty[int(param[i][1])]),
X_train, y_train,
scoring='accuracy',
cv=cv)
return -np.mean(scores, axis=1)
6 查看损失变化
查看目标函数随迭代增加的变化情况:
from pyswarms.utils.plotters import plot_cost_history
plot_cost_history(cost_history=optimizer.cost_history)

7 测试模型
X, y = make_classification(n_samples=2000, n_features=5, random_state=42)
X_train, y_train = X[:1000], y[:1000]
X_test, y_test = X[1000:], y[1000:]
y_pred = best_model.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
输出:
[[440 55]
[ 45 460]]
precision recall f1-score support
0 0.91 0.89 0.90 495
1 0.89 0.91 0.90 505
accuracy 0.90 1000
macro avg 0.90 0.90 0.90 1000
weighted avg 0.90 0.90 0.90 1000