神经进化-func不是函数错误

时间:2018-07-31 10:28:16

标签: javascript neural-network p5.js

我正在使用p5.js库。

我正在建立我的第一个神经网络 Toy-Neural-Network-JS。我遵循了Coding Train教程,它可以正常工作(对象在随机移动),但是出了点问题,这给了我一个错误(请参见图片)。

Developer Console Error

这是我的代码。每次杀死所有玩家时,都会发生错误。怎么了我检查了X次,没有看到任何错误。

let balls = [];
let totalBalls = 5;
let players = [];
let tmpplayers = [];
let totalPlayers = 100;

function nextGeneration(){
    calcFitness();
    for(let i = 0; i < totalPlayers; i++){
        players.push(pickOnePlayer());
    }
    tmpplayers = [];
    console.log("next generation");
}

function pickOnePlayer(){
    let index = 0;
    let r = random(1);

    while(r > 0){
        r = r - tmpplayers[index].fitness;
        index++;
    }
    index--;

    let player = tmpplayers[index];
    let child = new Player(player.brain);
    child.mutate();
    return child;
}

function calcFitness(){
    let sum = 0;
    for(let player of tmpplayers){
        sum += player.score;
    }

    for(let player of tmpplayers){
        player.fitness = player.score / sum;
    }
}

class Ball {
    constructor(){
        this.r = 15;
        this.randX = random(this.r, width - this.r);
        this.randY = random(this.r, height - this.r);
        this.pos = new p5.Vector(this.randX, this.randY);
        this.acc = new p5.Vector(random(-5, 5), random(-5, 5));
        this.count = 0;
        this.color = [random(0, 255), random(0, 255), random(0, 255)];
    }

    update(){
        this.pos.x += this.acc.x;
        this.pos.y += this.acc.y;

        if(this.pos.x < this.r || this.pos.x > width - this.r){
            this.acc.x *= -1;
        }

        if(this.pos.y < this.r || this.pos.y > height - this.r){
            this.acc.y *= -1;
        }
    }

    checkIntersect(another){ // check if ball hits another ball
        return dist(this.pos.x, this.pos.y, another.pos.x, another.pos.y) < (this.r + another.r);
    }

    show(){
        // show ball
        fill(this.color[0], this.color[1], this.color[2]);
        ellipse(this.pos.x, this.pos.y, this.r * 2);

        // show ball score
        fill(0);
        textSize(20);
        text(this.count, this.pos.x - (this.r / 2), this.pos.y + (this.r / 2));
    }
}

class Player {
    constructor(brain){
        this.range = 150;
        this.r = 15;
        this.count = 0;
        this.score = 0;
        this.fitness = 0;
        this.pos = new p5.Vector(width / 2, height / 2);
        this.acc = new p5.Vector();

        // if brain was passed, copy it, else make new neuralnetwork
        if(brain != undefined){
            this.brain = brain.copy();
        } else {
            this.brain = new NeuralNetwork(6, 4, 1);
        }
    }

    mutate(){
        this.brain.mutate(x=>x*0.1);
    }

    move(x, y){
        this.acc.x = x;
        this.acc.y = y;

        this.pos.x += this.acc.x;
        this.pos.y += this.acc.y;

        if(this.pos.x < this.r || this.pos.x > width - this.r){
            this.pos.x -= this.acc.x;
        }

        if(this.pos.y < this.r || this.pos.y > height - this.r){
            this.pos.y -= this.acc.y;
        }
    }

    think(){
        let inputs = [];

        // set INPUTS of this particular Player
        inputs.push(this.pos.x / width);
        inputs.push(this.pos.y / height);
        inputs.push(this.count);

        // get closest ball
        let closestBall = balls[0];
        let closestD = dist(this.pos.x, this.pos.y, closestBall.pos.x, closestBall.pos.y);
        for(let ball of balls){
            let d = dist(this.pos.x, this.pos.y, ball.pos.x, ball.pos.y);
            if(d < closestD){
                closestD = d;
                closestBall = ball;
            }
        }

        // set INPUTS of closest Ball
        inputs.push(closestBall.pos.x / width);
        inputs.push(closestBall.pos.y / height);
        inputs.push(closestBall.count);

        // predict inputs and then do actions
        let output = this.brain.predict(inputs);
        if(output < 0.25){
            this.move(0, -3); // up
        } else if(output >= 0.25 && output < 0.5){
            this.move(-3, 0); // left
        } else if(output >= 0.5 && output < 0.75){
            this.move(0, 3); // down
        } else {
            this.move(3, 0); // right
        }
    }

    checkIntersect(another){ // check if player hits ball
        return dist(this.pos.x, this.pos.y, another.pos.x, another.pos.y) < (this.r + another.r);
    }

