-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNeuron.cpp
102 lines (80 loc) · 3.23 KB
/
Neuron.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//
// Created by Tommy Ludwig on 23.09.23.
//
#include "Neuron.h"
#include "Connection.h"
#include "iostream"
Neuron::Neuron(unsigned int numOutputs, unsigned int myIndex) {
for (unsigned connection = 0; connection < numOutputs; ++connection) {
m_outputWeights.push_back(Connection()); // a random weight is assigned in the Connection constructor
}
m_myIndex = myIndex;
}
double Neuron::eta = 0.15; // overall net learning rate, [0.0..1.0]; 0.0 means: no learning, 1.0 means: learn at full
double Neuron::alpha = 0.5; // momentum, multiplier of last deltaWeight, [0.0..n]; 0.0 means: no momentum
void Neuron::setOutputVal(double value) {
m_outputVal = value;
}
double Neuron::getOutputVal() const {
return m_outputVal;
}
// this function is used for calculating the output of the neurons
void Neuron::feedForward(const vector<Neuron> &prevLayer) {
double sum = 0.0;
// print all the weights
for (unsigned neuron = 0; neuron < prevLayer.size(); ++neuron) {
/*std::cout << "Neuron " << m_myIndex << " weight " << neuron << ": " << prevLayer[neuron]
.m_outputWeights[m_myIndex].weight << std::endl;
*/
}
for (unsigned neuron = 0; neuron < prevLayer.size(); ++neuron) {
sum += prevLayer[neuron].getOutputVal() * prevLayer[neuron].m_outputWeights[m_myIndex].weight;
}
m_outputVal = Neuron::transferFunction(sum);
//m_outputVal = Neuron::sigmoid(sum);
//std::cout << "Neuron " << m_myIndex << " output: " << m_outputVal << std::endl;
}
double Neuron::sigmoid(double x) {
//sigmoid function
return 1 / (1 + exp(-x));
}
double Neuron::ReLu(double x) {
return x > 0 ? x : 0;
}
double Neuron::transferFunction(double x) {
return tanh(x);
}
void Neuron::calculateOutputGradients(double targetValue) {
double delta = targetValue - m_outputVal;
m_gradient = delta * Neuron::transferFunctionDerivative(m_outputVal);
}
void Neuron::calculateHiddenGradients(const vector<Neuron> &nextLayer) {
double dow = sumDOW(nextLayer);
m_gradient = dow * Neuron::transferFunctionDerivative(m_outputVal);
}
void Neuron::updateInputWeights(vector<Neuron> &prevLayer) const {
// n stands for the index of the neuron
for (unsigned n = 0; n < prevLayer.size(); ++n) {
Neuron &neuron = prevLayer[n];
double oldDeltaWeight = neuron.m_outputWeights[m_myIndex].deltaWeight;
// TODO: Implement quicker method;
double newDeltaWeight = eta * neuron.getOutputVal() * m_gradient + alpha * oldDeltaWeight;
neuron.m_outputWeights[m_myIndex].deltaWeight = newDeltaWeight;
neuron.m_outputWeights[m_myIndex].weight += newDeltaWeight;
//cout << "New weight: " << neuron.m_outputWeights[m_myIndex].weight << endl;
//cout << "New delta weight: " << neuron.m_outputWeights[m_myIndex].deltaWeight << endl;
}
}
vector<Connection> Neuron::getOutputWeights() const {
return m_outputWeights;
}
double Neuron::transferFunctionDerivative(double x) {
return 1 - x * x;
}
double Neuron::sumDOW(const vector<Neuron> &nextLayer) const {
double sum = 0.0;
for (unsigned neuron = 0; neuron < nextLayer.size() - 1; ++neuron) {
sum += m_outputWeights[neuron].weight * nextLayer[neuron].m_gradient;
}
return sum;
}