Advertisement
Graf_Rav

NN + GA

Mar 18th, 2020
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.73 KB | None | 0 0
  1. import numpy as np
  2. import random as rnd
  3. import math
  4. from abc import ABCMeta, abstractmethod
  5.  
  6.  
  7. #Сравнение двух списков
  8. #<param name="list1">Первый список (список float)</param>
  9. #<param name="list2">Второй список (список float)</param>
  10. #<returns>Результат сравнения (float)</returns>
  11. def list_compare(list1, list2):
  12.     if len(list1) != len(list2):
  13.         s=str(len(list1))+" "+str(len(list2))
  14.         raise Exception("Списки должны иметь одинаковый размер "+s)
  15.     if len(list1) == 1:
  16.         return abs(float(list1[0]) - float(list2[0]))
  17.     res = 0.0
  18.     i=0
  19.     while i<len(list1):
  20.         dif = float(list1[i]) - float(list2[i])
  21.         res=res+(dif*dif)
  22.         i=i+1
  23.     return math.sqrt(res)
  24.  
  25. #Абстрактный класс передаточной функции
  26. class TransFunc():
  27.     __metaclass__=ABCMeta
  28.  
  29.     @abstractmethod
  30.     def compute(self,income):
  31.         """Рассчитать передаточную функцию"""
  32.    
  33.     @abstractmethod
  34.     def get_id(self):
  35.         """ИД передаточной функции"""
  36.  
  37.     #level - уровнь мутации
  38.     @abstractmethod
  39.     def mutation(level):
  40.         """Мутация передаточной функции"""
  41.  
  42.     @abstractmethod
  43.     def clone(self):
  44.         """Копия передаточной функции"""            
  45.  
  46. #Передаточная функция "Как есть"
  47. class AsIs(TransFunc):
  48.  
  49.     def compute(self,income):
  50.         return income
  51.  
  52.     def get_id(self):
  53.         return 1
  54.  
  55.     def clone(self):
  56.         return AsIs()
  57.  
  58.     def mutation(level):
  59.         return        
  60.        
  61. assert issubclass(AsIs, TransFunc)
  62. assert isinstance(AsIs(), TransFunc)
  63.  
  64.  
  65. #Передаточная функция "Сигмоида"
  66. class SignFunc(TransFunc):
  67.     def __init__(self):
  68.         self.par=1
  69.        
  70.     def compute(self,income):
  71.         return 1/(1+np.exp(-self.par*income))
  72.  
  73.     def get_id(self):
  74.         return 2
  75.    
  76.     def clone(self):
  77.         trans=SignFunc()
  78.         trans.par=self.par
  79.         return trans
  80.  
  81.     def mutation(level):
  82.         self.par = self.par + rnd.random() * level - level / 2.0
  83.  
  84.    
  85. assert issubclass(SignFunc, TransFunc)
  86. assert isinstance(SignFunc(), TransFunc)
  87.  
  88. #Передаточная функция "Пороговая"
  89. class ThresholdFunc(TransFunc):
  90.     def compute(self,income):
  91.         if income>0:
  92.             return 1
  93.         else:
  94.             return 0
  95.  
  96.     def get_id(self):
  97.         return 3
  98.  
  99.     def clone(self):
  100.         return ThresholdFunc()
  101.  
  102.     def mutation(level):  
  103.         return
  104.    
  105. assert issubclass(ThresholdFunc, TransFunc)
  106. assert isinstance(ThresholdFunc(), TransFunc)
  107.  
  108. #Класс нейрона
  109. class Neuron:
  110.     def __init__(self, count, trans):
  111.         self.inputs=[0]*count
  112.         self.weights=[rnd.random()-0.5 for i in range(count+1)]
  113.         self.trans=trans
  114.         self.output=0
  115.  
  116.     #Рассчитать нейрон
  117.     def compute(self):
  118.         res=0
  119.         i=1
  120.         count=len(self.weights)
  121.         while i<count:
  122.             res = res+(self.weights[i] * self.inputs[i-1])
  123.             i=i+1
  124.         res=res+self.weights[0]
  125.         self.output = self.trans.compute(res)
  126.        
  127.     #Создать копию нейрона
  128.     def clone(self):
  129.         res = Neuron(len(self.weights)-1,self.trans.clone())
  130.         i=0
  131.         count=len(self.weights)
  132.         while i<count:
  133.             res.weights[i] = self.weights[i]
  134.             i=i+1
  135.         return res;
  136.  
  137.     def mutation(self,level):
  138.         i=0
  139.         count=len(self.weights)
  140.         while i<count:
  141.             self.weights[i] = self.weights[i] + rnd.random() * level - level / 2.0
  142.             i=i+1
  143.        
  144. #Класс слоя
  145. class Layer:
  146.     #Конструктор
  147.     #count - количество нейронов
  148.     #inputs_count - количество входов в каждом нейроне
  149.     #trans - передаточная функция
  150.     def __init__(self, count, inputs_count, trans=""):
  151.         self.inputs_count=inputs_count
  152.         self.outputs=[]
  153.         if count>0 and trans!="":
  154.             self.neurons=[Neuron(inputs_count, trans.clone())]*count
  155.         else:
  156.             self.neurons=[]
  157.  
  158.     #Создать копию слоя
  159.     def clone(self):
  160.         i=0
  161.         count=len(self.neurons)
  162.         res = Layer(0,self.inputs_count)
  163.         while i<count:
  164.             res.neurons.append(self.neurons[i].clone())
  165.             i=i+1
  166.         res.count=count
  167.         return res
  168.  
  169.     #Рассчитать слой
  170.     def compute(self):
  171.         res=0
  172.         i=0
  173.         count=len(self.neurons)
  174.         self.outputs=[]
  175.         while i<count:
  176.             self.neurons[i].compute()
  177.             self.outputs.append(self.neurons[i].output)
  178.             i=i+1
  179.  
  180.     #Установить входные параметры
  181.     def set_incomes(self, inputs):
  182.         count=len(self.neurons)
  183.         count_inputs=self.inputs_count
  184.         i=0
  185.         while i<count:
  186.             j=0
  187.             while j<count_inputs:
  188.                 self.neurons[i].inputs[j]=inputs[j]
  189.                 j=j+1
  190.             i=i+1
  191.  
  192.     def mutation(self,level):
  193.         i=0
  194.         count=len(self.neurons)
  195.         while i<count:
  196.             self.neurons[i].mutation(level)
  197.             i=i+1            
  198.  
  199. #Класс нейросети
  200. class NeuralNet:
  201.     #Конструктор
  202.     #input_count - количество входов
  203.     #output_count - количество выходов
  204.     def __init__(self,input_count,output_count):
  205.         self.target_function="Не расчитана"
  206.         self.layers=[]
  207.         if input_count>0:
  208.             self.inputs=[0]*input_count
  209.         else:
  210.             self.inputs=[]
  211.         if output_count>0:
  212.             self.outputs=[0]*output_count
  213.         else:
  214.             self.outputs=[]
  215.  
  216.     #Установить входные параметры
  217.     #<param name="a_incomes">Входные данные</param>
  218.     def set_incomes(self, a_incomes):
  219.         self.inputs=a_incomes
  220.  
  221.     #Создать копию нейросети
  222.     def clone(self):
  223.         i=0
  224.         count=len(self.layers)
  225.         res = NeuralNet(len(self.inputs), len(self.outputs))
  226.         while i<count:
  227.             res.layers.append(self.layers[i].clone())
  228.             i=i+1
  229.         return res
  230.  
  231.     #Рассчитать нейросеть
  232.     def compute(self):
  233.         res=0
  234.         i=0
  235.         count=len(self.layers)
  236.         self.layers[0].set_incomes(self.inputs)
  237.         while i<count:
  238.             self.layers[i].compute()
  239.             if i<count-1:
  240.                 self.layers[i+1].set_incomes(self.layers[i].outputs)
  241.             i=i+1
  242.  
  243.         i=0
  244.         count_outputs=len(self.layers[count-1].outputs)
  245.         while i<count_outputs:
  246.             self.outputs[i]=self.layers[count-1].outputs[i]
  247.             i=i+1
  248.  
  249.     def mutation(self,level):
  250.         i=0
  251.         count=len(self.layers)
  252.         while i<count:
  253.             self.layers[i].mutation(level)
  254.             i=i+1
  255.  
  256.     #Получить конфигурацию слоев
  257.     def get_layers_conf(self):
  258.         i=0
  259.         res=[]
  260.         count=len(self.layers)
  261.         while i<count:
  262.             res.append(len(self.layers[i].neurons))
  263.             i=i+1
  264.         return res
  265.  
  266.     #/// Создать слой по значению параметра сигмоидальной функции
  267.     #/// <param name="count">количество нейронов</param>
  268.     #/// <param name="inputs_count">Количество входов</param>
  269.     #/// <param name="param">Значение параметра сигмоидальной функции</param>
  270.     def create_layer(self,count, inputs_count, param):
  271.         sg=SignFunc()
  272.         sg.par=param
  273.         layer = Layer(count, inputs_count, sg)
  274.         self.layers.append(layer)
  275.  
  276.     #Печатать нейрость
  277.     def print(self):
  278.         print("------")
  279.         count=len(self.layers)
  280.         i=0
  281.         while i<count:
  282.             ncount=len(self.layers[i].neurons)
  283.             print("Слой ",i," Нейронов: ",)
  284.             j=0
  285.             while j<ncount:
  286.                 neuron=self.layers[i].neurons[j]
  287.                 print("  Нейрон ",j," входов ",len(neuron.inputs)," весов ",len(neuron.weights)," trans ", neuron.trans.get_id())
  288.                 icount=len(neuron.inputs)
  289.                 k=0
  290.                 while k<icount:
  291.                     print("    вход ",k,"=",neuron.inputs[k])
  292.                     k=k+1
  293.                 j=j+1
  294.             i=i+1    
  295.         print("------")
  296.  
  297. #Класс обучающей выборки
  298. class StudyMatrixItem:
  299.  
  300.     #Конструктор
  301.     #a_incomes - входы
  302.     #a_outcomes - выходы
  303.     def __init__(self,a_incomes, a_outcomes):
  304.         self.incomes=a_incomes #входы
  305.         self.outcomes=a_outcomes #выходы
  306.            
  307. #Класс генетического алгоритма
  308. class GeneticAlgorith:
  309.  
  310.     #Конструктор
  311.     def __init__(self):
  312.    
  313.         #Минимальное количество особей в популяции (если окажется меньше этого числа то селекцию не делаем)
  314.         self.min_count = 5
  315.  
  316.         #Максимальное количество особей в популяции (если окажется больше этого числа то обрезаем до этого числа)
  317.         self.max_count = 30
  318.  
  319.         #Начальное количество мест в популяции
  320.         self.count=10
  321.  
  322.         #Разрешить мутацию замены передаточной функции
  323.         self.allow_change_trans_function=True
  324.  
  325.         self.p_mutation=0.1 #Вероятность мутации
  326.         self.population=[] #популяция
  327.         self.selection=[] #Обучающая выборка
  328.  
  329.         self.level=0.5 #Уровень мутации
  330.  
  331.     #Инициализировать из нейросети
  332.     #net - нейросеть
  333.     #count_source_mutation - Количество мутаций исходной нейросети в начальной выборкe
  334.     def init_population_from_net(self, net, count_source_mutation):        
  335.         count_mut = count_source_mutation;
  336.         i=1
  337.         while i<=self.count:
  338.             lnet = None
  339.             if count_mut>0:
  340.                 if count_mut == count_source_mutation:
  341.                     lnet = net
  342.                 else:
  343.                     lnet = net.clone()
  344.                     lnet.mutation(self.level)
  345.                 count_mut=count_mut-1
  346.             else:
  347.                 lnet = NeuralNet(len(net.inputs), len(net.outputs))
  348.                 size = len(net.inputs)
  349.                 conf = net.get_layers_conf()
  350.                 for item in conf:
  351.                     lnet.create_layer(item, size, 1)
  352.                     size = item
  353.             self.population.append(lnet);
  354.             i=i+1
  355.         self.sorting()
  356.  
  357.  
  358.     #/// Размножение
  359.     def reproduction(self):
  360.         self.count=len(self.population)
  361.         i=0
  362.         while i<self.count:
  363.             j=i+1
  364.             while j<self.count:
  365.                 p=self.cross_probability(i,j,self.count)
  366.                 if rnd.random()<p:        
  367.                     self.population.append(self.cross(self.population[i],self.population[j]))
  368.                 j=j+1
  369.             i=i+1
  370.  
  371.     #/// Вычислить вероятность скрещивания
  372.     #/// <param name="net1">Первая нейросеть (номер)</param>
  373.     #/// <param name="net2">Вторая нейросеть (номер)</param>
  374.     #/// <param name="count">Количество "особей" в популяции</param>
  375.     #/// <returns>Вероятность скрещивания</returns>
  376.     def cross_probability(self,net1, net2, count):
  377.         return (2.0*float(count)-float(net1)-float(net2)) / (2.0*float(count)-1.0)
  378.            
  379.     #/// Скрещивание нейронных сетей
  380.     #/// <param name="net1">Первая нейросеть</param>
  381.     #/// <param name="net2">Вторая нейросеть</param>
  382.     #/// <returns>Результат скрещивания</returns>
  383.     def cross(self,net1, net2):
  384.         res = NeuralNet(len(net1.inputs), len(net1.outputs))
  385.         i=0
  386.         while i<len(net1.layers):
  387.             layer1=net1.layers[i]
  388.             layer2=net2.layers[i]
  389.             l_layer = Layer(count=0,inputs_count=layer1.inputs_count)
  390.             j=0
  391.             count = rnd.randint(0,len(layer1.neurons)-1)  
  392.             while j<=count:
  393.                 l_layer.neurons.append(layer1.neurons[j].clone())
  394.                 j=j+1
  395.             j = count + 1
  396.             while j<len(layer1.neurons):
  397.                 l_layer.neurons.append(layer2.neurons[j].clone())
  398.                 j=j+1
  399.             res.layers.append(l_layer);
  400.             i=i+1
  401.         if rnd.random()<self.p_mutation:
  402.             res.mutation(self.level)
  403.         return res;
  404.      
  405.  
  406.     #Осуществить селекцию
  407.     def selecticting(self):
  408.         if len(self.population)<self.min_count:
  409.             return
  410.         items_for_removed=[]
  411.  
  412.         #Начинаем со второго элемента (индекс 1), так как первый (индекс 0) должен выжить в любом случае)
  413.         while len(self.population)>self.max_count:
  414.             i = 1
  415.             _count=float(len(self.population))
  416.             while i < len(self.population):
  417.                 if rnd.random()<float(i)/_count:
  418.                     items_for_removed.append(self.population[i])
  419.                 i=i+1
  420.  
  421.             #удаляем выбранные для удаления
  422.             for item in items_for_removed:
  423.                 self.population.remove(item);
  424.  
  425.             #очистим список, чтобы не удалять второй раз
  426.             items_for_removed.clear()
  427.  
  428.     #Сортировка по передаточной функции
  429.     @staticmethod
  430.     def sort_by_target_function(net):
  431.         if net.target_function=="Не расcчитана":
  432.             return 99999999999999
  433.         else:
  434.             return net.target_function
  435.  
  436.     #Установить входные данные
  437.     #<param name="net">Нейросеть (GANeuralNet)</param>
  438.     #<param name="item">Входные данные (StudyMatrixItem)</param>
  439.     def set_incomes(self, net, item):
  440.         net.set_incomes(item.incomes)
  441.  
  442.     #Вычислить целевую функцию  
  443.          Esumm = 0.0
  444.         i = 0
  445.         count=float(len(self.x))
  446.         while i < len(self.selection):
  447.             item = self.selection[i]
  448.             res = item.outcomes
  449.             self.set_incomes(net,item)
  450.             net.compute()
  451.             Esumm = Esumm+list_compare(res, net.outputs)
  452.             i=i+1
  453.         net.target_function = Esumm/count;
  454.              
  455.     #Сортировка популяции
  456.     def sorting(self):
  457.                    
  458.         #сначала надо вычислить целевую функцию
  459.         i = 1
  460.         while i < len(self.population):
  461.             self.calk_target_function(self.population[i])
  462.             i=i+1
  463.  
  464.         #сортируем
  465.         self.population.sort(key=self.sort_by_target_function)
  466.  
  467.         self.best_net = self.population[0];                  
  468.  
  469.     #Следующая эпоха
  470.     def next_age(self):
  471.         self.prev_spec = self.population[0]
  472.         self.reproduction()
  473.         self.sorting()
  474.         self.selecticting()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement