Перейти к содержимому
Compvision.ru
Robin Hood

Обучение нейросети

Recommended Posts

Доброго времени суток, Господа.

Меня заинтересовала тема нейронных сетей и я решил почитать литературу по этой теме и поэкспериментировать. Для экспериментов выбрал библиотеку opencv и нашел тестовый пример, в котором на вход сети подается два числа (a,B) в диапазоне [0..100] а на выходе получаем середину отрезка (a+B)/2

Итак, диспозиция:

opencv 2.3.1

IDE - Visual Studio 2010

тип нейронной сети - многослойный перцептрон, два нейрона во входном слое, два скрытых слоя и один нейрон на выходном слое.

метод обучения - метод обратного распространения ошибки

Я написал небольшое консольное приложение (код в конце поста), генерирующее обучающую выборку заданного размера (функция generateTrainData) и далее заданное количество итераций (эпох) обучающее нейронную сеть на этой выборке. После каждого обучения (эпохи) я считаю суммарную ошибку сети - как сумму ошибок в 10 точках (массив quality_array), деленную на количество этих точек. Если Вы посмотрите на лог-файл, который генерирует программа, то увидите, что точность после каждой эпохи может улучшится, а может и ухудшится (строки Train quality ). Например первые две эпохи точность вроде бы улучшалась: была 0.509696, потом стала 0.467227, а потом снова ухудшилась 0.643969.

Вопрос: в чем причина того, что ошибка не уменьшается монотонно, как я предполагал?

Для увеличения точности, я варьировал параметрами самой сети и обучения - увеличил число нейронов в скрытом слое ажно до 100 !!! Увеличивал точность и число итераций при обучении (константы Epsilon и MaxIter). Увеличивал число эпох обучения и размер выборки - но все тщетно: точность не увеличивалась от эпохи к эпохе и ошибка не достигала 3 знака после запятой.

Вопрос: что можно предпринять для увеличения точности?

Лог-файл:


Train quality 0.509696

Train quality 0.467227

Train quality 0.643969

Train quality 0.986835

Train quality 0.718875

Train quality 0.781358

Train quality 0.826931

Train quality 0.855752

Train quality 0.617246

Train quality 0.778907


Predict input	1.000000	        8.000000	        Result	4.738886	        Error	        0.238886

Predict input	2.000000	        14.000000	Result	8.184313	        Error	        0.184313

Predict input	30.000000	40.000000	Result	35.144043	Error 	0.144043

Predict input	50.000000	54.000000	Result	51.961819	Error 	0.038181


Time elapsed 119 sec

Код программы

#include "stdafx.h"

#include "cv.h"

#include "ml.h"

#include <cstdlib> 

#include <iostream> 

#include <stdlib.h>

#include <math.h>


// The neural network

CvANN_MLP machineBrain;

using namespace std;


float td[100000][3];


#define train_sample_count 2000

#define MaxIter 1000000

#define Epsilon 0.0000001

#define Param1 0.1

#define Param2 0.5

#define Epoch 10

#define Range 100


#define quality_test 10

float quality_array[quality_test][2] = {{1,8},	{12,20}, {18,28}, {30,36}, {42,49}

	,	{50,54},{54,60}, {1,80}, {90,30}, {80,90}};


float round_2 (float val) {

	 return floorf(val * 100) / 100;

}


void generateTrainData (float parts, float over, FILE * ftrain) {

	int j = 0;

	for (float p = 0; p < 1.0; p+=parts) {

		for (int i=0;i<train_sample_count*parts;i++,j++)

		{

			td[j][0] = int((rand()/float(RAND_MAX))*(((int)(Range*(parts+over))) + 0.001) + Range*p + 1); //(rand()%((int)(Range*(parts+over)))) + Range*p + 1;

			td[j][1] = int((rand()/float(RAND_MAX))*(((int)(Range*(parts+over))) + 0.001) + Range*p + 1); //(rand()%((int)(Range*(parts+over)))) + Range*p + 1;

			td[j][2] = round_2((td[j][0] + td[j][1]) / 2.0);

			fprintf(ftrain,"%f\t%f\t%f\n",td[j][0],td[j][1],td[j][2]);

		}		

	}

}


