欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

粒子群算法 SVM

程序员文章站 2022-05-20 22:48:45
...

粒子群算法 SVM

SVM是调的包,辣鸡代码仅供参考,数据集有需要留下邮箱

#运用粒子群算法优化SVM正则参数C,以及核函数RBF函数的gamma的问题
import random
import numpy as np
from sklearn import svm
from sklearn import model_selection
import matplotlib.pyplot as plt

#设置PSO关键参数
particle_num = 30  #粒子数量,个数要适量,不能太大和太小
particle_dim = 2    #每个粒子的维度,维度要与优化的参数个数相同
iter_num = 400  # 最大迭代次数
c1 = 1.5  # 参考自己历史最优的权重
c2 = 1  # 参考全局最优的的权重
w_max = 1  # 惯性因子,表示粒子之前运动方向在本次方向上的惯性
w_min = 0.5
min_value = 0.0001  # 参数最小值
best_fit = []
no_change = 0 #全局最优未改变次数,达到50次则终止程序

#读取数据并进行预处理
def load_data(data_file):
    data = []   #存储特征
    label = []  #存储标签
    f = open(data_file)
    for line in f.readlines():
        lines = line.strip().split(' ')
        label.append(float(lines[0]))#提取标签
        #提取特征
        index = 0
        tmp = [] #存储每个标签对应的特征
        #数据预处理,对于缺少的特征以0补上
        for i in range(1, len(lines)):
            li = lines[i].strip().split(":")
            if int(li[0]) - 1 == index:     #特征存在
                tmp.append(float(li[1]))
            else:       #特征不存在以零补上,并将当前的添加上
                while (int(li[0]) - 1 > index):
                    tmp.append(0)
                    index += 1
                tmp.append(float(li[1]))
            index += 1
        while len(tmp) < 13:    #处理特征在最后缺少的情况
            tmp.append(0)
        data.append(tmp)
    f.close()
    return np.array(data), np.array(label).T

#PSO
#1.粒子及其运动方向初始化
def inti_origin():
    particle_loc = []   #记录所有粒子移动过的位置,为一个二维数组,
    particle_dir = []   #记录所有粒子要移动的方向,及其历史方向,为二维数组
    for i in range(particle_num):
        tempA = [] #存储每个粒子的参数
        tempB = []  #存储每个例子的移动方向
        for j in range(particle_dim):
            a = random.random()*(20-min_value) #随机参数
            b = random.random()  # 随机移动方向
            tempA.append(a)
            tempB.append(b)
        particle_loc.append(tempA)
        particle_dir.append(tempB)
    return particle_loc,particle_dir
#2.计算SVM的适应度函数值,并寻找局部和全局最优适应度,及其对应的参数
def fitness(particle_loc,trainX, trainY,pbest_fit,gbest_fit,pbest_loc,gbest_loc):
    #particle_loc粒子所在位置集合
    #pbest_fit 局部最优适应度
    #gbest_fit 全局最优适应度
    #pbest_loc 局部最优参数
    #gbest_loc 全局最优参数
    fit_value = []
    #对每个粒子计算其适应度,以3-fold拆分数据,RBF为核函数,求出3个适应度值,取平局值为最终结果
    for i in range(particle_num):
        rbf_svm = svm.SVC(kernel='rbf', C=particle_loc[i][0], gamma=particle_loc[i][1])
        cv_scores = model_selection.cross_val_score(rbf_svm, trainX, trainY, cv=3, scoring='accuracy')
        fit_value.append(cv_scores.mean())
    k = 0  # 记录循环下标
    for i in range(len(fit_value)):
        if(pbest_fit[k] < fit_value[k]):  #新的局部最优出现
            pbest_fit[k] = fit_value[k]
            pbest_loc[k] = particle_loc[k]
            if(fit_value[k] > gbest_fit): #新的全局最优出现
                gbest_fit = fit_value[k]
                gbest_loc = particle_loc[k]
    print('最优适应度为{},对应参数是{}'.format(gbest_fit,gbest_loc))
    best_fit.append(gbest_fit)
    return pbest_fit,gbest_fit,pbest_loc,gbest_loc
#3.更新粒子的位置
def updata(particle_loc,particle_dir,pbest_loc,gbest_loc,k):
    #k为当前迭代次数,动态更新w时使用
    w = w_max - (w_max-w_min)*((k+1)/iter_num)    #w采用新的更新方式
    for i in range(particle_num):   # 速度更新
        #新的速度由三部分组成
        a1 = [w * particle_dir[i][0],w * particle_dir[i][1]]
        a2 = [c1 * random.random() * (pbest_loc[i][0] - particle_loc[i][0]),c1 * random.random() * (pbest_loc[i][1] - particle_loc[i][1])] #参考局部
        a3 = [c2 * random.random() * (gbest_loc[0] - particle_loc[i][0]),c2 * random.random() * (gbest_loc[1] - particle_loc[i][1])] #参考全局
        new_dir = [a1[0]+a2[0]+a3[0],a1[1]+a2[1]+a3[1]]
        particle_dir[i] = new_dir #更新速度
        particle_loc[i] = [particle_dir[i][0] + new_dir[0],particle_dir[i][1] + new_dir[1]] #更新位置

        #由于SVM的要求是参数不能小于零,并且应该保持在一定范围保证其性能,所以要对更新后的参数进行判断
        particle_loc[i][0] = max(particle_loc[i][0], min_value)
        particle_loc[i][1] = max(particle_loc[i][1], min_value)

    return particle_dir,particle_loc
#画适应度折线图
def plot(best_fit):
    X = []
    Y = []
    for i in range(len(best_fit)):
        X.append(i + 1)
        Y.append(best_fit[i])
    plt.plot(X, Y)
    plt.xlabel('迭代次数', size=15)
    plt.ylabel('适应度', size=15)
    plt.show()
#画散点图
def plot_point(pbest_loc):
    X = []
    Y = []
    for i in range(len(pbest_loc)):
        X.append(pbest_loc[i][0])
        Y.append(pbest_loc[i][1])
    plt.figure(figsize=(20, 8), dpi=100) #创建画布
    plt.scatter(X,Y)
    plt.show()
if __name__ == '__main__':
    #读取数据
    trainX, trainY = load_data('rbf_data.txt')
    #初始化
    particle_loc, particle_dir = inti_origin()
    all_fitness = [] #记录所有计算过的适应度的值
    pbest_fit = [] #记录每个粒子各自的最优适应度
    pbest_loc = []  #记录每个粒子各自的最优位置
    for i in range(particle_num):
        pbest_fit.append(0.0)
        pbest_loc.append([0.0,0.0])
    gbest_fit = 0.0 #全局最优适应度
    gbest_loc = [0.0,0.0] #全局最优位置
    for i in range(iter_num):
        print('迭代次数:',i+1,end=",")
        old_gbest_fit = gbest_fit
        pbest_fit,gbest_fit,pbest_loc,gbest_loc = fitness(particle_loc, trainX, trainY,pbest_fit,gbest_fit,pbest_loc,gbest_loc)
        #如果过连续50代没有产生新的最优值则停止循环
        if(old_gbest_fit == gbest_fit):
            no_change += 1
        else:
            no_change = 0
        if(no_change == 50):
            break
        particle_dir, particle_loc = updata(particle_loc,particle_dir,pbest_loc,gbest_loc,i)
    plot_point(pbest_loc)
    plot(best_fit)
相关标签: 智能算法 算法