43
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GoAdvent Calendar 2014

Day 4

異常検知でGo!

Last updated at Posted at 2014-11-30

異常検知でGo!

こんにちは。ちょびえです。4日めですがいかがお過ごしでしょうか?
今日はGoで異常検知を試してみましたのでレポートしてみたいと思います。

異常検知の世界

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

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といえばコレですね

それじゃ、Happy Hacking

43
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?