智慧優化演算法——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,我們做以下假設:
s
i
m
=
a
f
f
−
A
∗
d
e
n
sim=aff-A*den
sim=aff−A∗den
這裡的A我們多思考一些,根據抗體更新的實質我們可以看出,最開始的時候抗體和抗原的親和度十分的低,其值都十分隨機,這時影響優化效果的因素與親和度aff相關性要比濃度den相關性大得多,這時就應該很小,而當他接近完全擬合時濃度den的相關性就變得更高了。由直覺可知,A的增長應該呈指數級
假設我們要得到取值範圍在0-maxn的A,我們可以由以下推導
假
設
:
0
≤
e
a
−
1
≤
m
a
x
n
=
>
1
≤
e
a
≤
m
a
x
n
+
1
=
>
l
n
1
≤
a
≤
l
n
(
m
a
x
n
+
1
)
=
>
e
l
n
1
≤
e
a
≤
e
l
n
(
m
a
x
n
+
1
)
假設:0 \leq e^a-1 \leq maxn \\ =>1 \leq e^a \leq maxn +1 \\ =>ln1 \leq a \leq ln(maxn+1) \\ =>e^{ln1} \leq e^a \leq e ^{ln(maxn+1)}
假設:0≤ea−1≤maxn=>1≤ea≤maxn+1=>ln1≤a≤ln(maxn+1)=>eln1≤ea≤eln(maxn+1)
由此如果我們要得到取值範圍在minn-maxn之間的A,再考慮到擬合的輪次我們可以得到
A
=
e
l
n
(
m
a
x
n
+
1
−
m
i
n
n
)
m
a
x
_
e
p
o
c
h
−
e
p
o
c
h
+
1
−
1
+
m
i
n
n
A=e^{\frac{ln(maxn+1-minn)}{max\_epoch - epoch+1}}-1+minn
A=emax_epoch−epoch+1ln(maxn+1−minn)−1+minn
通過這個公式我們可以實現對於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()
訓練效果對比
我們以小藍鳥為例進行擬合情況的對比
遺傳演算法部分擬合影像
免疫遺傳演算法部分擬合影像
對比總結
我們可以首先來觀察一下遺傳演算法的擬合效果,可以看出有很多輪都得到相似的結果,這樣顯然浪費了大量的時間去擬合,其原因是隨著不斷地更新,所有的個體都會向著同一方向優化,這時難免會出現大量相似的個體,而免疫遺傳演算法引入抗體濃度這一概念,可以使得濃度高的抗體被抑制,從而保障了個體特徵的多樣性。不過由於引入了計算抗體濃度這一過程,每一輪擬合要比遺傳演算法慢,但他有效的避免了大量相似個體的存在,所以總起來講會大大減少擬合需要的論次數。完全擬合的時間會比遺傳演算法早。
完整程式碼下載
CSDN下載地址:https://download.csdn.net/download/DuLNode/85110172
GitHub下載地址:https://github.com/AiXing-w/Python-Intelligent-Optimization-Algorithms
相關文章
- 【智慧優化演算法】遺傳演算法的精英選擇策略、期望選擇策略優化演算法
- Python-遺傳演算法君主交叉程式碼實現Python演算法
- 多目標遺傳演算法NSGA-Ⅱ與其Python實現多目標投資組合優化問題演算法Python優化
- 利用遺傳演算法庫DEAP優化交易策略演算法優化
- python遺傳演算法(詳解)Python演算法
- 人工智慧 (13) 遺傳演算法人工智慧演算法
- 基於遺傳演算法的HFSS和C#聯合模擬(一)演算法C#
- 如何學習python遺傳演算法?Python演算法
- 遺傳演算法演算法
- 【多目標優化演算法】非支配的精英策略遺傳演算法:NSGA-II優化演算法
- MATLAB實戰系列(十一)-多種群遺傳演算法的函式優化演算法(附MATLAB程式碼)Matlab演算法函式優化
- Python遺傳演算法工具箱的使用(一)求解帶約束的單目標優化Python演算法優化
- 遺傳演算法的基本框架演算法框架
- 遺傳演算法求解TSP問題(python版)演算法Python
- 遺傳演算法詳解與實驗演算法
- 模擬退火演算法(1)Python 實現演算法Python
- 寫了一個類GeneticOptimizeStrategy,針對VNPY策略遺傳演算法優化演算法優化
- 使用MPI並行化遺傳演算法框架GAFT並行演算法框架
- 基於遺傳最佳化的協同過濾推薦演算法matlab模擬演算法Matlab
- 粒子群演算法和遺傳演算法的比較演算法
- 遺傳演算法(一):Basic GA演算法
- 透過MATLAB分別對比二進位制編碼遺傳最佳化演算法和實數編碼遺傳最佳化演算法Matlab演算法
- Python遺傳演算法框架使用例項(二)多目標優化問題Geatpy for Python與Matlab的對比學習Python演算法框架優化Matlab
- 基於Python的遺傳演算法特徵約簡(附程式碼)Python演算法特徵
- 10分鐘搞懂遺傳演算法演算法
- 遺傳演算法解決函式最佳化問題演算法函式
- 基於免疫演算法的TSP問題求解matlab模擬演算法Matlab
- 遺傳演算法組卷使用心得演算法
- 遺傳演算法解決TSP問題演算法
- 社群發現之標籤傳播演算法(LPA)python實現演算法Python
- FM演算法python實現演算法Python
- python實現冒泡演算法Python演算法
- python實現FM演算法Python演算法
- 用遺傳演算法進行特徵選擇演算法特徵
- Unity中利用遺傳演算法訓練MLPUnity演算法
- 最優化演算法【牛頓法、擬牛頓法、BFGS演算法】優化演算法
- Warshall‘s algorithm 演算法的實現及優化(修改版)Go演算法優化
- c++實現的模擬退火演算法C++演算法