【问题标题】:Siamese neural network连体神经网络
【发布时间】:2020-10-07 01:14:54
【问题描述】:

我一直在研究 Yann LeCun 和他的同事在 1994 年引入的用于识别签名的 Siamese 神经网络架构("Signature verification using a Siamese time delay neural network".pdf,NIPS 1994)。

我在理解这个 Siamese 神经网络模型的一般架构时遇到了一些问题,并与 Cross Validated 的朋友讨论了它。我想我终于明白了,所以现在我要进行下一步:实现它。

我们最后说全局算法应该是这样的:

  • 为第一个签名创建卷积神经网络 convNetA。
  • 为第二个签名创建卷积神经网络 convNetB。
  • 将 convNetA 权重与 convNetB 权重绑定。
  • 设置余弦相似度函数来计算损失。
  • 运行训练(向前和向后)。

我是 Torch 的新手,所以我真的不知道如何实现这个算法。这是我的第一个版本:

-- training
function gradientUpdate(perceptron, dataset, target, learningRate, max_iterations)

for i = 1, max_iterations do

      predictionValue = perceptron:forward(dataset)
       -- is this the cosine similarity?
  -- [output] forward(input): 
  -- Takes an input object, and computes the corresponding output of the module. In general input and output are Tensors. 

      
      io.write(" pre-predictionValue= "..predictionValue .."\n");

      -- the minus is because we're goin' backwards
      gradientWrtOutput = torch.Tensor({-target})

      perceptron:zeroGradParameters() -- zeroGradParameters(): If the module has parameters, this will zero the accumulation of the gradients with respect to these parameters, accumulated through accGradParameters(input, gradOutput,scale) calls. Otherwise, it does nothing.
      -- initialization

      perceptron:backward(dataset, gradientWrtOutput) -- Performs a backpropagation step through the module, with respect to the given input. 

      perceptron:updateParameters(learningRate)
  end

end

require "os"
require "nn"

input_number=5
output_number=2

-- imagine we have one network we are interested in, it is called "perceptronAAA"
perceptronAAA= nn.Sequential(); 
perceptronAAA:add(nn.Linear(input_number, output_number))

-- But we want to push examples towards or away from each other
-- so we make another copy of it called perceptronBBB
-- this *shares* the same weights via the set command, but has its own set of temporary gradient storage
-- that's why we create it again (so that the gradients of the pair don't wipe each other)
perceptronBBB= perceptronAAA:clone('weight', 'bias')

-- we make a parallel table that takes a pair of examples as input. they both go through the same (cloned) perceptron
-- ParallelTable is a container module that, in its forward() method, applies the i-th member module to the i-th input, and outputs a table of the set of outputs.
parallel_table = nn.ParallelTable()
parallel_table:add(perceptronAAA)
parallel_table:add(perceptronBBB)

-- now we define our top level network that takes this parallel table and computes the cosine distance betweem
-- the pair of outputs
perceptron= nn.Sequential()
perceptron:add(parallel_table)
perceptron:add(nn.CosineDistance())


-- lets make two example vectors
x_vector = torch.rand(input_number)
y_vector = torch.rand(input_number)
dataset = {x_vector, y_vector}

function dataset:size() return #dataset end


-- matrix having 5 rows * 2 columns
max_iterations = 100
learnRate = 0.1
target = 1 -- the target for cosine similarity is +1 on forwards, that becomes -1 on backwards

-- TRAINING:

-- push the pair x_vector and y_vector together, the distance should get larger..


 gradientUpdate(perceptron, dataset, target, learnRate, max_iterations)

您认为这是对具有余弦相似度函数以最小化的连体神经网络的正确实现吗?或者您能看到其中的任何错误/错误内容吗?

2020 年 10 月编辑:感谢大家在过去 5 年里帮助我理解这个模型!我最近出版了一本书章节,解释了我对孪生神经网络的理解,并报告了我在科学文献中发现的这个模型的所有可能应用。你可以在这里找到它:“Siamese neural networks: an overview”。 我希望你能发现它有用:如果这本书的章节现在存在,那也是因为你们当时提供的极好的帮助。再次感谢!

【问题讨论】:

  • 这太酷了,你的灵感是什么?
  • 对设计的小评论:当您进行信号验证时,航空电子工程使用 3 个系统,这些系统必须在不同的数据集上进行训练:主系统接受输入并产生输出信号。然后使用二级和三级系统检查初级系统信号。如果二级和三级系统不一致,则认为系统 1 有故障并丢弃信号。这是双重冗余验证,对于关键任务黑盒系统非常有用。这种方法应该会稍微简化您的架构。
  • 我看到您在我回答后加入了 Code Review,我对您的反馈很感兴趣。请对我的回答发表评论,或在the 2nd Monitor 中给我发消息。如果您认为值得,也可以采纳答案。
  • @syb0rg 您的回答看起来很有趣,但它没有回答我的问题。我在问:“你认为这是一个具有余弦相似度函数最小化的连体神经网络的正确实现吗?”你认为是还是不是?谢谢
  • @DavideChicco.it 是的,但您确实明白代码审查的目的是改进代码,对吗?你应该自己验证它是一个正确的实现。

标签: performance algorithm lua machine-learning neural-network


【解决方案1】:

我认为这是一个很棒的项目!但它可以做一些改进:

Neuron Type(1)

假设我们有一个感知器网络,我们想用它来学习解决某个问题。例如,网络的输入可能是来自签名扫描图像的原始像素数据。我们希望网络学习权重和偏差,以便网络的输出正确分类数字。为了了解学习是如何工作的,假设我们对网络中的某些权重(或偏差)进行了微小的更改。我们希望权重的这种微小变化只引起网络输出的微小相应变化。