void trainMachine(FILE * flog)

{

   int i;


   printf("Found training file with %d samples...\n", train_sample_count);


   //Input data samples. Matrix of order (train_sample_count x 2)

   CvMat* trainData = cvCreateMat(train_sample_count, 2, CV_32FC1);


   //Output data samples. Matrix of order (train_sample_count x 1)

   CvMat* trainClasses = cvCreateMat(train_sample_count, 1, CV_32FC1);


   //The weight of each training data sample. We'll later set all to equal weights.

   CvMat* sampleWts = cvCreateMat(train_sample_count, 1, CV_32FC1);


   CvMat trainData1, trainClasses1, sampleWts1;


   cvGetRows(trainData, &trainData1, 0, train_sample_count);

   cvGetRows(trainClasses, &trainClasses1, 0, train_sample_count);

   cvGetRows(trainClasses, &trainClasses1, 0, train_sample_count);

   cvGetRows(sampleWts, &sampleWts1, 0, train_sample_count);


   //Assemble the ML training data.

   for (i=0; i<train_sample_count; i++)

   {

	   //Input 1

	   cvSetReal2D(&trainData1, i, 0, td[i][0]);

	   //Input 2

	   cvSetReal2D(&trainData1, i, 1, td[i][1]);

	   //Output

	   cvSet1D(&trainClasses1, i, cvScalar(td[i][2]));

	   //Weight (setting everything to 1)

	   cvSet1D(&sampleWts1, i, cvScalar(1));

   }


   //Train it with our data.

   //See the Machine learning reference at http://www.seas.upenn.edu/~bensapp/opencvdocs/ref/opencvref_ml.htm#ch_ann

   machineBrain.train(

	   trainData,

	   trainClasses,

	   sampleWts,

	   0,

	   CvANN_MLP_TrainParams(

		   cvTermCriteria(

			   CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,

			   MaxIter,

			   //! 1.0

			   Epsilon

			   ),

		   CvANN_MLP_TrainParams::BACKPROP,

		   //!0.01,

		   Param1,

		   //!0.05

		   Param2

		   )

	   );


   fprintf(flog,"Settings:\ntrain_sample_count %d MaxIter %d Epsilon %f Param1 %f Param2 %f\n",train_sample_count,MaxIter,Epsilon,Param1,Param2);


}


void createMachine() {

	//The matrix representation of our ANN. We'll have four layers.

	CvMat* neuralLayers = cvCreateMat(4, 1, CV_32SC1);


	CvMat neuralLayers1;

	cvGetRows(neuralLayers, &neuralLayers1, 0, 4);


	cvSet1D(&neuralLayers1, 0, cvScalar(2));

	cvSet1D(&neuralLayers1, 1, cvScalar(100));

	cvSet1D(&neuralLayers1, 2, cvScalar(100));

	cvSet1D(&neuralLayers1, 3, cvScalar(1));

	//Create our ANN.

	machineBrain.create(neuralLayers);


}


// Predict the output with the trained ANN given the two inputs.

float Predict(float data1, float data2,FILE * flog)

{

   float _sample[2];

   CvMat sample = cvMat(1, 2, CV_32FC1, _sample);

   float _predout[1];

   CvMat predout = cvMat(1, 1, CV_32FC1, _predout);

   sample.data.fl[0] = data1;

   sample.data.fl[1] = data2;


   machineBrain.predict(&sample, &predout);


   if (flog != NULL) {

		fprintf(flog,"Predict input\t%f\t%f\tResult\t%f\tError\t%f\n",data1,data2,predout.data.fl[0],abs(abs((data2+data1)/2.0)-abs(predout.data.fl[0])));

   }

   return predout.data.fl[0];

}


