美文网首页
转向感知器

转向感知器

作者: 大龙10 | 来源:发表于2022-08-29 05:45 被阅读0次

    书名:代码本色:用编程模拟自然系统
    作者:Daniel Shiffman
    译者:周晗彬
    ISBN:978-7-115-36947-5
    第10章目录

    10.5 转向感知器

    1、转向感知器

    • 将感知器的概念(多个输入,单个输出)应用到转向行为中,顺便展示增强式学习策略。
    • 用一种创新的方式诠释概念。这么做能够涵盖基础知识,又能避开一些复杂烦琐的工作。主要目的是让示例程序看起来更有趣、更贴近大脑的工作方式,并不关心人工智能教科书介绍的规则。
    • 前面的Vehicle类。
      Vehicle对象有自己的位置、速度和加速度,能根据一系列转向规则在屏幕中移动。它有一个遵循牛顿运动定律的applyForce()函数。
      如果我们在Vehicle类中再加入一个Perceptron对象。
    class Vehicle {
        Perceptron brain; 给小车加上大脑
        PVector location;
        PVector velocity;
        PVector acceleration;
        //……
    

    2、场景

    • 我们要研究的场景:Sketch中有一系列目标(放在ArrayList中)和一辆小车。


    • 小车的目的是寻找图中的所有目标。按照第6章提出的方法,我们要实现一个seek()函数,用它计算到每个目标的转向力,再将这些转向力作用在物体上。
      假设这些目标是由PVector对象组成的ArrayList,那么整体实现如下所示:

    void seek(ArrayList<PVector> targets) {
        for (PVector target : targets) {
            PVector force = seek(targets.get(i)); 物体对每个目标都有转向力
            applyForce(force);
        }
    }
    
    • 在第6章,为了创建更加动态的模拟效果,我们还为每个转向力分别指定了权重。比如根据距离确定权重:目标越远,转向力越强。
      我们可以在这里引入感知器,把所有转向力都当做输入,再用感知器的输入权重对它们进行处理,最后产生输出转向力。也就是:
    void seek(ArrayList<PVector> targets) {
        PVector[] forces = new PVector[targets.size()]; 为brain对象创建一系列输入
        for (int i = 0; i < forces.length; i++) {
            forces[i] = seek(targets.get(i)); 计算每个目标对应的转向力,填充转向力数组
        }
        PVector output = brain.process(forces); 从brain对象中获取输出结果,将转向力作用在物体上
        applyForce(output);
    }
    
    • 换句话说,vehicle对象不再做转向力加权运算,它把这部分工作转给brain对象。brain对象加权求和后的输出结果就是最后的转向力。这个改变能引入很多新的实现:小车可以按照自己的意愿做出转向决定,学习自身产生的错误,并对环境的刺激做出反应。

    3、具体实现

    • 我们可以把直线分类感知器用做基础模型,但需要进行一些修改:感知器的输入从数字变为向量!
      下表对比了两种情况下feedforward()函数的实现。


    这两个函数实现的几乎是同一个算法,但有两点区别。

    • 1.向量求和 
      每个输入不再是单个数字,而是一个向量,因此我们必须用PVector的运算方式将它们加权求和。
    • 2.没有激励函数 
      在这里,我们想要的结果是转向力。因此,我们不需要用一个布尔值对结果进行分类,只需直接返回结果向量。

    4、增强式学习

    • 将最终转向力作用于小车之后,我们下一步要做的就是给大脑施加反馈,也就是所谓的增强式学习。
      本次转向决策是有利的还是有害的?假如系统中同时存在捕食者(吃掉小车)和食物(提高小车的生命值),这时候,神经网络的权重调整规则就应该是:躲避捕食者,靠近食物。
    • 让我们来看一个更简单的例子,在这个例子中,小车想要朝着窗口的中心运动。我们用以下方式训练大脑对象:


    PVector desired = new PVector(width/2,height/2);
    PVector error = PVector.sub(desired, location);
    brain.train(forces,error);
    
    • 在这里,我们向brain对象传入所有输入的副本(后续要用它纠正误差),还传入了环境的观察值:一个由当前位置指向目标位置的PVector对象,这个向量就是小车的误差:误差越大,小车的表现越差;反之,表现越好。
    • 之后,大脑可以根据这个“误差”向量(有两个误差值:x坐标误差和y坐标误差)调整权重,这和之前直线分类器的训练是一样的。
    • 由于小车的误差是已知的,因此我们只需要将这个误差当做参数传入。注意权重的调整需要进行两次计算:一次调整x坐标,另一次调整y坐标。
    weights[i] += c*error.x*forces[i].x;
    weights[i] += c*error.y*forces[i].y;
    
    • 从Vehicle类的整体实现,我们可以看到转向函数如何用感知器控制转向行为。

    5、示例

    示例代码10-2 感知器转向

    class Vehicle {
        Perceptron brain; 小车有了大脑
        PVector location; 物理运动所需的变量
        PVector velocity;
        PVector acceleration;
        float maxforce;
        float maxspeed;
        Vehicle(int n, float x, float y) { 在小车的构造函数中创建感知器对象,传入输入数量和学习brain = new Perceptron(n,0.001);
            acceleration = new PVector(0,0);
            velocity = new PVector(0,0);
            location = new PVector(x,y);
            maxspeed = 4;
            maxforce = 0.1;
        }
        void update() { update()函数和之前一样
            velocity.add(acceleration);
            velocity.limit(maxspeed);
            location.add(velocity);
            acceleration.mult(0);
        }
        void applyForce(PVector force) { applyForce()函数和之前一样
            acceleration.add(force);
        }
        void steer(ArrayList&lt;PVector> targets) {
            PVector[] forces = new PVector[targets.size()];
            for (int i = 0; i < forces.length; i++) {
                forces[i] = seek(targets.get(i));
            }
            PVector result = brain.feedforward(forces); 所有转向力都是输入
            applyForce(result); 施加计算得到的结果
            PVector desired = new PVector(width/2,height/2); 根据和中心之间的距离训练大脑
            PVector error = PVector.sub(desired, location);
            brain.train(forces,error);
        }
        PVector seek(PVector target) { seek()函数和之前一样
            PVector desired = PVector.sub(target,location);
            desired.normalize();
            desired.mult(maxspeed);
            PVector steer = PVector.sub(desired,velocity);
            steer.limit(maxforce);
            return steer;
        }
    }
    

    6、运行结果

    相关文章

      网友评论

          本文标题:转向感知器

          本文链接:https://www.haomeiwen.com/subject/rihcnrtx.html