Blogger Syntax Highliter

Sunday, January 6, 2019

大きなコンテナイメージをKubernetesで使うためにエラーの対処法から構成を考えてみたメモ

はじめに

自然言語処理とか画像認識の機械学習向けのKubernetes環境にPython(Anacondaから構築した環境)のコンテナを使用する場合があると思います。処理のためのモデルやデータを含めてコンテナ化することがあると思いますが、7GぐらいのコンテナになってしまうとKubernetesのPull時に必ずエラーになるので、AKS(Azure Kubernetes Service)を使って対処法を検証してみました。(エラーメッセージは出ますが最終的にはPull完了しますします)

エラーメッセージの対処法を考える

例えば以下の様なエラーメッセージ。

Failed to pull image "kekekekenta.azurecr.io/nlp-tools": rpc error: code = FailedPrecondition desc = unexpected EOF

kubernetesのgithubやstackoverflowを探しても色々な人が悩みを持っているようですね。それらをまとめると以下のような案がありました。

  • Pullのタイムアウトを長くすることができるか?
  • Pullの速度(ダウンロードと展開)を速くすることができるか?
    • ネットワークは速いので展開時の時間を短くするために圧縮アルゴリズムを変更したい。

Pullのタイムアウトを長くすることができるか?

Pull時のタイムアウトは以下のURLにも書かれていますが、デフォルト設定で2分になっています。 https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/

--runtime-request-timeout duration

Timeout of all runtime requests except long running request - pull, logs, exec and attach. When timeout exceeded, kubelet will cancel the request, throw out an error and retry later. (default 2m0s)

AKSの実際のタイムアウトは何分に設定されているか不明ですが、Azure Container Service EngineのGithubでは以下のように書かれていました。

https://github.com/Azure/acs-engine/blob/master/parts/k8s/kubernetesconfigs.sh

setKubeletOpts " --container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"

どちらにしても、提供されているものを使っている限りはこの設定は変更できないので別の方法を探します。

Pullの速度(ダウンロードと展開)を早くすることができるか?

Pullの速度は、コンテナイメージのダウンロードと、tar.gzされたコンテナイメージのレイヤーを展開する測度が関係してきますが、ACR(Azure Container Registry)からのダウンロードはほぼ気にならないぐらい速いので、展開する方を速くできないか考えてみます。Githubでも色々な案が出ていましたが、現段階での実装でなんとかならないかと思い、gzipの測度を圧縮レベルを変えて測定してみます。

試しに/usrをtarしたファイルを2つ用意します。

 
$ ls -la
 
-rw-rw-r-- 1 kenta kenta 1114408960 Jan  5 01:50 usr1.tar
-rw-rw-r-- 1 kenta kenta 1114408960 Jan  5 01:52 usr9.tar

gzipする時の時間は遅くても問題ないのですが、とりあえず計測してみます。 -1は圧縮率が低いけど高速。-9は圧縮率が高いけど低速です。

 
$ time gzip -1 usr1.tar
 
real    0m19.791s
user    0m19.091s
sys    0m0.696s
$ time gzip -9 usr9.tar
 
real    3m47.467s
user    3m46.716s
sys    0m0.747s

圧縮したファイルをtarで展開してみますが、そんなに変りませんね。。

 
$ time tar xfz usr1.tar.gz
 
real    0m21.931s
user    0m10.419s
sys    0m4.389s
$ time tar xfz usr9.tar.gz
 
real    0m20.804s
user    0m9.375s
sys    0m4.292s

別の方法を考えて見ます。

コンテナイメージのレイヤーを複数に分割する

コンテナイメージを作る際はイメージサイズを小さくするためにレイヤーを纏めた方が良いとされていますが、レイヤーを纏めると1つのレイヤーの展開に時間がかかります。また、並列ダウンロードもされません。また、今回はRPCからエラーがでている事もあり、もっとレスポンスの良いコンテナイメージにしてあげる必要があるかもしれません。 そこで、レイヤーを纏めたコンテナイメージと、複数のレイヤーに分けたコンテナイメージを作成して、Pull時の動作を確認することにより、KubernetesのPullに適したコンテナ構造を検証します。

コンテナイメージを用意

