Guest User

Untitled

a guest
Feb 28th, 2016
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.38 KB | None | 0 0
  1.  
  2. #ifndef BRAIN_H
  3. #define BRAIN_H
  4. // #pragma once
  5.  
  6. #include <vector>
  7. #include <cmath>
  8. using namespace std;
  9.  
  10. #define nn_eta 0.15 // learning rate
  11. #define nn_alpha 0.5 // momentum
  12. #define nn_weight_size 0.1 // random weight size multiplier
  13.  
  14. namespace nn
  15. {
  16. namespace nt
  17. {
  18. enum
  19. {
  20. hidden = 1,
  21. input,
  22. output,
  23. bias,
  24. memory,
  25. };
  26. }
  27.  
  28. class neuron;
  29.  
  30. // neuron(output) ---> axon(weight) ---> target neuron( sum += output * weight )
  31. class axon
  32. {
  33. public:
  34. neuron *target;
  35. virtual double GetWeight() = 0;
  36. virtual double GetDetla() = 0;
  37. virtual void SetWeight(double NewWeight) = 0;
  38. virtual void SetDelta(double NewDelta) = 0;
  39. virtual bool IsMem() = 0; // memory axon doesn't need weight or delta, only a target neuron what is always memory neuron.
  40.  
  41. axon(neuron * Target) {
  42. target = Target;
  43. }
  44. virtual ~axon() = default;
  45. };
  46.  
  47. class normal_axon : public axon
  48. {
  49. public:
  50. double weight;
  51. double delta;
  52. double GetWeight() { return weight; }
  53. double GetDetla() { return delta; }
  54. void SetWeight(double NewWeight) { weight = NewWeight; }
  55. void SetDelta(double NewDelta){ delta = NewDelta; }
  56. bool IsMem() { return false; }
  57. normal_axon(neuron * Target) : axon(Target) {
  58. this->SetWeight(((double)rand() / double(RAND_MAX)) * nn_weight_size);
  59. this->SetDelta(0.0);
  60. };
  61. };
  62.  
  63. class memory_axon : public axon
  64. {
  65. public:
  66. double GetWeight() { return 0.0; }
  67. double GetDetla() { return 0.0; }
  68. void SetWeight(double NewWeight) { }
  69. void SetDelta(double NewDelta) { }
  70. bool IsMem() { return true; }
  71. memory_axon(neuron * Target) : axon(Target) {};
  72. };
  73.  
  74. class neuron {
  75. public:
  76.  
  77. virtual ~neuron() = default;
  78.  
  79. virtual double GetOutput() = 0;
  80. virtual void setOutput(double NewOutput) = 0;
  81. virtual double GetGradient() = 0;
  82. virtual void SetGradient(double NewGradient) = 0;
  83. virtual void SetTarget(double NewTarget) = 0;
  84. virtual double GetTarget() = 0;
  85. virtual bool HaveMemoryNeuron() = 0;
  86. virtual neuron *GetMemoryNeuron() = 0;
  87. virtual void PrintType() = 0;
  88. virtual int GetType() = 0;
  89. virtual void UpdateWeights() = 0;
  90. virtual void CalculateGradient() = 0;
  91. virtual void Activate() = 0;
  92. virtual void MemorizeOutput( double output ) = 0;
  93. virtual void Fire(double signal) = 0;
  94. virtual vector<axon *> GetAxons() = 0;
  95. virtual void AddConnection(neuron *Target) = 0;
  96. virtual bool CanBeConnected() = 0;
  97. };
  98.  
  99. class ninput : public neuron {
  100. public:
  101.  
  102. // output is the value it feeds to other neurons, since it input neuron it gets its output value from outside world, training data for example.
  103. double output;
  104.  
  105. // connections to other neurons
  106. vector<axon *> axons;
  107.  
  108. double GetOutput() { return this->output; }
  109. void setOutput(double NewOutput)
  110. {
  111. this->MemorizeOutput(this->output); // In case this neuron is connected to memory neuron, lets have that memory neuron remember the old output value
  112. this->output = NewOutput;
  113. }
  114. double GetGradient() { return 0.0; }
  115. void SetGradient(double NewGradient) {}
  116. void SetTarget(double NewTarget) {}
  117. double GetTarget() { return 0.0; }
  118. bool HaveMemoryNeuron() { if (this->axons.size() && this->axons[0]->IsMem()) return true; return false; }
  119. neuron *GetMemoryNeuron() { if (this->HaveMemoryNeuron()) return this->axons[0]->target; return 0; }
  120. void PrintType() { cout << "Input"; }
  121. int GetType() { return nt::input; }
  122.  
  123. void UpdateWeights() {
  124. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  125. this->axons[a]->SetDelta(nn_eta * this->output * this->axons[a]->target->GetGradient() + this->axons[a]->GetDetla() * nn_alpha);
  126. this->axons[a]->SetWeight(this->axons[a]->GetWeight() + this->axons[a]->GetDetla());
  127. }
  128. }
  129.  
  130. void CalculateGradient() {}
  131. void Activate() {
  132. // Lets loop this neuron all connections and fire our neuron's (output * current connection weight) to another neuron
  133. // If we have memory axon then ignore it. Its function isin't fire neuron. it's just a pointer to memory neuron
  134. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++)
  135. {
  136. this->axons[a]->target->Fire( this->output * this->axons[a]->GetWeight() );
  137. }
  138. // since input neuron doesn't use activation function, we're done here
  139. }
  140. void MemorizeOutput(double output) {
  141. if (this->HaveMemoryNeuron()) this->GetMemoryNeuron()->setOutput(output);
  142. }
  143.  
  144. bool CanBeConnected() { return false; }
  145.  
  146. void Fire(double signal) {}
  147. vector<axon *> GetAxons() { return this->axons; }
  148.  
  149. void AddConnection( neuron *Target ) {
  150. if (Target->GetType() == nt::memory) {
  151. if (this->HaveMemoryNeuron()) return;
  152.  
  153. // Insert memory axon as first so it would be easier to find it later on
  154. this->axons.insert(this->axons.begin(), new memory_axon(Target));
  155. }
  156. else
  157. {
  158. if (!Target->CanBeConnected()) return;
  159. this->axons.push_back(new normal_axon(Target));
  160. }
  161. }
  162.  
  163. ninput() {
  164. output = 0.0;
  165. }
  166.  
  167. ~ninput() {
  168. output = 0.0;
  169. }
  170. };
  171.  
  172. class nhidden : public neuron {
  173. public:
  174. double output;
  175. double gradient;
  176. double sum;
  177. vector<axon *> axons;
  178.  
  179. double GetOutput() { return this->output; }
  180. void setOutput(double NewOutput)
  181. {
  182. this->MemorizeOutput(this->output);
  183. this->output = NewOutput;
  184. }
  185. double GetGradient() { return this->gradient; }
  186. void SetGradient(double NewGradient) { this->gradient = NewGradient; }
  187. void SetTarget(double NewTarget) {}
  188. double GetTarget() { return 0.0; }
  189. bool HaveMemoryNeuron() { if (this->axons.size() && this->axons[0]->IsMem()) return true; return false; }
  190. neuron *GetMemoryNeuron() { if (this->HaveMemoryNeuron()) return this->axons[0]->target; return 0; }
  191. void PrintType() { cout << "hidden"; }
  192. int GetType() { return nt::hidden; }
  193.  
  194. void UpdateWeights() {
  195. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  196. this->axons[a]->SetDelta( nn_eta * this->output * this->axons[a]->target->GetGradient() + this->axons[a]->GetDetla() * nn_alpha);
  197. this->axons[a]->SetWeight(this->axons[a]->GetWeight() + this->axons[a]->GetDetla());
  198. }
  199. }
  200.  
  201. void CalculateGradient() {
  202. double Gsum = 0.0;
  203. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  204. Gsum += this->axons[a]->GetWeight() * this->axons[a]->target->GetGradient();
  205. }
  206. this->gradient = Gsum * (1.0 - this->output * this->output);
  207. }
  208.  
  209. void Activate() {
  210. this->setOutput(tanh(this->sum));
  211. this->sum = 0;
  212. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  213. this->axons[a]->target->Fire(this->output * this->axons[a]->GetWeight());
  214. }
  215. }
  216. void MemorizeOutput(double output) {
  217. if (this->HaveMemoryNeuron()) this->GetMemoryNeuron()->setOutput(output);
  218. }
  219.  
  220. bool CanBeConnected() { return true; }
  221.  
  222. void Fire(double signal) {
  223. this->sum += signal;
  224. }
  225. vector<axon *> GetAxons() { return this->axons; }
  226.  
  227. void AddConnection(neuron *Target) {
  228. if (Target->GetType() == nt::memory) {
  229. if (this->HaveMemoryNeuron()) return;
  230.  
  231. this->axons.insert(this->axons.begin(), new memory_axon(Target));
  232. }
  233. else
  234. {
  235. if (!Target->CanBeConnected()) return;
  236. this->axons.push_back(new normal_axon(Target));
  237. }
  238. }
  239.  
  240. nhidden() {
  241. output = 0.0;
  242. gradient = 0.0;
  243. sum = 0.0;
  244. }
  245.  
  246. ~nhidden() {
  247. }
  248. };
  249.  
  250.  
  251. class nbias : public neuron {
  252. public:
  253. vector<axon *> axons;
  254.  
  255. double GetOutput() { return 1.0; }
  256. void setOutput(double NewOutput) { }
  257. double GetGradient() { return 0.0; }
  258. void SetGradient(double NewGradient) { }
  259. void SetTarget(double NewTarget) {}
  260. double GetTarget() { return 1.0; }
  261. bool HaveMemoryNeuron() { return false; }
  262. neuron *GetMemoryNeuron() { return 0; }
  263. void PrintType() { cout << "bias"; }
  264. int GetType() { return nt::bias; }
  265.  
  266. void UpdateWeights() {
  267. for (int a = 0; a < this->axons.size(); a++) {
  268. this->axons[a]->SetDelta(nn_eta * this->axons[a]->target->GetGradient() + this->axons[a]->GetDetla() * nn_alpha);
  269. this->axons[a]->SetWeight(this->axons[a]->GetWeight() + this->axons[a]->GetDetla());
  270. }
  271. }
  272.  
  273. void CalculateGradient() { } // bias doesn't need gradient right?
  274.  
  275. void Activate() {
  276. for (int a = 0; a < this->axons.size(); a++) {
  277. this->axons[a]->target->Fire(this->axons[a]->GetWeight());
  278. }
  279. }
  280. void MemorizeOutput(double output) { }
  281.  
  282. bool CanBeConnected() { return false; }
  283.  
  284. void Fire(double signal) { }
  285. vector<axon *> GetAxons() { return this->axons; }
  286.  
  287. void AddConnection(neuron *Target) {
  288. if (Target->GetType() != nt::memory) {
  289. if (!Target->CanBeConnected()) return;
  290. this->axons.push_back(new normal_axon(Target));
  291. }
  292. }
  293.  
  294. nbias() {
  295. }
  296.  
  297. ~nbias() {
  298. }
  299. };
  300.  
  301. class nmemory : public neuron {
  302. public:
  303. double output;
  304. vector<axon *> axons;
  305.  
  306. double GetOutput() { return this->output; }
  307. void setOutput(double NewOutput)
  308. {
  309. this->MemorizeOutput(this->output);
  310. this->output = NewOutput;
  311. }
  312. double GetGradient() { return 0.0; }
  313. void SetGradient(double NewGradient) { }
  314. void SetTarget(double NewTarget) {}
  315. double GetTarget() { return 0.0; }
  316. bool HaveMemoryNeuron() { if (this->axons.size() && this->axons[0]->IsMem()) return true; return false; }
  317. neuron *GetMemoryNeuron() { if (this->HaveMemoryNeuron()) return this->axons[0]->target; return 0; }
  318. void PrintType() { cout << "memory"; }
  319. int GetType() { return nt::memory; }
  320.  
  321. void UpdateWeights() {
  322. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  323. this->axons[a]->SetDelta(nn_eta * this->output * this->axons[a]->target->GetGradient() + this->axons[a]->GetDetla() * nn_alpha);
  324. this->axons[a]->SetWeight(this->axons[a]->GetWeight() + this->axons[a]->GetDetla());
  325. }
  326. }
  327.  
  328. void CalculateGradient() { }
  329.  
  330. void Activate() {
  331. for (int a = this->HaveMemoryNeuron() == true ? 1 : 0; a < this->axons.size(); a++) {
  332. this->axons[a]->target->Fire(this->output * this->axons[a]->GetWeight());
  333. }
  334. }
  335. void MemorizeOutput(double output) {
  336. if (this->HaveMemoryNeuron()) this->GetMemoryNeuron()->setOutput(output);
  337. }
  338.  
  339. bool CanBeConnected() { return true; }
  340.  
  341. void Fire(double signal) {}
  342. vector<axon *> GetAxons() { return this->axons; }
  343.  
  344. void AddConnection(neuron *Target) {
  345. if (Target->GetType() == nt::memory) {
  346. if (this->HaveMemoryNeuron()) return;
  347. this->axons.insert(this->axons.begin(), new memory_axon(Target));
  348. }
  349. else
  350. {
  351. if (!Target->CanBeConnected()) return;
  352. this->axons.push_back(new normal_axon(Target));
  353. }
  354. }
  355.  
  356. nmemory() {
  357. output = 0.0;
  358. }
  359.  
  360. ~nmemory() {
  361. }
  362. };
  363.  
  364. class noutput : public neuron {
  365. public:
  366. double output;
  367. double target;
  368. double gradient;
  369. double sum;
  370. vector<axon *> axons;
  371.  
  372. double GetOutput() { return this->output; }
  373. void setOutput(double NewOutput) { this->output = NewOutput; }
  374. double GetGradient() { return this->gradient; }
  375. void SetGradient(double NewGradient) { this->gradient = NewGradient; }
  376. void SetTarget(double NewTarget)
  377. {
  378. this->MemorizeOutput(this->target);
  379. this->target = NewTarget;
  380. }
  381. double GetTarget() { return this->target; }
  382. bool HaveMemoryNeuron() { if (this->axons.size() && this->axons[0]->IsMem()) return true; return false; }
  383. neuron *GetMemoryNeuron() { if (this->HaveMemoryNeuron()) return this->axons[0]->target; return 0; }
  384. void PrintType() { cout << "output"; }
  385. int GetType() { return nt::output; }
  386.  
  387. void UpdateWeights() {}
  388.  
  389. void CalculateGradient() {
  390. this->gradient = ( this->target - this->output ) * (1.0 - this->output * this->output);
  391. }
  392.  
  393. void Activate() {
  394. this->setOutput(tanh(this->sum));
  395. this->sum = 0;
  396. }
  397. void MemorizeOutput(double output) {
  398. if (this->HaveMemoryNeuron()) this->GetMemoryNeuron()->setOutput(output);
  399. }
  400.  
  401. bool CanBeConnected() { return true; }
  402.  
  403. void Fire(double signal) {
  404. this->sum += signal;
  405. }
  406. vector<axon *> GetAxons() { return this->axons; }
  407.  
  408. void AddConnection(neuron *Target) {
  409. if (Target->GetType() == nt::memory) {
  410. if (this->HaveMemoryNeuron()) return;
  411. this->axons.insert(this->axons.begin(), new memory_axon(Target));
  412. }
  413. }
  414.  
  415. noutput() {
  416. output = 0.0;
  417. gradient = 0.0;
  418. sum = 0.0;
  419. target = 0.0;
  420. }
  421.  
  422. ~noutput() {
  423. }
  424. };
  425.  
  426.  
  427. class brain
  428. {
  429. public:
  430. vector<vector<neuron *>> map;
  431. void FeedForward()
  432. {
  433. for (int y = 0; y < map.size(); y++) {
  434. for (int x = 0; x < map[y].size(); x++) {
  435. map[y][x]->Activate();
  436. }
  437. }
  438. }
  439.  
  440. void BackPropagation()
  441. {
  442. for (int y = map.size() - 1; y >= 0; y--) {
  443. for (int x = 0; x < map[y].size(); x++) {
  444. map[y][x]->CalculateGradient();
  445. }
  446. }
  447.  
  448. for (int y = map.size() - 1; y >= 0; y--) {
  449. for (int x = 0; x < map[y].size(); x++) {
  450. map[y][x]->UpdateWeights();
  451. }
  452. }
  453. }
  454.  
  455. void AddNeuron(int layer, int NeuronType, int count)
  456. {
  457. for (int a = 0; a < count; a++) AddNeuron(layer, NeuronType);
  458. }
  459.  
  460. neuron *AddNeuron( int layer, int NeuronType )
  461. {
  462. _MakeLayer(layer);
  463. neuron *ret = 0;
  464. switch (NeuronType)
  465. {
  466. case nt::bias:
  467. ret = new nbias();
  468. map[layer].push_back(ret);
  469. break;
  470. case nt::hidden:
  471. ret = new nhidden();
  472. map[layer].push_back(ret);
  473. break;
  474. case nt::input:
  475. ret = new ninput();
  476. map[layer].push_back(ret);
  477. break;
  478. case nt::memory:
  479. ret = new nmemory();
  480. map[layer].push_back(ret);
  481. break;
  482. case nt::output:
  483. ret = new noutput();
  484. map[layer].push_back(ret);
  485. break;
  486. }
  487. return ret;
  488. }
  489.  
  490. neuron *GetNeuron(int y, int x) {
  491. return map[y][x];
  492. }
  493.  
  494. void ConnectLayers(int LayerOne, int LayerTwo)
  495. {
  496. for (int x = 0; x < map[LayerOne].size(); x++) _ConnectWithLayer(map[LayerOne][x], LayerTwo);
  497. }
  498.  
  499. void _MakeLayer(int layer)
  500. {
  501. if (layer >= map.size()) {
  502. for (int a = 0; a < (layer - map.size()) + 1; a++) map.push_back(vector<neuron *>());
  503. }
  504.  
  505. }
  506.  
  507. void _ConnectWithLayer(neuron *Neuron, int layer)
  508. {
  509. for (int x = 0; x < map[layer].size(); x++){
  510. Neuron->AddConnection(map[layer][x]);
  511. }
  512. }
  513.  
  514. brain(){}
  515. ~brain(){}
  516. };
  517.  
  518.  
  519. class input
  520. {
  521. public:
  522. vector<double> inputs;
  523. input(int InputCount, ...)
  524. {
  525. va_list vl;
  526. va_start(vl, InputCount);
  527. for (int i = 0; i<InputCount; i++) {
  528. inputs.push_back(va_arg(vl, double));
  529. }
  530. va_end(vl);
  531. }
  532. };
  533.  
  534. class target
  535. {
  536. public:
  537. vector<double> targets;
  538. target(int ResultCount, ...)
  539. {
  540. va_list vl;
  541. va_start(vl, ResultCount);
  542. for (int i = 0; i<ResultCount; i++)
  543. {
  544. targets.push_back(va_arg(vl, double));
  545. }
  546. va_end(vl);
  547. }
  548. };
  549.  
  550. class TrainingData
  551. {
  552. public:
  553. vector<input> Inputs;
  554. vector<target> Targets;
  555. int InputCount() { return Inputs[0].inputs.size(); }
  556. int TargetCount() { return Targets[0].targets.size(); }
  557. int DataCount() { return Inputs.size(); }
  558.  
  559. double GetInput(int index, int index2) {
  560. return Inputs[index].inputs[index2];
  561. }
  562.  
  563. double GetTarget(int index, int index2) {
  564. return Targets[index].targets[index2];
  565. }
  566.  
  567. TrainingData(int TrainingDataCount, ...)
  568. {
  569. va_list vl;
  570. va_start(vl, TrainingDataCount);
  571. for (int i = 0; i<TrainingDataCount; i++)
  572. {
  573. Inputs.push_back(va_arg(vl, input));
  574. Targets.push_back(va_arg(vl, target));
  575. }
  576. va_end(vl);
  577. }
  578. };
  579. }
  580. #endif
Advertisement
Add Comment
Please, Sign In to add comment