python应用

转自 http://blog.csdn.net/u014365862/article/details/54380422


代码下载:Here

很久以前微信流行过一个小游戏:打飞机,这个游戏简单又无聊。在2017年来临之际,我就实现一个超级弱智的人工智能(AI),这货可以躲避从屏幕上方飞来的飞机。本帖只使用纯Python实现,不依赖任何高级库。

本文的AI基于neuro-evolution,首先简单科普一下neuro-evolution。从neuro-evolution这个名字就可以看出它由两部分组成-neuro and evolution,它是使用进化算法(遗传算法是进化算法的一种)提升人工神经网络的机器学习技术,其实就是用进化算法改进并选出最优的神经网络。

neuro-evolution

定义一些变量:

[python]  view plain  copy
  1. import math  
  2. import random  
  3.    
  4. # 神经网络3层, 1个隐藏层; 4个input和1个output  
  5. network = [4, [16], 1]  
  6. # 遗传算法相关  
  7. population = 50  
  8. elitism = 0.2   
  9. random_behaviour = 0.1  
  10. mutation_rate = 0.5  
  11. mutation_range = 2  
  12. historic = 0  
  13. low_historic = False  
  14. score_sort = -1  
  15. n_child = 1  

定义神经网络:

[python]  view plain  copy
  1. # 激活函数  
  2. def sigmoid(z):  
  3.     return 1.0/(1.0+math.exp(-z))  
  4. # random number  
  5. def random_clamped():  
  6.     return random.random()*2-1  
  7.    
  8. # "神经元"  
  9. class Neuron():  
  10.     def __init__(self):  
  11.         self.biase = 0  
  12.         self.weights = []  
  13.    
  14.     def init_weights(self, n):  
  15.         self.weights = []  
  16.         for i in range(n):  
  17.             self.weights.append(random_clamped())  
  18.     def __repr__(self):  
  19.         return 'Neuron weight size:{}  biase value:{}'.format(len(self.weights), self.biase)  
  20.    
  21. # 层  
  22. class Layer():  
  23.     def __init__(self, index):  
  24.         self.index = index  
  25.         self.neurons = []  
  26.    
  27.     def init_neurons(self, n_neuron, n_input):  
  28.         self.neurons = []  
  29.         for i in range(n_neuron):  
  30.             neuron = Neuron()  
  31.             neuron.init_weights(n_input)  
  32.             self.neurons.append(neuron)  
  33.    
  34.     def __repr__(self):  
  35.         return 'Layer ID:{}  Layer neuron size:{}'.format(self.index, len(self.neurons))  
  36.    
  37. # 神经网络  
  38. class NeuroNetwork():  
  39.     def __init__(self):  
  40.         self.layers = []  
  41.    
  42.     # input:输入层神经元数 hiddens:隐藏层 output:输出层神经元数  
  43.     def init_neuro_network(self, input, hiddens , output):  
  44.         index = 0  
  45.         previous_neurons = 0  
  46.         # input  
  47.         layer = Layer(index)  
  48.         layer.init_neurons(input, previous_neurons)  
  49.         previous_neurons = input  
  50.         self.layers.append(layer)  
  51.         index += 1  
  52.         # hiddens  
  53.         for i in range(len(hiddens)):  
  54.             layer = Layer(index)  
  55.             layer.init_neurons(hiddens[i], previous_neurons)  
  56.             previous_neurons = hiddens[i]  
  57.             self.layers.append(layer)  
  58.             index += 1  
  59.         # output  
  60.         layer = Layer(index)  
  61.         layer.init_neurons(output, previous_neurons)  
  62.         self.layers.append(layer)  
  63.    
  64.     def get_weights(self):  
  65.         data = { 'network':[], 'weights':[] }  
  66.         for layer in self.layers:  
  67.             data['network'].append(len(layer.neurons))  
  68.             for neuron in layer.neurons:  
  69.                 for weight in neuron.weights:  
  70.                     data['weights'].append(weight)  
  71.         return data  
  72.    
  73.     def set_weights(self, data):  
  74.         previous_neurons = 0  
  75.         index = 0  
  76.         index_weights = 0  
  77.    
  78.         self.layers = []  
  79.         for i in data['network']:  
  80.             layer = Layer(index)  
  81.             layer.init_neurons(i, previous_neurons)  
  82.             for j in range(len(layer.neurons)):  
  83.                 for k in range(len(layer.neurons[j].weights)):  
  84.                     layer.neurons[j].weights[k] = data['weights'][index_weights]  
  85.                     index_weights += 1  
  86.             previous_neurons = i  
  87.             index += 1  
  88.             self.layers.append(layer)  
  89.    
  90.     # 输入游戏环境中的一些条件(如敌机位置), 返回要执行的操作  
  91.     def feed_forward(self, inputs):  
  92.         for i in range(len(inputs)):  
  93.             self.layers[0].neurons[i].biase = inputs[i]  
  94.    
  95.         prev_layer = self.layers[0]  
  96.         for i in range(len(self.layers)):  
  97.             # 第一层没有weights  
  98.             if i == 0:  
  99.                 continue  
  100.             for j in range(len(self.layers[i].neurons)):  
  101.                 sum = 0  
  102.                 for k in range(len(prev_layer.neurons)):  
  103.                     sum += prev_layer.neurons[k].biase * self.layers[i].neurons[j].weights[k]  
  104.                 self.layers[i].neurons[j].biase = sigmoid(sum)  
  105.             prev_layer = self.layers[i]  
  106.    
  107.         out = []  
  108.         last_layer = self.layers[-1]  
  109.         for i in range(len(last_layer.neurons)):  
  110.             out.append(last_layer.neurons[i].biase)  
  111.         return out  
  112.    
  113.     def print_info(self):  
  114.         for layer in self.layers:  
  115.             print(layer)  
