Мне нужно преобразовать обучение со стохастическим градиентным спуском в мини-пакетный градиентный спуск. Я сообщаю простой пример нейронной сети только с 4 обучающими выборками, поэтому мы можем, например, реализовать пакет размером 2 только для того, чтобы понять, как изменить обучающую часть.
Это простой пример сети, которая должна изучить операцию xor:
Эта часть — определение сети
#include <stdio.h>
#include <stdlib.h>
typedef double NNType;
// numer of inputs
#define IN 2
// number neurons layer hidden
#define HID 8
// numer of outputs
#define OUT 1
// learning constant
#define EPS 0.1
NNType input[IN]; // input
NNType hidden[HID]; // layer hidden
NNType output[OUT]; // output
NNType weightH[HID][IN]; // weights layer hidden
NNType biasesH[HID]; // biases layer hidden
NNType weightO[OUT][HID]; // weights output
NNType biasesO[OUT]; // biases output
inline NNType Activation(NNType x)
{
return x>0?x:0;
}
inline NNType Derivative(NNType x)
{
return x>0?1:0;
}
Эта функция представляет собой сетевой расчет.
NNType NetworkResult(NNType inp1,NNType inp2)
{
// load the inputs
input[0]=inp1;
input[1]=inp2;
// compute hidden layer
for (int i=0;i<HID;i++)
{
hidden[i]=biasesH[i];
for (int j=0;j<IN;j++)
hidden[i] += input[j]*weightH[i][j];
hidden[i]=Activation(hidden[i]);
}
// compute output
for (int i=0;i<OUT;i++)
{
output[i]=biasesO[i];
for (int j=0;j<HID;j++)
output[i] += hidden[j]*weightO[i][j];
output[i]=Activation(output[i]);
}
return output[0];
}
Это тренировочная часть, которую мне нужно изменить на мини-пакетный градиентный спуск.
void TrainNet(NNType inp1,NNType inp2,NNType result,NNType *error)
{
NetworkResult(inp1,inp2);
NNType DeltaO[OUT];
NNType DeltaH[HID];
// layer output
NNType err= result-output[0];
*error+=err*err*0.5;
DeltaO[0]=err*Derivative(output[0]);
// layer hidden
for (int i=0;i<HID;i++)
{
NNType err=0;
for (int j=0;j<OUT;j++)
err+= DeltaO[j]*weightO[j][i];
DeltaH[i]=err*Derivative(hidden[i]);
}
// change weights
// layer output
for (int i=0;i<OUT;i++)
{
for (int j=0;j<HID;j++)
weightO[i][j]+=EPS*DeltaO[i]*hidden[j];
biasesO[i]+=EPS*DeltaO[i];
}
// layer hidden
for (int i=0;i<HID;i++)
{
for (int j=0;j<IN;j++)
weightH[i][j]+=EPS*DeltaH[i]*input[j];
biasesH[i]+=EPS*DeltaH[i];
}
}
Основная программа
// constant for weights initializations
#define CONSTINIT 0.1
int main(int argc, char *argv[])
{
srand(1);
// initalize weights and biases
for (int i=0;i<HID;i++)
{
for (int j=0;j<IN;j++)
weightH[i][j]= 2.0 * ( (rand()/((NNType)RAND_MAX)) - 0.5 ) * CONSTINIT;
biasesH[i]=0.1;
}
for (int i=0;i<OUT;i++)
{
for (int j=0;j<HID;j++)
weightO[i][j]= 2.0 * ( (rand()/((NNType)RAND_MAX)) - 0.5 ) * CONSTINIT;
biasesO[i]=0.1;
}
// calculate the results with the random weights
printf("0 0 = %f\n",NetworkResult(0,0));
printf("0 1 = %f\n",NetworkResult(0,1));
printf("1 0 = %f\n",NetworkResult(1,0));
printf("1 1 = %f\n",NetworkResult(1,1));
printf("\n");
// Train the net to recognize an xor operation
int i;
for (i=0;i<10000;i++)
{
NNType error=0;
TrainNet(0,0,0,&error); // input 0 0 result 0
TrainNet(0,1,1,&error); // input 0 1 result 1
TrainNet(1,0,1,&error); // input 1 0 result 1
TrainNet(1,1,0,&error); // input 1 1 result 0
if (error<0.0001) break; // exit the training with a low error
}
// calculate the results after the train
printf("After %d iterations\n",i);
printf("0 0 = %f\n",NetworkResult(0,0));
printf("0 1 = %f\n",NetworkResult(0,1));
printf("1 0 = %f\n",NetworkResult(1,0));
printf("1 1 = %f\n",NetworkResult(1,1));
printf("\n");
return 0;
}
Проверьте Каковы различия между «эпохой» и «пакетом» ‘и’ мини-батч ‘?.
В вашем случае ваш ввод случайный. Вы можете разделить тренировочные данные на 2 мини-пакета. Выполните два раза цикл for с массивом ошибок. В вашем основном:
Но TrainNet обновляет веса после каждой выборки, а я хочу обновлять их только 1 раз в конце пакетного цикла. — person Border; 03.10.2020
Можете ли вы определить одну партию? Вы имеете в виду обновление веса после 4 запусков TrainNet? — person Border; 04.10.2020
Хорошо, я решил. Я суммирую все градиенты для каждого веса, а затем использую среднее значение каждого градиента для обновления весов. — person Border; 05.10.2020