Class: Value

Inherits:
Object
  • Object
show all
Defined in:
lib/value.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, prev = []) ⇒ Value

Returns a new instance of Value.



5
6
7
8
9
10
# File 'lib/value.rb', line 5

def initialize(value, prev = [])
    @value = value
    @grad = 0
    @prev = prev.uniq.freeze
    @calc_gradient = lambda { }
end

Instance Attribute Details

#calc_gradientObject

Returns the value of attribute calc_gradient.



12
13
14
# File 'lib/value.rb', line 12

def calc_gradient
  @calc_gradient
end

#gradObject

Returns the value of attribute grad.



12
13
14
# File 'lib/value.rb', line 12

def grad
  @grad
end

#prevObject (readonly)

Returns the value of attribute prev.



12
13
14
# File 'lib/value.rb', line 12

def prev
  @prev
end

#valueObject

Returns the value of attribute value.



12
13
14
# File 'lib/value.rb', line 12

def value
  @value
end

Instance Method Details

#*(other) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/value.rb', line 27

def *(other)
    other = to_v(other)
    out = Value.new(self.value * other.value, [self, other])

    out.calc_gradient = lambda do
        self.grad += other.value * out.grad
        other.grad += self.value * out.grad
    end

    return out
end

#**(other) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/value.rb', line 39

def **(other)
    out = Value.new(self.value ** other, [self])

    out.calc_gradient = lambda do
        self.grad += (other * self.value ** (other - 1)) * out.grad
    end

    return out
end

#+(other) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/value.rb', line 15

def +(other)
    other = to_v(other)
    out = Value.new(self.value + other.value, [self, other])

    out.calc_gradient = lambda do
        self.grad += out.grad
        other.grad += out.grad
    end

    return out
end

#-(other) ⇒ Object



97
98
99
# File 'lib/value.rb', line 97

def -(other)
    self + (-other)
end

#-@Object



93
94
95
# File 'lib/value.rb', line 93

def -@
    self * -1
end

#/(other) ⇒ Object



101
102
103
# File 'lib/value.rb', line 101

def /(other)
    self * (other ** -1)
end

#backwardObject



126
127
128
129
130
131
132
# File 'lib/value.rb', line 126

def backward
    topo = build_topo_graph(self)
    self.grad = 1.0
    topo.reverse_each do |node|
        node.calc_gradient.call
    end
end

#build_topo_graph(start) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/value.rb', line 110

def build_topo_graph(start)
    topo = []
    visited = Set.new
    build_topo = lambda do |v|
        if !visited.include?(v)
            visited.add(v)
            v.prev.each do |child|
                build_topo.call(child)
            end
            topo.append(v)
        end
    end
    build_topo.call(start)
    return topo
end

#coerce(other) ⇒ Object



105
106
107
108
# File 'lib/value.rb', line 105

def coerce(other)
    other = to_v(other)
    [other, self.value]
end

#expObject



83
84
85
86
87
88
89
90
91
# File 'lib/value.rb', line 83

def exp 
    out = Value.new(Math.exp(self.value), [self])

    out.calc_gradient = lambda do
        self.grad += out.value * out.grad
    end

    return out
end

#inspectObject



138
139
140
# File 'lib/value.rb', line 138

def inspect
    "Value(value=#{value}, grad=#{grad})"
end

#reluObject



72
73
74
75
76
77
78
79
80
81
# File 'lib/value.rb', line 72

def relu
    n = self.value < 0 ? 0.0 : self.value
    out = Value.new(n, [self])

    out.calc_gradient = lambda do
        self.grad += (out.value > 0 ? 1.0 : 0.0) * out.grad
    end

    return out
end

#sigmoidObject



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/value.rb', line 60

def sigmoid
    e = Math.exp(-1.0 * self.value)
    t = 1.0 / (1.0 + e)
    out = Value.new(t, [self])
    
    out.calc_gradient = lambda do
        self.grad += t * (1.0 - t) * out.grad
    end

    return out
end

#tanhObject



49
50
51
52
53
54
55
56
57
58
# File 'lib/value.rb', line 49

def tanh
    t = (Math.exp(2.0 * self.value) - 1.0) / (Math.exp(2.0 * self.value) + 1.0)
    out = Value.new(t, [self])

    out.calc_gradient = lambda do
        self.grad += (1.0 - t ** 2.0) * out.grad
    end

    return out
end

#to_sObject



134
135
136
# File 'lib/value.rb', line 134

def to_s
    value.to_s
end