Radiomics heat mapを描こう

# あらまし

Radiomicsは、たくさんの画像特徴を機械学習の説明変数として利用して、予測モデルを作成することがよく行われます。
例えば、分類問題であれば、説明変数にクラス間で差があれば、分類精度の高い予測モデルが作成できます。
予測モデルを作成する前に、このような説明変数の差を大まかに確認したり、グループにまとめることができれば、効率的に機械学習を進めることができます。
このようなグループの差をわかりやすく説明するために、ヒートマップが用いられることがあります。

# データセット
RSNA 1p19q codel datasetからRadiomicsJを用いて抽出されたRadiomics特徴
LABELは、0: 共欠失なし,1: 共欠失あり

読み込んで、標準化までしておきます。
（標準化はseabornでもできるのですが、ここは一例として先に標準化します）

```
# データ（CSV）の場所　（公開リンク）
# https://drive.google.com/file/d/1FNsZcDGoiPdGE5K4Iyb2kA51tREhWZB5/view?usp=sharing

import seaborn as sns; sns.set_theme(color_codes=True)
import pandas as pd
import numpy as np

# リンクのCSVをColabへアップロードしてから
features = pd.read_csv("RadiomicsJ_result_weka.csv", dtype=np.float64)
# NaN（0 dividedとなってしまった結果）がStringで入っているので、0に置き換えます。
features = features.fillna(0) 
# クラスラベルで行を並び替えます
sorted_features = features.sort_values(by=['LABEL'], ignore_index=True) # 0: no codel, 1: codel
# ラベルをデータセットから分けます
codel = sorted_features.pop("LABEL")

# standardize
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(sorted_features)
std_ds = scaler.transform(sorted_features)
std_ds = pd.DataFrame(std_ds, columns=sorted_features.columns)
```

# ヒートマップ

まずは単純なヒートマップです。

```
# シンプルなヒートマップ
ax = sns.heatmap(std_ds, vmin=-1.5, vmax=1.5)
ax.set_xlabel("features")
ax.set_ylabel("subjects")
ax.set_title("Radiomic features heatmap")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/c696a42d-1cc9-7148-af3b-9fecbdbe25e8.png)

共欠失有りのほうが、T2W画像の信号強度関連の特徴が低い傾向があるように見えます。

# クラスラベル付きのヒートマップ

クラス間の差を見やすくしたヒートマップです。
クラスごとのLUTを作成してセットします。

```
# lutの準備
# 赤: 0, 青: 1
lut = dict(zip(codel.unique(), "rb"))
# print(lut)
row_colors = codel.map(lut)

# simple heat map with class label
g = sns.clustermap(std_ds,
                   cmap="viridis",
                   # Turn off the clustering
                   row_cluster=False, col_cluster=False,
                   # Add colored class labels
                   row_colors=row_colors, col_colors=None,
                   # Make the plot look better when many rows/cols
                   linewidths=0,
                   vmin=-1.5, vmax=1.5,
                   xticklabels=False, # features list
                   yticklabels=False # subjects
                   )
g.ax_heatmap.set_title('Cluster map')
g.ax_heatmap.set_xlabel('features')
g.ax_heatmap.set_ylabel('subjects')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/bbd10f63-c386-cd53-b89a-d6d6ead2f65f.png)


# クラスターマップ

クラスタリングを組み合わせたマップです。
```
g = sns.clustermap(std_ds, row_colors=row_colors, vmin=-1.5, vmax=1.5)
# g.fig.suptitle('Cluster map') # 重なってしまうので一旦コメントアウト
g.ax_heatmap.set_xlabel('features')
g.ax_heatmap.set_ylabel('subjects')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379410/e6977390-549a-8a00-0356-cbeb46443b3c.png)

ここで、うまくクラスがまとまれば、いいデータなのですが、クラスラベルのばらつきを見てみると、このデータでは少し難しいようだ、ということがわかります。
クラスターがうまく作れるか、各特徴はどう相関しそうか、グループはどうわけられそうかなど、おおまかに俯瞰できます。

# References
- seaborn.heatmap: https://seaborn.pydata.org/generated/seaborn.heatmap.html
- seaborn.clustermap: https://seaborn.pydata.org/generated/seaborn.clustermap.html
- クラスラベルを追加する: https://stackoverflow.com/questions/27988846/how-to-express-classes-on-the-axis-of-a-heatmap-in-seaborn
- seaborn の clustermap をちゃんと理解する:https://nykergoto.hatenablog.jp/entry/2018/11/19/seaborn_%E3%81%AE_clustermap_%E3%82%92%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B
- RadiomicsJ: https://sites.google.com/vis-ionary.com/public/ij-plugin_radiomicsj