遗传算法与NN

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

一、作业要求

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

▲ 图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 串表示

  对题目中的神经网络,存在着六个权系数和三个阈值。使用8bit的有符号整数表示。这样九个参数共由72bit表示。

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

  72bit分配关系如下:

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

  前48bit分别对应,后面24bit对于。每8bit分别表示 -128 ~ 127 之间的整数。

(2)个体适应度

  对于任一个72bit 0-1串,根据上述编码,将其转换成网络的权系数以及偏移量。

  比如,对于一个72位的 0 - 1串,

[100010001010000011110011111101100010010111010000101111101111101111110010]

  转换成对应九个有符号整形数字,分别对应以及

[-120-96-13-1037-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.23599616110011430.162081197599516860.162707299831120920.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 * 0return 100000
    elsereturn 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  # 变异步骤
Ⅱ.进化曲线
▲ 图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.000101029193998547870.99999931898445840.99999723840441120.000101029204937878]

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

(2)改变适应度函数

  修改后的适应度函数为:

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

  演变后神经网络的参数为:

w1,2,3,4,5,6:107,59,-126,-106,-90,-87
b1,2,3:-98,-85,52
Y: [0.14745901925915010.90343001278701850.91942723140237550.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 演变过程中神经网络最优的适应度变化

  最终的神经网络参数:

w1,2,3,4,5,6:-68,-89,-108,-96,-116,101
b1,2,3:-123,101,-64
Y: [0.040276127104949420.85277794943548070.86151993762223230.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 遗传算法种群平均适应度变化

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

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

案总结 ※

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

参考资料

[1]

2021年人工神经网络第三次作业要求以及参考答案: https://zhuoqing.blog.csdn.net/article/details/121508788