【问题标题】:How do I properly implement my mutation function?如何正确实现我的突变功能?
【发布时间】:2021-03-21 02:54:27
【问题描述】:

我正在实现一个简单的遗传算法,一切正常,但我发现变异函数出了点问题。我将代理神经网络的权重和偏差设置为与一代中最适合的代理相同,然后应用突变,但所有代理的移动方式相同。

您可以在此在线 p5 编辑器草图上为自己运行我的网络应用程序:https://editor.p5js.org/aideveloper/sketches/Ot-SA1ulw

谁能帮我理解我的变异函数做错了什么?

agent.js:

class Agent {
  constructor(args) {
    this.x = args.x
    this.y = args.y
    this.color = args.color
    this.weights = []
    this.biases = []
    this.lost = false

    for(let i = 0; i < args.layers.length-1; i++)
      this.weights.push([...new Array(args.layers[i+1])].map(() => [...new Array(args.layers[i])].map(() => random(-1, 1))))

    for(let i = 0; i < args.layers.length-1; i++)
      this.biases.push([...new Array(args.layers[i+1])].map(() => random(-1, 1)))
  }

  predict(x) {
    let y = x
    for(let i = 0; i < this.weights.length; i++) {
      let hidden = [...new Array(this.weights[i].length)]

      for(let j = 0; j < this.weights[i].length; j++) {
        hidden[j] = 0

        for(let k = 0; k < this.weights[i][j].length; k++)
          hidden[j] += this.weights[i][j][k] * y[k]

        hidden[j] += this.biases[i][j]
        hidden[j] = 1 / (1 + Math.exp(-hidden[j]))
      }

      y = hidden
    }

    return y
  }

  mutate(rate=0.1) {
    for(let i = 0; i < this.weights.length; i++) {
      for(let j = 0; j < this.weights[i].length; j++) {
        if(Math.random() < rate)
          this.biases[i][j] += random(-1, 1)
        for(let k = 0; k < this.weights[i][j].length; k++) {
          if (Math.random() < rate)
            this.weights[i][j][k] += random(-1, 1)
        }
      }
    }
  }
}

sketch.js:

const speed = 5
const n = 2000

let fittest_agent = null
let agents = []
let generation = 1

function setup() {
  createCanvas(window.innerWidth, window.innerHeight)

  for (let i = 0; i < n; i++) {
    agents.push(new Agent({
      x: 20,
      y: window.innerHeight/2,
      color: color(
        Math.random() * 255,
        Math.random() * 255,
        Math.random() * 255
      ),
      layers: [2, 10, 10, 1]
    }))
  }
  fittest_agent = agents[0]

  document.querySelector('#controls button').addEventListener('click', () => {
    reproduce()
    generation += 1
    document.querySelector('#controls h1').textContent = `Generation: #${generation}`
  })
}

function draw() {
  noStroke()
  background(255)

  for (let i = 0; i < n; i++) {
    fill(agents[i].color)
    ellipse(agents[i].x, agents[i].y, 30, 30)

    if(!agents[i].lost) {
      let a = agents[i].predict([agents[i].x, agents[i].y])
      agents[i].x += speed * cos(a * 100000)
      agents[i].y += speed * sin(a * 100000)
    }

    fittest_agent = agents[i].x > fittest_agent.x ? agents[i] : fittest_agent
    document.querySelector('#controls div').outerHTML = `<div id="fittest" style="background-color:rgb(${fittest_agent.color.levels[0]},${fittest_agent.color.levels[1]},${fittest_agent.color.levels[2]})"></div>`
    document.querySelector('#controls span').textContent = Math.ceil(fittest_agent.x)

    if(agents[i].x+15>window.innerWidth/4 && agents[i].x-15<window.innerWidth/4+30 && agents[i].y-15<window.innerHeight*2/3)
      agents[i].lost = true
    if(agents[i].x+15>window.innerWidth/2 && agents[i].x-15<window.innerWidth/2+30 && agents[i].y+15>window.innerHeight/3)
      agents[i].lost = true
    if(agents[i].x+15>window.innerWidth*3/4 && agents[i].x+15<window.innerWidth*3/4+30 && agents[i].y-15<window.innerHeight*2/3)
      agents[i].lost = true
    if(agents[i].x<15)
      agents[i].lost = true
    if(agents[i].y<15)
      agents[i].lost = true
    if(agents[i].x+15>window.innerWidth)
      agents[i].lost = true
    if(agents[i].y+15>window.innerHeight)
      agents[i].lost = true
  }

  fill(135, 206, 235)
  rect(window.innerWidth/4, 0, 30, window.innerHeight*2/3)
  rect(window.innerWidth/2, window.innerHeight/3, 30, window.innerHeight*2/3)
  rect(window.innerWidth*3/4, 0, 30, window.innerHeight*2/3)
}

function reproduce() {
  agents.map(agent => {
    agent.x = 20
    agent.y = window.innerHeight/2
    agent.lost = false
    agent.weights = fittest_agent.weights
    agent.biases = fittest_agent.biases
    agent.color = color(random() * 255, random() * 255, random() * 255)

    agent.mutate()

    return agent
  })
}

这是问题的直观表示:

【问题讨论】:

    标签: neural-network p5.js genetic-algorithm


    【解决方案1】:

    问题出在reproduce() 函数中——您将最适合代理的权重/偏差数组的引用分配给新代理的权重/偏差,并且所有代理最终都具有相同的“大脑”。您应该首先创建最适合代理的权重/偏差的深层副本,然后将其分配给代理。
    function reproduce() {
      agents.map(agent => {
        // other code
        agent.weights = deepCopy(fittest_agent.weights)
        agent.biases = deepCopy(fittest_agent.biases)
        // other code
       }
    }
    
    function deepCopy(arr) {
      // your implementation
    }
    

    您可以使用前。来自 lodash 库的 cloneDeep。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-27
      • 2019-09-07
      • 1970-01-01
      • 2020-09-03
      • 2013-11-11
      • 2018-09-05
      • 1970-01-01
      • 2017-01-30
      相关资源
      最近更新 更多