Edited at
GoDay 4

異常検知でGo!

More than 3 years have passed since last update.


異常検知でGo!

こんにちは。ちょびえです。4日めですがいかがお過ごしでしょうか?

今日はGoで異常検知を試してみましたのでレポートしてみたいと思います。


異常検知の世界

ふつうのWebプログラマーの私がデータマイニングによる異常検知読んで、機械学習ってなんて便利なんだろう!?と驚いたと共に機械学習の魅力に引き込まれていきました。

https://github.com/chobie/go-anomalydetector/blob/master/anomalydetector.go

https://github.com/muddydixon/fluent-plugin-anomalydetect のSDAR部分を再実装したものです。私は高校をドロップアウトしてるので線形代数周りの理解・実装でだいぶ難儀しましたが、良き実装があればなんとかなるもんだなぁ、、、とw

anomalydetectorはChangeFinder部分のスムージングなどの実装は含んでいないのでこんな感じで作ってみてください。

package main

import (
"fmt"
"bufio"
"strconv"
"os"
"strings"
anomalydetector "github.com/chobie/go-anomalydetector"
)

type ChangeFinder struct {
O *anomalydetector.AnomalyDetector
S *anomalydetector.AnomalyDetector
Smooth int
Last float64
LastScore float64
Buffer []float64
Buffer2 []float64
}

func sum(array *[]float64) float64 {
sum := 0.0
for _, value := range *array {
sum += value
}
return sum
}

func (finder *ChangeFinder) Update(v float64) float64 {
var score float64 = 0.0

if v == finder.Last && finder.LastScore < 3.0 {
score = finder.LastScore
} else {
r := finder.O.Update(v)
finder.Buffer = append(finder.Buffer, r)

if len(finder.Buffer) > finder.Smooth {
finder.Buffer = finder.Buffer[1:]
}

score = finder.S.Update(sum(&finder.Buffer) / float64(len(finder.Buffer)))
}

finder.Last = v
finder.LastScore = score

return finder.LastScore
}

func NewChangePoint(outlier_term int, outlier_discount float64, score_term int, score_discount float64, smooth_term int) *ChangeFinder {
v := ChangeFinder{}
v.O = anomalydetector.NewAnomalyDetector(outlier_term, outlier_discount)
v.S = anomalydetector.NewAnomalyDetector(score_term, score_discount)
v.Smooth = smooth_term

return &v
}

func main() {
p, err := os.Open("go.tsv")
if err != nil {
panic(err)
}
defer p.Close()

cp := NewChangePoint(12, 0.0275, 6, 0.1, 12)
scanner := bufio.NewScanner(p)
for scanner.Scan() {
args := strings.Split(scanner.Text(), "\t")
result, err := strconv.ParseFloat(args[1], 64)
if err != nil {
panic(err)
}
score := cp.Update(result)
fmt.Printf("%s\t%f\t%f\n", args[0], result, score)
}
}

Google TrendでGolangを検索した結果を下記にはりつけておきます。ダウンロードしてgo.tsvで保存して置いてください。

https://gist.github.com/chobie/16b15c35f8452ed8d59f

それでは実行結果をExcelでPlotしてみたいと思います。スコアはそのままだと小さくて読みづらいのでなんとなく自乗しときました。

Screenshot_11_30_14__22_54.png

2008/9は記憶にありませんが、2009/11といえばコレですね

https://www.youtube.com/watch?v=rKnDgT73v8s#t=8m53

それじゃ、Happy Hacking