float train_quality (FILE * flog) {

	float a,b,summary_error;

	summary_error=0;

	for (int i = 0 ; i < quality_test; i++) {

			a = quality_array[i][0];//int((rand()/float(RAND_MAX))*((int)(Range + 0.001))) + 1; //(rand()%((int)(Range*(parts+over)))) + Range*p + 1;

			b = quality_array[i][1];//int((rand()/float(RAND_MAX))*((int)(Range + 0.001))) + 1; //(rand()%((int)(Range*(parts+over)))) + Range*p + 1;

			summary_error += abs(abs((a +  / 2.0)-abs(Predict(a,b,NULL)));

	}

	fprintf(flog,"%f\t%f\t%f\tPredict (a, %f\tTrain quality %f\n",a,b,summary_error,Predict(a,b,NULL),summary_error/quality_test );

	return summary_error/quality_test;

}


int _tmain(int argc, _TCHAR* argv[])

{

	  time_t seconds;


  seconds = time (NULL);

FILE * flog;

FILE * ftrain;

   ftrain= fopen("C:\\train_data.txt", "a+");

   fprintf(ftrain,"\nNext training set:\n");


   flog = fopen("C:\\train_log.txt", "a+");


  time_t rawtime;

  struct tm * timeinfo;

  float quality=10000;

  time ( &rawtime );

  timeinfo = localtime ( &rawtime );


   fprintf(flog,"\nPredict transaction, date %s \n",asctime (timeinfo) );


	srand((unsigned)time(0));

   int wait;



   createMachine();

   generateTrainData (0.1,0.05,ftrain);

   // Train the neural network  with the samples

   for (int i = 0; i < Epoch; i++) {

		trainMachine(flog);

		quality = train_quality(flog);

   }


   machineBrain.save("C:\\savednet.txt");

   //machineBrain.load("C:\\savednet.txt");


   Predict(1.0,8.0,flog);

   Predict(2.0,14.0,flog);

   Predict(30.0,40.0,flog);

   Predict(50.0,54.0,flog);

   Predict(50.0,54.0,flog);


   seconds = time (NULL) - seconds;


   fprintf(flog,"\nTime elapsed %ld sec",seconds );

   fflush(flog);

   fclose(flog);

   //I'll wait for an integer. 

   scanf("%d",&wait);

   fclose(ftrain);

   return 0;

}


[/code]

Заранее благодарен за Ваши ответы!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Устойчивость обучения нейронной сети зависит, в основном от параметра скорости обучения (обычно обозначают альфой).

Для Вашей задачи хватит и ОДНОГО нейрона, что весьма удобно для экспериментов.

Обученный для Вашего случая нейрон:

post-1-0-52688700-1325610501_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо за Ваш ответ,

если я правильно понимаю, то у структуры cvTermCriteria член Param1 как раз и отвечает за скорость обучения - в документации написано:

bp_dw_scale (задается через Param1) -

(Backpropagation only): The coefficient to multiply the computed weight gradient by. The recommended value is about 0.1 . The parameter can be set via param1 of the constructor. Я так понимаю - это и есть альфа.

bp_moment_scale (задается через Param2) -

(Backpropagation only): The coefficient to multiply the difference between weights on the 2 previous iterations. This parameter provides some inertia to smooth the random fluctuations of the weights. It can vary from 0 (the feature is disabled) to 1 and beyond. The value 0.1 or so is good enough. The parameter can be set via param2 of the constructor. А вот что это такое - не совсем ясно.

Понятие устойчивости обучения ИНС связано с проблемой переобучения сети?

Я нашел интересную фразу: "Переобучение (для нейронных сетей). При итерационном обучении - чрезмерно точная подгонка, которая начинает иметь место, если алгоритм обучения работает слишком долго (а сеть слишком сложна для такой задачи или для имеющегося объема данных)."

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

Может ли быть дело в начальных весах? Они у меня все инициализированы единицей, а кое-где пишут, что их нужно инициализировать малыми случайными величинами...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Веса нужно инициализировать именно случайными величинами, дело может быть и в этом.

И еще, обучение нейросети аналогично решению переопределенной, в общем случае, системы линейных уравнений. Веса сети можно рассчитать решив систему методом поиска приближенных решений, например SVD.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Отлично, я нашел в чем была моя проблема - нужно было указать параметр UPDATE_WEIGHTS начиная со второй эпохи обучения, иначе ИНС каждый раз пересчитывает веса заново. Теперь если посмотреть на лог-файл - видно, что ошибка последовательно уменьшается с каждой эпохой с 0.626248 до 0.188037, далее мы видимо "проскакиваем" минимум и ошибка начинает снова скакать (начиная со значения выделенного стрелкой). Правда она скачет не сильно и в вполне приемлемых пределах...

Я нашел о какой альфе Вы мне говорили - я так понимаю, что речь о параметре функции активации?

Сигма:

post-4922-0-50328900-1325694737_thumb.pn

Формула:

post-4922-0-61688500-1325694751_thumb.pn

Варьируя эту альфу и бетту от 0.0 по умолчанию, до 7.0 я добился того, что ошибка сильно уменьшилась. Однако она все равно не падает ниже 0.05 (при альфа=7.0 и бетта=0.05). Для этой конкретной задачи такой точности более чем достаточно, но вопрос в другом:

Каким образом я могу регулировать точность (допустим жертвуя временем обучения)? Есть ли некий "предел" точности ИНС, выше которого точность уже не получить (возможно ли свести ошибку на обучающей выборке вообще к нулю и имеет ли это смысл?)


Predict transaction, date Wed Jan 04 19:22:14 2012


80.000000    90.000000    6.262481    Predict (a, 85.221535    Train quality 0.626248

80.000000    90.000000    4.949169    Predict (a, 85.218071    Train quality 0.494917

80.000000    90.000000    4.184603    Predict (a, 85.130402    Train quality 0.418460

80.000000    90.000000    3.531571    Predict (a, 85.161407    Train quality 0.353157

80.000000    90.000000    3.379418    Predict (a, 85.138649    Train quality 0.337942

80.000000    90.000000    2.664121    Predict (a, 85.069229    Train quality 0.266412

80.000000    90.000000    2.444851    Predict (a, 85.067818    Train quality 0.244485

80.000000    90.000000    2.250171    Predict (a, 85.066582    Train quality 0.225017

80.000000    90.000000    2.157671    Predict (a, 85.083549    Train quality 0.215767

80.000000    90.000000    1.880372    Predict (a, 84.985764    Train quality 0.188037  <---------

80.000000    90.000000    1.892758    Predict (a, 85.055656    Train quality 0.189276

80.000000    90.000000    1.683270    Predict (a, 85.005287    Train quality 0.168327

80.000000    90.000000    1.555419    Predict (a, 84.947639    Train quality 0.155542

80.000000    90.000000    1.466363    Predict (a, 84.989815    Train quality 0.146636

80.000000    90.000000    1.410999    Predict (a, 84.983231    Train quality 0.141100

80.000000    90.000000    1.395071    Predict (a, 84.949280    Train quality 0.139507

80.000000    90.000000    1.636884    Predict (a, 85.020828    Train quality 0.163688

80.000000    90.000000    1.522165    Predict (a, 84.912651    Train quality 0.152216

80.000000    90.000000    1.677424    Predict (a, 84.991425    Train quality 0.167742

80.000000    90.000000    1.682278    Predict (a, 84.931664    Train quality 0.168228

80.000000    90.000000    1.823288    Predict (a, 84.987816    Train quality 0.182329

80.000000    90.000000    1.841351    Predict (a, 84.911789    Train quality 0.184135

80.000000    90.000000    1.889462    Predict (a, 84.969589    Train quality 0.188946

80.000000    90.000000    1.867035    Predict (a, 84.996300    Train quality 0.186703

80.000000    90.000000    1.928409    Predict (a, 84.941795    Train quality 0.192841

80.000000    90.000000    1.994905    Predict (a, 84.947372    Train quality 0.199490

80.000000    90.000000    1.951897    Predict (a, 84.904999    Train quality 0.195190

80.000000    90.000000    2.027108    Predict (a, 84.918060    Train quality 0.202711

80.000000    90.000000    2.059041    Predict (a, 84.927536    Train quality 0.205904

80.000000    90.000000    2.131978    Predict (a, 84.929909    Train quality 0.213198

80.000000    90.000000    2.104108    Predict (a, 84.925797    Train quality 0.210411

80.000000    90.000000    2.165461    Predict (a, 84.947586    Train quality 0.216546

80.000000    90.000000    2.099828    Predict (a, 84.894402    Train quality 0.209983

80.000000    90.000000    2.198324    Predict (a, 84.971550    Train quality 0.219832

80.000000    90.000000    2.122487    Predict (a, 84.933182    Train quality 0.212249

80.000000    90.000000    2.130229    Predict (a, 84.910973    Train quality 0.213023

80.000000    90.000000    2.204371    Predict (a, 84.903511    Train quality 0.220437

80.000000    90.000000    2.150970    Predict (a, 84.919106    Train quality 0.215097

80.000000    90.000000    2.194093    Predict (a, 84.956841    Train quality 0.219409

80.000000    90.000000    2.171475    Predict (a, 84.906990    Train quality 0.217147

80.000000    90.000000    2.263687    Predict (a, 84.948997    Train quality 0.226369

80.000000    90.000000    2.234221    Predict (a, 84.948563    Train quality 0.223422

80.000000    90.000000    2.267097    Predict (a, 84.984558    Train quality 0.226710

80.000000    90.000000    2.205862    Predict (a, 84.888870    Train quality 0.220586

80.000000    90.000000    2.236631    Predict (a, 84.938507    Train quality 0.223663

80.000000    90.000000    2.232929    Predict (a, 84.998695    Train quality 0.223293

80.000000    90.000000    2.145130    Predict (a, 84.865524    Train quality 0.214513

80.000000    90.000000    2.432119    Predict (a, 85.049431    Train quality 0.243212

80.000000    90.000000    2.229727    Predict (a, 84.944740    Train quality 0.222973

80.000000    90.000000    2.201638    Predict (a, 84.878754    Train quality 0.220164


Predict input    1.000000    8.000000    Result    4.984049    Error    0.484049

Predict input    2.000000    14.000000    Result    8.245624    Error    0.245624

Predict input    30.000000    40.000000    Result    34.734020    Error    0.265980

Predict input    50.000000    54.000000    Result    52.026516    Error    0.026516

Predict input    50.000000    54.000000    Result    52.026516    Error    0.026516


Time elapsed 1 sec

[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

abs(abs((a + B) / 2.0)-abs(Predict(a,b,NULL))[/code]

Не находите что здесь fabs должно быть? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо, поменял, правда ничего не изменилось...

Так все же, есть ли идеи по поводу:

Каким образом я могу регулировать точность (допустим жертвуя временем обучения)? Есть ли некий "предел" точности ИНС, выше которого точность уже не получить (возможно ли свести ошибку на обучающей выборке вообще к нулю и имеет ли это смысл?)

Может я не четко формулирую вопрос, или может Вы знаете где можно почитать более углубленную информацию по ИНС (не обзоры и статьи типа смотри-как-круто, а что то типа "учебника") ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ищите книгу

Хайкин Нейронные сети. Полный курс.

Лучшая на мой взгляд книга по НС.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×