实现简单的遗传算法+神经网络训练权值,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
else:
if fitness_sum[j-1]
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)