Я пытаюсь реализовать свой собственный многослойный персептрон, к сожалению, я делаю ошибку, которую не могу найти. Ссылка на полную программу находится здесь (это легкое, простое консольное приложение на c #). Я учусь из этой книги , код, который я пытаюсь переписать из партии в последовательную форму, находится в этом github .
Ссылка на мой мой проект здесь (github).
Сам перцептрон находится здесь .
Мои тестовые входы - это функция Xor и функция или функция и некоторая случайная функция с небольшим шумом.
Мои вопросы:
1)
Прежде, чем я покрыл весь мой код проверками бесконечности (для двойного переполнения), все мои результаты (и веса) очень быстро (более 100 итераций) сходились к некоторым сверхвысоким значениям, и результаты стали NaN
. После добавления чеков я только что получил double.MaxValue
. Интересно то, что если я запустил одну и ту же программу около 5 раз, я получу правильные результаты (в зависимости от количества итераций). Единственной случайной величиной являются веса, которые инициализируются с использованием случайных чисел (в диапазоне -1/sqrt(n) < x < 1/sqrt(n)
, где n
- число нейронов в скрытом слое). Что может быть причиной этого?
2)
Я тренируюсь и проверяю один и тот же набор данных (потому что сейчас это не имеет значения), и, поскольку это последовательный алгоритм, я перетасовываю учебные материалы и цели ВНУТРИ моего класса.
public void Train(int iterations, double eta)
{
_lastHiddenUpdates = new double[_hiddenWeights.RowLength(), _hiddenWeights.ColumnLength() + 1];
_lastOutputUpdates = new double[_outputWeights.Length];
for (int i = 0; i < iterations; i++)
{
ShuffleRows(); // <---- ShuffleRows is a private method without any ref parameter!
this._currentIteration = i;
var result = ForwardPhase(_trainingInput);
BackwardsPhase(result.OutputResult, result.HiddenValues, eta);
}
}
Это класс MultiLayerPerceptron
. Дело в том, что после обучения исходный массив double[]
также перемешивается! массив double является структурой, а структуры передаются по значению, а не по ссылке, а исходный массив находится в program.cs
. Почему это изменилось за пределами области видимости? Я что-то пропустил? Теперь я просто клонирую целевые массивы.
3)
Это супер уродливо
var infinity = deltasHs[i, j];
if (double.IsNegativeInfinity(infinity))
{
deltasHs[i, j] = double.MinValue;
}
else if (double.IsPositiveInfinity(infinity))
{
deltasHs[i, j] = double.MaxValue;
}
Как я могу это просто?
Примечание: во время написания этой программы я не обращал внимания на производительность, иногда я многократно циклически проходил по одному массиву, чтобы поддерживать читабельность на разумном уровне.
Я также знаю, что вы не должны тренироваться и проверять один и тот же набор данных, но это не моя цель, я буду совершенно счастлив, если мой персептрон также узнает шум. Я просто хочу, чтобы этот тупой гусь работал (и понимал).