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

Posted

技术标签:

【中文标题】如何提高前馈神经网络的准确性?【英文标题】:How to improve accuracy of a FeedForward Neural Network? 【发布时间】:2020-12-09 04:40:36 【问题描述】:

我想用这个神经网络绘制 *** 的标志:

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

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


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

从左到右:

    *** 的 256 色徽标。 有 15 个隐藏神经元:左手柄永远不会出现。 50 个隐藏神经元:总体上效果很差。 0.03 作为学习率:在结果中显示为蓝色(原始图像中没有蓝色) 学习率随时间递减:左侧手柄出现,但其他细节现在丢失。

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

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


如何提高此 NN 的准确性?

你能改进sn-p吗?如果是这样,请解释你做了什么。如果有更好的神经网络架构来解决这类工作,您能否提供一个示例?

附加信息:

使用的人工神经网络库:Synaptic.js 要在本地主机中运行此示例:See repository

【问题讨论】:

【参考方案1】:

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

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

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

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,效果更好:

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

顺便说一句,它很可能是过度拟合的。 感知器定义:

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

【讨论】:

您可以尝试的另一件事是使用 RGB 以外的其他东西。我相信 Lab* 或 HSV 颜色空间可能效果更好。 另外,您的误差函数目前是线性的。我的直觉是,均方误差也可能会更好。 谢谢!结果看起来还不错。赏金时间已过,我决定将其奖励给你。我唯一真正想知道的是新价值观背后的原因。基本上如何选择合适的?运气?谢谢! 感谢您的奖励,非常感谢 :-) 回答您的问题:运气和经验的组合。基本上,只有一层的感知器就像一个线性聚类算法(即它可以定义一个分隔空间的平面)。每个额外的层都允许 NN 将输入转换为另一种更容易线性分割的形式。基于此,我的想法是“图像太复杂而无法线性分离,让我们尝试额外的层”。检查内核技巧以获取更多理论:en.wikipedia.org/wiki/Kernel_method.【参考方案2】:

从 Bhiksha Raj 的讲座/slides(从幻灯片 62 开始)中获得一些见解,总结如下:

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

回到圆形等复杂形状的总结,它可能需要一层中的无限节点。或者这可能适用于具有两个不相交形状(非重叠三角形和矩形)的单层。但是,这仍然可以使用超过 1 个隐藏层来学习。其中,第 1 层学习基本形状,然后第 2 层近似它们的不相交组合。

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

【讨论】:

以上是关于如何提高前馈神经网络的准确性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在卷积神经网络中确定三重态丢失的准确性

如何评估/提高来自具有不平衡数据集的神经网络的预测的准确性?

使用Python,Keras和TensorFlow训练第一个CNN

使用Python,Keras和TensorFlow训练第一个CNN

猿创征文|深度学习基于前馈神经网络完成鸢尾花分类

基于前馈神经网络和支持向量机分类器的叶片识别