遗传算法:

[python]  view plain  copy
  1. # "基因组"  
  2. class Genome():  
  3.     def __init__(self, score, network_weights):  
  4.         self.score = score  
  5.         self.network_weights = network_weights  
  6.    
  7. class Generation():  
  8.     def __init__(self):  
  9.         self.genomes = []  
  10.    
  11.     def add_genome(self, genome):  
  12.         i = 0  
  13.         for i in range(len(self.genomes)):  
  14.             if score_sort < 0:  
  15.                 if genome.score > self.genomes[i].score:  
  16.                     break  
  17.             else:  
  18.                 if genome.score < self.genomes[i].score:  
  19.                     break  
  20.         self.genomes.insert(i, genome)  
  21.    
  22.         # 杂交+突变  
  23.     def breed(self, genome1, genome2, n_child):  
  24.         datas = []  
  25.         for n in range(n_child):  
  26.             data = genome1  
  27.             for i in range(len(genome2.network_weights['weights'])):  
  28.                 if random.random() <= 0.5:  
  29.                     data.network_weights['weights'][i] = genome2.network_weights['weights'][i]  
  30.    
  31.             for i in range(len(data.network_weights['weights'])):  
  32.                 if random.random() <= mutation_rate:  
  33.                     data.network_weights['weights'][i] += random.random() * mutation_range * 2 - mutation_range  
  34.             datas.append(data)  
  35.         return datas  
  36.    
  37.         # 生成下一代  
  38.     def generate_next_generation(self):  
  39.         nexts = []  
  40.         for i in range(round(elitism*population)):  
  41.             if len(nexts) < population:  
  42.                 nexts.append(self.genomes[i].network_weights)  
  43.    
  44.         for i in range(round(random_behaviour*population)):  
  45.             n = self.genomes[0].network_weights  
  46.             for k in range(len(n['weights'])):  
  47.                 n['weights'][k] = random_clamped()  
  48.             if len(nexts) < population:  
  49.                 nexts.append(n)  
  50.    
  51.         max_n = 0  
  52.         while True:  
  53.             for i in range(max_n):  
  54.                 childs = self.breed(self.genomes[i], self.genomes[max_n], n_child if n_child > 0 else 1)  
  55.                 for c in range(len(childs)):  
  56.                     nexts.append(childs[c].network_weights)  
  57.                     if len(nexts) >= population:  
  58.                         return nexts  
  59.             max_n += 1  
  60.             if max_n >= len(self.genomes)-1:  
  61.                 max_n = 0  

NeuroEvolution:

[python]  view plain  copy
  1. class Generations():  
  2.     def __init__(self):  
  3.         self.generations = []  
  4.    
  5.     def first_generation(self):  
  6.         out = []  
  7.         for i in range(population):  
  8.             nn = NeuroNetwork()  
  9.             nn.init_neuro_network(network[0], network[1], network[2])  
  10.             out.append(nn.get_weights())  
  11.         self.generations.append(Generation())  
  12.         return out  
  13.           
  14.     def next_generation(self):  
  15.         if len(self.generations) == 0:  
  16.             return False  
  17.    
  18.         gen = self.generations[-1].generate_next_generation()  
  19.         self.generations.append(Generation())  
  20.         return gen  
  21.    
  22.     def add_genome(self, genome):  
  23.         if len(self.generations) == 0:  
  24.             return False  
  25.    
  26.         return self.generations[-1].add_genome(genome)  
  27.    
  28. class NeuroEvolution():  
  29.     def __init__(self):  
  30.         self.generations = Generations()  
  31.    
  32.     def restart(self):  
  33.         self.generations = Generations()  
  34.    
  35.     def next_generation(self):  
  36.         networks = []  
  37.         if len(self.generations.generations) == 0:  
  38.             networks = self.generations.first_generation()  
  39.         else:  
  40.             networks = self.generations.next_generation()  
  41.    
  42.         nn = []  
  43.         for i in range(len(networks)):  
  44.             n = NeuroNetwork()  
  45.             n.set_weights(networks[i])  
  46.             nn.append(n)  
  47.    
  48.         if low_historic:  
  49.             if len(self.generations.generations) >= 2:  
  50.                 genomes = self.generations.generations[len(self.generations.generations) - 2].genomes  
  51.                 for i in range(genomes):  
  52.                     genomes[i].network = None  
  53.    
  54.         if historic != -1:  
  55.             if len(self.generations.generations) > historic+1:  
  56.                 del self.generations.generations[0:len(self.generations.generations)-(historic+1)]  
  57.    
  58.         return nn  
  59.    
  60.     def network_score(self, score, network):  
  61.         self.generations.add_genome(Genome(score, network.get_weights()))  