レイヤーを纏めたDockerfile(1つのRUNで纏める)を用意しました。色々インストールしています。

 
FROM continuumio/anaconda3
RUN buildDeps='make libc6-dev gcc g++' \
    && set -x \
    && echo 'Installing Mecab' \
    && apt-get update && apt-get install -y $buildDeps --no-install-recommends \
    && apt-get -y install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8 \
    && mkdir -p `mecab-config --dicdir` \
    && git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git \
    && /mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y \
    && export VAL=`mecab-config --dicdir`/mecab-ipadic-neologd; sed -i 's#^\(dicdir\s*=\s*\).*$#\1'$VAL'#' /etc/mecabrc \
    && echo 'Installing Tika' \
    && apt-get -y install openjdk-8-jre-headless tesseract-ocr tesseract-ocr-eng tesseract-ocr-jpn \
    && curl --output /tmp/tika-server.jar http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/1.16/tika-server-1.16.jar \
    && curl --output /tmp/tika-server.jar.md5 http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/1.16/tika-server-1.16.jar.md5 \
    && echo 'Installing Python' \
    && apt-get install -y swig \
    && conda update -y -n base conda \
    && conda install -y -c anaconda gensim requests nltk \
    && conda install -y -c conda-forge tika \
    && pip install tinysegmenter sumy mecab-python3 langdetect \
    && rm -rf /mecab-ipadic-neologdclone \
    && rm -rf /var/lib/apt/lists/*

複数のレイヤーに分割したDockerfile(複数のRUNで分割する)は以下の通り。

 
FROM continuumio/anaconda3
RUN buildDeps='make libc6-dev gcc g++' \
    && set -x \
    && echo 'Installing Mecab' \
    && apt-get update && apt-get install -y $buildDeps --no-install-recommends
RUN apt-get -y install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8 \
    && mkdir -p `mecab-config --dicdir` \
    && git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
RUN /mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y \
    && export VAL=`mecab-config --dicdir`/mecab-ipadic-neologd; sed -i 's#^\(dicdir\s*=\s*\).*$#\1'$VAL'#' /etc/mecabrc
RUN echo 'Installing Tika' \
    && apt-get -y install openjdk-8-jre-headless tesseract-ocr tesseract-ocr-eng tesseract-ocr-jpn \
    && curl --output /tmp/tika-server.jar http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/1.16/tika-server-1.16.jar \
    && curl --output /tmp/tika-server.jar.md5 http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/1.16/tika-server-1.16.jar.md5
RUN echo 'Installing Python' \
    && apt-get install -y swig \
    && conda update -y -n base conda \
    && conda install -y -c anaconda gensim requests nltk \
    && conda install -y -c conda-forge tika
RUN pip install tinysegmenter sumy mecab-python3 langdetect \
    && rm -rf /mecab-ipadic-neologdclone \
    && rm -rf /var/lib/apt/lists/*

ビルドします。

 
$ docker build -t kekekekenta.azurecr.io/nlp-tools nlp-tools
$ docker build -t kekekekenta.azurecr.io/layered-nlp-tools layered-nlp-tools

ビルド後のコンテナイメージサイズは以下の通り。どちらも同じぐらいのサイズ。

 
$ docker images
REPOSITORY                                TAG                 IMAGE ID            CREATED             SIZE
kekekekenta.azurecr.io/nlp-tools          latest              370bb5c6837e        4 hours ago         7.17GB
kekekekenta.azurecr.io/layered-nlp-tools   latest              cff610a7e062        4 hours ago         7.17GB
continuumio/anaconda3                     latest              69acfdf1121f        41 hours ago        3.72GB

便利なdiveでレイヤーを確認。Anacondaのレイヤーは3.4G。大丈夫かな。。。 https://github.com/wagoodman/dive

 
$ dive kekekekenta.azurecr.io/nlp-tools
[● Layers]────────────────────────────────────────────────────────────────────── [Current Layer Contents]────────────────────────────────────────────────────────
Cmp Image ID                     Size  Command                                   Permission     UID:GID       Size  Filetree
    sha256:b28ef0b6fef80faa25  101 MB  #(nop) ADD file:58d5c21fcabcf1eec94e8676a drwxr-xr-x         0:0     5.2 MB  ├── bin
    sha256:60b398413f86c0f8ac  231 MB  apt-get update --fix-missing && apt-get i -rwxr-xr-x         0:0     1.1 MB  │   ├── bash
    sha256:b1f721b57648924150  3.4 GB  wget --quiet https://repo.anaconda.com/ar -rwxr-xr-x         0:0      36 kB  │   ├── cat
    sha256:abd2c1804296f74fae   20 MB  apt-get update --fix-missing  && apt-get  -rwxr-xr-x         0:0      64 kB  │   ├── chgrp
    sha256:aac6d3b7d1450a4434  3.4 GB  FROM sha256:aac6d3b7d1450a4434            -rwxr-xr-x         0:0      60 kB  │   ├── chmod
....
 
$ dive kekekekenta.azurecr.io/layered-nlp-tools
[● Layers]────────────────────────────────────────────────────────────────────── [Current Layer Contents]────────────────────────────────────────────────────────
Cmp Image ID                     Size  Command                                   Permission     UID:GID       Size  Filetree
    sha256:b28ef0b6fef80faa25  101 MB  #(nop) ADD file:58d5c21fcabcf1eec94e8676a drwxr-xr-x         0:0     5.2 MB  ├── bin
    sha256:60b398413f86c0f8ac  231 MB  apt-get update --fix-missing && apt-get i -rwxr-xr-x         0:0     1.1 MB  │   ├── bash
    sha256:b1f721b57648924150  3.4 GB  wget --quiet https://repo.anaconda.com/ar -rwxr-xr-x         0:0      36 kB  │   ├── cat    
    sha256:abd2c1804296f74fae   20 MB  apt-get update --fix-missing  && apt-get  -rwxr-xr-x         0:0      64 kB  │   ├── chgrp              
    sha256:546ef8f4ba85d10b69  154 MB  buildDeps='make libc6-dev gcc g++'     && -rwxr-xr-x         0:0      60 kB  │   ├── chmod         
    sha256:0cabb03f966e749806  282 MB  apt-get -y install mecab libmecab-dev mec -rwxr-xr-x         0:0      64 kB  │   ├── chown
    sha256:7abb783748c90e7e13  2.5 GB  /mecab-ipadic-neologd/bin/install-mecab-i -rwxr-xr-x         0:0     130 kB  │   ├── cp              
    sha256:30242b13e105ca7ba4  293 MB  echo 'Installing Tika'     && apt-get -y  -rwxr-xr-x         0:0     117 kB  │   ├── dash
    sha256:752f8655a9f8c5b758  245 MB  echo 'Installing Python'     && apt-get i -rwxr-xr-x         0:0     105 kB  │   ├── date            
    sha256:89e71c7f05b61effb0  5.9 MB  FROM sha256:89e71c7f05b61effb0            -rwxr-xr-x         0:0      77 kB  │   ├── dd    
....

ACRに登録します。

 
$ az acr login -n kekekekenta
$ docker push kekekekenta.azurecr.io/nlp-tools
$ docker push kekekekenta.azurecr.io/layered-nlp-tools

初回のapply動作

AKSにapplyしてみます。(yamlファイルは省略しますがKubernetesにはJobとして展開しています。また、それぞれのコンテナで同じレイヤーを使っている箇所があるので、キャッシュされたレイヤーが使われないように異なるノードに展開します。)

レイヤーを纏めたコンテナイメージ

nlp-tools(レイヤーを纏めたコンテナイメージ)の初回Apply後の経過は以下の通り。エラーは出ますが最終的に約19分でJob動作完了。

 
$ kubectl apply -f nlp.yaml
job.batch/nlp created
$ kubectl get pods -o wide -w
NAME        READY   STATUS              RESTARTS   AGE   IP       NODE                       NOMINATED NODE   READINESS GATES
nlp-9thhn   0/1     ContainerCreating   0          14s   <none>   aks-agentpool-35064155-0   <none>           <none>
nlp-9thhn   0/1   ErrImagePull   0     2m6s   10.244.1.12   aks-agentpool-35064155-0   <none>   <none>
nlp-9thhn   0/1   ImagePullBackOff   0     2m22s   10.244.1.12   aks-agentpool-35064155-0   <none>   <none>
nlp-9thhn   0/1   ContainerCreating   0     10m   10.244.1.12   aks-agentpool-35064155-0   <none>   <none>
nlp-9thhn   0/1   Completed   0     19m   10.244.1.12   aks-agentpool-35064155-0   <none>   <none>
 
$ kubectl describe pods nlp-9thhn
....
Events:
  Type     Reason     Age                From                               Message
  ----     ------     ----               ----                               -------
  Normal   Scheduled  33m                default-scheduler                  Successfully assigned default/nlp-9thhn to aks-agentpool-35064155-0
  Warning  Failed     31m                kubelet, aks-agentpool-35064155-0  Failed to pull image "kekekekenta.azurecr.io/nlp-tools": rpc error: code = FailedPrecondition desc = unexpected EOF
  Warning  Failed     31m                kubelet, aks-agentpool-35064155-0  Error: ErrImagePull
  Normal   BackOff    31m                kubelet, aks-agentpool-35064155-0  Back-off pulling image "kekekekenta.azurecr.io/nlp-tools"
  Warning  Failed     31m                kubelet, aks-agentpool-35064155-0  Error: ImagePullBackOff
  Normal   Pulling    31m (x2 over 33m)  kubelet, aks-agentpool-35064155-0  pulling image "kekekekenta.azurecr.io/nlp-tools"
  Normal   Pulling    22m                kubelet, aks-agentpool-35064155-0  pulling image "kekekekenta.azurecr.io/nlp-tools"
  Normal   Pulled     14m                kubelet, aks-agentpool-35064155-0  Successfully pulled image "kekekekenta.azurecr.io/nlp-tools"
  Normal   Created    14m                kubelet, aks-agentpool-35064155-0  Created container
  Normal   Started    14m                kubelet, aks-agentpool-35064155-0  Started container

複数レイヤーに分割したコンテナイメージ

layered-nlp-tools(複数レイヤーに分割したコンテナイメージ)の初回apply後の経過は以下の通り。エラーは出ずに約8分でJob動作完了。

 
$ kubectl apply -f layerednlp.yaml
job.batch/layerednlp created
$ kubectl get pods -o wide -w
NAME               READY   STATUS              RESTARTS   AGE   IP       NODE                       NOMINATED NODE   READINESS GATES
layerednlp-ngkng   0/1     ContainerCreating   0          13s   <none>   aks-agentpool-35064155-2   <none>           <none>
layerednlp-ngkng   0/1   Completed   0     8m17s   10.244.0.12   aks-agentpool-35064155-2   <none>   <none>
 
$ kubectl describe pods layerednlp-ngkng
....
Events:
  Type    Reason     Age    From                               Message
  ----    ------     ----   ----                               -------
  Normal  Scheduled  11m    default-scheduler                  Successfully assigned default/layerednlp-ngkng to aks-agentpool-35064155-2
  Normal  Pulling    11m    kubelet, aks-agentpool-35064155-2  pulling image "kekekekenta.azurecr.io/layered-nlp-tools"
  Normal  Pulled     3m47s  kubelet, aks-agentpool-35064155-2  Successfully pulled image "kekekekenta.azurecr.io/layered-nlp-tools"
  Normal  Created    3m18s  kubelet, aks-agentpool-35064155-2  Created container
  Normal  Started    3m18s  kubelet, aks-agentpool-35064155-2  Started container

複数レイヤーに分割したコンテナイメージの方は、レイヤーを纏めたコンテナイメージと比べて、エラーも出ず、素早くPull完了していますね。

2回目以降のapplyの動作

2回目以降のapplyはキャッシュされているコンテナイメージを使うので、それぞれ約2秒で完了しています。

レイヤーを纏めたコンテナイメージ

 
$ kubectl apply -f nlp.yaml
job.batch/nlp created
$ kubectl get pods -o wide -w
NAME        READY   STATUS      RESTARTS   AGE   IP            NODE                       NOMINATED NODE   READINESS GATES
nlp-zzl4s   0/1     Completed   0          28s   10.244.1.16   aks-agentpool-35064155-0   <none>           <none>
$ kubectl describe pods nlp-zzl4s
....
Events:
  Type    Reason     Age   From                               Message
  ----    ------     ----  ----                               -------
  Normal  Scheduled  53s   default-scheduler                  Successfully assigned default/nlp-zzl4s to aks-agentpool-35064155-0
  Normal  Pulling    52s   kubelet, aks-agentpool-35064155-0  pulling image "kekekekenta.azurecr.io/nlp-tools"
  Normal  Pulled     52s   kubelet, aks-agentpool-35064155-0  Successfully pulled image "kekekekenta.azurecr.io/nlp-tools"
  Normal  Created    51s   kubelet, aks-agentpool-35064155-0  Created container
  Normal  Started    51s   kubelet, aks-agentpool-35064155-0  Started container

複数レイヤーに分割したコンテナイメージ

 
$ kubectl apply -f layerednlp.yaml
job.batch/layerednlp created
$ kubectl get pods -o wide -w
NAME               READY   STATUS      RESTARTS   AGE   IP            NODE                       NOMINATED NODE   READINESS GATES
layerednlp-9p478   0/1     Completed   0          13s   10.244.0.13   aks-agentpool-35064155-2   <none>           <none>
$ kubectl describe pods layerednlp-9p478
....
Events:
  Type    Reason          Age    From                               Message
  ----    ------          ----   ----                               -------
  Normal  Scheduled       2m23s  default-scheduler                  Successfully assigned default/layerednlp-9p478 to aks-agentpool-35064155-2
  Normal  Pulling         2m22s  kubelet, aks-agentpool-35064155-2  pulling image "kekekekenta.azurecr.io/layerd-nlp-tools"
  Normal  Pulled          2m21s  kubelet, aks-agentpool-35064155-2  Successfully pulled image "kekekekenta.azurecr.io/layerd-nlp-tools"
  Normal  Created         2m21s  kubelet, aks-agentpool-35064155-2  Created container
  Normal  Started         2m21s  kubelet, aks-agentpool-35064155-2  Started container

まとめ

機械学習系のコンテナイメージをKubernetesに展開する際は、なるべく小さいサイズのレイヤーに分けた方が良さそうですね。

もしくは、もっと細かくコンテナを分けた方が良いかも知れません。Pullされた後にセットアップするようなコンテナでも良いですね。

では。メモでしたー。

参照先

https://github.com/kubernetes/kubernetes/blob/39529006f0f47a105f6c08371df11be00726378a/pkg/kubelet/kubelet.go#L315 https://github.com/moby/moby/issues/1266 https://github.com/moby/moby/pull/34610

Tuesday, December 18, 2018

Azure Cognitive Services Bing Image Search でデータセットを作成する

この記事は Microsoft Azure Advent Calendar 2018 の 11 日目の記事です。 https://qiita.com/advent-calendar/2018/azure

はじめに

こんにちは。みなさん Azure Cognitive Service を使ってますか? Cognitive Service は簡単にAIを自分のアプリケーションに組み込むことができて便利ですよね。ちなみに、僕が好きな Cognitive Service は、Custom Vision (preview) です。少ないデータセットで学習済みモデルを作れるだけでなく、簡単にTensorFlow や ONNX、Docker向けに学習済みモデルをエクスポートできるところが素敵です。

ところで、2017年末から2018年にかけて ImageNet を使った ResNet-50 の学習時間を競うニュースが発表されてましたね。

ディープラーニングの分散学習で世界最高速を達成(2018/11) https://www.sony.co.jp/SonyInfo/News/Press/201811/18-092/

Preferred Networks、深層学習の学習速度において世界最速を実現(2017/11) https://www.preferred-networks.jp/ja/news/pr20171110

こういうのを見ると自分でもImageNetの学習をしてみたくなりますね。ためしにImageNetのデータセットをダウンロードしてみましたが、20%ぐらいのURLがリンク切れになっていました。残念なことに、これからDeep Learningを試したい人は、当時よりも少ないデータセットで学習することになってしまいます。7年ぐらい経つと状況も変わりますよね…。

今回はImageNetのURLだけではなく、同じSynsetsを Azure Cognitive Services Bing Image Search を使って取得してみようと思います。Azure Cognitive ServicesをAIとして使うのではなく、学習のためのデータセットを作るために使います。

Azure Cognitive Services Bing Image Searchの作成

まずは、Microsoft Azureのポータルから、Azure Cognitive Services Bing Image Searchのサービスを作成します。「リソースの作成」から「AI + Machine Learning」の「Bing Search v7」を選択します。

次に、Bing Search v7のリソース設定を行います。「価格レベル」によって使用可能なリクエスト数が決まっているので注意してください。設定が終わったら「作成」を押します。

作成されたサービスを利用するために、APIアクセスに使用するKeyを取得します。「KEY 1」と「KEY 2」の2つのKeyがありますが、どちらのKeyを使っても構いません。2つのKeyを交互に使うことによりアプリで使用している鍵を新しい物に入れ替えることができます。

プログラムの作成

データセットを作成するプログラムを書いていきます。プログラム内で使用しているImageNetのSynsetsリストは以下のURLにあります。

https://gist.github.com/KentaroAOKI/5712515f66d1ec6a92acb3bf0b215a5b

import json
import os
import pandas as pd
import requests
 
def get_bing_images(search_word, offset = 0, count = 50):
    # ここのsubscription_keyにAzure Portalに書かれていたKeyを設定する
    subscription_key = "put here your azure bing search api key"
    search_url = "https://api.cognitive.microsoft.com/bing/v7.0/images/search"
    headers = {"Ocp-Apim-Subscription-Key" : subscription_key}
    params  = {"q": search_word, "mkt": "en-US", "safeSearch": "Moderate", "offset": str(offset), "count": str(count)}
    response = requests.get(search_url, headers=headers, params=params)
    response.raise_for_status()
    search_results = response.json()
    return search_results
 
def main():
    image_search_list = 'ILSVRC2012.csv'
    download_dir = 'download_images'
    number_of_image = 1500
    # Synsetsのリストを読み込む
    search_words = pd.read_csv(image_search_list, header=None, delimiter=',')
    search_words.columns = ['id', 'name']
 
    for index, row in search_words.iterrows():
        print(query)
        query = row['name']
        dir_name = os.path.join(download_dir, str(row['id']).zfill(5))
        if (os.path.exists(dir_name) == False):
            os.makedirs(dir_name)
        # Bingで検索してサムネイル画像のURLを取得
        thumbnail_urls = []
        next_offset = 0
        while(next_offset < number_of_image):
            searched_images_json = get_bing_images(query, offset=next_offset, count=50)
            print('{}/{}'.format(searched_images_json['nextOffset'], searched_images_json['totalEstimatedMatches']))
            next_offset = searched_images_json['nextOffset']
            thumbnail_urls.extend([img["thumbnailUrl"] for img in searched_images_json["value"][:]])
            if (next_offset > searched_images_json['totalEstimatedMatches']):
                break
        # 検索結果で得られたBingのサムネイル画像をダウンロード
        image_no = 0
        for url in thumbnail_urls:
            response = requests.get(url)
            content_type = response.headers['Content-Type']
            save_file = os.path.join(dir_name, str(image_no).zfill(5))
            save_file = save_file + '.' + content_type.split('/')[1]
            with open(save_file, 'wb') as saveFile:
                saveFile.write(response.content)
            image_no = image_no + 1
 
if __name__ == '__main__':
    main()

実行してみる

Pythonの環境を設定した後にプログラムを実行します。 Anacondaの環境を作って必要なパッケージをインストール。

conda create -n py36 python=3.6
activate py36
conda install pandas requests

プログラムを実行する。

python download_synsets_from_azure.py

ダウンロードに時間がかかりますが、それぞれの種類に分けてフォルダが作成され、フォルダの中には、同じ種類の画像が多数格納されます。

さいごに

Azure Cognitive Services Bing Image Search APIに渡す検索クエリは日本語も使用することができますが、英語でクエリを実行したほうが多くの検索結果を得られることができます。日本語圏で使われている文字でも検索結果が少ない場合は英語で検索してみてください。今回はImageNetを例にしましたが、Azure Cognitive Services Bing Image Searchを使えば、独自のデータセットを作成することができます。是非みなさんも使ってみてください。ではー。

Tuesday, December 11, 2018

Windows 10にNVIDIA GPUを使用したDeep Learning環境をインストール。(CUDA10、VS2017、Chainerのインストール)

こんにちは。2017年2月に Windows 10 の Deep Learning モデル開発環境を紹介しましたが、約2年経過し色々環境が変ってますね。RTX 20-も出ましたし。ですので、今回は最新(2018年11月時点)の環境構築方法を紹介します。NVIDIA GPU が搭載された Windows 10 に Chainer をインストールしていきます。

Deep Learning 環境としては Linuxを使用した記事が多く紹介されていますが、Windows 10 は使いやすいディスクトップ環境と NVIDIA GPUを使うことができるので、モデル開発作業環境としては最適だと思います。

Visual Studio 2017 のインストール

まずは、Visual Studio 2017 のビルド環境を整えます。CUDAのコード(特にChainerが使うcupy)をビルドするときに必要になります。今回紹介するDeep Learning環境で GPU を使わない場合は必要ありません。(たまにビルドが必要なPythonパッケージがありますので、インストールしておいたほうがいいと思います)

注意点としては、インストール時に、「C++ ワークロードを使用したデスクトップ開発」を選択することです。以下のページを参考にしてください。

Visual Studio 2017 を使わず、Pythonでビルドだけできればいい人は、以下の Tools for Visual Studio 2017(上と同じサイト)だけでも大丈夫です。インストーラーを立ち上げたら、ワークロードの「Visual C++ Build Tools」を選択します。

  • Tools for Visual Studio 2017

NVIDIA CUDA と cuDNN のインストール

CUDAをインストールする前に最新のNVIDIAドライバをインストールしてください。リリースノートによると CUDA 10.0.130 は、411.31以上のドライバが必要です。

Visual Studio 2017をインストールした後に、CUDA のインストールを行います。CUDAのインストーラーはインストールされている Visual Studio を探して最適な追加パッケージをインストールします。GPUを利用しない場合はCUDAと下記のcuDNNは必要ありません。

次にcuDNNをインストールします。Downloadページから、「Download cuDNN v7.4.1 (Nov 8, 2018), for CUDA 10.0」を選択、次に「cuDNN Library for Windows 10」を選択してダウンロードを行います。ダウンロードしたzipを展開して、CUDAのインストールフォルダ(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0 )にコピーします。CUDAのフォルダ名称に合わせてcuDNNのファイルをコピーしてください。なお、cuDNNのダウンロードには、ユーザの登録が必要になりますので、先に登録しておいてください。

Pythonのインストール

Chainerを動かすためのプログラミング環境を整えていきます。機械学習をはじめとしたプログラミング言語としてはPythonが人気です。Python環境としてはAnacondaが有名で分析や機械学習を行うためのライブラリも問題なく利用できます。Azure Machine LearningでもAnacondaが使われているようです。

Anacondaは下記のサイトよりダウンロードします。利用しているOSに合わせて適切なパッケージをインストールしてください。ボタンをそのままクリックし続ける(標準の設定)だけで大丈夫です。

python の 環境の作成(Visual Studio 2017対応)

スタートメニューからAnaconda Promptを実行して、環境を作成していきます。環境を作ることで作業環境を分けることができます。

conda create -n py36 python=3.6

環境を作成したら、Anaconda環境で、Visual Studio 2017 を使えるように設定します。 先ほど作成した環境に変えて

activate py36

Visual Studio 2017 を使えるようにパッケージをインストール

conda install -c anaconda vs2017_win-64

これをインストールしておかないと、「 error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools 」のようなエラーメッセージが出てcupyをインストールできません。リンクも違っているし、VS2015も簡単にはダウンロードできないし。

Chainerのインストール

Chainerをインストールします。Chainerは容易に複雑なネットワークを作ることができるDeep Learningのフレームワークです。データによりノードを変えることができる Define by Run が特徴です。あと、質の良いサンプルコードも多く公開されているイメージです。

スタートメニューからAnaconda Promptを実行しますが、Chainerをインストールする前にcupyをインストールします。

インストールする前に環境を先ほど作成した環境に変えておきます。

activate py36

そして、インストール。インストール時に、Visual Studio 2017でビルドされます。

pip install cupy --no-cache-dir

次に、下記のコマンドでChainerをインストールします。

pip install chainer --no-cache-dir

ChainerやCuPyが正しくインストールされたことを確認します。

python -c "import chainer; chainer.print_runtime_info()"

以下のように Runtime Virsion などが取得できれば大丈夫です。

Platform: Windows-10-10.0.17134-SP0
Chainer: 5.0.0
NumPy: 1.15.4
CuPy:
  CuPy Version          : 5.0.0
  CUDA Root             : C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0
  CUDA Build Version    : 10000
  CUDA Driver Version   : 10000
  CUDA Runtime Version  : 10000
  cuDNN Build Version   : 7401
  cuDNN Version         : 7401
  NCCL Build Version    : None
iDeep: Not Available

NVIDIA GPUの状態を知る

実際にDeep Learningの学習を始めるとGPUが熱くなりますが、下記のコマンドを使うことによりGPUの状態を知ることができます。

cd C:\Program Files\NVIDIA Corporation\NVSMI
nvidia-smi.exe

実行すると下記のようにGPUの状態を知ることができます。寒い時期は安心してガンガンぶん回すことができますね。

(py36) C:\Program Files\NVIDIA Corporation\NVSMI>nvidia-smi.exe
Sun Nov 11 09:23:39 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 416.81       Driver Version: 416.81       CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name            TCC/WDDM | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1070   WDDM  | 00000000:01:00.0  On |                  N/A |
| 27%   24C    P8     7W / 151W |    243MiB /  8192MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

さいごに

最近は、Windows 10 ディスクトップ環境で動くことを確認してから、多くのGPUが使えるAzure DSVMなどのクラウド環境で学習させてます。(2日ぐらいの学習であればディスクトップ環境でもいですが、他のことができなくなるので)LinuxでもWindowsでも動くPythonコードを書くように心がけるのが大事です。

あと、画像を使う場合はOpenCVなどを使いますが、下記のコマンドでインストールすることができます。

conda install opencv

CUDA 10になったし、GeForce RTX 20- も使えるようになったし、TensorCore も使える環境になりましたね!あとは、GPUを買うだけですね!d(´∀`*) ではー。

Saturday, October 20, 2018

Microsoft COCOデータセットを使うためのCOCO APIをWindows 10にインストールするメモ

はじめに

COCO APIは、Microsoft COCOデータセットを容易に扱うためのAPIです。COCOは、オブジェクトの検出、セグメンテーション、人のキーポイントの検出、物のセグメンテーション、およびキャプションの生成用に設計された大規模な画像データセットです。

環境構築

COCO APIのパッケージをインストールする際、C/C++コードのビルドが発生します。ここでは Visual Studio 2017 のインストールとPythonのインストールを行います。

Visual Studio 2017 のインストール

まずは、Visual Studio 2017のビルド環境を整えます。cythonなどを利用するPythonパッケージのインストールで使用するため、Windows環境でPyhtonを使う場合は整えておいたほうが良いでしょう。

Visual Studio 2017のどのエディションでも大丈夫だとおもいますが、注意点としては、インストール時に、「C++ ワークロードを使用したデスクトップ開発」を選択することです。以下のページを参考にしてください。

Pythonのインストール

Python環境はAnacondaを使用します。Anacondaは分析や機械学習を行うためのライブラリも問題なく利用できます。また、パッケージのインストールや環境作成が非常に簡単に実行できるのが特徴です。Anacondaは下記のサイトよりダウンロードします。利用しているOSに合わせて適切なパッケージをインストールしてください。次をクリックしていくような感じで、標準の設定で大丈夫です。あと、PATHもそのまま登録するようにしてください。

COCO API利用環境の作成

スタートメニューからAnaconda Promptを実行して、Python 3.6の環境を作成します。condaコマンドで環境を作成してからactivateコマンドで作成した環境を使用しています。

conda create -n py36 python=3.6
activate py36
conda install setuptools
conda install cython
conda install matplotlib

次にCOCO APIをGithubから取得します。

git clone https://github.com/cocodataset/cocoapi.git

コンパイラのオプションを変更します。cocoapi/PythonAPI/setup.py の extra_compile_args を以下に変更します。引っかかるのはワーニングのオプションなので

ext_modules = [ 
    Extension(
        'pycocotools._mask',
        sources=['../common/maskApi.c', 'pycocotools/_mask.pyx'],
        include_dirs = [np.get_include(), '../common'],
        extra_compile_args=[],
    )
]

COCO APIのインストールを実行します。

python setup.py build_ext install

COCO APIのモジュール読み込み確認

以下のようにパッケージをインポートしてエラーが出ないことを確認します。

from pycocotools.coco import COCO

以上です。

Tuesday, August 28, 2018

Microsoft Azure DSVMでUnity ML-Agentsを使用した強化学習を行う

Microsoft Azure DSVMでUnity ML-Agentsを使用した強化学習

Unity ML-Agentsでは、PCで開発したUnityアプリのゲームオブジェクトに脳(学習済みモデル)を持たせて動かすことができますが、頭の良い脳を育てるには多くの時間がかかります。育て方には様々な方法がありますが、複数の異なる脳を育てることもできますし、同じ脳を複数のオブジェクト同士を競い合わせて育てることもできます。  今回は時間のかかる強化学習の学習をUnityでアプリ開発しているPCではなく、コンピュートリソース豊富なAzureのDSVMを使用して実施する方法を紹介します。

Microsoft Azure DSVMとは

Data Science Virtual Machine(DSVM)は、機械学習の各種ツールがプレインストールされている便利な仮想マシンです。  今回使うLinuxのDSVMは、UbuntuとAnacondaをベースに、The Microsoft Cognitive Toolkit, TensorFlow, MXNet, Caffe, Caffe2, Chainer, NVIDIA DIGITS, Deep Water, Keras, Theano, Torch, PyTorch などのDeep Learningツールが初めからインストールされています。また、NシリーズのようなNVIDIA GPUが搭載された仮想マシンを素早く利用するために、NVIDIAドライバ、CUDA、cuDNNも初めからインストールされています。 https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/

Unity ML-Agentsとは

Unity Machine Learning Agents Toolkit(ML-Agents)は、ゲームオブジェクトに強化学習を適用できるオープンソースのUnityプラグインです。外部のTensorflow環境を使用して学習を行うことが可能であり、生成された学習モデルをゲームオブジェクトを使って推論動作させることもできます。 https://github.com/Unity-Technologies/ml-agents

ML-Agentsを動かすDSVMの準備

Microsoft AzureのポータルでDSVMの仮想マシンを作成した後、DSVMでML-Agentsの動作環境を構築します。Microsoft Azureのポータルは以下よりアクセスします。 https://portal.azure.com

DSVM仮想マシンの作成

Microsoft Azureのポータルの「リソースの作成」より、"Data Science Virtual Machine"で検索して出てくる「Data Science Virtual Machine for Linux(Ubuntu)」を選択します。  仮想マシン作成時の注意点としては次の通りです。ステップ2のサイズ選択では、強化学習を行うため、NC, NVなどのようなNシリーズようなGPUを使っても強化学習内容によっては思っていたほどの効果が出ないかもしれません。ステップ3の設定では、sshのポートだけ使用します。sshを経由してシェルとTensorBoardを利用します。

ML-Agentsのインストール

githubのML-AgentsのリポジトリをDSVMの仮想マシンにクローンします。また、ML-Agentsで利用するPythonのパッケージをインストールします。(以下はDSVMにログインして実行)
$ cd ~
$ git clone https://github.com/Unity-Technologies/ml-agents.git
$ cd ml-agents/python
$ conda create -n ml-agents python=3.6
$ source activate ml-agents
$ pip install .

UnityアプリのビルドとDSVMへのコピー

今回はUnityアプリにML-Agentsのサンプルを例として使用します。このサンプルをPCでLinux向けアプリとしてビルドした後、前章で作成したDSVMの仮想マシンにコピーします。

プロジェクトの作成とTensorFlowSharpの設定

Unityのプロジェクトを作成してください。次にEdit > Project Settings > Playerから、PlayerSettingsのInspectorの、Display Resolution DialogをDisableに、Script Runtime Versionを.NET 4.xに、Script Define SymbolsをENABLE_TENSORFLOWとして設定します。

プロジェクトでは強化学習にTensorflowを使用するため、C#からTensorFlowを使うためのTensorFlowSharpプラグインをインポートします。以下のURLにリンクされている「TensorFlowSharp plugin」をクリックしてプラグインをダウンロードします。
https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Basic-Guide.md
 次に、ダウンロードしたファイルを、Assets > Import Package よりインポートします。

サンプルアプリのビルド

サンプルアプリはML-Agentsのリポジトリに含まれていますのでML-Agentsをクローンします。(gitがインストールされていない場合は、https://github.com/Unity-Technologies/ml-agents よりZipファイルをダウンロードしてください。)(以下はPCで実行)
> git clone https://github.com/Unity-Technologies/ml-agents.git
ml-agents\unity-environment\Assets\ML-Agents フォルダ配下にサンプルのシーンがありますので、このML-AgentsフォルダをUnityのアセットに追加します。追加したアセット内の「3D Ball」シーンを開きます。Hierarchyより、Ball3DAcademy(Academy)のBall3DBrain(Brain)を選択し、InspectorのBrain TypeをExternalに設定します。これによりTensorflowを利用して学習を行うことが可能になります。

次に、ビルドです。AzureのDSVMはLinuxで動作するため、Linux向けのビルド設定をします。File > Build Settingsより、Target PlatformをLinuxにして、Headless Modeにチェックを入れます。Headless Modeのチェックは、DSVMにSSHを使用したターミナルだけで接続するためです。

ビルドにより作成された実行ファイルは以下のような構成です。(以下はPCで実行)
> dir linux-build
2018/08/25  10:57    <DIR>          .
2018/08/25  10:57    <DIR>          ..
2018/08/19  17:00        25,630,440 3DBall.x86_64
2018/08/25  10:57    <DIR>          3DBall_Data
これをSCPでDSVMにコピーします。(以下はPCで実行)
> scp -r linux-build <ユーザ>@<DSVMのアドレス>:./

DSVMで学習を行う

DSVMにコピーしたUnityアプリをchmodコマンドで実行できるように変更します。(以下はDSVMで実行)
$ cd ~
$ chmod +x linux-build/3DBall.x86_64
学習にはlearn.pyを使用します。オプションとしてコピーしたUnityアプリと学習モードを指定します。(以下はDSVMで実行)
$ cd ~
$ source activate ml-agents
$ python ml-agents/python/learn.py linux-build/3DBall.x86_64 --train
学習には時間がかかりますが、学習中の状況はTensorbordで表示することが可能です。(以下はDSVMの別ターミナルなどで実行)
$ cd ~
$ source activate ml-agents
$ tensorboard --logdir=summaries --host 127.0.0.1
Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
TensorBoard 1.7.0 at http://127.0.0.1:6006 (Press CTRL+C to quit)
PCからTensorBoardへのアクセスには、SSHのポートフォワード機能を使用します。SSHのポートフォワード接続が確立された後に、PCのブラウザよりTensorBoardに接続して学習状況を確認します。(以下はPCで実行)
> ssh -L 6006:localhost:6006 <ユーザ>@<DSVMのアドレス>
PCのブラウザでローカルの6006にアクセスすることにより学習状況を確認することができます。 http://localhost:6006/

学習済みモデルの取得と動作確認

DSVMで学習された学習済みモデルは、Unityアプリで使うことができます。まず、学習済みモデルをPCにコピーします。(以下はPCで実行)
> scp <ユーザ>@<DSVMのアドレス>:./models/<run-identifier>/3DBall*.bytes <アセットのディレクトリ>
Hierarchyより、Ball3DAcademy(Academy)のBall3DBrain(Brain)を選択し、InspectorのBrain TypeをInternalに設定し、Graph ModelにDSVMよりコピーした学習済みモデルを設定します。アプリケーションを実行することにより学習済みモデルを反映したゲームオブジェクトの動きを見ることができます。

さいごに

強化学習を動かしていると、ナルトが多重影分身して修行するシーンを思い出します。Unity ML-Agentsは触ったばかりなので、Azureをもっと活用しながら、もっと面白いことを試してみたいと思います。