-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmicrograd.h
115 lines (103 loc) · 3.1 KB
/
micrograd.h
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
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef MICROGRAD_H
#define MICROGRAD_H
#include <iostream>
#include <cmath>
#include <functional>
#include <set>
#include <vector>
using namespace std;
class Value {
public:
double data;
double grad;
set<Value*> prev ={};
function<void()> backwardFunction;
// Constructors
Value() : data(0), grad(0), prev(), backwardFunction([](){ /* do nothing */ }) {}
Value(double data, const initializer_list<Value*>& children = {})
: data(data), grad(0), prev(children), backwardFunction([](){ /* do nothing */ }) {}
// Overloaded << operator to print Value objects
friend std::ostream& operator<<(std::ostream& os, const Value& v) {
os << "Value(data=" << v.data << ", grad=" << v.grad << ")";
return os;
}
// Getters
double getGrad() const { return grad; }
double getValue() const { return data; }
// Operator overloadings
Value operator+( Value& other) {
Value out;
out.data = this->data + other.data;
out.prev = {this, &other};
out.backwardFunction = [this, &out, &other]() {
this->grad += out.grad; ;
other.grad += out.grad; ;
};
return out;
}
Value operator-( Value& other) {
Value out;
out.data = this->data - other.data;
out.backwardFunction =[this,&out,&other](){
this->grad += out.grad;
other.grad -= out.grad;
};
return out;
}
Value operator*( Value& other) {
Value out;
out.data = this->data * other.data;
out.backwardFunction =[this,&out,&other](){
this->grad += other.data * out.grad;
other.grad += this->data * out.grad;
};
return out;
}
Value operator^(const Value& other) {
Value out;
out.data = pow(this->data, other.data);
out.backwardFunction =[this,&out,&other](){
this->grad += other.data * pow(this->data, other.data - 1) * out.grad;
};
return out;
}
Value relu(){
Value out;
data < 0 ?out.data = 0:out.data=data;
out.backwardFunction =[this, &out]() {
grad += (out.data > 0) ? out.grad : 0.0;
};
return out;
}
Value sigmoid() {
Value out;
out.data = 1.0 / (1.0 + exp(-data));
out.backwardFunction = [this, &out]() {
double temp = out.data * (1 - out.data);
grad += temp * out.grad;
};
return out;
}
void backward() {
vector<Value*> topo;
set<Value*> visited;
const function<void(Value*)> buildTopo = [&](Value* v) {
if (visited.count(v) == 0) {
visited.insert(v);
for (const auto child : v->prev) {
cout << "child: "<<*child << endl;
buildTopo(child);
}
topo.push_back(v);
}
};
buildTopo(this);
this->grad = 1;
for (auto node : topo) {
}
for (auto it = topo.rbegin(); it != topo.rend(); ++it) {
(*it)->backwardFunction();
}
}
};
#endif