之前简单地学习了神经网络相关的知识,回想起了之前在B站上看到的小车自动在迷宫寻路的视频(还有用类似方法解决flappy bird的视频:https://www.bilibili.com/video/av13940007/?from=search&seid=8284022935044659565),就寻思着利用神经网络的知识自己也写一个出来。
其实其结构并不用非常复杂,可以先考虑小车上有几个传感器,可以计算小车在不同方向上距离边界的距离。而寻路的算法就是确定一个函数,将这几个距离作为输入,输出一个0到1的数字即可,大于0.5为左转,否则为右转。并且神经网络用一个隐藏层即可,这样就可以近似出一个确定左转还是右转的函数(神经网络的本质就是对一个分类函数的近似)。
接下来让我不知所措的是这个问题的训练集到底是什么,因为不同于之前我博客写过的很简单的平面点分类问题,这个函数我们事先并不知道,而作为当前输入的唯一可评价的输出就是小车是否到达了终点,仅凭这些是无法训练神经网络的。
后来我逐渐明白了,这其实是一种无监督学习,因为我们并没有事先标记好的样例来供神经网络来学习。之后我突然想起了遗传算法这个东西,所以去学习了一下,发现其思想和结构都十分适合这种模型。接下来的文章就是通过具体的代码实现这样一个学习程序以及其可视化的动画。
动画的话我只在学校学过opengl所以就现学现用了。
首先需要安装python上的OpenGL,这个在百度查就可以了。由于OpenGL的实现都有单独的函数,所以在python上的语法跟C语言几乎没有区别。在这里我利用python建立了Lines和Rectangles两个类分别用于画出边界和小车。
这是需要引用的库
import OpenGL.GL
import OpenGL.GLU
import OpenGL.GLUT
from math import tan
from math import atan
from math import pi
from math import sqrt
from math import sin
from math import cos
from math import hypot
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import time
这是Lines的代码
class Lines:
startx=0
starty=0
endx=0
endy=0
def __init__(self, sx, sy, ex, ey, r, g, b):
self.startx=sx
self.starty=sy
self.endx=ex
self.endy=ey
self.r=r
self.g=g
self.b=b
def Display(self):
glColor3f(self.r, self.g, self.b)
glBegin(GL_LINE_STRIP)
glVertex2f(self.startx,self.starty)
glVertex2f(self.endx,self.endy)
glEnd()
对于我来说,画出迷宫边界最简单的方式就是利用多条的折线,这样方便于自定义迷宫的形状。
这是Rectangles的代码
class Rectangles:
centerx=0
centery=0
length=0
width=0
angle=0
startcenterx=0
startcentery=0
startangle=0
starttime=0
def __init__(self,cx,cy,l,w,a,r,g,b):
self.centerx=cx
self.centery=cy
self.startcenterx=cx
self.startcentery=cy
self.length=l
self.width=w
self.angle=a
self.startangle=a
self.r=r
self.g=g
self.b=b
self.starttime=time.time()
def Display(self):
glColor3f(self.r, self.g, self.b)
glBegin(GL_QUADS);
glVertex2f(self.centerx+self.length*cos(self.angle)/2-self.width*sin(self.angle)/2,self.centery+self.length*sin(self.angle)/2+self.width*cos(self.angle)/2);
glVertex2f(self.centerx-self.length*cos(self.angle)/2-self.width*sin(self.angle)/2,self.centery-self.length*sin(self.angle)/2+self.width*cos(self.angle)/2);
glVertex2f(self.centerx-self.length*cos(self.angle)/2+self.width*sin(self.angle)/2,self.centery-self.length*sin(self.angle)/2-self.width*cos(self.angle)/2);
glVertex2f(self.centerx+self.length*cos(self.angle)/2+self.width*sin(self.angle)/2,self.centery+self.length*sin(self.angle)/2-self.width*cos(self.angle)/2);
glEnd();
def Move(self,movex,movey):
self.centerx+=movex
self.centery+=movey
def Rotate(self,direc,a):
leftanchorvx=self.centerx-4*self.width*sin(self.angle)
leftanchorvy=self.cent