1
0
mirror of https://github.com/fumiama/jieba.git synced 2026-06-19 09:50:25 +08:00
Files
jieba/finalseg/viterbi.go
2015-02-28 17:51:03 +08:00

102 lines
2.1 KiB
Go

package finalseg
import (
"fmt"
"sort"
)
const MinFloat = -3.14e100
var (
prevStatus = make(map[byte][]byte)
probStart = make(map[byte]float64)
)
func init() {
prevStatus['B'] = []byte{'E', 'S'}
prevStatus['M'] = []byte{'M', 'B'}
prevStatus['S'] = []byte{'S', 'E'}
prevStatus['E'] = []byte{'B', 'M'}
probStart['B'] = -0.26268660809250016
probStart['E'] = -3.14e+100
probStart['M'] = -3.14e+100
probStart['S'] = -1.4652633398537678
}
type Viterbi struct {
prob float64
state byte
}
func (v Viterbi) String() string {
return fmt.Sprintf("(%f, %x)", v.prob, v.state)
}
type Viterbis []*Viterbi
func (vs Viterbis) Len() int {
return len(vs)
}
func (vs Viterbis) Less(i, j int) bool {
if vs[i].prob == vs[j].prob {
return vs[i].state < vs[j].state
}
return vs[i].prob < vs[j].prob
}
func (vs Viterbis) Swap(i, j int) {
vs[i], vs[j] = vs[j], vs[i]
}
func viterbi(obs []rune, states []byte) (float64, []byte) {
path := make(map[byte][]byte)
V := make([]map[byte]float64, len(obs))
V[0] = make(map[byte]float64)
for _, y := range states {
if val, ok := probEmit[y][obs[0]]; ok {
V[0][y] = val + probStart[y]
} else {
V[0][y] = MinFloat + probStart[y]
}
path[y] = []byte{y}
}
for t := 1; t < len(obs); t++ {
newPath := make(map[byte][]byte)
V[t] = make(map[byte]float64)
for _, y := range states {
vs0 := make(Viterbis, 0)
var em_p float64
if val, ok := probEmit[y][obs[t]]; ok {
em_p = val
} else {
em_p = MinFloat
}
for _, y0 := range prevStatus[y] {
var transP float64
if tp, ok := probTrans[y0][y]; ok {
transP = tp
} else {
transP = MinFloat
}
prob0 := V[t-1][y0] + transP + em_p
vs0 = append(vs0, &Viterbi{prob: prob0, state: y0})
}
sort.Sort(sort.Reverse(vs0))
V[t][y] = vs0[0].prob
pp := make([]byte, len(path[vs0[0].state]))
copy(pp, path[vs0[0].state])
newPath[y] = append(pp, y)
}
path = newPath
}
vs := make(Viterbis, 0)
for _, y := range []byte{'E', 'S'} {
vs = append(vs, &Viterbi{V[len(obs)-1][y], y})
}
sort.Sort(sort.Reverse(vs))
v := vs[0]
return v.prob, path[v.state]
}