Может ли перетасовка моих обучающих данных привести к снижению производительности модели?

Я пишу нейронную сеть на C ++ для аппроксимации функции xSin (x), используя один скрытый слой с 5 скрытыми нейронами. Скрытые нейроны используют активацию tanh, а выходной слой использует активацию Linear. Я использовал 30 обучающих примеров для 10 000 эпох.

Пока я не перетасовал свои данные, я получил следующее:  введите описание изображения здесь (КРАСНЫЙ: прогнозируемые данные, ЗЕЛЕНЫЙ: фактические данные), также MSE была близка к 0

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

введите здесь описание изображения,

и Ошибка против эпохи как:

введите описание изображения здесь

Что возможно могло пойти не так? Может ли это быть причиной перетасовки?

Вот простой код для справки

//Shuffle Function 
void shuffle(int *array, size_t n)
{
    if (n > 1) //If no. of training examples > 1
    {
        size_t i;
        for (i = 0; i < n - 1; i++)
        {
            size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
            int t = array[j];
            array[j] = array[i];
            array[i] = t;
        }
    }
}


int main(int argc, const char * argv[])
{
    //Some other actions

    ///FOR INDEX SHUFFLING
    int trainingSetOrder[numTrainingSets];
    for(int j=0; j<numTrainingSets; ++j)
        trainingSetOrder[j] = j;


    ///TRAINING
    //std::cout<<"start train\n";
    vector<double> performance, epo; ///STORE MSE, EPOCH
    for (int n=0; n < epoch; n++)
    {

        shuffle(trainingSetOrder,numTrainingSets);
         for (int i=0; i<numTrainingSets; i++)
        {
            int x = trainingSetOrder[i];
            //cout<<" "<<"("<<training_inputs[x][0]<<","<<training_outputs[x][0] <<")";

            /// Forward pass
            for (int j=0; j<numHiddenNodes; j++)
            {
                double activation=hiddenLayerBias[j];
                //std::cout<<"Training Set :"<<x<<"\n";
                 for (int k=0; k<numInputs; k++) {
                    activation+=training_inputs[x][k]*hiddenWeights[k][j];
                }
                hiddenLayer[j] = tanh(activation);
            }

            for (int j=0; j<numOutputs; j++) {
                double activation=outputLayerBias[j];
                for (int k=0; k<numHiddenNodes; k++)
                {
                    activation+=hiddenLayer[k]*outputWeights[k][j];
                }
                outputLayer[j] = lin(activation);
            }



           /// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[i][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

            ///   For W
           //Some Code

            ///Updation
            ///   For V and b
            ///Some Code

            ///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
                }
            }
        }
      }


    return 0;
}

person Pe Dro    schedule 29.11.2019    source источник
comment
Ваша ссылка на код у меня не работает. Возьмите за хорошую привычку включать рассматриваемый код непосредственно в свое сообщение внутри соответствующих тегов кода вместо того, чтобы ссылаться на что-то еще, что не всегда может быть действительным.   -  person Fareanor    schedule 29.11.2019
comment
Извините за беспокойство. В целом код для этого вопроса будет длинным и громоздким, поскольку я не могу сосредоточиться на конкретном фрагменте. Следовательно, я добавил ссылку. Я поправлю.   -  person Pe Dro    schedule 29.11.2019
comment
Я понимаю, без проблем :) AFAIK, перетасовка порядка набора обучающих данных не должна приводить к сбою прогноза. Я предполагаю, что вы допустили небрежную ошибку, когда перемешивали или обрабатывали перемешанные данные. Но без кода это не может быть ничего, кроме предположения.   -  person Fareanor    schedule 29.11.2019
comment
Функция перемешивания перемешивает индексы, а не данные.   -  person Pe Dro    schedule 29.11.2019


Ответы (2)


Кажется, ваша модель не инициализирована случайным образом, потому что функция init_weight

double init_weight() { return (2*rand()/RAND_MAX -1); }

Почти всегда возвращает -1, потому что выполняет целочисленное деление. Такая инициализация, вероятно, делает модель очень сложной или невозможной для обучения.

Исправить:

double init_weight() { return 2. * rand() / RAND_MAX - 1; }

Этот 2. выше имеет тип double, который запускает продвижение других целочисленных терминов, задействованных в бинарных операторах, с ним до double.


Инициализация Xavier - это хорошо метод, ускоряющий обучение.

person Maxim Egorushkin    schedule 29.11.2019
comment
Но, как я показал на рисунке, веса модели могли давать хорошие прогнозы. Как перетасовать проблему? - person Pe Dro; 29.11.2019
comment
@PeDro Это мало что доказывает. Влияет ли исправление init_weight на результативность обучения? - person Maxim Egorushkin; 29.11.2019
comment
Я протестирую это в ближайшее время, но все, что я могу заверить, - это то, что ранее модель уже имела почти нулевую среднеквадратичную ошибку. - person Pe Dro; 29.11.2019
comment
Я проверил, но результаты все равно были ужасными. Это что-то другое. - person Pe Dro; 30.11.2019

В обучающей части обнаружил 2 ошибки (глупые!):

1)

/// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[i][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

должно было

/// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[x][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

2)

///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
                }
            }

должно было

///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[x][k]*deltaHidden[j]*lr;
                }
            }

Отправьте сообщение, я получаю  введите здесь описание изображения и введите описание изображения здесь

person Pe Dro    schedule 30.11.2019