MWS Cup参戦記

この記事は、[大阪工業大学 Advent Calendar 2023](https://adventar.org/calendars/9140)の6日目の記事です  

- [はじめに](#はじめに)  
- [注意](#注意)
- [ところで](#ところで) 
- [主にしたこと](#主にしたこと)
    - [基礎知識](#基礎知識)
    - [練習段階](#練習段階)
    - [本番](#本番)
    - [寄り道](#寄り道)
- [感想など](#感想など) 
- [参考文献](#参考文献)


# はじめに
今年もAdvent Calendarに出没しましたゆらぎです。  
今年あったことと言えば研究室配属などですが、会う人ほぼ全員にあなたそっち行ったのと言われ遺憾の意を示したいところです。  
さて、本記事では配属された研究室で出たMWS Cupで私が担当した分野のアウトプットをしたいと思います。  

# 注意
本記事は私がMWS Cupに出場する際に0から学んだ知識のみをまとめているため、不正確な情報が存在していたり、kaggleに特化した内容が多く含まれています。  

# ところで
MWS Cupって何?というと以下の引用文を読んでください。  
>MWS Cup は、研究用データセットの活用によるマルウェア対策研究の成果を活用して、規定時間内で課題に取り組み解析結果を競います。技術的な解析の正確性と、採点委員による解析方法のプレゼンテーションの採点から、合計点が高いチームから表彰します。研究用データセット活用WGにおいて、1チーム当り 6名までエントリーを募集し、受付後に各課題の事前準備を各チームに依頼します。[^1]  


上記の通りマルウェアに関する競技を4つ行います。  
分野は、事前課題、表層解析、静的解析、DFIRの4つです。  
私はどこぞの人と表層解析を担当しました。  
表層解析では、約1週間と当日数時間でkaggleを使用したデータ分析を行います。  
詳しくはMWS Cupの[ページ](https://www.iwsec.org/mws/mwscup.html)を見てください。  
ちなむとcss併設イベントです。  

# 主にしたこと　　
したこととしては、まず「初めてのマルウェア解析」と「Kaggleで勝つデータ分析の技術」を読みました。  
両方2~3周はしています。  
終わり次第手を動かしました。

実装練習を行う時にはkaggleを使用しました。  
kaggleのコンペでは予測したデータを提出したら精度を表示してくれます。  
また、本番でもkaggleが使用される予定でしたのでkaggleに慣れる意図もありました。  
kaggleのコンペを使用して実際に分析をする際には、titanicコンペを使用しました。  
kaggleには様々なコンペが存在しており、その実装などが転がっていますが一々データの分析をしたりコンペについて理解を深める時間があったら実装に慣れる方がいいと判断しtitanicコンペのみを使用しました。  
titanicコンペは初心者向けなこともあってか様々な手法でデータ分析を行っている記事が多く存在していたのでとても助かった記憶が未だ新しいです。(手に馴染むまではできなかった)  

## 基礎知識
### 目的変数  
実際に予測するラベルや値のこと。

### 特徴量
変数や説明変数と呼ぶこともある。各レコードにある目的変数を予測するために使うことができる様々な値。  


### 学習データ
予測モデルを作成するために使用するデータ。  
特徴量と目的変数が含まれ、特徴量と目的変数の関係を学習するために使用する。

### テストデータ
実際にモデルを使用して予測を行う際に使用するデータ。  
特徴量のみが含まれている。  

### 評価指標
学習させたモデルの性能やその予測値の良し悪しを計る指標。

### 混合行列
- TP(True Positive)  
実際に正例であるものを正例であると予測したものの数
- TN(True Negative)  
実際に負例であるものを負例であると予測したものの数
- FP(False Positive)  
実際に負例であるものを正例であると予測したものの数
- FN(False Negative)  
実際に正例であるものを負例であると予測したものの数

### accuracy(正答率)とerror rate(誤答率)
accuracyは予測が正しい割合、error rateは予測が間違っている割合を表す指標のこと。  
$$ accuracy = \frac{TP + TN}{TP + TN + FP + FN} $$  
$$ error rate = 1 - accuracy$$

```python:サンプルコード
from sklearn.metrics import accuracy_score
accuracy_score(y_true, y_pred)
```

### precision(適合率)とrecall(再現率)
precisionは、正例と予測したもののうち、真の値も正例であるものの割合。  
recallは、真の値が正例のもののうちどの程度を正例として含めれているのかの割合。  
$$ precision = \frac{TP}{TP + FP} $$
$$ recall = \frac{TP}{TP + FN} $$

### f1-scoreとfβ-score
F1-scoreは、precisionとrecallの調和平均。  
$$ F1-score = \frac{2}{\frac{1}{precision} + \frac{1}{recall}} = \frac{2TP}{2TP + FP + FN} $$
Fβ-scoreは、precisionとrecallの調和平均をとる際に、recallの重みをβ倍する。
$$ Fβ-score = \frac{(1 + β^2)TP}{(1 + β^2)TP + β^2FN + FP} $$

※F1-scoreは陽性と陰性について対称に扱っていない。

### 目的関数
モデルの学習において最適化される関数。  
モデルの学習では、目的関数が最小となるように決定木の分岐や線形モデルの係数の追加や更新などを行う。

### out-of-fold
データをいくつかに分割し、そのうちの1つを予測対象とし、残りを予測用の学習データとする手法。

### 欠損値
本来得られるはずだったデータが欠損している状態のこと。

#### 欠損地の扱い
欠損値となっている理由としては以下の理由が考えられる。
- 値が存在しないケース
- 何らかの意図があるケース
- 値を取得するのに失敗したケース

欠損値が存在している場合何らかの方法でそれを無くす必要がある。  
しかし、欠損値は何らかの理由で欠損しているという情報を持っていると考えると、欠損値を無くすことはデータの歪みを招く可能性がある。  
そのため、欠損地を埋めずにそのまま扱うこともある。  
scilit-learnのランダムフォレスト等では欠損値を扱えないため、-9999などの通常取り得る値にない値を欠損値とすることで欠損値と似たような挙動をするようにすることがある。

欠損値を代表値で埋めるという方法もある。  
これは、欠損の発生がランダムならば、最もあり得る値をいれればいいだろうと言う考え方である。
代表値としては、平均値や中央値、最頻値などがある。

### モデル
特徴量を入力データとし、予測値を出力する変換器のこと。  
```python:サンプルコード
# モデルのハイパーパラメータを辞書型で定義
params = {'param1': 10, 'param2': 100}
# モデルのインスタンスを作成
model = Model(**params)
# モデルの学習
model.fit(X_train, y_train)
# テストデータに対して予測結果を出力
y_pred = model.predict(X_test)
```

### モデルの評価(バリデーション)
モデルを作る上で、そのモデルがいいのか悪いのかの評価を行う必要がある。  
しかし、すでに使用したデータで評価しようとしても、未知のデータに対する予測性能を評価することができない。  
そのため、一部のデータをバリデーションデータ(検証用データ)として分けておき、評価のために使用する。  

### hold-out法
データを学習データとテストデータに分割し、学習データでモデルを学習させ、テストデータでモデルの評価を行う手法。

### クロスバリデーション
データをいくつかに分割し、そのうちの1つを予測対象とし、残りを予測用の学習データとする。分割した回数だけ、バリデーションデータを買えて学習及び評価、バリデーションデータでのスコアを求める。  
それらのスコアの平均でモデルの評価を行う。

### 過学習
学習データのランダムなノイズまで学習してしまい、学習データではスコアがいいが、それ以外のデータではスコアが悪くなること。  

### アンダーフィッティング
十分に学習データの性能が学習できていなく、学習データでもそれ以外のデータでもスコアがよくないこと。  

### 正則化
学習時にモデルが複雑なときに罰則を科すこと。  

### アーリーストッピング
学習時にバリデーションデータのスコアをモニタリングし、一定の間スコアが上がらない場合、途中で学習を終了する手法。

## 練習段階
kaggleのコンペが始まる前に実装に慣れるために記事や本を参考にしながら実装したものや知った知識。

### GBDT(勾配ブースティング木)
勾配降下法とブースティングと決定木の3つの手法を組み合わせた手法。  
昨年効果的だった手法の中に勾配ブースティング木があったためその実装を何回かや行った。  
lightgbmとかxgboostとかcatboostとか

### xgboost
決定木の勾配ブースティングアルゴリズム  
```python:サンプルプログラム
import xgboost as xgb

dtrain = xgb.DMatrix(train_X, label=train_y)
dvalid = xsb.DMatrix(valid_x, label=valid_y)
dtest = xgb.DMatrix(test_x)

params = {"random_state":7}
num_round = 50

model = xbg.train(params, dtrain, num_round,evals=[(dtrain, 'train'),(dvalid, 'eval')],early_stopping_rounds=num_round)

y_pred = model.predict(dtest)
```

### lightgbm
2016年にリリースされ、xgboostを改良した手法  
弱学習器である決定木を勾配ブースティングによりアンサンブル学習[^3]した手法
```python:サンプルプログラム
import lightgbm as lgb

# 特徴量と目的変数をlightgbmのデータ構造に変換
lgb_train = lgb.Dataset(train_x, train_y)
lgb_test = lgb.Dataset(test_x, test_y)

params = {"randomstate":42}
model = lgb.train(params, lgb_train)

pred = model.predict(test_x)
```

### catboost
2017年にリリースされた勾配ブースティングの一種  
Categorical Featuresが多いデータに強い  
```python:サンプルプログラム
from catboost import CatBoostClassifier

cbc = CatBoostClassifier(num_boost_round  = 100, depth = 10)

cbc.fit(train_x, train_y,
        eval_set = [(valid_x, valid_y)],
        early_stopping_rounds = 100, verbose = 10)

y_pred = cbc.predict(test_x)
```

### BERT
自然言語処理系のすごいやつ  
記事や[解説動画](https://youtu.be/IaTCGRL41_k?si=en4B6-fO78-6CkrK)を読んでも触りしか分からなかった  

### random forest
決定木の集合により予測を行うモデルだが、GBDT
とは違い並列に決定木を作成する。  
それぞれの決定木の学習においてレコードや特徴量をサンプリングして与えることで多様な決定機を作成し、これらをアンサンブルすることで汎化性能の高い予測を行う。
```python:サンプルコード
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(train_x, train_y)

y_pred = model.predict(test_x)
```

### bag-of-words
文書などのテキストを単語に分割し、各単語の出現数を順序を見死して単純にカウントする方法。  
sklearn-learnのfeature_extraction.txtモジュールのCountVectorizerでこの処理を行うことができる。

### TFIDF
bag-of-wordsで作成した単語文書のカウント行列を変換する手法。  
- tf(term frequency)  
あるテキストでのその単語の出現比率  
- idf(inverse docment frequency)  
その単語が存在するテキストの割合の逆数の対数。

## 本番
kaggleのコンペが始まった段階で行ったこと。
上記の勾配ブースティング木は実装したけれど精度は誤差の範囲内でしか変わらなかった。  

### オーバーサンプリング
今回与えられたデータの分布を確認するとラベルのうち1つだけ圧倒的に数が少なかったためオーバーサンプリングという手法を用いて、データの増幅を行った。  
オーバーサンプリングは少ない方のデータをただ単にコピーするのではなく、近傍にあるデータを用いて増やす手法。  
使用したのはオーバーサンプリングの中で代表的なSMOTE。

### bagging
複数のモデルを組み合わせてモデルを作成する方法の一つ。  
同じ種類のモデルを並列に複数作成し、それらの予測値の平均などを用いて予測する。  

### 半教師あり学習
教師あり学習はラベル付きデータで学習させたモデルを使用する手法。一方で、半教師あり学習は少量のラベルありデータで学習させた後、ラベルなしデータで再度学習させる手法のこと。  

- 教師あり学習のメリットデメリット  
教師あり学習のメリットとして、正解となるデータを与えるため学習制度が高く、学習速度も早いことがある。  
デメリットとして、正解が存在しない分野には利用できないことや、正解となるデータの質が精度に影響を与える。
- 半教師あり学習のメリットデメリット  
半教師あり学習のメリットとして、ラベルありデータとラベルなしデータの両方を使用して学習ができるため、学習データが不足しているときに有効活用できる可能性がある。  
デメリットとして、ラベルありデータに偏りがあると上手くモデルが学習できないことがある。  

## 寄り道
練習時や本番時に使用するものを調べるついでに知った知識たち

### アンダーサンプリング
多数派のデータを少数派のデータ数に合わせて削除する手法。  

### 重みづけ
目的関数の誤差にラベルごとのペナルティを加えることで不均衡データでも均衡データと同じように目的関数を最適化させる方法。

### pandas 
pythonのライブラリの一つ  
データ整形やデータ分析を行う際に使用する。  
例えば、csvの読み込みやデータの結合、データの抽出などができる。  
今回ではtrainデータやtestデータの読み込みや、データの結合などを行う際に使用した。  

### numpy
pythonのライブラリの一つ
高速計算処理を得意とする  
今回では、行列の形状を調べる際に使用したり、np.argmaxなどを使用した。

### scikit-learn
pythonのライブラリの一つ  
機械学習の手法を実装する際に使用する。

# 感想など
これに出場が決定した時点での私の表層解析に関わる知識のレベルは以下の通りです。  
- 機械学習:名前だけ知ってる  
- python:1年の時に軽く触って文法などは忘れてないけど慣れてない  
- kaggle:名前しか知らない  
- マルウェア:授業で習った程度    

2か月ほぼない状態で上記の状態からどうにかするのは普通の方法じゃどうしようもできないので同じく表層担当した人に  
「パワハラしていいよ」  
と言いました。  
それで結局やった覚えてる限りのスケジュールを以下に書くと  
- 9月上旬: 出場が確定したので、本1冊[^1]1章読む  
- 9月下旬から10月上旬: 本一冊[^2] 2周
- 10月中頃: 実装練習  (勾配ブースティング木とbertなど)
- 10月下旬: kaggleコンペ開始  

大体こんな感じだったはず  
正直こんなに手をかけてもらったのに何もできなかったことがとても悔しいです。    
2か月あるかないかくらいの時間じゃあまり身につかなくて結局役に立てなかったのでもっと知識付けます。(どうせ来年出場ほぼ確定しているし)  
来年表層に新しい人が来る場合は、このスケジュールじゃきついので早めに取り組むかこれより頑張ってほしいです。  
他の2分野では惜しいところまで行っていたので来年がとてもたのしみです。



# 大会のために読んだ本
- Kaggleで勝つデータ分析の技術  
- はじめてのマルウェア解析  


[^1]: https://www.iwsec.org/mws/mwscup.html
[^2]: Kaggleで勝つデータ分析の技術
[^3]: アンサンブル学習とは弱学習器を多く使うことで精度を上げる手法のこと

# 参考文献
[不均衡データ](https://qiita.com/tk-tatsuro/items/10e9dbb3f2cf030e2119)  
[Kaggleで勝つデータ分析の技術](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94/dp/4297108437)  
[【Python】Pandasの基本まとめ（初心者向け）](https://qiita.com/shimotaroo/items/d3fd17b4d5f470cae957)  
[【完全版】NumPyの使い方を徹底解説【機械学習】](https://qiita.com/juri_engineer/items/f641870b0644d2f8d667)