粒子群算法优化K邻近模型参数(scikit-opt包)

前言

  • 最近在学习scikit-opt包,尝试使用启发式算法对机器学习模型参数进行优化。
  • 因为时间关系,挑了一个简单的机器学习模型进行尝试,即K邻近分类模型。
  • 推荐读scikit-opt官方文档,了解各启发式算法输入参数与输出。

安装scitit-opt包

pip install scikit-opt

导入必要包

#加载包
import numpy as np
import pandas as pd
from plotnine import*
import seaborn as sns
from scipy import stats

import matplotlib as mpl
import matplotlib.pyplot as plt
#中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# notebook嵌入图片
%matplotlib inline
# 提高分辨率
%config InlineBackend.figure_format='retina'

# 切分数据
from sklearn.model_selection import train_test_split
# 评价指标
from sklearn.metrics import mean_squared_error

# 忽略警告
import warnings
warnings.filterwarnings('ignore')

# 导入粒子群算法
from sko.PSO import PSO
# 交叉检验
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score

粒子群算法

  • 首先展示一个官方小例子理解一下算法构造。

定义目标函数

def demo_func(x):
    x1, x2 = x
    return -20 * np.exp(-0.2 * np.sqrt(0.5 * (x1 ** 2 + x2 ** 2))) - np.exp(
        0.5 * (np.cos(2 * np.pi * x1) + np.cos(2 * np.pi * x2))) + 20 + np.e

不等式约束

  • 末尾的逗号,一定要加,否则会报错
constraint_ueq = (lambda x: (x[0] - 1) ** 2 + (x[1] - 0) ** 2 - 0.5 ** 2,)

优化求解

# 迭代次数
max_iter = 50
pso = PSO(func=demo_func,
          n_dim=2,pop=40,
          max_iter=max_iter,
          lb=[-2, -2],
          ub=[2, 2],
          constraint_ueq=constraint_ueq)
pso.record_mode = True
pso.run()
print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y)

输出

best_x is  [9.52188498e-01 4.39396655e-05] best_y is [2.57992762]

迭代曲线

plt.figure(dpi = 300)
plt.plot(pso.gbest_y_hist)
plt.show()

请添加图片描述

利用粒子群算法调参

生成分类数据

# 生成分类数据
from sklearn.datasets import make_classification

x, y = make_classification(n_samples=1000, # 样本个数
n_features=3, # 特征个数
n_informative=2, # 有效特征个数
n_redundant=1, # 冗余特征个数(有效特征的随机组合)
n_repeated=0, # 重复特征个数(有效特征和冗余特征的随机组合)
n_classes=3, # 样本类别
n_clusters_per_class=1, # 簇的个数
random_state=42)
# 可视化分类数据集,只选择前两个特征
plt.figure(dpi = 600,figsize = (6,4))
plt.scatter(x[:,0],x[:,1],c = y)

请添加图片描述

切分数据集

# 切分数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=45, test_size=0.2)

K邻近算法

  • 使用未调参K邻近算法,并检验模型效果
# K邻近算法
from sklearn import neighbors
knn_clf_old = neighbors.KNeighborsClassifier()
knn_clf_old.fit(x_train,y_train)
print('训练集准确率:{:.2f}'.format(accuracy_score(y_train, knn_clf_old.predict(x_train))))
print('测试集准确率:{:.2f}'.format(accuracy_score(y_test, knn_clf_old.predict(x_test))))

输出

训练集准确率:0.95
测试集准确率:0.92

定义目标函数

  • 目标函数为10折交叉检验f1_macro平均值
  • 因为算法以最小化为目标,所以这里对f1_macro值取负
def knn_score(x):
    knn_score = cross_val_score(neighbors.KNeighborsClassifier(n_neighbors = int(x)),
                                x_train,y_train,scoring='f1_macro',cv=10).mean()
    return -knn_score

优化

max_iter = 50
knn_pso = PSO(func=knn_score,
              n_dim=1,pop=40,
              max_iter=max_iter,
              lb=[1],ub=[100])
knn_pso.record_mode = True
knn_pso.run()
print('best_k is ', int(knn_pso.gbest_x))

输出

best_k is  [12.5256584]

迭代曲线

plt.figure(dpi = 300)
plt.plot(knn_pso.gbest_y_hist)
plt.show()

请添加图片描述
可以看到当k为12时,算法收敛。

使用最优参

knn_clf_new = neighbors.KNeighborsClassifier(n_neighbors = 12)
knn_clf_new.fit(x_train,y_train)
print('训练集准确率:{:.2f}'.format(accuracy_score(y_train, knn_clf_new.predict(x_train))))
print('测试集准确率:{:.2f}'.format(accuracy_score(y_test, knn_clf_new.predict(x_test))))

输出

训练集准确率:0.93
测试集准确率:0.90
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羽星_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值