Сиамская нейронная сеть

Я изучал архитектуру сиамской нейронной сети, представленную Янном ЛеКуном и его коллегами в 1994 году для признания подписей ( 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)

Считаете ли вы, что это правильная реализация сиамской нейронной сети с функцией подобия косинуса для минимизации? Или вы можете увидеть какие-либо ошибки /неправильные вещи в нем?

75 голосов | спросил DavideChicco.it 1 J0000006Europe/Moscow 2015, 22:02:23

1 ответ


26

Я думаю, что это отличный проект! Но это может сделать несколько улучшений:

Тип нейрона (1)

Предположим, у нас есть сеть персептронов, которую мы хотели бы использовать, чтобы научиться решать какую-то проблему. Например, входы в сеть могут быть необработанными пиксельными данными от сканированного изображения подписи. И мы хотели бы, чтобы сеть изучала вес и предубеждения, чтобы результат из сети правильно классифицировал цифру. Чтобы увидеть, как может работать обучение, предположим, что мы немного изменили некоторый вес (или смещение) в сети. Мы хотим, чтобы это небольшое изменение веса вызывало только небольшое соответствующее изменение в выходе из сети.

 введите описание изображения здесь>> </a> </p>

<p> Если бы правда, что небольшое изменение в весе (или смещении) вызывает только небольшое изменение в выходе, мы могли бы использовать этот факт для изменения весов и уклонов, чтобы наша сеть вела себя так, как мы хотим , Например, предположим, что сеть ошибочно классифицировала изображение как «c», когда оно должно быть «o». Мы могли бы выяснить, как сделать небольшое изменение в весах и смещениях, чтобы сеть немного приблизилась к классификации изображения как «о». И тогда мы повторяем это, изменяя вес и смещения снова и снова, чтобы производить лучшую и лучшую выходную информацию. Сеть будет учиться. </p>

<p> Проблема в том, что  это не то, что происходит, когда наша сеть содержит персептроны . Фактически, небольшое изменение веса или смещения любого одного персептрона в сети может иногда приводить к тому, что выход этого персептрона полностью переворачивается, скажем, от 0 до 1. Этот флип затем может привести к поведению остальной сети полностью меняются каким-то очень сложным образом. Поэтому, пока ваше «o» теперь можно классифицировать правильно, поведение сети на всех других изображениях, вероятно, полностью изменилось бы в некотором жестком контроле. Это затрудняет понимание того, как постепенно изменять вес и смещения, чтобы сеть приблизилась к желаемому поведению. Возможно, есть какой-то умный способ обойти эту проблему. Но не сразу видно, как мы можем получить сеть персетронов, чтобы учиться. </p>

<p> Мы можем преодолеть эту проблему, введя новый тип искусственного нейрона, называемый сильным сигмовидным нейроном <strong>. Сигмоидные нейроны подобны персептронам, но модифицированы так, что небольшие изменения в их весах и смещении вызывают лишь небольшое изменение в их выходе. Это важный факт, который позволит узнать сеть сигмовидных нейронов. </p>

<p> Как и персептрон, сигмовидный нейрон имеет входы, \ $ x1 \ $, \ $ x2 \ $, ... Но вместо того, чтобы быть только 0 или 1, эти входы также могут принимать любые значения от 0 до 1 Так, например, 0,638 является допустимым входом для сигмовидного нейрона. </p>

<p> <a href= введите описание изображения здесь>> </a> </p>

<p> Сигмовидный нейрон определяется как: </p>

<p> $$ \ sigma (z) = \ dfrac {1} {1 + e ^ {- z}} $$ </p>

<p> Факел реализует этот тип нейрона <a href= здесь .

(1) Выдержка с небольшими изменениями из Нейронные сети и глубокое обучение суб>


Функция затрат

Я не вижу использования функции стоимости в вашем коде. Я рекомендую вам прочитать этот раздел в нейронных сетях и глубоком обучении, чтобы получить хорошая причина, почему вы должны использовать ее.

Короче говоря, функция стоимости возвращает число, показывающее, насколько хорошо выполняется нейронная сеть для сопоставления примеров обучения для исправления вывода. Основная идея заключается в том, что чем более «неправильная» наша сеть заключается в достижении желаемых результатов, тем выше стоимость и тем больше мы хотим скорректировать вес и смещение для достижения более низких затрат. Мы стараемся минимизировать эту стоимость, используя такие методы, как градиентный спуск .

