[神经网络][遗传算法] python下用遗传算法训练神经网络的权值

实现简单的遗传算法+神经网络训练权值,python下只能在单核上跑,有点耗时。

 

借鉴:

遗传算法:https://blog.csdn.net/WFRainn/article/details/80458246

神经网络:《python神经网络编程》

编码解码::https://blog.csdn.net/robert_chen1988/article/details/79159244  (很多书上都有,不过这个简单易懂)

 

分数变化部分情况:(100个个体,迭代1000次,太耗时没跑完,karas下BP很快就能完成)

0.1804,0.2004,0.182,0.2004,0.2004,0.1888,0.174,0.1932,0.2008,0.2376,0.2372,0.2448,0.2572,0.2224,0.2248,0.2392,0.2516,0.2412,0.2412,0.2416,0.2508,0.2668,0.2668,0.2564,0.274,0.256,0.2488,0.2568,0.2528,0.2528,0.258,0.2716,0.2632,0.2696,0.2696,0.2712
后面会越来越好

代码:

import numpy as np
import numpy
import pandas as pd
import scipy.special
import matplotlib.pyplot as plt

class neuralNetwork:
    # initialise the neural network
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        # set number of nodes in each input, hidden, output layer
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes
        #不需要初始化权值,由遗传算法进行确定
        #self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
        #self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))
        self.lr = learningrate
        self.activation_function = lambda x: scipy.special.expit(x)
    
#不需要训练网络,直接用预测来判断神经网络的性能,这里只是之前写神经网络写下来的
    def train(self, inputs_list, targets_list):
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        output_errors = targets - final_outputs
        hidden_errors = numpy.dot(np.transpose(self.who), output_errors) 
        
        #反向传播,用遗传算法不需要用反向传播,不然就是在找一个比较接近最大值的初始值
        #self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
        #self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
    
    # 预测
    def predict(self, inputs_list):
        inputs = numpy.array(inputs_list, ndmin=2).T
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
    
    #计算网络的得分
    def score(self,y_test,y_predict):
        scorecard = []
        y_predict=np.transpose(y_predict)
        for i in range(len(y_predict)):
            correct_label=(y_test.values.tolist())[0][i]
            
            record=y_predict[i]
            label = numpy.argmax(record)
            if (label == correct_label):
                scorecard.append(1)
            else:
                scorecard.append(0)
        scorecard_array = numpy.asarray(scorecard)
        return scorecard_array.sum() / scorecard_array.size

#编码,将二进制串编码成实数
def decode(personalgene):
    #一个y[]就是一个个体的染色体
    y=[]
    for i in personalgene:
        y.append((int(i,2)*2/(2**18-1))-1)
    return y

#目标函数
def aimfunction(personalgene,inputnum,hiddennum,outputnum,x,y):   
    w1=personalgene[0:inputnum*hiddennum]
    w2=personalgene[inputnum*hiddennum:] 
    #初始化一个神经网络
    net=neuralNetwork(inputnum,hiddennum,outputnum,0.1)
    #网络进化参数
    net.lr=0.1
    #网络权值赋值
    net.wih=list(np.array(w1).reshape(hiddennum,inputnum))
    net.who=list(np.array(w2).reshape(outputnum,hiddennum))
    y_predict=net.predict(x)
    score=net.score(y.T,y_predict)
    return score

#计算全体中每个个体的适应度,调用目标函数进行计算
def fitness(polulation,inputnum,hiddennum,outputnum,x,y):
    value=[]
    for i in range(len(population)):
        value.append(aimfunction(decode(population[i]),inputnum,hiddennum,outputnum,x,y))
    return value

#选择
def selection(population,value):
        #轮盘赌选择
    fitness_sum=[]
    for i in range(len(value)):
        if i ==0:
            fitness_sum.append(value[i])
        else:
            fitness_sum.append(fitness_sum[i-1]+value[i])

    for i in range(len(fitness_sum)):
        fitness_sum[i]/=np.sum(value)

    #select new population
    population_new=[]
    for i in range(len(value)):
        rand=np.random.uniform(0,1)
        for j in range(len(value)):
            if j==0:
                if 0                     population_new.append(population[j])
            else:
                if fitness_sum[j-1]                     population_new.append(population[j])             
    return population_new

#重组
def crossover(population_new,pc):
    half=int(len(population_new)/2)
    father=population_new[:half]
    mother=population_new[half:]
    np.random.shuffle(father)
    np.random.shuffle(mother)
    offspring=[]
    for i in range(half):      
        if np.random.uniform(0,1)<=pc:
            copint = np.random.randint(0,int(len(father[i])/2))
            son=father[i][:copint]+(mother[i][copint:])
            daughter=mother[i][:copint]+(father[i][copint:])
        else:
            son=father[i]
            daughter=mother[i]
        offspring.append(son)
        offspring.append(daughter)
    return offspring

#变异
def mutation(offspring,pm):
    for i in range(len(offspring)):
        if np.random.uniform(0,1)<=pm:
            position=np.random.randint(0,len(offspring[i]))
            if offspring[i][position]=='1':
                offspring[i][position]=='0'
            else:
                offspring[i][position]=='1'
    return offspring

#读取本地Minist数据。
digits=pd.read_csv(r"e:\mnist_test.csv",header=None)
X=digits.loc[:,1:]
Y=digits.loc[:,:0]
#取100个数据进行测试,
y=Y[:100]
x=X[:100]
x=(x / 255.0 * 0.99) + 0.01

 

#初始化网络参数
inputnum,hiddennum,outputnum=784,200,10
#初始化种群参数
pc=0.85
pm=0.05
population=[]

#调整种群人数
for i in range(100):
    #个体基因
    persongene=[]
    #需要确定的15880个参数(权值),784*200+200*10,
    for j in range(158800):
        #单个权值
        gene=""
        #用18位2进制表示一个权值
        for k in range(18):
            gene+=str(np.random.randint(0,2))
        persongene.append(gene)
    population.append(persongene) 

 

主函数:

#保持每一代中最好的个体分数
t=[]
#循环x代
for i in range(1000):
    #计算每一代中每个个体的分数
    value=fitness(population,inputnum,hiddennum,outputnum,x,y)
    #选择新的个体
    population_new=selection(population,value)
    #重组交叉
    offspring=crossover(population_new,pc)
    #变异
    population=mutation(offspring,pm)
    result=[]
    
    for j in range(len(population)):
        result.append(aimfunction(decode(population[j]),inputnum,hiddennum,outputnum,x,y))
    print(max(result))
    t.append(max(result))
plt.plot(t)

 

 

你可能感兴趣的:(算法,ML,python)