GO言語のTFIDFパッケージ v1.1.0リリース
GO言語のTFIDFパッケージv1.1.0をリリースしました。
異常検知のためのIsolation ForestとLocal Outlier Factorを使うと特徴量のベクトルの次元が高すぎてプログラム固まる問題のために諦めかけていました。
昨日、マチス展
に行ってリフレッシュして帰ってきたあと、昼寝をしていると、良いアイデアが浮かびました。
TFIDFで作った全単語のベクトルの次元を減らしてみるものです。
3万あった単語を100ぐらいのベクトルに集約してみました。
学術的な意味とかはわかりませんが、直感的に
if len(vector) < limit || limit <= 0 {
ret = append(ret, vector)
} else {
rv := make([]float64, limit)
for i, e := range vector {
rv[i%limit] += e
}
ret = append(ret, rv)
}
のようにしてみました。limitで次元の上限を指定する方法です。
そうすると、Isolation Forestは固まらなくなりました。
Local Outlier Factorは、次元を低くしてもログの数が多いと固まります。
それでも半日ではなく1時間ぐらいにはなったようです。
フィルターでログの量を減らせば、使えるのでrarelogコマンドに異常検知のアルゴリズムIsolation ForestとLocal Outlier Factorを組み込みました。
組み込んだバージョンが今回のリリースでです。
#rarelog -h
Usage of /tmp/rarelog:
-a string
anomaly detection(sum|if|lof)
-c int
show top n count (default 10)
-d debug
-f string
regexp filter
-g use time grinder
-l int
vector limit (default 100)
-t string
tokenizer (en|log|ja) (default "en")
-v show version
のように使います。
異常検知は-aで指定します。
デフォルトはsumで、単純にTFIDFの値の合計で判断します。珍しい単語が多い行のスコアが高くなるものです。これが最初に作ったものです。
# rarelog -d -f postfix -g -t log /var/log/syslog.1
2023/06/09 06:34:58 start args=1 alloc=381000
2023/06/09 06:34:58 read args=/var/log/syslog.1
2023/06/09 06:34:58 lines=4206 alloc=3051208
2023/06/09 06:34:58 tfidf end alloc=5201896
Score Log
6.524 Jun 8 18:59:03 minipc postfix/cleanup[31745]: BF7ACC066F: message-id=<20230608095903.BF7ACC066F@minipc>
6.524 Jun 8 06:59:06 minipc postfix/cleanup[12217]: 38082C066F: message-id=<20230607215906.38082C066F@minipc>
6.524 Jun 8 12:59:03 minipc postfix/cleanup[21998]: F0855C066F: message-id=<20230608035903.F0855C066F@minipc>
6.524 Jun 8 00:59:03 minipc postfix/cleanup[2315]: BC7DFC066F: message-id=<20230607155903.BC7DFC066F@minipc>
4千件の中の珍しいログを探してくれます。元のログは8万件ありますが、フィルターかけて実行して1秒以内に完了します。
異常検知にifを指定するとIsolation Forestになります。
#rarelog -d -f postfix -g -t log -a if /var/log/syslog.1
2023/06/09 06:30:27 start args=1 alloc=379864
2023/06/09 06:30:27 read args=/var/log/syslog.1
2023/06/09 06:30:27 lines=4206 alloc=3141240
2023/06/09 06:30:27 if all words=100 alloc=8851376
2023/06/09 06:30:29 if end train alloc=18285152
2023/06/09 06:30:30 if end alloc=18545312
Score Log
0.532 Jun 8 18:59:03 minipc postfix/local[31747]: BF7ACC066F: to=<root@minipc>, orig_to=<root>, relay=local, delay=0.03, delays=0.02/0.01/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
0.532 Jun 8 06:59:06 minipc postfix/local[12219]: 38082C066F: to=<root@minipc>, orig_to=<root>, relay=local, delay=0.03, delays=0.02/0.01/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
3秒ぐらいで終了しますが、sum とは違う結果になります。
異常検知にlofを指定するとLocal Outlier Factorになります。
# /tmp/rarelog -d -f postfix -g -t log -a lof /var/log/syslog.1
2023/06/09 06:31:44 start args=1 alloc=380424
2023/06/09 06:31:44 read args=/var/log/syslog.1
2023/06/09 06:31:44 lines=4206 alloc=2424136
2023/06/09 06:31:44 lof all words=100 alloc=8118040
2023/06/09 06:32:35 lof end train alloc=379310456
2023/06/09 06:33:30 lof end alloc=345389120
Score Log
237089204147175.812 Jun 8 18:59:03 minipc postfix/cleanup[31745]: BF7ACC066F: message-id=<20230608095903.BF7ACC066F@minipc>
219545030204855.812 Jun 8 00:59:03 minipc postfix/cleanup[2315]: BC7DFC066F: message-id=<20230607155903.BC7DFC066F@minipc>
182207350389513.438 Jun 8 06:59:06 minipc postfix/cleanup[12217]: 38082C066F: message-id=<20230607215906.38082C066F@minipc>
2分近くかかります。結果はsumの場合に似ています。
なんだか、一番最初に作ったシンプルなsumが一番使えそうです。
ここで、助手の猫が天から
「難しいアルゴリズムよりもシンプルなものが良いこともある。」
と行っています。
TFIDFのパッケージの改善ができたので、当初の目的のログ分析ツール
に組み込もうと思います。
明日に続く