見出し画像

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のパッケージの改善ができたので、当初の目的のログ分析ツール

に組み込もうと思います。

明日に続く


開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。