forked from xlvector/hector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
factorize_machine.go
107 lines (92 loc) · 2.34 KB
/
factorize_machine.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
package fm
import (
"github.com/pantsing/hector/internal/core"
"github.com/pantsing/hector/internal/utils"
"github.com/urfave/cli"
)
type FactorizeMachine struct {
w *core.Vector
v []*core.Vector
params FactorizeMachineParams
}
type FactorizeMachineParams struct {
LearningRate float64
Regularization float64
FactorNumber int
}
func (self *FactorizeMachine) SaveModel(path string) {
}
func (self *FactorizeMachine) LoadModel(path string) {
}
func (c *FactorizeMachine) Predict(sample *core.Sample) float64 {
for _, f := range sample.Features {
c.w.RandomInit(f.Id, 0.1)
for k, _ := range c.v {
c.v[k].RandomInit(f.Id, 0.1)
}
}
ret := c.w.DotFeatures(sample.Features)
for k, _ := range c.v {
a := c.v[k].DotFeatures(sample.Features)
b := 0.0
for _, f := range sample.Features {
vkf := c.v[k].GetValue(f.Id)
b += f.Value * f.Value * vkf * vkf
}
ret += 0.5 * (a*a - b)
}
return utils.Sigmoid(ret)
}
func (c *FactorizeMachine) Command() cli.Command {
return cli.Command{
Name: "fm",
Usage: "FactorizeMachine",
Category: "FM",
Flags: []cli.Flag{
cli.IntFlag{
Name: "factors",
},
cli.Float64Flag{
Name: "learning-rate,lrate",
},
cli.Float64Flag{
Name: "regularization,r",
},
},
}
}
func (c *FactorizeMachine) Init(ctx *cli.Context) {
c.w = core.NewVector()
c.params.FactorNumber = ctx.Int("factors")
c.params.LearningRate = ctx.Float64("learning-rate")
c.params.Regularization = ctx.Float64("regularization")
for i := 0; i < c.params.FactorNumber; i++ {
c.v = append(c.v, core.NewVector())
}
}
func (c *FactorizeMachine) Clear() {}
func (c *FactorizeMachine) Train(dataset *core.DataSet) {
n := 0
for _, sample := range dataset.Samples {
n += 1
if n%10000 == 0 {
c.params.LearningRate *= 0.9
}
pred := c.Predict(sample)
err := sample.LabelDoubleValue() - pred
vx := []float64{}
for _, vf := range c.v {
vx = append(vx, vf.DotFeatures(sample.Features))
}
for _, f := range sample.Features {
fweight := c.w.GetValue(f.Id)
fweight += c.params.LearningRate * (err*f.Value - c.params.Regularization*fweight)
c.w.SetValue(f.Id, fweight)
for k, _ := range c.v {
vkx := c.v[k].GetValue(f.Id)
vkx += c.params.LearningRate * (err*(f.Value*vx[k]-f.Value*f.Value*vkx) - c.params.Regularization*vkx)
c.v[k].SetValue(f.Id, vkx)
}
}
}
}