是AI就躲个飞机
[python]  view plain  copy
  1. import pygame  
  2. import sys  
  3. from pygame.locals import *  
  4. import random  
  5. import math  
  6.    
  7. import neuro_evolution  
  8.    
  9. BACKGROUND = (200200200)  
  10. SCREEN_SIZE = (320480)  
  11.    
  12. class Plane():  
  13.     def __init__(self, plane_image):  
  14.         self.plane_image = plane_image  
  15.         self.rect = plane_image.get_rect()  
  16.    
  17.         self.width = self.rect[2]  
  18.         self.height = self.rect[3]  
  19.         self.x = SCREEN_SIZE[0]/2 - self.width/2  
  20.         self.y = SCREEN_SIZE[1] - self.height  
  21.    
  22.         self.move_x = 0  
  23.         self.speed = 2  
  24.    
  25.         self.alive = True  
  26.    
  27.     def update(self):  
  28.         self.x += self.move_x * self.speed  
  29.    
  30.     def draw(self, screen):  
  31.         screen.blit(self.plane_image, (self.x, self.y, self.width, self.height))  
  32.    
  33.     def is_dead(self, enemes):  
  34.         if self.x < -self.width or self.x + self.width > SCREEN_SIZE[0]+self.width:  
  35.             return True  
  36.    
  37.         for eneme in enemes:  
  38.             if self.collision(eneme):  
  39.                 return True  
  40.         return False  
  41.    
  42.     def collision(self, eneme):  
  43.         if not (self.x > eneme.x + eneme.width or self.x + self.width < eneme.x or self.y > eneme.y + eneme.height or self.y + self.height < eneme.y):  
  44.             return True  
  45.         else:  
  46.             return False  
  47.    
  48.     def get_inputs_values(self, enemes, input_size=4):  
  49.         inputs = []  
  50.    
  51.         for i in range(input_size):  
  52.             inputs.append(0.0)  
  53.    
  54.         inputs[0] = (self.x*1.0 / SCREEN_SIZE[0])  
  55.         index = 1  
  56.         for eneme in enemes:  
  57.             inputs[index] = eneme.x*1.0 / SCREEN_SIZE[0]  
  58.             index += 1  
  59.             inputs[index] = eneme.y*1.0 / SCREEN_SIZE[1]  
  60.             index += 1  
  61.         #if len(enemes) > 0:  
  62.             #distance = math.sqrt(math.pow(enemes[0].x + enemes[0].width/2 - self.x + self.width/2, 2) + math.pow(enemes[0].y + enemes[0].height/2 - self.y + self.height/2, 2));  
  63.         if len(enemes) > 0 and self.x < enemes[0].x:  
  64.             inputs[index] = -1.0  
  65.             index += 1  
  66.         else:  
  67.             inputs[index] = 1.0  
  68.    
  69.         return inputs  
  70.    
  71. class Enemy():  
  72.     def __init__(self, enemy_image):  
  73.         self.enemy_image = enemy_image  
  74.         self.rect = enemy_image.get_rect()  
  75.    
  76.         self.width = self.rect[2]  
  77.         self.height = self.rect[3]  
  78.         self.x = random.choice(range(0, int(SCREEN_SIZE[0] - self.width/2), 71))  
  79.         self.y = 0  
  80.    
  81.     def update(self):  
  82.         self.y += 6  
  83.    
  84.     def draw(self, screen):  
  85.         screen.blit(self.enemy_image, (self.x, self.y, self.width, self.height))  
  86.    
  87.     def is_out(self):  
  88.         return True if self.y >= SCREEN_SIZE[1else False  
  89.    
  90. class Game():  
  91.     def __init__(self):  
  92.         pygame.init()  
  93.         self.screen = pygame.display.set_mode(SCREEN_SIZE)  
  94.         self.clock = pygame.time.Clock()  
  95.         pygame.display.set_caption('是AI就躲个飞机')  
  96.    
  97.         self.ai = neuro_evolution.NeuroEvolution()  
  98.         self.generation = 0  
  99.    
  100.         self.max_enemes = 1  
  101.                 # 加载飞机、敌机图片  
  102.         self.plane_image = pygame.image.load('plane.png').convert_alpha()  
  103.         self.enemy_image = pygame.image.load('enemy.png').convert_alpha()  
  104.    
  105.     def start(self):  
  106.         self.score = 0  
  107.         self.planes = []  
  108.         self.enemes = []  
  109.    
  110.         self.gen = self.ai.next_generation()  
  111.         for i in range(len(self.gen)):  
  112.             plane = Plane(self.plane_image)  
  113.             self.planes.append(plane)  
  114.    
  115.         self.generation += 1  
  116.         self.alives = len(self.planes)  
  117.    
  118.     def update(self, screen):  
  119.         for i in range(len(self.planes)):  
  120.             if self.planes[i].alive:  
  121.                 inputs = self.planes[i].get_inputs_values(self.enemes)  
  122.                 res = self.gen[i].feed_forward(inputs)  
  123.                 if res[0] < 0.45:  
  124.                     self.planes[i].move_x = -1  
  125.                 elif res[0] > 0.55:  
  126.                     self.planes[i].move_x = 1  
  127.    
  128.    
  129.                 self.planes[i].update()  
  130.                 self.planes[i].draw(screen)  
  131.    
  132.                 if self.planes[i].is_dead(self.enemes) == True:  
  133.                     self.planes[i].alive = False  
  134.                     self.alives -= 1  
  135.                     self.ai.network_score(self.score, self.gen[i])  
  136.                     if self.is_ai_all_dead():  
  137.                         self.start()  
  138.    
  139.           
  140.         self.gen_enemes()  
  141.    
  142.         for i in range(len(self.enemes)):  
  143.             self.enemes[i].update()  
  144.             self.enemes[i].draw(screen)  
  145.             if self.enemes[i].is_out():  
  146.                 del self.enemes[i]  
  147.                 break  
  148.    
  149.         self.score += 1  
  150.    
  151.         print("alive:{}, generation:{}, score:{}".format(self.alives, self.generation, self.score), end='\r')  
  152.    
  153.     def run(self, FPS=1000):  
  154.         while True:  
  155.             for event in pygame.event.get():  
  156.                 if event.type == QUIT:  
  157.                     pygame.quit()  
  158.                     sys.exit()  
  159.    
  160.             self.screen.fill(BACKGROUND)  
  161.    
  162.             self.update(self.screen)  
  163.    
  164.             pygame.display.update()  
  165.             self.clock.tick(FPS)  
  166.    
  167.     def gen_enemes(self):  
  168.         if len(self.enemes) < self.max_enemes:  
  169.             enemy = Enemy(self.enemy_image)  
  170.             self.enemes.append(enemy)  
  171.    
  172.     def is_ai_all_dead(self):  
  173.         for plane in self.planes:  
  174.             if plane.alive:  
  175.                 return False  
  176.         return True  
  177.    
  178.    
  179. game = Game()  
  180. game.start()  
  181. game.run()  

AI的工作逻辑

假设你是AI,你首先繁殖一个种群(50个个体),开始的个体大都是歪瓜裂枣(上来就被敌机撞)。但是,即使是歪瓜裂枣也有表现好的,在下一代,你会使用这些表现好的再繁殖一个种群,经过代代相传,存活下来的个体会越来越优秀。其实就是仿达尔文进化论,种群->自然选择->优秀个体->杂交、变异->种群->循环n世代。

ai开始时候的表现:

是AI就躲个飞机 - 纯Python实现人工智能 图片被拉扁了 sorry

经过几百代之后,ai开始娱乐的躲飞机:

是AI就躲个飞机 - 纯Python实现人工智能

网络爬虫 http://blog.csdn.net/pleasecallmewhy/article/details/8927832
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值