Нейронные сети Лаба 5 (генетика)
.pdf11
trainf = nl.train.train_rprop #алгоритм обучения errorf = nl.error.MSE() #функция измерения ошибки
net = nl.core.Net(nl.tool.minmax(P),co,layers,connect,trainf,errorf) #формируем сеть net.init() #инициализируем сеть (хоть в данном случае это необязательно)
return net #===============================================================================
# Генетические операторы
#=============================================================================== def mutate(population, mutability):
""" Функция мутации случайным образом меняет все или некоторые хромосомы"""
#при данном методе кодирования мы оперирум целыми числами,
#старый диапазон параметра мутабельности не подходит, расширим его до 1..10 mut = mutability*10
for i, chromosome in enumerate(population): #для каждой хромосомы в популяции neurons = chromosome[ 0]
functions = chromosome[1]
#каждый параметр отклоняется на величину, пропорциональную мутабельности neurons = np.array([n + np.random.randint( 0,mut) for n in neurons]) functions = np.array([f - np.random.randint( 0,mut) for f in functions]) chromosome = [neurons, functions]
population[i] = chromosome
return population def select(population):
""" Функция селекции выбирает наиболее приспособленных особей из популяции"""
def fitness_function(x):
""" Для простоты определим функцию приспособленности как функцию, обратную квадрату ошибки
"""
#множитель просто для удобства восприятия return 1 / np.sum(np.square(x)) * 100
fitness = np.zeros(len(population)) #массив для хранения приспособленности каждой хромосомы
err = np.zeros(len(population))
for i, chromosome in enumerate(population): #для каждой хромосомы в популяции net = generate_net(chromosome) #порождаем сеть на основе генотипа
err[i] = net.train(P,T,epochs = 5, show = 0)[-1] #короткая настройка сети out = net.sim(P) #ловим отклик
fitness[i] = fitness_function(T - out) #вычисляется приспособленность как функция
ошибки
sort_indecies = fitness.argsort()
population = population[sort_indecies[::-1]] #популяция отсортирована в порядке уменьшения приспособленности
fitness.sort()
fitness = fitness[::-1]
#худшая половина популяции отсекается, лучшая дублируется population = np.concatenate((population[:len(population)/2],
population[:len(population)/2]))
#возвращаем среднее значение ошибки, приспособленности и новую популяцию return population, np.average(fitness), np.average(err)
def generation(population, mutability):
"""Одно поколение эволюции"""
population = mutate(population, mutability) # мутируем принятую популяцию
population, fit, err = select(population) # формируем новую популяцию на основе селекции return population, fit, err # возвращаем новую популяцию
#===============================================================================
# Общий алгоритм эволюции
#=============================================================================== def evolution(epochs = 50, show = 1, goal = 0.1, lr = 0.1, population_size = 5):
population = generate_population(population_size) errorf = nl.error.SSE()
err = np.zeros(epochs)
12
fit = np.zeros(epochs)
for i in range(epochs): #для каждого поколения
population, fit[i], err[i] = generation(population, lr) if i%show == 0:
print('Generation '+str( i), 'Error '+str(err[i])) if 0!= err[i] < goal: #по достижении целевой ошибки
err = [e for e in err if e != 0] # выбрасываем из массивов нули fit = [f for f in fit if f != 0]
print('Goal is reached') break #выходим из цикла
return err, fit, population #===============================================================================
# Скрипт эксперимента
#=============================================================================== err, fit, population = evolution()
net = generate_net(population[ 0]) #формируем сеть на основе лучшей особи последней популяции net.trainf = nl.train.train_bfgs
e = net.train(P,T,epochs = 100, show = 10) pl.figure(1)
pl.title('Simulation') pl.plot(P, T) pl.plot(P, net.sim(P))
pl.legend(["Target","Best output"]) pl.figure(2)
pl.title('Error') pl.plot(err) pl.figure(3) pl.title('Fitness') pl.plot(fit)