Средняя потеря, застрявшая на локальных минимумах (Саморазвитый Перцептрон в C #) - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь создать пользовательскую библиотеку машинного обучения на C #, я достаточно исследовал эту тему.Мой первый пример (оценщик XOR) был успешным, я смог снизить среднюю потерю почти до нуля.Затем я попытался построить модель для классификации рукописных цифр (с использованием текстовой базы данных MNIST). Проблема заключается в том, что независимо от того, как я настраиваю модель, я всегда застреваю на определенной средней потере по набору данных. Вторая проблема, потому что MNISTнабор данных очень большой, для вычисления модели требуется много времени, может быть, я могу воспользоваться некоторыми советами о том, как выполнять самые медленные части алгоритма (я использую стохастический градиентный спуск). Я собираюсь показать основной метод, которыйвыполняет большую часть работы.

Я пытался использовать функции потери MSE и CrossEntropy, а также функции активации tanh, sigmoid, reLu и softPlus.Модель, которую я пытаюсь построить, является четырехслойной.Первый слой, 784 входных нейронов;Во-вторых, 16 нейронов, сигмовидная кишка;В-третьих, 16 нейронов, сигмовидный и выходной слой, 10 нейронов (одна горячая закодированная цифра) с сигмоидом.Я знаю, что приведенный ниже код не может быть минимальным воспроизводимым примером, но он представляет алгоритм, который я пытаюсь изобразить.Я также загрузил решение в GitHub, может быть, кто-нибудь может помочь мне разобраться в проблеме.Это ссылка https://github.com/juan-carvajal/MachineLearningFramework Сначала запустится метод Main приложения, запустит классификатор XOR, который работает нормально.Тогда MNIST классификатор.

Модель лучше всего представлена ​​здесь:

            DataSet dataSet = new DataSet("mnist2.txt", ' ', 10, false);
            //This creates a model with batching=128 , learningRate=0.5 and 
            //CrossEntropy loss function
            var p = new Perceptron(128, 0.5, ErrorFunction.CrossEntropy())
            .Layer(784, ActivationFunction.Sigmoid())
            .Layer(16, ActivationFunction.Sigmoid())
            .Layer(16, ActivationFunction.Sigmoid())
            .Layer(10, ActivationFunction.Sigmoid());
            //1000 is the number of epochs
            p.Train2(dataSet, 1000);

Фактический алгоритм (стохастический градиентный спуск):

Console.WriteLine("Initial Loss:"+ CalculateMeanErrorOverDataSet(dataSet));
            for (int i = 0; i < epochs; i++)
            {   
                //Shuffle the data in every step
                dataSet.Shuffle();
                List<DataRow> batch = dataSet.NextBatch(this.Batching);
                //Gets random batch from the dataSet
                int count = 0;
                    foreach (DataRow example in batch)
                    {

                    count++;

                    double[] result = this.FeedForward(example.GetFeatures());
                        double[] labels = example.GetLabels();
                        if (result.Length != labels.Length)
                        {
                            throw new Exception("Inconsistent array size, Incorrect implementation.");
                        }
                        else
                        {
                            //What follows is the calculation of the gradient for this example, every example affects the current gradient, then all those changes are averaged an every parameter is updated.
                            double error = CalculateExampleLost(example);


                            for (int l = this.Layers.Count - 1; l > 0; l--)
                            {
                                if (l == this.Layers.Count - 1)
                                {
                                    for (int j = 0; j < this.Layers[l].CostDerivatives.Length; j++)
                                    {
                                    this.Layers[l].CostDerivatives[j] = ErrorFunction.GetDerivativeValue(labels[j], this.Layers[l].Activations[j]);

                                    }

                                }
                                else
                                {
                                    for (int j = 0; j < this.Layers[l].CostDerivatives.Length; j++)
                                    {

                                        double acum = 0;
                                        for (int j2 = 0; j2 < Layers[l + 1].Size; j2++)
                                        {
                                            acum += Layers[l + 1].WeightMatrix[j2, j] * this.Layers[l+1].ActivationFunction.GetDerivativeValue(Layers[l + 1].WeightedSum[j2]) * Layers[l + 1].CostDerivatives[j2];
                                        }
                                        this.Layers[l].CostDerivatives[j] = acum;
                                    }
                                }

                                for (int j = 0; j < this.Layers[l].Activations.Length; j++)
                                {
                                    this.Layers[l].BiasVectorChangeRecord[j] += this.Layers[l].ActivationFunction.GetDerivativeValue(Layers[l].WeightedSum[j]) * Layers[l].CostDerivatives[j];
                                    for (int k = 0; k < Layers[l].WeightMatrix.GetLength(1); k++)
                                    {
                                        this.Layers[l].WeightMatrixChangeRecord[j, k] += Layers[l - 1].Activations[k]
                                            * this.Layers[l].ActivationFunction.GetDerivativeValue(Layers[l].WeightedSum[j])
                                            * Layers[l].CostDerivatives[j];
                                    }
                                }
                            }
                        }



                    }
                    TakeGradientDescentStep(batch.Count);

                if ((i + 1) % (epochs / 10) == 0)
                {
                    Console.WriteLine("Epoch " + (i + 1) + ", Avg.Loss:" + CalculateMeanErrorOverDataSet(dataSet));
                }
            }

Here is an example of the local minima

Это пример того, как локальные минимумы выглядят в текущей модели.В своем исследовании я обнаружил, что подобные модели могут обеспечивать точность до 90%.Моя модель едва получила 10%.

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