Нейронная сеть всегда выдает одинаковые / похожие выходы для любого входа - PullRequest
27 голосов
/ 20 декабря 2010

У меня есть проблема, когда я пытаюсь создать нейронную сеть для Tic-Tac-Toe.Однако, по какой-то причине, обучение нейронной сети приводит к тому, что она выдает почти одинаковый выход для любого заданного ввода.

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

Чтобы убедиться, что проблема не только в моем выборе обучающего набора (1218 состояний доски и ходы, генерируемые генетическималгоритм), я пытался обучить сеть для воспроизведения XOR.Была использована функция логистической активации.Вместо того, чтобы использовать производную, я умножил ошибку на output*(1-output), так как некоторые источники предположили, что это эквивалентно использованию производной.Я могу поместить исходный текст на Haskell в HPaste, но на это немного неловко смотреть.Сеть имеет 3 уровня: первый уровень имеет 2 входа и 4 выхода, второй имеет 4 входа и 1 выход, а третий имеет 1 выход.Увеличение до 4 нейронов во втором слое не помогло, равно как и увеличение до 8 выходов в первом слое.

Затем я вычислял ошибки, выход в сеть, обновления смещения и обновления веса вручную, основываясь наhttp://hebb.mit.edu/courses/9.641/2002/lectures/lecture04.pdf чтобы убедиться, что в этих частях кода не было ошибки (не было, но я, вероятно, сделаю это снова, просто чтобы убедиться).Поскольку я использую пакетное обучение, я не умножил на x в уравнении (4).Я добавляю изменение веса, хотя http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-2.html предлагает вместо этого вычесть это.

Проблема сохранялась даже в этой упрощенной сети.Например, это результаты после 500 эпох пакетного обучения и дополнительного обучения.

Input    |Target|Output (Batch)      |Output(Incremental)
[1.0,1.0]|[0.0] |[0.5003781562785173]|[0.5009731800870864]
[1.0,0.0]|[1.0] |[0.5003740346965251]|[0.5006347214672715]
[0.0,1.0]|[1.0] |[0.5003734471544522]|[0.500589332376345]
[0.0,0.0]|[0.0] |[0.5003674110937019]|[0.500095157458231]

Вычитание вместо сложения приводит к той же самой проблеме, за исключением того, что все равно 0,99 что-то вместо 0,50 что-то.5000 эпох дает тот же результат, за исключением того, что сеть с обучением по пакетам возвращает точно 0,5 для каждого случая.(Черт, даже 10 000 эпох не работали для пакетного обучения.)

Есть ли вообще что-нибудь, что могло бы вызвать такое поведение?

Кроме того, я посмотрел на промежуточные ошибки для инкрементального обучения,и хотя входы скрытого / входного слоев варьировались, ошибка для выходного нейрона всегда была +/- 0,12.Для пакетного обучения ошибки увеличивались, но очень медленно, и все ошибки были чрезвычайно малы (x10 ^ -7).Разные начальные случайные веса и смещения также не имели значения.

Обратите внимание, что это школьный проект, поэтому советы / руководства будут более полезными.Хотя изобретать велосипед и создавать свою собственную сеть (на языке, которого я не очень хорошо знаю!) Было ужасной идеей, я чувствовал, что это будет более уместно для школьного проекта (так что я знаю, что происходит ... в теории,по крайней мере, в моей школе, кажется, нет учителя информатики.)

РЕДАКТИРОВАТЬ: два слоя, входной слой с 2 ​​входами на 8 выходов и выходной слой с 8 входами на 1 выход, дает почти одинаковые результаты: 0,5 +/- 0,2 (или около того) для каждого случая обучения.Я также играю с pyBrain, чтобы посмотреть, будет ли работать какая-либо структура сети.

Редактировать 2: Я использую скорость обучения 0,1.Извините, что забыл об этом.

Редактировать 3: "TrainUntilConvergence" из Pybrain также не дает мне полностью обученную сеть, как 20000 эпох, с 16 нейронами в скрытом слое.10000 эпох и 4 нейрона, не так много, но близко.Итак, в Haskell с входным слоем, имеющим 2 входа и 2 выхода, скрытым слоем с 2 входами и 8 выходами и выходным слоем с 8 входами и 1 выходом ... У меня такая же проблема с 10000 эпохами.И с 20000 эпохами.

Редактировать 4: Я снова запустил сеть вручную на основе MIT PDF, приведенного выше, и значения совпадают, поэтому код должен быть правильным, если я не понимаю эти уравнения.

Часть моего исходного кода находится по адресу http://hpaste.org/42453/neural_network__not_working; Я работаю над тем, чтобы немного очистить свой код и поместить его в Github (а не в частный Bitbucket) репозиторий.

Весь соответствующий исходный код теперь находится на https://github.com/l33tnerd/hsann.

Ответы [ 9 ]

24 голосов
/ 06 октября 2014

У меня были похожие проблемы, но я смог решить их, изменив:

  • Уменьшите проблему до приемлемого размера. Сначала я попробовал слишком много входов со слишком большим количеством скрытых юнитов слоя. Как только я уменьшил масштаб проблемы, я смог увидеть, работает ли решение более мелкой проблемы. Это также работает, потому что при уменьшении время для вычисления весов значительно уменьшается, поэтому я могу попробовать много разных вещей без ожидания.
  • Убедитесь, что у вас достаточно скрытых юнитов. Для меня это было серьезной проблемой. У меня было около 900 входов, подключенных к ~ 10 единицам в скрытом слое. Это было слишком мало, чтобы быстро сходиться. Но также стал очень медленным, если я добавил дополнительные единицы. Уменьшение количества входов очень помогло.
  • Измените функцию активации и ее параметры. Сначала я использовал tanh. Я пробовал другие функции: сигмовидную, нормализованную сигмовидную, гауссовскую и т. Д. Я также обнаружил, что изменение параметров функции, чтобы сделать функции круче или мельче, влияло на скорость схождения сети.
  • Изменение параметров алгоритма обучения. Попробуйте разные скорости обучения (от 0,01 до 0,9). Также попробуйте другие параметры импульса, если ваш алгоритм поддерживает это (от 0,1 до 0,9).

