智能优化算法——python实现免疫遗传算法的图像拟合

介绍

算法思路

免疫算法是通过模仿生物体内的免疫反应进行优化的算法。我们正在拟合的问题可以被视为一种抗原,而可能被分解的抗原被视为抗体。当抗原侵入生物体时,免疫系统会进行免疫反应。在免疫反应的早期,会产生大量的抗体作为反应,然后复制和保留对抗原亲和力高的抗体,抑制高浓度抗体的复制,以保证抗体的多样性。在此过程中,还会产生新抗体并将其添加到原始抗体集合中。为了更直观的介绍免疫遗传算法,我们还是以图片为例来实现和拟合免疫遗传算法。

流程图

智能优化算法——python实现免疫遗传算法的图像拟合

算法体

预备知识与智能优化算法——python实现使用遗传算法进行图片拟合相同,在此不再赘述,我们现在直接开始算法主体的实现。同样为了方便理解,将代码分割成若干部分介绍,完整代码可以在文末下载。

初始化

初始化与遗传算法的实现相同

def __init__(self, imgPath, saveName="temp", alpha=5, beta=0.5, maxgroup=200, features=100, epochs=1000):
	self.orignal_img, self.type, self.row, self.col = self.OpenImg(imgPath)
    self.max_group = maxgroup
    self.saveName = saveName
    self.groups = []
    self.features = features
    self.epochs = epochs
    self.group_dict = dict()
    self.alpha = alpha
    self.beta = beta
    if not os.path.exists(saveName):
       	os.mkdir(saveName)
    print("初始化...")
    for i in range(randint(self.max_group, self.max_group * 2)):
       	g = []
        for j in range(self.features):
       		tmp = [[choice(np.linspace(0, self.row, features)), choice(np.linspace(0, self.col, features))] for x in range(3)]
            tmp.append("#" + ''.join(choice('0123456789ABCDEF') for x in range(6)))

            g.append(tmp.copy())

        self.groups.append(g.copy())

    self.maxg = self.groups[0]
    print("初始化完成!")

获得抗体与抗体的相似性

我们使用structural_similarity函数来比较两个抗体的相似度

def get_antibody_similar(self, g1, g2):
    ssim = structural_similarity(np.array(g1), np.array(g2), multichannel=True)
    return ssim

克隆和突变

这个过程和遗传算法一样

注:在遗传算法中生物繁殖的后代不会与父辈和母辈完全相同,但是在抗体是可以做到完全一致的。所以在breeds函数在遗传算法中代表的是繁殖过程,而在免疫遗传算法的抗体的克隆和变异中,函数breeds代表的是抗体的变异。按照流程来讲免疫算法还应该具有克隆抗体的过程,而这里我们只需保留原有的抗体即可以看作是克隆过程已完成。为了方便对照,所以我们保留了原有的函数名。

def exchange(self, father, mother)->[]:
    # 交换
    # 随机生成互换个数
    min_locate = min(len(father), len(mother))
    n = randint(0, int(randint(25, 100) / 100 * min_locate))
    # 随机选出多个位置
    selected = sample(range(0, min_locate), n)
    # 交换内部
    for s in selected:
        father[s], mother[s] = mother[s], father[s]

    # 交换尾部
    locat = randint(0, min_locate)
    fhead = father[:locat].copy()
    mhead = mother[:locat].copy()

    ftail = father[locat:].copy()
    mtail = mother[locat:].copy()

    # print(fhead, ftail, mhead, mtail)
    fhead.extend(mtail)
    father = fhead
    mhead.extend(ftail)
    mother = mhead
    return [father, mother]

def mutation(self, gen):
    # 突变
    # 随机生成变异个数
    n = int(randint(1, 100) / 1000 * len(gen))

    selected = sample(range(0, len(gen)), n)

    for s in selected:
        tmp = [[choice(np.linspace(0, self.row, 100)), choice(np.linspace(0, self.col, 100))] for x in
                   range(3)]
        tmp.append("#" + ''.join(choice('0123456789ABCDEF') for x in range(6)))
        gen[s] = tmp

    return gen

