Skip to content

Commit

Permalink
Update functional option pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
itsubaki committed Aug 17, 2024
1 parent a3b61a5 commit 4ab0c58
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 115 deletions.
11 changes: 6 additions & 5 deletions autograd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func Example_double() {

func Example_linearRegression() {
// p318
s :=rand.Const()
s := rand.Const()
xrand := matrix.Rand(100, 1, s)
yrand := matrix.Rand(100, 1, s)

Expand Down Expand Up @@ -424,10 +424,11 @@ func Example_linearRegression() {

func Example_mlp() {
s := rand.Const()
m := model.NewMLP([]int{10, 1}, model.MLPOpts{
Activation: F.ReLU,
Source: s,
})
m := model.NewMLP([]int{10, 1},
model.MLPWithSource(s),
model.MLPWithActivation(F.ReLU),
)

o := optimizer.SGD{
LearningRate: 0.2,
}
Expand Down
45 changes: 27 additions & 18 deletions layer/linear.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,45 @@ import (
"github.com/itsubaki/autograd/variable"
)

type LinearOpts struct {
InSize int
NoBias bool
Source randv2.Source
}
type OptionFunc func(*LinearT)

func Linear(outSize int, opts ...LinearOpts) *LinearT {
var s randv2.Source
if len(opts) != 0 && opts[0].Source != nil {
s = opts[0].Source
func WithSource(s randv2.Source) OptionFunc {
return func(l *LinearT) {
l.s = s
}
}

p := make(Parameters)
if len(opts) == 0 || !opts[0].NoBias {
p.Add("b", variable.Zero(1, outSize))
func WithInSize(inSize int) OptionFunc {
return func(l *LinearT) {
l.Parameters.Add("w", initw(inSize, l.outSize, l.s))
}
if len(opts) != 0 && opts[0].InSize > 0 {
p.Add("w", initw(opts[0].InSize, outSize, s))
}

func WithNoBias() OptionFunc {
return func(l *LinearT) {
l.Parameters.Delete("b")
}
}

return &LinearT{
func Linear(outSize int, opts ...OptionFunc) *LinearT {
p := make(Parameters)
p.Add("b", variable.Zero(1, outSize))

l := &LinearT{
outSize: outSize,
source: s,
Parameters: p,
}

for _, opt := range opts {
opt(l)
}

return l
}

type LinearT struct {
outSize int
source randv2.Source
s randv2.Source
Parameters
}

Expand All @@ -49,7 +58,7 @@ func (l *LinearT) First(x ...*variable.Variable) *variable.Variable {
func (l *LinearT) Forward(x ...*variable.Variable) []*variable.Variable {
if _, ok := l.Parameters["w"]; !ok {
inSize := variable.Shape(x[0])[1]
l.Parameters.Add("w", initw(inSize, l.outSize, l.source))
l.Parameters.Add("w", initw(inSize, l.outSize, l.s))
}

return []*variable.Variable{
Expand Down
16 changes: 6 additions & 10 deletions layer/linear_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
)

func ExampleLinear() {
l := L.Linear(5, L.LinearOpts{
Source: rand.Const(),
})
l := L.Linear(5, L.WithSource(rand.Const()))

x := variable.New(1, 2, 3)
y := l.Forward(x)
Expand All @@ -28,10 +26,10 @@ func ExampleLinear() {
}

func ExampleLinear_inSize() {
l := L.Linear(5, L.LinearOpts{
InSize: 3,
Source: rand.Const(),
})
l := L.Linear(5,
L.WithSource(rand.Const()),
L.WithInSize(3),
)

x := variable.New(1, 2, 3)
y := l.Forward(x)
Expand All @@ -48,9 +46,7 @@ func ExampleLinear_inSize() {
}

func ExampleLinear_nobias() {
l := L.Linear(5, L.LinearOpts{
NoBias: true,
})
l := L.Linear(5, L.WithNoBias())

x := variable.New(1, 2, 3)
l.Forward(x)
Expand Down
41 changes: 23 additions & 18 deletions layer/lstm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,38 @@ import (
"github.com/itsubaki/autograd/variable"
)

type LSTMOpts struct {
Source randv2.Source
}
type LSTMOptionFunc func(*LSTMT)

func LSTM(hiddenSize int, opts ...LSTMOpts) *LSTMT {
var s randv2.Source
if len(opts) != 0 && opts[0].Source != nil {
s = opts[0].Source
func LSTMWithSource(s randv2.Source) LSTMOptionFunc {
return func(l *LSTMT) {
l.s = s
}
}

l := make(Layers)
l.Add("x2f", Linear(hiddenSize, LinearOpts{Source: s}))
l.Add("x2i", Linear(hiddenSize, LinearOpts{Source: s}))
l.Add("x2o", Linear(hiddenSize, LinearOpts{Source: s}))
l.Add("x2u", Linear(hiddenSize, LinearOpts{Source: s}))
l.Add("h2f", Linear(hiddenSize, LinearOpts{Source: s, InSize: hiddenSize, NoBias: true}))
l.Add("h2i", Linear(hiddenSize, LinearOpts{Source: s, InSize: hiddenSize, NoBias: true}))
l.Add("h2o", Linear(hiddenSize, LinearOpts{Source: s, InSize: hiddenSize, NoBias: true}))
l.Add("h2u", Linear(hiddenSize, LinearOpts{Source: s, InSize: hiddenSize, NoBias: true}))
func LSTM(hiddenSize int, opts ...LSTMOptionFunc) *LSTMT {
lstm := &LSTMT{
Layers: make(Layers),
}

return &LSTMT{
Layers: l,
for _, opt := range opts {
opt(lstm)
}

lstm.Layers.Add("x2f", Linear(hiddenSize, WithSource(lstm.s)))
lstm.Layers.Add("x2i", Linear(hiddenSize, WithSource(lstm.s)))
lstm.Layers.Add("x2o", Linear(hiddenSize, WithSource(lstm.s)))
lstm.Layers.Add("x2u", Linear(hiddenSize, WithSource(lstm.s)))
lstm.Layers.Add("h2f", Linear(hiddenSize, WithSource(lstm.s), WithInSize(hiddenSize), WithNoBias()))
lstm.Layers.Add("h2i", Linear(hiddenSize, WithSource(lstm.s), WithInSize(hiddenSize), WithNoBias()))
lstm.Layers.Add("h2o", Linear(hiddenSize, WithSource(lstm.s), WithInSize(hiddenSize), WithNoBias()))
lstm.Layers.Add("h2u", Linear(hiddenSize, WithSource(lstm.s), WithInSize(hiddenSize), WithNoBias()))

return lstm
}

type LSTMT struct {
h, c *variable.Variable
s randv2.Source
Layers
}

Expand Down
8 changes: 2 additions & 6 deletions layer/lstm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
)

func ExampleLSTM() {
l := L.LSTM(2, L.LSTMOpts{
Source: rand.Const(),
})
l := L.LSTM(2, L.LSTMWithSource(rand.Const()))

x := variable.New(1)
y := l.Forward(x)
Expand Down Expand Up @@ -39,9 +37,7 @@ func ExampleLSTM() {
}

func ExampleLSTM_backward() {
l := L.LSTM(2, L.LSTMOpts{
Source: rand.Const(),
})
l := L.LSTM(2, L.LSTMWithSource(rand.Const()))

x := variable.New(1)
y := l.First(x)
Expand Down
4 changes: 4 additions & 0 deletions layer/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ func (p Parameters) Add(name string, param Parameter) {
p[name] = param
}

func (p Parameters) Delete(name string) {
delete(p, name)
}

func (p Parameters) Params() Parameters {
return p
}
Expand Down
28 changes: 16 additions & 12 deletions layer/rnn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ import (
"github.com/itsubaki/autograd/variable"
)

type RNNOpts struct {
Source randv2.Source
type RNNOptionFunc func(*RNNT)

func RNNWithSource(s randv2.Source) RNNOptionFunc {
return func(l *RNNT) {
l.s = s
}
}
func RNN(hiddenSize int, opts ...RNNOptionFunc) *RNNT {
rnn := &RNNT{
Layers: make(Layers),
}

func RNN(hiddenSize int, opts ...RNNOpts) *RNNT {
var s randv2.Source
if len(opts) != 0 && opts[0].Source != nil {
s = opts[0].Source
for _, opt := range opts {
opt(rnn)
}

l := make(Layers)
l.Add("x2h", Linear(hiddenSize, LinearOpts{Source: s}))
l.Add("h2h", Linear(hiddenSize, LinearOpts{Source: s, InSize: hiddenSize, NoBias: true}))
rnn.Layers.Add("x2h", Linear(hiddenSize, WithSource(rnn.s)))
rnn.Layers.Add("h2h", Linear(hiddenSize, WithSource(rnn.s), WithInSize(hiddenSize), WithNoBias()))

return &RNNT{
Layers: l,
}
return rnn
}

type RNNT struct {
h *variable.Variable
s randv2.Source
Layers
}

Expand Down
8 changes: 2 additions & 6 deletions layer/rnn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
)

func ExampleRNN() {
l := L.RNN(2, L.RNNOpts{
Source: rand.Const(),
})
l := L.RNN(2, L.RNNWithSource(rand.Const()))

x := variable.New(1)
y := l.Forward(x)
Expand All @@ -29,9 +27,7 @@ func ExampleRNN() {
}

func ExampleRNN_backward() {
l := L.RNN(2, L.RNNOpts{
Source: rand.Const(),
})
l := L.RNN(2, L.RNNWithSource(rand.Const()))

x := variable.New(1)
y := l.First(x)
Expand Down
34 changes: 20 additions & 14 deletions model/lstm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,36 @@ import (
"github.com/itsubaki/autograd/variable"
)

type LSTMOpts struct {
Source randv2.Source
type LSTMOptionFunc func(*LSTM)

func LSTMWithSource(s randv2.Source) LSTMOptionFunc {
return func(l *LSTM) {
l.s = s
}
}

type LSTM struct {
s randv2.Source
Model
}

func NewLSTM(hiddenSize, outSize int, opts ...LSTMOpts) *LSTM {
var s randv2.Source
if len(opts) > 0 && opts[0].Source != nil {
s = opts[0].Source
func NewLSTM(hiddenSize, outSize int, opts ...LSTMOptionFunc) *LSTM {
lstm := &LSTM{
Model: Model{
Layers: make([]L.Layer, 0),
},
}

layers := []L.Layer{
L.LSTM(hiddenSize, L.LSTMOpts{Source: s}),
L.Linear(outSize, L.LinearOpts{Source: s}),
for _, opt := range opts {
opt(lstm)
}

return &LSTM{
Model: Model{
Layers: layers,
},
}
lstm.Layers = append(lstm.Layers, []L.Layer{
L.LSTM(hiddenSize, L.LSTMWithSource(lstm.s)),
L.Linear(outSize, L.WithSource(lstm.s)),
}...)

return lstm
}

func (m *LSTM) ResetState() {
Expand Down
4 changes: 1 addition & 3 deletions model/lstm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ func ExampleLSTM() {
}

func ExampleLSTM_backward() {
m := model.NewLSTM(1, 1, model.LSTMOpts{
Source: rand.Const(),
})
m := model.NewLSTM(1, 1, model.LSTMWithSource(rand.Const()))

x := variable.New(1, 2)
y := m.Forward(x)
Expand Down
Loading

0 comments on commit 4ab0c58

Please sign in to comment.