Надеюсь, это поможет тем, кто находит эту тему в Google!

2 голосов
/ 17 апреля 2019

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

Я работал над простой проблемой регрессии, но каждый раз, когда я обучал сеть, она сходилась к точке, где она давала мне один и тот же выход (или иногда несколько разных выходов) для каждого входа. Я играл со скоростью обучения, количеством скрытых слоев / узлов, алгоритмом оптимизации и т. Д., Но это не имело значения. Даже когда я посмотрел на смехотворно простой пример, пытаясь предсказать вывод (1d) двух разных входов (1d):

    import numpy as np
    import torch
    import torch.nn as nn
    import torch.nn.functional as F

    class net(nn.Module):
        def __init__(self, obs_size, hidden_size):
            super(net, self).__init__()
            self.fc = nn.Linear(obs_size, hidden_size)
            self.out = nn.Linear(hidden_size, 1)

        def forward(self, obs):
            h = F.relu(self.fc(obs))
            return self.out(h)

    inputs = np.array([[0.5],[0.9]])
    targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

    network = net(1,5)
    optimizer = torch.optim.Adam(network.parameters(), lr=0.001)

    for i in range(10000):
        out = network(torch.tensor(inputs, dtype=torch.float32))
        loss = F.mse_loss(out, targets)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        print("Loss: %f outputs: %f, %f"%(loss.data.numpy(), out.data.numpy()[0], out.data.numpy()[1]))

но все же всегда выводилось среднее значение выходов для обоих входов. Оказывается, причина в том, что размеры моих выходных данных и целей не были одинаковыми: целями был Размер [2], а выходными данными был Размер [2,1], и по какой-то причине PyTorch передавал выходные данные, чтобы иметь размер [2,2] в потере MSE, которая полностью все испортила. Однажды я изменился:

targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

до

targets = torch.tensor([[3.0], [2.0]], dtype=torch.float32)

Работало как надо. Очевидно, это было сделано с помощью PyTorch, но я подозреваю, что другие библиотеки передают переменные таким же образом.

0 голосов
/ 24 июня 2019

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

0 голосов
/ 07 февраля 2019

Я сталкивался с подобной проблемой ранее, когда мои данные не были должным образом нормализованы. Как только я нормализовал данные, все работало правильно.

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

Я использовал пакет caret для R. Сначала я использовал гиперпараметр затухания = 0,01. Когда я посмотрел на диагностику, я увидел, что среднеквадратическое среднеквадратичное отклонение рассчитывалось для каждого сгиба (перекрестной проверки), но Rsquared всегда был NA. В этом случае все прогнозы выходили на одно и то же значение.

Как только я уменьшил затухание до гораздо более низкого значения (1E-5 и ниже), я получил ожидаемые результаты.

Надеюсь, это поможет.

0 голосов
/ 06 октября 2014

У меня были похожие проблемы с алгоритмами машинного обучения, и когда я посмотрел код, я обнаружил случайные генераторы, которые не были действительно случайными. Если вы не используете новое случайное начальное число (например, время Unix, см. http://en.wikipedia.org/wiki/Unix_time), то можно получать одни и те же результаты снова и снова.

0 голосов
/ 19 марта 2011

Я не проверял это с проблемой XOR в этом вопросе, но для моего исходного набора данных, основанного на Tic-Tac-Toe, я полагаю, что я немного обучил сеть (у меня было всего 1000 эпох, что было не достаточно): сеть быстрого распространения может выиграть / завязать более половины своих игр; обратное распространение может получить около 41%. Проблемы сводились к ошибкам реализации (мелким) и непониманию разницы между производной ошибки (которая составляет на вес ) и ошибкой для каждого нейрона , которую я не делал продолжить в моем исследовании. Ответ @ darkcanuck о тренировке смещения, подобного весу, вероятно, помог бы, хотя я этого не реализовал. Я также переписал свой код на Python, чтобы мне было легче взломать его. Поэтому, хотя я не получил сеть, которая соответствовала бы эффективности минимаксного алгоритма, я считаю, что мне удалось решить эту проблему.

0 голосов
/ 16 января 2011

На основании ваших комментариев я бы согласился с @finnw, что у вас есть проблема смещения. Вы должны рассматривать смещение как постоянный «1» (или -1, если вы предпочитаете) вход для каждого нейрона. Каждый нейрон также будет иметь свой собственный вес для смещения, поэтому выходной сигнал нейрона должен быть суммой взвешенных входных данных плюс смещение, умноженное на его вес, пропущенный через функцию активации. Веса смещения обновляются во время тренировки так же, как и другие веса.

В «Основах нейронных сетей» Фозетта (стр.300) приведен пример XOR с использованием двоичных входов и сети с 2 входами, 1 скрытым слоем из 4 нейронов и одним выходным нейроном. Веса случайным образом инициализируются между +0,5 и -0,5. При скорости обучения 0,02 пример сети сходится примерно после 3000 эпох. Вы должны быть в состоянии получить результат на том же этапе, если вы решите проблемы смещения (и любые другие ошибки).

Также обратите внимание, что вы не можете решить проблему XOR без скрытого слоя в вашей сети.

0 голосов
/ 16 января 2011

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

0 голосов
/ 20 декабря 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...