三日坊主のプログラミング日誌

なんか色々書いておくところ。

Deep Learning for Time Series No.2

2020年初投稿です。

コロナで殆どの就活が止まり、推薦で進んでいた某JTBCは落ち、 泣きっ面にJASSMな中の人です。

お祈りメールを受ける30分前に前回の Deep Learning for Time Series No. 1 にスターがついたって通知が来て、こんな事やってたなって思い出したので、ちまちま書いていきます。

今回のお題は、CNNを使ってセンサーデータを分類するタスク。

準備

前回と同じく、SensorDatasetCollection の中に入ってるUCR HARデータセットを使います。 インストールは以下のようにして下さい。

pip install git+https://github.com/khirotaka/SensorDatasetCollection.git

次に、自分がKaggleや修士の研究のために作っている PyTorchラッパーをインストールしましょう。

github.com

pip install enchanter

Enchanterは comet.ml にガッツリ依存するように設計しているので、この先に進むには、アカウントを取得することをお勧めします。

実装

まずは使うモジュールの読み込みと、データセットの準備をします。

from comet_ml import Experiment

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader

import enchanter
import enchanter.addons as addons

from sdc.datasets.uci import load_har


(x_train, y_train), (x_test, y_test) = load_har(raw=True)
x_train = x_train.astype("float32")    # PyTorchの入力は float32 なので
x_test = x_test.astype("float32")

y_train = y_train.astype("int64")       # PyTorchのラベルはint64なので
y_test = y_test.astype("int64")

y_train = y_train.reshape(-1, ) - 1       # データセットのラベルが1はじまりなので
y_test = y_test.reshape(-1, ) - 1

データセットの準備が終わったので、次はPyTorchに流せるようにします。 今回のデータセットは固定長なので、次のようにするだけで解決です。

train_ds = enchanter.engine.modules.get_dataset(x_train, y_train)
test_ds = enchanter.engine.modules.get_dataset(x_test, y_test)

train_loader = DataLoader(train_ds, batch_size=512)
test_loader = DataLoader(test_ds, batch_size=512)

あとは、ネットワークの実装をするだけです。 ここで実装するネットワークは非常に簡単なCNNで、活性化関数にMishを使っています。 理由はなんとなく。 ちゃんと設計するのだったら、層数や中間層のパラメータ、活性化関数の種類、あとはモデル構造(ResNetとか)を考える。

class Network(nn.Module):
    def __init__(self, in_channels, n_class):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv1d(in_channels, 32, 3),
            nn.MaxPool1d(3),
            addons.Mish()
        )
        self.fc = nn.Sequential(
            nn.Linear(32 * 42, 128),
            addons.Mish(),
            nn.Linear(128, n_class)
        )
    
    def forward(self, x):
        x = x.permute(0, 2, 1)
        out = self.conv(x)
        out = out.view(-1, 32*42)
        out = self.fc(out)
        return out


model = Network(9, 6)
optimizer = optim.Adam(model.parameters())

これで準備が完了です。あとはラッパーに丸投げしましょう。

runner = enchanter.wrappers.ClassificationRunner(
    model, 
    optimizer,
    nn.CrossEntropyLoss(), 
    Experiment("XXXXXXXXXXXXXXXXXX")    # Comet.ml のAPIキー
)
runner.add_loader("train", train_loader)
runner.add_loader("test", test_loader)
runner.train_config(epochs=50)
runner.run()

Enchanterの RunnerはGPUが使える場合は、自動的に使ってくれます。 明示的に指定する場合は、

runner.device = torch.device("gpu:1")
# or
runner.device = torch.device("cpu")

とすればOK。

最後に

これで、RNN・CNNの両方で、時系列データ(センサーデータ)を使ってニューラルネットで分類タスクを行う事ができました。 やる気が出れば、Transformer(Self-Attention) 系を使って時系列分類タスクを行おうと思います。

就活ツライ、どっか拾ってくんねぇかな... 人柄もスキルもとても評価してくれたなら採用してくれよ!

あ、あと、Kaggleで銀メダル取りました!!拾って下さい!

www.kaggle.com

EnchanterのAPIに関しては、 enchanter.readthedocs.io

プライバシーポリシー お問い合わせ