def move(self, gen):
    # 易位
    exchage = int(randint(1, 100) / 1000 * len(gen))
    for e in range(exchage):
        sec1 = randint(0, len(gen) - 1)
        sec2 = randint(0, len(gen) - 1)

        gen[sec1], gen[sec2] = gen[sec2], gen[sec1]

    return gen

def add(self, gen):
    # 增加
    n = int(randint(1, 100) / 1000 * len(gen))

    for s in range(n):
        tmp = [[choice(np.linspace(0, self.row, self.features)), choice(np.linspace(0, self.col, self.features))] for x in range(3)]
        tmp.append("#" + ''.join(choice('0123456789ABCDEF') for x in range(6)))
        gen.append(tmp)

    return gen

def cut(self, gen):
    # 减少
    n = int(randint(1, 100) / 1000 * len(gen))
    selected = sample(range(0, len(gen)), n)

    g = []
    for gp in range(len(gen)):
        if gp not in selected:
           	g.append(gen[gp])

    return g

def variation(self, gen):
    # 变异
    gen = self.mutation(gen.copy())
    gen1 = self.move(gen.copy())
    gen2 = self.add(gen1.copy())
    gen3 = self.cut(gen2.copy())
    return [gen, gen1, gen2, gen3]

def breeds(self, father, mother):
    # 繁殖
    new1, new2 = self.exchange(father.copy(), mother.copy())

    # 变异
    new3, new4, new5, new6 = self.variation(father.copy())
    new7, new8, new9, new10 = self.variation(mother.copy())

    return [new1, new2, new3, new4, new5, new6, new7, new8, new9, new10]

获得抗体亲和力和抗体浓度

这里传进来的参数g_img是各个抗体的图片格式,通过两层循环获取抗体亲浓度和抗体亲和度

def get_aff(self, g_img):
    # 抗体浓度和抗体亲和度(抗体与抗体间的亲和度和抗体与抗原的亲和度)
    group_len = len(g_img)
    den = np.zeros((group_len, group_len))
    aff = np.zeros(group_len)
    for i in range(group_len):
        for j in range(i, group_len):
            if self.get_antibody_similar(g_img[i], g_img[j]) > 0.75:
                den[i][j] += 1
                den[j][i] += 1

        aff[i] = self.getSimilar(g_img[i])

    return aff, den.sum(axis=0) / group_len

抗体收集更新

先将抗体转换成图片格式,然后计算抗体浓度和抗体亲和力,根据抗体亲和力更新抗体集合。

其中对于抗体集合的更新由抗体浓度den和抗体亲和度aff决定。

假设我们将这个决定方式规定为激励算子sim,我们做以下假设:
智能优化算法——python实现免疫遗传算法的图像拟合
这里的A我们多思考一些,根据抗体更新的实质我们可以看出,最开始的时候抗体和抗原的亲和度十分的低,其值都十分随机,这时影响优化效果的因素与亲和度aff相关性要比浓度den相关性大得多,这时就应该很小,而当他接近完全拟合时浓度den的相关性就变得更高了。由直觉可知,A的增长应该呈指数级

假设我们要得到取值范围在0-maxn的A,我们可以由以下推导
智能优化算法——python实现免疫遗传算法的图像拟合

由此如果我们要得到取值范围在minn-maxn之间的A,再考虑到拟合的轮次我们可以得到
智能优化算法——python实现免疫遗传算法的图像拟合
通过这个公式我们可以实现对于A参数的动态调整,当然这里也可以换成其他表达式或者设成一个定值(定值也可以看作一个特殊的表达式)

def eliminated(self, groups, epoch):
    g_img = []
    for g in groups:
        g_img.append(self.to_image(g.copy()))

    aff, den = self.get_aff(g_img)
    sim = aff - (np.e ** (np.log(self.alpha+1-self.beta) / (self.epochs - epoch + 1)) - 1 + self.beta) * den
    sim = sim.tolist()
    self.group_dict.clear()
    self.group_dict = {key: value for key, value in enumerate(sim)}
    self.group_dict = {key: value for key, value in
                         sorted(self.group_dict.items(), key=lambda item: item[1], reverse=True)}

    g = []
    Acc = 0
    Den = 0
    Sim = 0
    for key in list(self.group_dict.keys())[:self.max_group]:
        if Acc == 0 and Den == 0 and Sim == 0:
            Acc, Den, Sim = aff[key], den[key], sim[key]

        g.append(groups[key].copy())

    return g, Acc, Den, Sim

