AI機械学習コンペ2位【睡眠段階の判定 〜睡眠の深さを判別しよう〜】参加＆振り返り

# はじめに
2022/11/18～2023/1/20開催のコンペティション「**睡眠段階の判定 〜睡眠の深さを判別しよう〜**」に参加しました。
本記事では取り組み内容の共有を通して、コンペティションの振り返りをしたいと思います。
# コンペティション概要


https://competition.nishika.com/sleep/summary

* 主催：Nishika
* コンペティション名：睡眠段階の判定 〜睡眠の深さを判別しよう〜
* 参加：633人、投稿：1986件
* 投稿回数は1日5投稿まで（最終スコアは２つ選択可能）
* 概要：睡眠ポリグラフデータ（脳波、眼電図など）から睡眠の深さ段階（覚醒、レム睡眠、stage1～4）を予測
* 評価指標：Accuracy

# コンペティション結果
　**最終ランキング：2位　（ユーザー名：shell1234）**
![コメント 2023-02-10 155216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/bc947425-38d4-013d-9d5c-a6514491fb80.png "睡眠段階の判定コンペランキングボード")
 _睡眠段階の判定[コンペランキングボード](https://competition.nishika.com/sleep/ranking)より抜粋_

# 取り組み内容　 目次
1. 環境
2. データ項目、チュートリアル実行
3. AIモデル検討、全体構成
4. 特徴量エンジニアリング1
5. 特徴量エンジニアリング2
6. モデルチューニング
7. 全体チューニング
8. モデルスコアの推移、最終提出モデル

# 取り組み内容
### 1. 環境 
以下のPC環境でコンペに取り組みました。
  * CPU：Intel(R) Core(TM) i5-8279U CPU @ 1.70GHz  2.21 GHz
  * メモリー：16G 
  * GPU：非搭載
### 2. データ項目、チュートリアル実行
* データ項目
    * 睡眠ポリグラフデータ：脳波、眼電図、顎下筋電図、口鼻呼吸、直腸温
                            （すべて数値データ、edfファイルで提供、100ms毎1レコード）
    * 属性データ：年齢、性別、lights_off時間
    * 睡眠の深さ段階（目的変数）：段階データ（覚醒、レム睡眠、stage1～4）、30秒毎1レコード
* チュートリアル実行
    コンペ開催初期に、EDA（探索的データ分析）、機械学習モデル（Randomforest、CNN）のチュートリアルがディスカッションボードに共有されており、これを活用しデータフォーマット（edfファイル）や実装方法を理解しました。

        
### 3. AIモデル検討、全体構成
* 今回は、GPUを使用しない機械学習モデルを選択
* 機械学習モデルは、AutoMLの一つとされる [Pycaret](https://pycaret.gitbook.io/docs/)  ライブラリーを利用
    * 機械学習モデル比較
        モデル精度の比較は[Pycaret](https://pycaret.gitbook.io/docs/) ライブラリーのcompare_models() を実行すると各種評価指標に対するスコアが出力される。
    * 機械学習モデルベースライン選択
            サンプリングしたスモールデータを利用し、各機械学習モデルの評価において精度の一番高かったLightGBMを選択しました。
    各モデルと評価結果の比較は以下で出力される。

    ```python
    from pycaret.classification import *
    exp1 = setup(traindata, target='目的変数')
    compare_models() 
    ```
    ![モデル選択該当.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/c72e5865-ebb1-46dd-990f-99548c1aa551.png)

* 全体構成
生データから出力までは以下の流れで実施しました。
![モデルフローコメント拡大 2023-02-13 181640.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/fe82bd7f-3bbb-16e3-03c3-2a4982c011e2.png)


### 4. 特徴量エンジニアリング1
 （1st Feature Engineering：周辺知識情報収集、波形特徴量作成）
データの周辺情報の確認として、睡眠ポリグラフ各種データを簡易可視化し周期性のある波形であると確認しました。睡眠に関する各種データ周波数をネット検索し、調査した上で以下の特徴量を作成しました。

* 周波数スペクトラムの作成
    睡眠ポリグラフ各種データを周波数分解し、睡眠に関係がありそうな区間での周波数スペクトラムを特徴量としてモデルの説明変数としました。
* 基本統計量の作成
    30秒区間で1ラベルであるため、100ms行のデータを30秒分まとめて、基本統計量（平均、最大、最小、標準偏差）を特徴量としてモデルの説明変数に追加。
* 波形データの特徴化
    30秒区間で周期性のある波形ととらえ、波形のピーク点数、１波形当たりの区間平均、標準偏差を特徴量としてモデルの説明変数に追加。
* 特徴量集計区間の細分化
    30秒区間をさらに細分化して、5秒区間で上記周波数スペクトラムを抽出し、5秒前、10秒前・・・30秒前と6個の詳細区間の特徴をモデルの説明変数に追加。
    周波数スペクトラム以外の特徴量の細分化は精度が悪化したため非採用としました。
    
### 5. 特徴量エンジニアリング2
（2nd Feature Engineering：時系列特徴量作成）
* 直近情報を時系列特徴量化
    直近XX区間の移動統計量（最大、最小、平均、標準偏差、指数平均）をモデルの説明変数に追加。
* 直近XX区間の特徴量を複数作成
    XXについては、区間増減実験しながら精度向上する区間を決定しました。
    結果的には直近1.5分、3分、中期区間の30分、60分の移動統計量を入れると精度アップが確認できた。

### 6. モデルチューニング
* モデル
　「3. AIモデル検討、全体構成」で選択したLightGBMのみ
* チューニング
　Pycaretのcreate_models()、tune_model()を利用して、CV（Cross Validation：交差検証）やパラメータチューニングをデフォルト設定で実施。
　デフォルト CV：10、パラメータチューニング回数：100回

    コードは以下の4行のみで実施。
```python
from pycaret.classification import *
exp1 = setup(traindata, target='目的変数')
lgbm = create_model("lightgbm")  # モデル作成、CV：10
tuned_lgbm = tune_model(lgbm)  #　パラメータチューニング　CV：10×10回
```
* 評価結果確認
    学習データでの評価結果は以下で出力される。
```python
predict_model(tuned_lgbm)  
```
![スコアイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/fc708bc2-b5d0-a288-9b9b-1a6f9a8bf82b.png)

### 7. 全体チューニング
以下のように説明変数を追加・削除しながら、6. モデルチューニングを実施
* 説明変数の追加
    4.特徴量エンジニアリング1の項目でデータ加工パターンの詳細化、5.特徴量エンジニアリング2のXX区間において直近を細かくしながら、中長期区間を追加していき、精度向上したら説明変数として採用しました。
* 説明変数の削除
    モデル作成後以下のコマンドで表示される説明変数のFeature Importance（重要度ランキング）を確認し、重要でない説明変数は削除しました。
```python
evaluate_model(tuned_lgbm)  # 全体表示
plot_model(tuned_lgbm, plot="feature")  # 上位のみ表示下記出力図 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/516811cf-aa25-1c2a-f99e-7eb7db66642b.png)


### 8. モデルスコアの推移、最終提出モデル
* 提出モデルスコアの推移は以下の通り。極端にスコアが落ちている点は実装ミスによるもの。
![スコア遷移2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636082/d09f9035-1c86-3364-7057-ae41274c1a67.png)


* 最終提出モデル（2つ提出可能）
    1：暫定スコアの一番よいモデル
    2：各特徴がバランスよく選ばれた説明変数モデル※　**今回スコア2位獲得**
    　　※生データの特徴は周波数と基本統計量の両方使用していたが、生データの基本統計量は周波数と重複し、ノイズを含んでいると考え、周波数特徴量のみとしました。

# おわりに
コンペでは1、2回提出して、データの傾向を把握したり、腕試しするのも面白いです。
さらに、期間中何度か調査、試しながら実施することでいろいろなデータ特徴の抽出方法を体感できたり、実装効率化の技術を学べると感じました。

特にモデル作成作業において、CV（Cross Validation：交差検証）やパラメータチューニングを数行で実施可能なPycaretを活用し、作業コストを削減させ、特徴量作成に集中できたことが高精度、高スコアにつながったと考えております。

ここまでお読みいただきありがとうございました。