zl程序教程

您现在的位置是:首页 >  其它

当前栏目

2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案

2021 作业 第二 遗传算法 参考答案 人工神经网络 第三次
2023-09-11 14:15:20 时间

简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。

关键词 遗传算法NN人工神经网络

第二题:遗传算法与NN
文章目录
作业要求
作业求解
异或问题
构造遗传算法
遗传算法进化
不同参数遗传结果
种群平均适应度变化
答案总结

  2021年人工神经网络第三次作业要求以及参考答案

 

§02 二题:
遗传算法与NN


一、作业要求

  利用遗传算法可以训练神经网络的权系数。特别是神经网络用于复杂对象控制的情况下,无法给出神经网络准确的期望输出,只能给出整个系统性能的评价时,可以使用遗传算法完成网络训练。

▲ 图1.1.1  异或网络以及传递函数要求

▲ 图1.1.1 异或网络以及传递函数要求

二、作业求解

1、异或问题

  根据题目中给定的神经元传递函数,它的输出在(0,1)之间,使用(-1,1)来表示异或问题中样本的输出,(0,1)表示样本的期望输出。对应的四个样本如下表格所示:

【表2-2-1 异或问题四个样本】

样本输入(X1,X2)输出:Y
样本11,10
样本2-1,11
样本31,-11
样本4-1,-10

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 求解异或问题的神经网络

▲ 图1.2.1 求解异或问题的神经网络

  72bit分配关系如下:

▲ 图1.2.2 72bit 0-1串与网络系数之间关系

▲ 图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]

  转换成对应九个有符号整形数字,分别对应 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]

  将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]

  定义,个体适应度为:

  其中, 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

(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]]
Ⅱ.变异算子

  定义遗传算法变异比率: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		# 变异步骤
Ⅱ.进化曲线

▲ 图1.2.3 适应度曲线演变过程

▲ 图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 遗传算法演变过程中最好的样本对应的适应度变化

▲ 图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]

  可以看到,此时神经网络最终演变的结果误差更小。

(2)改变适应度函数

  修改后的适应度函数为:

▲ 图1.2.5 演变过程中最好的样本对应的适应度的变化

▲ 图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]

(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.6 演变过程中神经网络最优的适应度变化

▲ 图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]

5、种群平均适应度变化

  前面给出的是在遗传算法演变过程中,最优个体适应度随着演变过程的变化。它呈现的是阶跃式的变化。下面给出种群平均适应度的演变。

(1)演变参数

GA_SELECT_RATIO             = 0.2   # 选择比率
GA_MUTATE_RATIO             = 0.2   # 变异比率
GA_CROSS_RATIO              = 0.25  # 交叉比率
GA_NUMBER                   = 100   # 种群个数
GA_STEP                     = 100   # 演化步骤

(2)种群平均适应度变化

▲ 图1.2.7 遗传算法种群平均适应度变化

▲ 图1.2.7 遗传算法种群平均适应度变化

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

▲ 图1.2.8 遗传算法种群平均适应度的变化

▲ 图1.2.8 遗传算法种群平均适应度的变化

▲ 图1.2.9  进化过程中种群适应度的分布
▲ 图1.2.9 进化过程中种群适应度的分布

 

案总结 ※


  出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程。所使用的遗传算法是最基本的遗传算法。利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化。对于不同的遗传算法参数对于结果的影响进行的试验对比。


■ 相关文献链接:

● 相关图表链接:

● 完成的程序

#!/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
#============================================================