拟合过程

拟合过程类似于遗传算法,但增加了一个创建新抗体的过程。

def fit(self):
    self.groups, _, _, _ = self.eliminated(self.groups, 1)
    for cur in range(self.epochs):
        # 繁殖过程
        breed_n = randint(self.max_group // 2, self.max_group)
        g_f = np.abs(np.array(list(self.group_dict.values())))
        p = g_f / np.sum(g_f)
        for i in range(breed_n):
            f = np.random.choice(list(self.group_dict.keys()), p=p.ravel())
            m = np.random.choice(list(self.group_dict.keys()), p=p.ravel())
            if f < self.max_group and m < self.max_group:
                self.groups.extend(self.breeds(self.groups[int(f)].copy(), self.groups[int(m)].copy()))


        for i in range(randint(0, self.max_group // 2)):
            g = []
            for j in range(self.features):
               tmp = [[choice(np.linspace(0, self.row, self.features)), choice(np.linspace(0, self.col, self.features))] for
                           x in range(3)]
               tmp.append("#" + ''.join(choice('0123456789ABCDEF') for x in range(6)))

               g.append(tmp.copy())

            self.groups.append(g.copy())

        # 淘汰
        self.groups, Acc, Den, Sim = self.eliminated(self.groups.copy(), cur+1)
        print("Epochs :", cur+1, " Acc:", Acc, " Den:", Den, " Sim:", Sim)
        with open("Log.txt", 'a') as f:
            f.write(str(Acc))
            f.write(" ")
            f.write(str(Den))
            f.write(" ")
            f.write(str(Sim))
            f.write("\n")

        if cur % 100 == 0:
            self.draw_image(self.groups[0], cur)
        if Acc >= 0.95:
            break

    self.draw_image(self.groups[0], "End")

培训过程评估

我们可以使用以下代码进行绘图评估

Acc = []
Den = []
Sim = []
with open('Log.txt') as f:
    for s in f.readlines():
        s = s.strip()
        s1 = s.split(" ")
        Acc.append(float(s1[0]))
        Den.append(float(s1[1]))
        Sim.append(float(s1[2]))


import matplotlib.pyplot as plt

plt.plot(range(len(Acc)), Acc, label='Acc')
plt.plot(range(len(Den)), Den, label='Den')
plt.plot(range(len(Sim)), Sim, label='Sim')
plt.legend()
plt.show()

训练效果对比

我们以小蓝鸟为例,对比一下拟合情况
智能优化算法——python实现免疫遗传算法的图像拟合

遗传算法部分拟合图像

智能优化算法——python实现免疫遗传算法的图像拟合

部分拟合图像的免疫遗传算法

智能优化算法——python实现免疫遗传算法的图像拟合

比较总结

我们可以先观察遗传算法的拟合效果。可以看出,结果相似的轮次很多,显然浪费了很多时间去拟合。原因是随着不断的更新,所有个体都会朝着同一个方向优化时,难免会出现大量相似的个体。在免疫遗传算法中引入抗体浓度的概念,可以抑制高浓度的抗体,从而保证个体特征的多样性。但是由于引入了计算抗体浓度的过程,每轮拟合都比遗传算法慢,但有效避免了大量相似个体的存在,所以一般情况下会大大减少拟合所需的参数。完整的拟合时间将早于遗传算法。

完整代码下载

CSDN下载地址:https://download.csdn.net/download/DuLNode/85110172
GitHub下载地址:https://github.com/AiXing-w/Python-Intelligent-Optimization-Algorithms

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
上一篇 2022年4月13日 下午2:02
下一篇 2022年4月13日 下午2:15

相关推荐