    show(){
        //fill(255, 0, 0, 20);
        //ellipse(this.pos.x, this.pos.y, this.range * 2);

        // show player
        fill(0, 255, 0);
        ellipse(this.pos.x, this.pos.y, this.r * 2);

        // show player score
        fill(0);
        textSize(20);
        text("!" + this.count, this.pos.x - (this.r / 2), this.pos.y + (this.r / 2));
    }
}

function setup(){
    createCanvas(windowWidth, windowHeight);

    // create balls
    for(let i = 0; i < totalBalls; i++){
        balls.push(new Ball());
    }

    // create players
    for(let i = 0; i < totalPlayers; i++){
        players.push(new Player());
    }
}

function draw(){
    background(51);

    // keep spawning new balls
    if(balls.length != totalBalls){
        while(balls.length != totalBalls){
            balls.push(new Ball());
        }
    }

    // reset game and make a nextGeneration out of previous
    if(players.length == 0 || frameCount == 1000){
        nextGeneration();
    }

    // some special graphic stuff, NOT IMPORTANT
    let rw = round(windowWidth / totalBalls);
    for(let i = 0; i < balls.length; i++){
        let rh = constrain(balls[i].count, 0, height);
        let c = balls[i].color;
        c[3] = 50; // transparent background
        fill(c);
        rect(i * rw, height, rw, -rh);
    }

    for(let player of players){
        player.score++;
        player.think();
        player.show();

        for(let ball of balls){
            if(player.checkIntersect(ball)){
                if(player.count > ball.count){
                    player.count += 1;
                    player.count += ball.count;
                    balls.splice(balls.indexOf(ball), 1);
                } else {
                    ball.count += 1;
                    ball.count += player.count;
                    tmpplayers.push(players.splice(players.indexOf(player), 1)[0]);
                }
            }
        }
    }

    for(let ball of balls){
        ball.update();
        ball.show();

        for(let another of balls){
            if(ball != another){
                if(ball.checkIntersect(another)){
                    if(ball.count > another.count){
                        ball.count += 1;
                        ball.count += another.count;
                        balls.splice(balls.indexOf(another), 1);
                    } else {
                        another.count += 1;
                        another.count += ball.count;
                        balls.splice(balls.indexOf(ball), 1);
                    }
                }
            }
        }
    }
}
* {
  padding: 0;
  margin: 0;
  overflow: hidden;
}
<script src="https://rawgit.com/CodingTrain/Toy-Neural-Network-JS/master/lib/matrix.js"></script>
<script src="https://rawgit.com/CodingTrain/Toy-Neural-Network-JS/master/lib/nn.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

1 个答案:

答案 0 :(得分:1)

似乎mutate需要函数参数,而不是数字。

