Advertisement
TShiva

Neuron_Network

Mar 5th, 2018
1,329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <windows.h>
  2. #include <math.h>
  3. #include <random>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <sstream>
  7. #include <vector>
  8. #include <cmath>
  9. #include <ctime>
  10. using namespace std;
  11.  
  12. #define Pi 3.14
  13.  
  14. #define isFunction 1 // выбор функции, 1 = cos(2*pi*x), 2 = pow(x,3)*5.0+pow(x,2)+5.0, 3 = sin(2*pi*x)*x
  15.  
  16. double coef_x;
  17. double coef_y;
  18.  
  19. int points = 10;//кол-во нейронов во внутреннем слое
  20.  
  21.  
  22. double mis;
  23. //int present = 10;
  24. double mistake = 0.25;// модуль максимального значения ошибки
  25. int typeOfError = 1;//тип ошибки: равномерная =1  или нормальная =2.
  26.  
  27. double step = 0.0005;//шаг
  28. double currentError = 0.;
  29.  
  30. std::mt19937 gen(time(0));
  31. std::uniform_real_distribution<> uid(0, 1);
  32.  
  33. inline double tan(double x)//функция активации
  34. {
  35.     return tanh(x*3.5);
  36. }
  37.  
  38. inline double diff(double x)//тупо производная гиперболического тангенса через формулу тейлора
  39. {
  40.     return 3.5*(1 - pow(x ,2)+2*pow(x,4)/3);
  41. }
  42.  
  43. inline double cosinus(double x) {
  44.     return cos(2 * Pi*x / coef_x);
  45. }
  46. inline double cube(double x) {//не подогнал
  47.     double cock = pow(x / coef_x, 3)*5.0 + pow(x / coef_x, 2) + 5.0 / coef_x;
  48.     return cock;
  49. }
  50. inline double sinus(double x) {
  51.     double cock = sin(2.0 * Pi*x / coef_x)*x / coef_x;
  52.     return cock;
  53. }
  54.  
  55. double WhatTheFunction(int f, double coef_y, int i)
  56. {
  57.     if (f == 1)
  58.         return coef_y * cosinus(i);
  59.     if (f == 2)
  60.         return coef_y * cube(i);
  61.     if (f == 3)
  62.         return coef_y * sinus(i);
  63. }
  64.  
  65. double NormalErr(double mistake) {
  66.     double ksi = 0, randomNumber;
  67.     for (int i = 0; i< 12; i++) {
  68.         randomNumber = uid(gen);
  69.         ksi += randomNumber;//сумма 12 случайно распределённых числел
  70.     }
  71.     double etha = ksi - 6;//Etha принадлежит отрезку от 0 до 1
  72.     randomNumber = uid(gen);
  73.     double randomValue = mistake * (2 * randomNumber - 1);
  74.     return etha * randomValue;
  75. }
  76.  
  77. LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  78. {
  79.     static int cxClient, cyClient;
  80.     HDC hdc;
  81.     PAINTSTRUCT ps;
  82.     HPEN hPen, hPenOld;
  83.     HBRUSH hBrush, hBrushOld;
  84.  
  85.     switch (iMsg)
  86.     {
  87.  
  88.     case WM_CREATE:
  89.         break;
  90.  
  91.     case WM_SIZE:
  92.         cxClient = LOWORD(lParam);//ширина
  93.         cyClient = HIWORD(lParam);//высота
  94.         break;
  95.  
  96.     case WM_PAINT:
  97.     {
  98.    
  99.         double *xx = new double[points];
  100.         double *yy = new double[points];
  101.         double *tt = new double[points];
  102.  
  103.         hdc = BeginPaint(hwnd, &ps);//начало рисования
  104.  
  105.         SetMapMode(hdc, MM_ISOTROPIC);// режим рисования с единообразными осями
  106.         SetWindowExtEx(hdc, cxClient, cyClient, 0);//установили размеры
  107.         SetViewportExtEx(hdc, cxClient / 2, -cyClient / 2, 0);
  108.         SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, 0);
  109.  
  110.         MoveToEx(hdc, -cxClient, 0, nullptr);//переместили курсор
  111.         LineTo(hdc, cxClient, 0);//нарисовали одну ось
  112.         MoveToEx(hdc, 0, -cyClient, nullptr);
  113.         LineTo(hdc, 0, cyClient);//нарисовали другую
  114.  
  115.  
  116.         hPen = CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
  117.         SelectObject(hdc, hPen);
  118.  
  119.         coef_x = cxClient;
  120.         coef_y = cyClient/ 2;
  121.  
  122.         MoveToEx(hdc, -cxClient, static_cast<int>(WhatTheFunction(isFunction, coef_y, -coef_x)), nullptr);//устанавливаем начальную позицию
  123.  
  124.         for (int i = -cxClient; i < cxClient; i++)//рисуем график функции
  125.         {
  126.             double y = static_cast<int>(WhatTheFunction(isFunction, coef_y, i));
  127.             LineTo(hdc, i, (int)y);
  128.         }
  129.  
  130.         for (int i = 0; i < points; i++)
  131.         {
  132.             // вычисление равномерного распределённого вектора X
  133.             //генерируем точки для метода
  134.             xx[i] = uid(gen)*coef_x * 2 - coef_x;// генерация элемента выборки, из отрезка [0,1] -> [-cxClient,cxClient]
  135.             yy[i] = WhatTheFunction(isFunction, coef_y, xx[i]);
  136.  
  137.             //находим t[i] в зависимости от вида распределения ошибки
  138.             if (typeOfError == 1)//имеет равномерное распределение
  139.             {
  140.                 currentError = uid(gen) * 2 * mistake*coef_y - mistake * coef_y;
  141.                 //домножение на коэффициент (coef_y) оправдано
  142.                 tt[i] = yy[i] + currentError;
  143.             }
  144.             if (typeOfError == 2)//имеет нормальное распределение
  145.             {
  146.                 currentError = NormalErr(mistake*coef_y);
  147.                 tt[i] = yy[i] + currentError;
  148.             }
  149.  
  150.             hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 255));
  151.             hPenOld = (HPEN)SelectObject(hdc, hPen);
  152.             hBrush = CreateSolidBrush(RGB(0, 0, 255));
  153.             hBrushOld = (HBRUSH)SelectObject(hdc, hBrush);
  154.             Ellipse(hdc, xx[i] - 5, tt[i] - 5, xx[i] + 5, tt[i] + 5);
  155.  
  156.                                                                                                                                                                                                                                             xx[i] /= coef_x;
  157.                                                                                                                                                                                                                                             yy[i] /= coef_y;
  158.                                                                                                                                                                                                                                             tt[i] /= coef_y;
  159.             SelectObject(hdc, hBrushOld);
  160.             DeleteObject(hBrush);
  161.  
  162.             SelectObject(hdc, hPenOld);
  163.             DeleteObject(hPen);
  164.         }
  165.        
  166.         for (int t = 0; t < 100; t++)//эпохи
  167.         {
  168.             double* v = new double[points];         //веса для дуг от входного нейрона
  169.             double* w = new double[points];         //веса для дуг к выходному нейрону
  170.             double* v0 = new double[points];        //веса нейронов смещения
  171.             double* z = new double[points];     //хранение промежуточных значений
  172.             double* a = new double[points];
  173.  
  174.             double* delta_v = new double[points];   //ошибки для соответствующих дуг
  175.             double* delta_w = new double[points];
  176.             double* delta_v0 = new double[points];
  177.             double w0;                              //нейрон смещения для выхода
  178.             double delta;                           //ошибка - градиент?
  179.             double f;                               //выходное значение
  180.  
  181.             for (int i = 0; i < points; i++)
  182.             {
  183.                 v[i] = uid(gen)* 2 - 1;
  184.                 w[i] = uid(gen) * 2 - 1;//назначения весов дуг графа случайными значениями
  185.                 v0[i] = uid(gen) * 2 - 1;
  186.             }
  187.             w0 = uid(gen) * 2 - 1;
  188.  
  189.             for (int u = 0; u < 10000; u++)//итерации для тренировки
  190.             {
  191.  
  192.                 //прямое распространение, ищем a[i] и z[i] для внутреннего и последнего слоя
  193.                 for (int h = 0; h < points; h++)//для каждого элемента выборки, их не обязательно должно быть столько же, сколько нейронов, просто я так реализовал это
  194.                 {
  195.                     for (int i = 0; i < points; i++)
  196.                     {
  197.                         a[i] = xx[h] * v[i] + v0[i];//преобразование задаваемое нейронной сетью
  198.                         z[i] = tan(a[i]);//функция активации
  199.                     }
  200.  
  201.                     f = 0;
  202.                     for (int i = 0; i < points; i++)
  203.                         f += w[i] * z[i];//суммируем значения в выходном нейроне
  204.                     f += w0;
  205.                     f = tan(f);
  206.  
  207.                     //обратное распространение
  208.                     delta = (f - tt[h])*diff(f);// вычисление градиента функции ошибки
  209.  
  210.                     w0 -= step   * delta;//меняем дугу для выходного нейрона смещения
  211.                     for (int i = 0; i < points; i++)
  212.                     {
  213.                         delta_w[i] = -step * delta*z[i];//считаем дельты для весов дуг между выходом и внутренним слоем
  214.                         delta_v[i] = -step * delta*w[i] * xx[h] * diff(z[i]);//между входом и внутренним слоем
  215.                         delta_v0[i] = -step * delta*w[i] * diff(z[i]);//для нейронов смещения
  216.                     }
  217.  
  218.                     for (int i = 0; i < points; i++)
  219.                     {
  220.                         v[i] += delta_v[i];//изменение весов дуг
  221.                         w[i] += delta_w[i];
  222.                         v0[i] += delta_v0[i];
  223.                     }
  224.                 }
  225.             }
  226.  
  227.             f = w0;
  228.             for (int i = 0; i < points; i++)
  229.             {
  230.                 a[i] = (-coef_x)*v[i] + v0[i];
  231.                 z[i] = tan(a[i]);
  232.             }
  233.             for (int i = 0; i < points; i++)
  234.                 f += z[i] * w[i];
  235.             f = tan(f);
  236.             f *= coef_y;//поправка для отрисовки
  237.  
  238.             MoveToEx(hdc, -coef_x, f, NULL);
  239.  
  240.  
  241.             hPen = CreatePen(PS_SOLID, 0, RGB(30, 225, 0));
  242.             SelectObject(hdc, hPen);
  243.  
  244.             for (int j = -coef_x; j <= coef_x; j++)//отрисовка
  245.             {
  246.                 f = w0;
  247.                 for (int i = 0; i < points; i++)
  248.                 {
  249.                     a[i] = (j / coef_x)*v[i] + v0[i];
  250.                     z[i] = tan(a[i]);
  251.                 }
  252.                 for (int i = 0; i < points; i++)
  253.                     f += z[i] * w[i];
  254.                 f = tan(f);
  255.                 f *= coef_y;
  256.                 LineTo(hdc, j, (int)f);
  257.             }
  258.         }
  259.         return 0;
  260.     }
  261.     case WM_DESTROY:
  262.         PostQuitMessage(0);
  263.         return 0;
  264.     }
  265.     return DefWindowProc(hwnd, iMsg, wParam, lParam);
  266. }
  267.  
  268. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  269.     PSTR szCmdLine, int iCmdShow)
  270. {
  271.     static TCHAR szAppName[] = TEXT("SineWave");
  272.     HWND hwnd;
  273.     MSG msg;
  274.  
  275.     WNDCLASSEX wndclass;
  276.     wndclass.cbSize = sizeof(wndclass);
  277.     wndclass.style = CS_HREDRAW | CS_VREDRAW;
  278.     wndclass.lpfnWndProc = WndProc;
  279.     wndclass.cbClsExtra = 0;
  280.     wndclass.cbWndExtra = 0;
  281.     wndclass.hInstance = hInstance;
  282.     wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
  283.     wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);
  284.     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  285.     wndclass.lpszMenuName = TEXT("MYMENU");
  286.     wndclass.lpszClassName = (szAppName);
  287.     wndclass.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
  288.     RegisterClassEx(&wndclass);
  289.     hwnd = CreateWindow(szAppName, TEXT("Нейронная сеть"),
  290.         WS_OVERLAPPEDWINDOW,
  291.         CW_USEDEFAULT, CW_USEDEFAULT,
  292.         1000, 750,
  293.         nullptr, nullptr, hInstance, nullptr);
  294.     ShowWindow(hwnd, iCmdShow);
  295.     UpdateWindow(hwnd);
  296.     while (GetMessage(&msg, nullptr, 0, 0))
  297.     {
  298.         TranslateMessage(&msg);
  299.         DispatchMessage(&msg);
  300.     }
  301.     return msg.wParam;
  302. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement