Splunk DLTK で Networkグラフをクラスタリング with Louvain on Rapids cuGraph


# はじめに

以前 [NetworkX を使った可視化](https://qiita.com/maroon/items/025e415b9bd53197d8b0)で、3D化した Network Topologyグラフをご紹介しました。
このようにグラフによる可視化をするのは非常に分析にとって有益ですが、これらのデータをクラスタリングして、さらに分析を進めるにはどうしたらいいでしょうか？　通常のK-Meansや G-Meansなどではうまく分類できません。

そこでこのようなソーシャルグラフに対して、クラスタリングする手法の一つに Louvainというのがあります。ソーシャルグラフのクラスタリングについてはこちらのスライドが大変わかりやすかったです。
https://www2.slideshare.net/komiyaatsushi/newman-6670300

Splunk DLTK のサンプルにもこの Louvain によるクラスタリングがありましたので、今回 GPU環境を使い cuGraphライブラリにある Louvainを試してみました。


### Rapids cuGraphについて 

こちらの [Readme.md](https://github.com/rapidsai/cugraph/blob/main/README.md)にありますとおり、Rapids は nVIDIAが作ったGPUを使うためのライブラリー群がセットになったフレームワークであり、その中の一つにcuGraphというグラフ分析を扱うライブラリがあります。Louvainを始めいくつものアルゴリズムがサポートされております。

### Louvainとは

ネットワーク内のコミュニティ（密に結合しているノードの集合）を抽出する手法の一つであり、従来の手法に比べ高速で抽出することができます。　[参考サイトはこちらです。](https://guarana001.hateblo.jp/entry/2020/08/24/020201#Louvain%E6%B3%95%E6%8F%90%E6%A1%88%E6%89%8B%E6%B3%95)


# 準備

利用するには、Splunk DLTK環境になります。
今回は Rapidsを利用するため、GPU環境は必須となります。

## 1. GPU環境の準備
Splunkサーバーの他に、GPUの搭載されたコンテナ環境を別に用意して接続する必要があります。今回はこちらのブログを参考に環境を準備しました。（かなり詳しく書かれております）
https://www.splunk.com/en_us/blog/tips-and-tricks/splunk-with-the-power-of-deep-learning-analytics-and-gpu-acceleration.html

今回利用した環境は上記Blogにもありますが、[AWSの DeepLearning AMI](https://aws.amazon.com/marketplace/pp/Amazon-Web-Services-AWS-Deep-Learning-AMI-Ubuntu-1/B07Y43P7X5)を利用しました。Dockerや必要なライブラリーがすでにインストールされております。

EC2インスタンスタイプは、g4dn.xlarge (4vCPU , 1GPU(T4), 16GB Memory, 0.526USD/時間)を利用しました。(利用しない時はこまめに落としましょう）

また Splunk Server (SH) と通信するため、以下のポートを許可します。（セキュリティグループ）
TCP 22 : Remote access via SSH
TCP 32768: Container SPL application server
TCP 2375: Remote Docker API
TCP 8888: Jupyter Labs DEV image
TCP 6006: Tensorboard DEV image

あとは、コンテナに対してリモートコントロールを許可するため、APIを有効にします。

```
cat /lib/systemd/system/docker.service |sed 's/containerd.sock/containerd.sock -H=tcp:\/\/0.0.0.0:2375/g' |sudo tee /lib/systemd/system/docker.service sudo systemctl daemon-reload;sleep 2;sudo service docker restart
```

これでコンテナ側のセットアップは終了です。
セットアップの詳細は、上記のブログを参照ください。

## 2. DLTK側セットアップ

今度は、Splunk Server (SH) に DLTKをインストールして、セットアップします。
ちょっと古い記事ですが、[こちらの記事](https://qiita.com/maroon/items/5a8b027631a674d6d8be)も参考にしてください。

DLTK3.3 では、Dockerと Kubernetesのどちらかが選べますが、今回は Dockerにして、ホストを先ほど作成したリモートホストにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/7ed4c015-66da-fc07-8fba-1a61520d9e80.png)

実行するコンテナを選択する際に、Rapids + nvidia を選択してください。 (Golden Imageの中には入っておりません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/4c2aebd8-ec62-d043-1963-cb50c5011c46.png)

# ノートブックの確認

Jupyter Labに接続すると、graph_algo_louvain.ipynb というノートブックがあります。
中身をみてみましょう。

最初はライブラリーのインポートです。 cugraph がありますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/ee21dfa6-69fc-d106-cdbc-ac2734b68140.png)

次にノートブック上でコード実行のため、サンプルデータを取り込みます。Splunk側で以下を実行してください。
データの中身は、bitcoinのトランザクションログになります。

```
| inputlookup bitcoin_transactions.csv
| rename user_id_from as src user_id_to as dest
| fit MLTKContainer mode=stage algo=graph_algo_louvain from src dest into app:bitcoin_graph_louvain as graph
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/9ad52108-374f-edbc-4e42-95623019df7d.png)

その後、ノートブック上でサンプルログを取り込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/ecf3aba0-b576-8a1e-e1a1-60c85e608792.png)

その後、初期化、fitとありますが、こちらは形式上のもので中身はなにもしてません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/2883655d-b1a4-610e-f90a-57c53e1ad6c5.png)

こちらがこのモデルの中身になります。
最初にグラフを作成して、その後に Louvainによってクラスタリングがされております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/21911d45-ef31-4a7e-8061-25e9136c11fb.png)

実行結果はこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/2b0de39a-b645-8af5-69b0-3a8c10b66ccd.png)

partitionと書かれている部分が、Louvainによってクラスタリングされた際のラベルになります。

一度、これらの関数定義を実行しておけば完了です。

# 可視化してみよう。

それでは、DLTKにあるサンプルダッシュボードを使って可視化してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/722d4463-3fb6-1e27-32d1-5806c2785241.png)

左にある、3D Graph Network Topologyを使った可視化ですが、クラスタリングされたパーティション（ラベル）ごとに色がついているのがわかります。

実際に、どのように色をつけているかみてみたいと思います。

```
| inputlookup bitcoin_transactions.csv
| rename user_id_from as src user_id_to as dest
| stats count by src dest
| fit MLTKContainer algo=graph_algo_louvain from src dest into app:bitcoin_graph_louvain as graph
| rename graph_src_partition as labeled_community
| table src dest count labeled_community
| head 2000 |  eval color_src="#".upper(substr(md5(labeled_community),0,6))
| eval color_dest=color_src 
| table src dest color_src color_dest
```
ポイントは２つです。

１つ目は、こちらで、対象のデータ(src,dest)を先ほど作成した graph_algo_louvain　アルゴリズムに送りクラスタリング結果を返してもらいます。

fit MLTKContainer algo=graph_algo_louvain from src dest into app:bitcoin_graph_louvain as graph

２つ目はこちらで、3D Graph Network Topologyでは、色を指定しないといけないのですが、md5 のハッシュを使って、その先頭の６文字に"#"をつけて表示することで、以下のようにカラー分けしております。（賢い！）

eval color_src="#".upper(substr(md5(labeled_community),0,6))


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/03a05c74-746e-853d-b71d-a34c88be387c.png)

視覚エフェクトで 3D Network Topologyを選択するとこのように見事に色分けされてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/f03d9b48-5025-9b0c-29ec-6fbe2a131c82.png)

# まとめ

これでグラフ図に対してもクラスタリングができ、しかも可視化まで行えるようになりました。
注意点としては、今回GPUを使っているので、クラスタリングまでは大量のデータでも計算はできますが、最後のNetwork Toplogyによる可視化では、Splunk SH側のリソースに依存するため、可視化の時にデータサイズを絞る必要があります。

でも面白いですね。