在以下行中更改播放器方法var express = require('express'); var cors = require('cors'); var app = express().use("*",cors()); var router = app.Router(); /* GET users listing. */ router.get('/', function(req, res, next) { // Comment out this line: //res.send('respond with a resource'); // And insert something like this instead: res.json([{ id: 1, username: "samsepi0l" }, { id: 2, username: "D0loresH4ze" }]); }); module.exports = router;

mutate


this.brain.mutate(0.1)

这会将每个元素乘以0.1

this.brain.mutate(x=>x*0.1)
let balls = [];
let totalBalls = 5;
let players = [];
let tmpplayers = [];
let totalPlayers = 100;

function nextGeneration(){
    calcFitness();
    for(let i = 0; i < totalPlayers; i++){
        players.push(pickOnePlayer());
    }
    tmpplayers = [];
    console.log("next generation");
}

function pickOnePlayer(){
    let index = 0;
    let r = random(1);

    while(r > 0){
        r = r - tmpplayers[index].fitness;
        index++;
    }
    index--;

    let player = tmpplayers[index];
    let child = new Player(player.brain);
    child.mutate();
    return child;
}

function calcFitness(){
    let sum = 0;
    for(let player of tmpplayers){
        sum += player.score;
    }

    for(let player of tmpplayers){
        player.fitness = player.score / sum;
    }
}

class Ball {
    constructor(){
        this.r = 15;
        this.randX = random(this.r, width - this.r);
        this.randY = random(this.r, height - this.r);
        this.pos = new p5.Vector(this.randX, this.randY);
        this.acc = new p5.Vector(random(-5, 5), random(-5, 5));
        this.count = 0;
        this.color = [random(0, 255), random(0, 255), random(0, 255)];
    }

    update(){
        this.pos.x += this.acc.x;
        this.pos.y += this.acc.y;

        if(this.pos.x < this.r || this.pos.x > width - this.r){
            this.acc.x *= -1;
        }

        if(this.pos.y < this.r || this.pos.y > height - this.r){
            this.acc.y *= -1;
        }
    }

    checkIntersect(another){ // check if ball hits another ball
        return dist(this.pos.x, this.pos.y, another.pos.x, another.pos.y) < (this.r + another.r);
    }

    show(){
        // show ball
        fill(this.color[0], this.color[1], this.color[2]);
        ellipse(this.pos.x, this.pos.y, this.r * 2);

        // show ball score
        fill(0);
        textSize(20);
        text(this.count, this.pos.x - (this.r / 2), this.pos.y + (this.r / 2));
    }
}

class Player {
    constructor(brain){
        this.range = 150;
        this.r = 15;
        this.count = 0;
        this.score = 0;
        this.fitness = 0;
        this.pos = new p5.Vector(width / 2, height / 2);
        this.acc = new p5.Vector();

        // if brain was passed, copy it, else make new neuralnetwork
        if(brain != undefined){
            this.brain = brain.copy();
        } else {
            this.brain = new NeuralNetwork(6, 4, 1);
        }
    }

    mutate(){
        this.brain.mutate(x=>x*0.1);
    }

    move(x, y){
        this.acc.x = x;
        this.acc.y = y;

        this.pos.x += this.acc.x;
        this.pos.y += this.acc.y;

        if(this.pos.x < this.r || this.pos.x > width - this.r){
            this.pos.x -= this.acc.x;
        }

        if(this.pos.y < this.r || this.pos.y > height - this.r){
            this.pos.y -= this.acc.y;
        }
    }

    think(){
        let inputs = [];

        // set INPUTS of this particular Player
        inputs.push(this.pos.x / width);
        inputs.push(this.pos.y / height);
        inputs.push(this.count);

        // get closest ball
        let closestBall = balls[0];
        let closestD = dist(this.pos.x, this.pos.y, closestBall.pos.x, closestBall.pos.y);
        for(let ball of balls){
            let d = dist(this.pos.x, this.pos.y, ball.pos.x, ball.pos.y);
            if(d < closestD){
                closestD = d;
                closestBall = ball;
            }
        }

        // set INPUTS of closest Ball
        inputs.push(closestBall.pos.x / width);
        inputs.push(closestBall.pos.y / height);
        inputs.push(closestBall.count);

        // predict inputs and then do actions
        let output = this.brain.predict(inputs);
        if(output < 0.25){
            this.move(0, -3); // up
        } else if(output >= 0.25 && output < 0.5){
            this.move(-3, 0); // left
        } else if(output >= 0.5 && output < 0.75){
            this.move(0, 3); // down
        } else {
            this.move(3, 0); // right
        }
    }

    checkIntersect(another){ // check if player hits ball
        return dist(this.pos.x, this.pos.y, another.pos.x, another.pos.y) < (this.r + another.r);
    }

    show(){
        //fill(255, 0, 0, 20);
        //ellipse(this.pos.x, this.pos.y, this.range * 2);

        // show player
        fill(0, 255, 0);
        ellipse(this.pos.x, this.pos.y, this.r * 2);

        // show player score
        fill(0);
        textSize(20);
        text("!" + this.count, this.pos.x - (this.r / 2), this.pos.y + (this.r / 2));
    }
}

function setup(){
    createCanvas(windowWidth, windowHeight);

    // create balls
    for(let i = 0; i < totalBalls; i++){
        balls.push(new Ball());
    }

    // create players
    for(let i = 0; i < totalPlayers; i++){
        players.push(new Player());
    }
}

function draw(){
    background(51);

    // keep spawning new balls
    if(balls.length != totalBalls){
        while(balls.length != totalBalls){
            balls.push(new Ball());
        }
    }

    // reset game and make a nextGeneration out of previous
    if(players.length == 0 || frameCount == 1000){
        nextGeneration();
    }

    // some special graphic stuff, NOT IMPORTANT
    let rw = round(windowWidth / totalBalls);
    for(let i = 0; i < balls.length; i++){
        let rh = constrain(balls[i].count, 0, height);
        let c = balls[i].color;
        c[3] = 50; // transparent background
        fill(c);
        rect(i * rw, height, rw, -rh);
    }

    for(let player of players){
        player.score++;
        player.think();
        player.show();

        for(let ball of balls){
            if(player.checkIntersect(ball)){
                if(player.count > ball.count){
                    player.count += 1;
                    player.count += ball.count;
                    balls.splice(balls.indexOf(ball), 1);
                } else {
                    ball.count += 1;
                    ball.count += player.count;
                    tmpplayers.push(players.splice(players.indexOf(player), 1)[0]);
                }
            }
        }
    }

    for(let ball of balls){
        ball.update();
        ball.show();

        for(let another of balls){
            if(ball != another){
                if(ball.checkIntersect(another)){
                    if(ball.count > another.count){
                        ball.count += 1;
                        ball.count += another.count;
                        balls.splice(balls.indexOf(another), 1);
                    } else {
                        another.count += 1;
                        another.count += ball.count;
                        balls.splice(balls.indexOf(ball), 1);
                    }
                }
            }
        }
    }
}
* {
  padding: 0;
  margin: 0;
  overflow: hidden;
}