如果权重(或偏差)的微小变化确实只会导致输出的微小变化,那么我们可以使用这个事实来修改权重和偏差,以使我们的网络以我们想要的方式表现得更多.例如,假设网络错误地将图像分类为“c”,而它应该是“o”。我们可以弄清楚如何对权重和偏差进行小幅更改,以便网络更接近将图像分类为“o”。然后我们会重复这一点,一遍又一遍地改变权重和偏差以产生越来越好的输出。网络正在学习。

问题在于,当我们的网络包含感知器时,不会发生这种情况。事实上,网络中任何单个感知器的权重或偏差的微小变化有时会导致该感知器的输出完全翻转,例如从 0 到 1。这种翻转可能会导致网络其余部分的行为以某种非常复杂的方式彻底改变。因此,虽然您的“o”现在可能被正确分类,但网络在所有其他图像上的行为可能已经以某种难以控制的方式完全改变。这使得很难看出如何逐渐修改权重和偏差,以使网络更接近所需的行为。也许有一些巧妙的方法可以解决这个问题。但我们如何让感知器网络进行学习并不是很明显。

我们可以通过引入一种称为 sigmoid 神经元的新型人工神经元来克服这个问题。 Sigmoid 神经元类似于感知器,但经过修改后,它们的权重和偏差的微小变化只会导致其输出的微小变化。这是允许 sigmoid 神经元网络学习的关键事实。

就像感知器一样,sigmoid 神经元有输入,\$ x1 \$, \$ x2 \$, ... 但是这些输入不仅可以是 0 或 1,还可以取 0 到 1 之间的任何值. 因此,例如,0.638 是 sigmoid 神经元的有效输入。

Sigmoid 神经元定义为:

$$ \sigma(z) = \dfrac{1}{1 + e^{-z}} $$

Torch 实现了这种神经元类型here

(1) 摘自Neural Networks and Deep learning的小幅编辑


Cost Function

我没有在您的代码中看到任何成本函数的使用。我将建议您阅读神经网络和深度学习中的this section,以了解您应该使用它的充分理由。

简而言之,成本函数返回一个数字,表示神经网络在将训练示例映射到正确输出方面的表现如何。基本思想是,我们的网络在实现预期结果方面越“错误”,成本就越高,我们就越想调整权重和偏差以实现更低的成本。我们尝试使用gradient descent 等方法将成本降至最低。

您在成本函数中寻找某些属性,例如convexity(因此梯度下降会找到全局最优值,而不是陷入局部最优值)。正如本书所暗示的,我倾向于使用cross-entropy cost function

我们在 Torch 中实现这一点的方式是使用 Criterions。 Torch 似乎已经实现了这些成本函数,我鼓励你尝试不同的成本函数,看看它们如何影响你的神经网络准确性。


Over-fitting

您的数据可能拟合得很好,以至于我们不能很好地概括。图中给出了一个例子:

嘈杂的线性数据适合线性和多项式函数。虽然多项式函数完美拟合,但线性版本更好地概括了数据。

我不太了解 Lua,但是通过查看您的代码,我没有看到任何减少过度拟合的尝试。一种常见的方法是实现regularization。由于这个话题太难在这里深入介绍,如果您愿意,我会让您理解它。理解了它的概念后使用起来相当简单,可以从this Torch implementation here看到。

另一种减少过拟合的方法是引入dropout。在每个训练阶段,单个节点都会从网络中“退出”,从而留下一个简化的网络。只有简化的网络在该阶段的数据上进行训练。然后将删除的节点以其原始权重重新插入网络。节点对其他节点的权重变得更加不敏感,并且他们学会了如何自行决定。

Dropout 还显着提高了训练速度,同时提高了性能(对于深度学习很重要)!


Gradient Checking

对于更复杂的模型,众所周知,梯度计算很难调试和正确处理。有时,一个有缺陷的实现会设法学习一些看起来非常合理的东西(但性能不如正确的实现)。因此,即使有错误的实现,也可能根本看不出有什么不对劲。因此,您应该通过代码计算numerically check the derivatives,以确保您的实现是正确的。

我找到了gradient checking with Torch here 的实现。请注意,此检查的计算量很大,因此一旦您验证了反向传播的实现是正确的,您应该关闭梯度检查。


Principal Components Analysis

PCA 可用于数据压缩以加速学习算法,也可用于visualize feature relations。基本上,在您拥有大量自变量的情况下,PCA 可以帮助您找出最重要的变量并消除其他变量(考虑将厘米和英寸都作为输入特征,我们只需要一个即可获得相同的信息)。

查看您链接的研究论文,看起来只有 10 个特征输入到神经网络中。但对我来说,看起来我们可以摆脱 2 个,可能 3 个功能!对于我们拥有的少数功能来说,这已经相当多了。函数 \$ \sin \$ 和 \$ \cos \$ 是相互关联的,为什么我们只需要一个来测量轨迹的方向和曲率,并且将相同的信息输入到神经网络

也可以说向心加速度和切向加速度相互关联,或者速度和曲率一起排除了向心加速度的需要,因为 \$ a_c = \frac{v^2}{r }\$。软件需要进行更多分析才能彻底确定。

请注意,如果应用不正确,PCA 会降低神经网络的准确性。 PCA 也用于处理过拟合(因为过拟合通常在存在许多特征时发生)。有一个nice GitHub repo here covering PCA using Torch

【讨论】:

    猜你喜欢
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 2012-03-24
    • 2017-01-27
    • 2020-05-03
    • 2014-01-15
    • 1970-01-01
    相关资源
    最近更新 更多