В функции затрат есть определенные свойства, такие как выпуклость (так градиентный спуск находит глобальную оптимуму вместо того, чтобы застревать в локальном оптимуме). Как следует из книги, я склоняюсь к использованию функции затрат на кросс-энтропии .

Как мы реализуем это в факеле, с Criterions . Факел, похоже, реализовал кучу этих функций затрат, и я призываю вас попробовать разные и посмотреть, как они влияют на точность вашей нейронной сети.


Переустановка

Возможно, что вы хорошо подходите к вашим данным слишком , к тому, что мы недостаточно хорошо обобщаем. Пример этого приведен на рисунке:

 введите описание изображения здесь>> </a> </p>

<p> Шумные, линейные данные устанавливаются как для линейных, так и для полиномиальных функций. Хотя полиномиальная функция идеально подходит, линейный вариант лучше обобщает данные. </p>

<p> Я не очень хорошо знаю Lua, но, посмотрев на свой код, я не вижу попыток уменьшить чрезмерную установку. Общий подход к этому заключается в реализации <a href= регуляризации . Поскольку здесь слишком сложно затронуть тему, я оставлю вас понять это, если хотите. Это очень просто использовать, как только понятны его понятия, вы можете видеть из этого факела здесь .

Еще один способ уменьшить переустановку - ввести отключение . На каждом этапе обучения отдельные узлы «выпадают» из сети, так что уменьшается сеть. Только данные в данной группе обучаются только по приведенной сети. Удаленные узлы затем снова вставляются в сеть с их исходными весами. Узлы становятся несколько более нечувствительными к весам других узлов, и они учатся решать самостоятельно.

Выпадение также значительно улучшает скорость обучения, улучшая производительность (важно для глубокого обучения)!


Проверка градиента

Для более сложных моделей вычисление градиента может быть трудно отлаживать и получить право. Иногда багги-реализации может научиться чему-то, что может выглядеть удивительно разумно (при выполнении менее хорошо, чем правильная реализация). Таким образом, даже при использовании с ошибкой может показаться совершенно не очевидным, что что-то не так. Поэтому вы должны численно проверить производные инструменты , рассчитанные вашим кодом, чтобы убедиться, что ваша реализация правильный.

Я нашел реализацию проверки градиента с помощью Torch здесь . Будьте осторожны, чтобы эта проверка была дорогостоящей, поэтому, как только вы подтвердите правильность реализации backpropagation, вы должны отключить проверку градиента.


Анализ основных компонентов

PCA может использоваться для сжатия данных для ускорения алгоритмов обучения, а также может использоваться для визуализировать отношения функций . В принципе, в ситуации, когда у вас есть WHOLE BUNCH независимых переменных, PCA помогает вам выяснить, какие из них имеют наибольшее значение и избавиться от других (подумайте о том, чтобы иметь сантиметры и дюймы как в качестве входных функций, нам нужно только одно, чтобы получить такая же информация).

Глядя на исследовательскую работу, которую вы связали, похоже, что в нейронную сеть входит только 10 функций. Но для меня, похоже, мы могли бы избавиться от 2, возможно, 3 функций! Это немного для тех немногих функций, которые у нас есть. Функции \ $ \ sin \ $ и \ $ \ cos \ $ связаны между собой, почему нам нужно как измерять направление и кривизну траектории, когда мы могли бы использовать только один, и получить одну и ту же информацию в нейронной сети ?

Можно также утверждать, что центростремительное и тангенциальное ускорения связаны друг с другом, или что скорость и кривизна вместе исключают необходимость центростремительного ускорения, так как \ $ a_c = \ frac {v ^ 2} {r } \ $. Программному обеспечению потребуется более подробный анализ, чтобы тщательно его определить.

Будьте осторожны, если не применять правильно, PCA может уменьшить точность нейронной сети. PCA также not используется для обработки переустановки (поскольку переназначение обычно возникает, когда присутствует множество функций). Существует хорошая реплика GitHubздесь покрытие PCA с использованием факела .

ответил syb0rg 13 J000000Wednesday16 2016, 23:38:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132