日本語CTRLを1から学習する - 1

はじめに

前回 日本語での文章生成器作成のために必要なことをまとめた。
今回は計算リソース確保のためにGCPについて調査した。

GCP

GCPGoogle が提供するクラウドプラットフォームである。

GCP機械学習を行うためには以下の処理が必要である

  • プロジェクトの作成
  • Compute Engineの設定
  • Storageの設定

プロジェクト

  • プロジェクトはGCPのリソース(計算マシン、ストレージなど)をまとめる単位である
  • GCPの計算リソースはすべていずれかのプロジェクトに属する必要がある
  • 異なるプロジェクト間の通信には共有VPC(Virtual private cloud)が必要
  • 課金はプロジェクト単位で行われる

Compute Engine1

GCPのCompute Engineは計算用の仮想マシンを作成するサービスである。
以下の要素を指定して仮想マシンを作成する

Cloud Storage2

GCPのCloud Storageはファイル保存用のストレージである。
Compute Engineも独自のディスクを持っているいるため
小規模なデータを取得、学習し、モデルや結果を保持することは可能である。
しかし、Compute Engineはinstanceが存在するだけでそれなりに料金がかかるため
学習するとき以外は止めておいたほうが良い。

Cloud Storageはただデータを保管するだけのためのサービスであり、
維持費用はCompute Engineよりもはるかに安い。
そのため学習対象のデータや学習結果・モデルなどはCloud Storageに保存しておいて
学習するときにCompute Engineとデータのやりとりを行うほうがリーズナブルである。

GCPによる機械学習

今回はGCPの使い方を覚えるために
「Compute Engine上でMNISTデータによりCNNを学習し、 学習済みモデルをCloud Storageに保存する」
というタスクを行った。

これを実現するために以下の順に処理を行った。

  1. プロジェクトを作成する
  2. Compute Engineを立ち上げる
  3. Cloud Storageを作成する
  4. Cloud StorageにMNISTデータをアップロードする
  5. Cloud StorageからCompute Engineにデータを転送する
  6. Compute Engineで学習を行う
  7. 学習済みのモデルとログをCloud Storageに送る。

※ MNISTの場合、Compute Engineに直接webからデータをダウンロードしたほうが楽だが、練習のため一度Cloud Storageを経由している。

プロジェクトを作成する

プロジェクト名は全ユーザーで共通しているため
ユニークに指定する必要がある

Compute Engineを立ち上げる

基本的にデフォルト値で問題ないが、 ブートディスクはデフォルトで
Debian GNU/Linux 9 (stretch)」となっている。
機械学習環境が最初から入っていた方が楽なのでブートディスクを

オペレーティングシステム
Deep Learning on Linux
バージョン
Deep Learning Image: Pytorch 1.4.0 and fastai m45

に変更した。
(pytorch, torchvision は入っていたがtorchtextは入っていなかったので利用する場合は pip等でインストールする必要がある)

今回はGPUなしで検証するため一番安いCPU(1-CPU 3.75GBメモリ) でinstanceを作成した。

Cloud Storageを作成する

Storageはバケットという単位で管理される。
今回はデフォルトの設定で適当に名前をつけて作成した。

Cloud Storageにデータをアップロード

今回はMNISTを小さなモデルで学習するため
以下の2つのファイルをアップロードする

  • MNIST.zip (torchvisionのMNISTデータセットによってダウンロードしたMNISTデータが入ったフォルダをzip圧縮したもの)
  • train.py (学習用スクリプト, logs.csv, model.pthの2つのファイルを出力する)

train.py

import numpy as np
import pandas as pd
from tqdm import tqdm
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
import torchvision
# パラメータ設定
batch_size = 32
root_dir = "./"
num_epochs = 5
# データ読み込み
img_transform = transforms.Compose([transforms.ToTensor()])
label_transform = lambda x:torch.Tensor([x]).long()
train_dataset = torchvision.datasets.MNIST(root_dir, train=True, transform=img_transform, target_transform=label_transform, download=False)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
# モデル構築
class SmallModel(nn.Module):
  def __init__(self):
    super().__init__()
    self.conv1 = nn.Conv2d(1, 16, 3, padding=1)
    self.conv2 = nn.Conv2d(16, 32, 3, padding=1)
    self.pred = nn.Linear(32, 10)
    self.act = nn.ReLU(inplace=True)    
  def forward(self, x):
    x = self.act(self.conv1(x))
    x = F.max_pool2d(x, 2)
    x = self.act(self.conv2(x))
    x = F.max_pool2d(x, 14).view([-1, 32])
    x = self.pred(x)
    return x
model = SmallModel()
criteria = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters())
# 学習
logs = []
for epoch in range(num_epochs):
  losses = []
  for imgs, labels in tqdm(train_loader):
    optimizer.zero_grad()
    out = model(imgs)
    loss = criteria(out, labels.view([-1]))
    loss.backward()
    optimizer.step()
    losses.append(loss.item())
  logs.append([epoch + 1, np.mean(losses)])
  print("epoch {}, train loss {}".format(*logs[-1]))
logs_df = pd.DataFrame(logs, columns=["epoch", "loss"])
logs_df.to_csv("logs.csv", index=None)
torch.save(model.state_dict(), "model.pth")

Cloutd StorageからCompute Engineへのデータ転送

Cloud StorageからCompute Engineへのデータ転送は
Compute Engineにログインしてからgsutilコマンドを使う方法が簡単だった。

参考: https://cloud.google.com/compute/docs/instances/connecting-to-instance#gcetools

コピーコマンド(Compute Engineインスタンス上で実行)

gsutil cp gs://bucket_name/* .

これによりCloud Storage上で作成したbucket_nameというバケット内のファイルが Compute Engineのインスタンス上にコピーされる。

Compute Engineで学習を行う

Compute Engine上でMNIST.zipを解凍して、以下のコマンドを実行するだけである。

python train.py

最低性能のCPUでも3分ほどで学習が終わった。

学習済みのモデルとログをCloud Storageに送る

基本的にはStorageからコピーした時と同じコマンドで転送可能なのだが
今回はストレージの権限を適当に設定していたので
Compute Engine上で以下のコマンドにより権限を設定する必要があった。

権限の設定
gcloud auth login
ファイルの転送
gsutil cp logs.csv gs://bucket_name/* 
gsutil cp model.pth gs://bucket_name/* 

コマンド実行後、Cloud Storage上でも2つのファイルが保存されていることを確認できた。

まとめと今後

今回はGCP上で最低限機械学習を行う上で必要と思われる処理を調査・実行した。

  • Compute Engine, Cloud Storageの使い方を学んだ
  • gsutilによりCompute EngineとCloud Storage間でデータの転送を行うことができる
  • 権限関係は最初から設定しておいたほうが良い

今後はどのようなシステム構成にすれば費用対効果が高いかなどを調査する必要がある。

参考文献