-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayer_relu.go
110 lines (92 loc) · 1.87 KB
/
layer_relu.go
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
package torch
import (
"github.com/Jimmy2099/torch/data_store/tensor"
)
type ReLULayer struct {
input *tensor.Tensor
negative float32
inplace bool
}
func (r *ReLULayer) GetWeights() *tensor.Tensor {
return tensor.NewEmptyTensor()
}
func (r *ReLULayer) GetBias() *tensor.Tensor {
return tensor.NewEmptyTensor()
}
func NewReLULayer() *ReLULayer {
return &ReLULayer{
negative: 0.0,
inplace: false,
}
}
func NewLeakyReLULayer(negativeSlope float32) *ReLULayer {
if negativeSlope < 0 {
panic("negative slope must be non-negative")
}
return &ReLULayer{
negative: negativeSlope,
inplace: false,
}
}
func (r *ReLULayer) SetInplace(inplace bool) {
r.inplace = inplace
}
func (r *ReLULayer) Forward(x *tensor.Tensor) *tensor.Tensor {
if x == nil {
panic("input tensor cannot be nil")
}
if r.inplace {
r.input = x
} else {
r.input = x.Clone()
}
return x.Apply(func(val float32) float32 {
if val > 0 {
return val
}
return r.negative * val
})
}
func shapeEqual(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func (r *ReLULayer) ActivationType() string {
if r.negative == 0 {
return "ReLU"
}
return "LeakyReLU"
}
func (r *ReLULayer) NegativeSlope() float32 {
return r.negative
}
func (r *ReLULayer) Backward(gradOutput *tensor.Tensor, learningRate float32) *tensor.Tensor {
if r.input == nil {
panic("must call Forward first")
}
if gradOutput == nil {
panic("gradient tensor cannot be nil")
}
if !shapeEqual(r.input.GetShape(), gradOutput.GetShape()) {
panic("input and gradient shapes must match")
}
grad := r.input.Apply(func(val float32) float32 {
if val > 0 {
return 1.0
}
return r.negative
})
return grad.Multiply(gradOutput)
}
func (r *ReLULayer) ZeroGrad() {
}
func (r *ReLULayer) Parameters() []*tensor.Tensor {
return nil
}