Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

異常検知でGo!

More than 5 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

chobie@github
PECLメンテナです。 PECL ProtocolBuffers, Sundown author. also maintained several experimental exts like php-uv, php-git. develop mobile web gaming services. #PHP #HHVM, #MySQL
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away