
“简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。
关键词: 遗传算法,NN,人工神经网络
一、作业要求
利用遗传算法可以训练神经网络的权系数。特别是神经网络用于复杂对象控制的情况下,无法给出神经网络准确的期望输出,只能给出整个系统性能的评价时,可以使用遗传算法完成网络训练。

二、作业求解
1、异或问题
根据题目中给定的神经元传递函数,它的输出在(0,1)之间,使用(-1,1)来表示异或问题中样本的输出,(0,1)表示样本的期望输出。对应的四个样本如下表格所示:
【表2-2-1 异或问题四个样本】
| 样本 | 输入(X1,X2) | 输出:Y |
|---|---|---|
| 样本1 | 1,1 | 0 |
| 样本2 | -1,1 | 1 |
| 样本3 | 1,-1 | 1 |
| 样本4 | -1,-1 | 0 |
2、构造遗传算法
(1)网络个体使用72bit 0-1 串表示
对题目中的神经网络,存在着六个权系数和三个阈值。使用8bit的有符号整数表示。这样九个参数共由72bit表示。

72bit分配关系如下:

前48bit分别对应,后面24bit对于。每8bit分别表示 -128 ~ 127 之间的整数。
(2)个体适应度
对于任一个72bit 0-1串,根据上述编码,将其转换成网络的权系数以及偏移量。
比如,对于一个72位的 0 - 1串,
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0]
转换成对应九个有符号整形数字,分别对应以及。
[-120, -96, -13, -10, 37, -48, -66, -5, -14]
将72bit 0-1 字符串转换成9个参数的程序如下:
def bit8(r):
bytestr = ''.join(['%d'%rr for rr in r])
n = int(bytestr, 2)
if n >= 128: n = n - 256
return n
def wb012(wb):
wwbb = list(zip(*([iter(wb)]*8)))
wb = [bit8(r) for r in wwbb]
return wb
将上述参数代入网络【1.2.1】中,根据神经元的传递函数:

可以计算出表格【2-2-1】中四个样本对应的网络输出。
[0.2359961611001143, 0.16208119759951686, 0.16270729983112092, 0.16270729983112092]
定义,个体适应度为:

其中,分别是四个样本的网络输出以及期望值。
具体计算样本的适应度的函数为:
def fnn(x):
return 1/(1+exp(-x/20))
def xornn(wb, x1, x2):
v1 = fnn(x1*wb[0] + x2*wb[1] + wb[6])
v2 = fnn(x1*wb[2] + x2*wb[3] + wb[7])
y = fnn(v1*wb[4] + v2*wb[5] + wb[8])
return y
#------------------------------------------------------------
x12 = ((1,1),(1,-1),(-1,1),(-1,1))
yt = (0,1,1,0)
def xornnout(wb):
global x12
return [xornn(wb,a[0],a[1]) for a in x12]
def xorerr(yo):
global yt
error = sum([abs(x-y) for x,y in zip(yt,yo)])
return error
def funcC(error):
if error * 0: return 100000
else: return 1/e
(3)构建选择,变异,交叉算子
Ⅰ.选择算子
定义遗传算法选择比率:GA_SELECT_RATIO,从给定的样本中选择适应度在前比率的样本,遗传到下一代。
def GA_select(a, r=1):
ac = [a01C(aa) for aa in a]
ac01sort = sorted(zip(ac, a), key=lambda x:x[0], reverse=True)
selnum = int(len(a) * r)
return ac01sort[:selnum]
Ⅱ.变异算子
定义遗传算法变异比率:GA_MUTATE_RATIO, 对每个给定的样本,选择其中给定比率的0,1进行变异,也就是从0变道1,从1变道0。
def GA_mutate(a, r=0.25):
outa = []
mutnum = int(len(a[0]) * r)
for aa in a:
s01 = [1] * len(aa)
s01[:mutnum] = [-1]*mutnum
random.shuffle(s01)
newa = [((a*2-1)*b+1)//2 for a,b in zip(aa, s01)]
outa.append(newa)
return outa
Ⅲ.交叉算子
定义遗传算子交叉比率 GA_CROSS_RATIO,对于样本随机抽取比率次样本进行交叉,交叉位置随机确定。
def GA_cross(a, r=0.25):
num = len(a)
crossnum = int(num*r)
listA = list(range(num))
listB = list(range(num))
random.shuffle(listA)
random.shuffle(listB)
printf(listA, listB)
for i in range(crossnum):
aa = listA[i]
bb = listB[i]
c1 = a[aa]
c2 = a[bb]
crossP = random.randint(0, len(a[0]))
c1[crossP:],c2[crossP:] = c2[crossP:],c1[crossP:]
a[aa] = c1
a[bb] = c2
return a
3、遗传算法进化
(1)遗传迭代过程
下面函数定义了简单的遗传算法迭代过程:
def GA_iterate(a, sr=0.8, mr=0.25, cr=0.25):
sa = GA_select(a, int(len(a) * sr))
am = GA_mutate(a, mr)
amc = GA_cross(am, cr)
amcs = GA_select(amc, len(a) - len(sa))
sa.extend(amcs)
return sa
具体的步骤为:
对于给定的群体,先按照适应度选择比率 sr 的个体作为下一代遗传群体; 对群体中按照比例 mr 进行变异; 变异后,在按照比例 cr进行交叉; 然后在选择变异交叉后的个体中,适应度高的群体补足群体个数。
(2)遗传算法结果
Ⅰ.进化参数
GA_SELECT_RATIO = 0.2 # 选择比率
GA_MUTATE_RATIO = 0.8 # 变异比率
GA_CROSS_RATIO = 0.25 # 交叉比率
GA_NUMBER = 100 # 种群个数
GA_STEP = 100 # 变异步骤
Ⅱ.进化曲线

Ⅲ.进化结果
四个样本对应的输出:
“[0.035727307060094554, 0.9458490274836487, 0.9528182214514648, 0.1047363087760371]
网络系数:
“[-113, -116, 124, 109, -105, -128, -87, -88, 62]
4、不同参数遗传结果
(1)改变神经网络传递函数
将神经网络传递函数修改为:

演变参数不变,演变过程中适应度变化:

演变神经网络参数:
w1,2,3,4,5,6:-98,86,76,-88,110,117
b1,2,3:-128,-108,-46
Y: [0.00010102919399854787, 0.9999993189844584, 0.9999972384044112, 0.000101029204937878]
可以看到,此时神经网络最终演变的结果误差更小。
(2)改变适应度函数
修改后的适应度函数为:


演变后神经网络的参数为:
w1,2,3,4,5,6:107,59,-126,-106,-90,-87
b1,2,3:-98,-85,52
Y: [0.1474590192591501, 0.9034300127870185, 0.9194272314023755, 0.14839883180784771]
(3)调整演变参数
将其中的变异参数的比率降低,从0.8 改为0.2。
GA_SELECT_RATIO = 0.2 # 选择比率
GA_MUTATE_RATIO = 0.2 # 变异比率
GA_CROSS_RATIO = 0.25 # 交叉比率
GA_NUMBER = 100 # 种群个数
GA_STEP = 100 # 演化步骤
演变过程中最好的神经网络对应的适应度演变为:

最终的神经网络参数:
w1,2,3,4,5,6:-68,-89,-108,-96,-116,101
b1,2,3:-123,101,-64
Y: [0.04027612710494942, 0.8527779494354807, 0.8615199376222323, 0.04504067981481253]
5、种群平均适应度变化
前面给出的是在遗传算法演变过程中,最优个体适应度随着演变过程的变化。它呈现的是阶跃式的变化。下面给出种群平均适应度的演变。
(1)演变参数
GA_SELECT_RATIO = 0.2 # 选择比率
GA_MUTATE_RATIO = 0.2 # 变异比率
GA_CROSS_RATIO = 0.25 # 交叉比率
GA_NUMBER = 100 # 种群个数
GA_STEP = 100 # 演化步骤
(2)种群平均适应度变化

下面是将变异比率改成0.8,对应的种群平时适应度的变化。

※ 答案总结 ※
给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。
参考资料
2021年人工神经网络第三次作业要求以及参考答案: https://zhuoqing.blog.csdn.net/article/details/121508788