2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案
简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。
关键词
: 遗传算法,NN,人工神经网络
§02 第二题:
遗传算法与NN
遗传算法与NN
一、作业要求
利用遗传算法可以训练神经网络的权系数。特别是神经网络用于复杂对象控制的情况下,无法给出神经网络准确的期望输出,只能给出整个系统性能的评价时,可以使用遗传算法完成网络训练。
▲ 图1.1.1 异或网络以及传递函数要求
二、作业求解
1、异或问题
根据题目中给定的神经元传递函数,它的输出在(0,1)之间,使用(-1,1)来表示异或问题中样本的输出,(0,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 串表示
对题目中的神经网络,存在着六个权系数 w 1 , w 2 , ⋯ , w 6 w_1 ,w_2 , \cdots ,w_6 w1,w2,⋯,w6和三个阈值 b 1 , b 2 , b 3 b_1 ,b_2 ,b_3 b1,b2,b3。使用8bit的有符号整数表示。这样九个参数共由72bit表示。
▲ 图1.2.1 求解异或问题的神经网络
72bit分配关系如下:
▲ 图1.2.2 72bit 0-1串与网络系数之间关系
前48bit分别对应 w 1 , 2 , ⋯ , 6 w_{1,2, \cdots ,6} w1,2,⋯,6,后面24bit对于 b 1 , b 2 , b 3 b_1 ,b_2 ,b_3 b1,b2,b3。每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]
- 1
转换成对应九个有符号整形数字,分别对应 w 1 , 2 , ⋯ , 6 w_{1,2, \cdots ,6} w1,2,⋯,6以及 b 1 , 2 , 3 b_{1,2,3} b1,2,3。
[-120, -96, -13, -10, 37, -48, -66, -5, -14]
- 1
将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
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
将上述参数代入网络【1.2.1】中,根据神经元的传递函数:
可以计算出表格【2-2-1】中四个样本对应的网络输出。
[0.2359961611001143, 0.16208119759951686, 0.16270729983112092, 0.16270729983112092]
- 1
定义,个体适应度为:
其中, y i , t i , i = 1 , 2 , 3 , 4 y_i ,t_i ,i = 1,2,3,4 yi,ti,i=1,2,3,4分别是四个样本的网络输出以及期望值。
具体计算样本的适应度的函数为:
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
(3)构建选择,变异,交叉算子
Ⅰ.选择算子
定义遗传算法选择比率:GA_SELECT_RATIO,从给定的样本中选择适应度在前比率的样本,遗传到下一代。
def GA_select(a, num=0):
if num == 0:
num = len(a)
ac = [a01C(aa) for aa in a]
ac01sort = sorted(zip(ac, a), key=lambda x:x[0], reverse=True)
return [b[1] for b in ac01sort[:num]]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Ⅱ.变异算子
定义遗传算法变异比率: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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Ⅲ.交叉算子
定义遗传算子交叉比率 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
具体的步骤为:
- 对于给定的群体,先按照适应度选择比率 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 # 变异步骤
- 1
- 2
- 3
- 4
- 5
Ⅱ.进化曲线
▲ 图1.2.3 适应度曲线演变过程
Ⅲ.进化结果
- 四个样本对应的输出:
[0.035727307060094554, 0.9458490274836487, 0.9528182214514648, 0.1047363087760371]
- 网络系数:
[-113, -116, 124, 109, -105, -128, -87, -88, 62]
4、不同参数遗传结果
(1)改变神经网络传递函数
将神经网络传递函数修改为:
演变参数不变,演变过程中适应度变化:
▲ 图1.2.4 遗传算法演变过程中最好的样本对应的适应度变化
演变神经网络参数:
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]
- 1
- 2
- 3
可以看到,此时神经网络最终演变的结果误差更小。
(2)改变适应度函数
修改后的适应度函数为:
▲ 图1.2.5 演变过程中最好的样本对应的适应度的变化
演变后神经网络的参数为:
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]
- 1
- 2
- 3
(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 # 演化步骤
- 1
- 2
- 3
- 4
- 5
演变过程中最好的神经网络对应的适应度演变为:
▲ 图1.2.6 演变过程中神经网络最优的适应度变化
最终的神经网络参数:
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]
- 1
- 2
- 3
5、种群平均适应度变化
前面给出的是在遗传算法演变过程中,最优个体适应度随着演变过程的变化。它呈现的是阶跃式的变化。下面给出种群平均适应度的演变。
(1)演变参数
GA_SELECT_RATIO = 0.2 # 选择比率
GA_MUTATE_RATIO = 0.2 # 变异比率
GA_CROSS_RATIO = 0.25 # 交叉比率
GA_NUMBER = 100 # 种群个数
GA_STEP = 100 # 演化步骤
- 1
- 2
- 3
- 4
- 5
(2)种群平均适应度变化
▲ 图1.2.7 遗传算法种群平均适应度变化
下面是将变异比率改成0.8,对应的种群平时适应度的变化。
▲ 图1.2.8 遗传算法种群平均适应度的变化
▲ 图1.2.9 进化过程中种群适应度的分布
※ 答案总结 ※
给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。
■ 相关文献链接:
● 相关图表链接:
- 图1.1.1 异或网络以及传递函数要求
- 表2-2-1 异或问题四个样本
- 图1.2.1 求解异或问题的神经网络
- 图1.2.2 72bit 0-1串与网络系数之间关系
- 图1.2.3 适应度曲线演变过程
- 图1.2.4 遗传算法演变过程中最好的样本对应的适应度变化
- 图1.2.5 演变过程中最好的样本对应的适应度的变化
- 图1.2.6 演变过程中神经网络最优的适应度变化
- 图1.2.7 遗传算法种群平均适应度变化
- 图1.2.8 遗传算法种群平均适应度的变化
● 完成的程序
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2021-11-25
#
# Note:
#============================================================
from headm import *
#------------------------------------------------------------
random.seed()
def rand01(l=72):
r = random.rand(l)
rr = [1 if a else 0 for a in r > 0.5]
return rr
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
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)**2) for x,y in zip(yt,yo)])
return error
def funcC(error):
if error == 0: return 100000
else: return 1/error
def a01C(a01):
wb = wb012(a01)
yout = xornnout(wb)
e = xorerr(yout)
return funcC(e)
#------------------------------------------------------------
'''
wb01 = rand01()
wb = wb012(wb01)
printf(wb01, wb)
yout = xornnout(wb)
printf(yout)
printf(xorerr(yout))
printf(a01C(wb01))
'''
#------------------------------------------------------------
def GA_select(a, num=0):
if num == 0:
num = len(a)
ac = [a01C(aa) for aa in a]
ac01sort = sorted(zip(ac, a), key=lambda x:x[0], reverse=True)
return [b[1] for b in ac01sort[:num]]
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
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
#------------------------------------------------------------
'''
aa = []
for _ in range(10):
aa.append(rand01())
#printf(aa)
#sa = GA_mutate(aa)
#printf(sa)
a = [[i]*20 for i in range(10)]
printf(a)
aa = GA_cross(a, 0.5)
printf(aa)
'''
#------------------------------------------------------------
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
#------------------------------------------------------------
GA_SELECT_RATIO = 0.2 # 选择比率
GA_MUTATE_RATIO = 0.8 # 变异比率
GA_CROSS_RATIO = 0.25 # 交叉比率
GA_NUMBER = 100 # 种群个数
GA_STEP = 100 # 演化步骤
aall = []
for _ in range(GA_NUMBER):
aall.append(rand01())
cdim = []
for i in range(GA_STEP):
aall = GA_iterate(aall)
wb = wb012(aall[0])
yout = xornnout(wb)
e = xorerr(yout)
printff(i, yout, e, funcC(e))
edim = [a01C(na) for na in aall]
ea = average(edim)
cdim.append(ea)
wb = wb012(aall[0])
yout = xornnout(wb)
printf('w1,2,3,4,5,6:%d,%d,%d,%d,%d,%d'%(wb[0],wb[1],wb[2],wb[3],wb[4],wb[5]))
printf('b1,2,3:%d,%d,%d'%(wb[6], wb[7], wb[8]))
printff("Y:", yout)
plt.plot(cdim)
plt.xlabel("Step")
plt.ylabel("FuncC")
plt.grid(True)
plt.tight_layout()
plt.show()
#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/121547538
- 点赞
- 收藏
- 关注作者
评论(0)