如何提高前馈神经网络的准确性?

时间:2020-08-19 21:05:15

标签: javascript neural-network artificial-intelligence training-data synaptic.js

我想使用此神经网络绘制StackOverflow的徽标:

enter image description here

理想情况下,NN应该变为 [r,g,b] = f([x,y])。换句话说,它应该为给定的一对坐标返回RGB颜色。 FFNN非常适合简单的形状,例如圆形或盒子。例如,在数千个纪元之后,一个圆圈看起来像这样:

enter image description here

自己尝试:https://codepen.io/adelriosantiago/pen/PoNGeLw


但是,由于即使经过数千次迭代,StackOverflow的徽标也要复杂得多,所以FFNN的结果有些差:

enter image description here

从左到右:

  1. StackOverflow的徽标为256种颜色。
  2. 具有15个隐藏的神经元:永远不会出现左手柄。
  3. 50个隐藏的神经元:总体上效果很差。
  4. 0.03作为学习率:结果中显示蓝色(原始图像中没有蓝色)
  5. 学习速度递减:出现左手柄,但其他细节现在丢失了。

自己尝试:https://codepen.io/adelriosantiago/pen/xxVEjeJ

一些令人感兴趣的参数是synaptic.Architect.Perceptron的定义和learningRate的值。


如何提高该NN的准确性?

您可以改善摘要吗?如果是这样,请说明您做了什么。如果有更好的NN体系结构来解决此类工作,您可以举个例子吗?

其他信息:

  • 使用的人工神经网络库:Synaptic.js
  • 要在您的本地主机中运行此示例,请执行以下操作:See repository

2 个答案:

答案 0 :(得分:7)

通过添加另一层,您可以获得更好的结果:

let perceptron = new synaptic.Architect.Perceptron(2, 15, 10, 3)

1000 iterations 2000 iterations

您可以做一些小改进来提高效率(略微提高): 这是我的优化代码:

const width = 125
const height = 125
const outputCtx = document.getElementById("output").getContext("2d")
const iterationLabel = document.getElementById("iteration")
const stopAtIteration = 3000
let perceptron = new synaptic.Architect.Perceptron(2, 15, 10, 3)
let iteration = 0

let inputData = (() => {
  const tempCtx = document.createElement("canvas").getContext("2d")
  tempCtx.drawImage(document.getElementById("input"), 0, 0)
  return tempCtx.getImageData(0, 0, width, height)
})()

const getRGB = (img, x, y) => {
  var k = (height * y + x) * 4;
  return [
    img.data[k] / 255, // R
    img.data[k + 1] / 255, // G
    img.data[k + 2] / 255, // B
    //img.data[(height * y + x) * 4 + 3], // Alpha not used
  ]
}
const paint = () => {
  var imageData = outputCtx.getImageData(0, 0, width, height)
  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      var rgb = perceptron.activate([x / width, y / height])
      var k = (height * y + x) * 4;
      imageData.data[k] = rgb[0] * 255
      imageData.data[k + 1] = rgb[1] * 255
      imageData.data[k + 2] = rgb[2] * 255
      imageData.data[k + 3] = 255 // Alpha not used
    }
  }
  outputCtx.putImageData(imageData, 0, 0)

  setTimeout(train, 0)
}

const train = () => {
  iterationLabel.innerHTML = ++iteration

  if (iteration > stopAtIteration) return

  let learningRate = 0.01 / (1 + 0.0005 * iteration) // Attempt with dynamic learning rate
  //let learningRate = 0.01 // Attempt with non-dynamic learning rate
      
  for (let x = 0; x < width; x += 1) {
    for (let y = 0; y < height; y += 1) {
      perceptron.activate([x / width, y / height])
      perceptron.propagate(learningRate, getRGB(inputData, x, y))
    }
  }
  paint()
}

const startTraining = (btn) => {
  btn.disabled = true
  train()
}

编辑:我制作了另一个CodePen,效果更好:

enter image description here

https://codepen.io/xurei/pen/KKzWLxg

BTW可能过拟合。 感知器定义:

let perceptron = new synaptic.Architect.Perceptron(2, 8, 15, 7, 3)

答案 1 :(得分:1)

从比克莎·拉吉(Bhiksha Raj)的演讲/ slides中获得一些见解(从幻灯片62开始),并总结如下:

可以像线性分类器那样假设每个节点,并且在神经网络的单层中多个节点的组合可以近似任何基本形状。例如,假设每个节点对一条线有贡献,则矩形可以由每条线的4个节点组成,并且形状可以由最终输出层近似。

回到复杂形状(例如圆形)的摘要,它可能需要一层中的无限个节点。否则,对于具有两个不相交形状(非重叠三角形和矩形)的单层来说,这可能适用。但是,仍然可以使用多个隐藏层来学习。在那里,第一层学习基本形状,第二层学习它们的不相交组合。

因此,您可以假定此徽标是不相交的矩形的组合(橙色为5个矩形,灰色为3个矩形)。我们可以在第一个隐藏层中使用至少32个节点,在第二个隐藏层中使用几个节点。但是,我们无法控制每个节点的学习内容。因此,比所需神经元多一些的神经元应该会有所帮助。