nikkie-ftnextの日記

イベントレポートや読書メモを発信

イベントレポート | Microsoft Machine Learning Meetup 学習編 #dllab

はじめに

だんないよ、nikkieです。
dllabさんのイベント「Microsoft Machine Learning Meetup」
(マイクロソフト機械学習系ソリューションを1日で知る日)のメモをブログとして公開します。
まずは「学習編」です。

勉強会の概要

Microsoft Machine Learning Meetup - connpass

5-6月は開発者にとって大変忙しかったですね!マイクロソフトもBuild と de:code という年1の開発者イベントを行いました。今回は、そこで発表されたものから機械学習系のソリューションを紹介します。Brainwave/FPGAやQuantumなども紹介したいですが、今回はスキップして、明日から使える、データ整備/蓄積・学習・推論を支えるAzureのプラットフォームをご紹介します。

学習編:Azure GPUクラスタ、Data Science VM、Batch AI、Low Priority VM
AzureではGPUやInfiniBandを搭載したハイスペックなインフラでディープラーニングを行うことできます。本セッションでは、GPUやInfiniBandを搭載したインフラの種類やパフォーマンスについてご説明します。さらに、それらを最大限活用できるソリューション群:環境構築済み仮想マシンのデータサイエンスVMクラスター・深層学習のトレーニングジョブの実行を自動化するBatch AI、それらで使える低優先度仮想マシンをご紹介します。

データ前処理編、学習編、推論編と3部構成でした。
学習編の資料はこちらです。

配信はこちらです: https://www.youtube.com/watch?v=f398XHjSX74

学習編 AzureインフラとBatch AI

学習のツール

  • Data Science 仮想マシン(DSVM)
  • VMSC(スケールセット) 100台立ち上げることも可能
  • Machine Learning ブラウザで機械学習
  • Batch AI: セッションのメイン

Azureはこれらのツールが簡単に使えるだけでなく、強力なインフラをもつ
どんなインフラがあり、どんなハイパフォーマンス1なことができるのかという話

どうやったら性能が伸びるか <- 処理にかかるスピードの話

  • アムダールの法則: 処理を並列化するとどのくらい性能が伸びるか 1-p + p/n (並列化できるpの部分をn並列) スピードアップS
    • 実際はオーバヘッドでp/nにはならない
  • 並列化できない: 依存関係がある File I/Oなど
  • 並列化できる: 依存関係なし <- DeepLearningでは並列化利用できる
  • 100%にはならない(128並列で128倍にはならない。99%並列で60倍程度) pの領域をいかに増やすか(スピードアップのポイント)
  • スケーラビリティの観点ではpの領域をいかに増やすか
  • インフラの観点

    • 並列化できる処理にGPUを用いる
    • ノード間通信にInfiniband
    • ストレージの最適化
  • 高速ネットワーク(SR-IOV)

    • 通常は仮想のネットワークスイッチをはさむ(性能のネックになる)
    • スイッチをはさまないことでネットワークの高速化 17倍性能上昇
    • ノード間通信も高速化できる
  • InfiniBand

    • RDMA: 直接メモリにアクセスする通信 216倍の性能上昇
    • 仮想マシンHシリーズ(Rがついたもの) 512コアでも性能劣化しない(100%の直線に近い)
    • High Performance Linpack(HPL): ベンチマーク
  • GPUインスタンス

    • NVIDIA: Kepler(K80), Maxwell(M60), Pascal(P100), Volta(V100)
    • 仮想化したマシンの上で性能が出るのが強み
    • ChainerMN GPU増やしても(並列増やしても)性能が劣化しない(100%の直線に近い線)
    • DeepLearningはNCシリーズ、NVシリーズ NVシリーズは東日本(ドキュメントは可視化用途だが、単精度2のDeepLearningは可能) InfiniBandは使っていない
  • VOLTA TENSORコア

  • TENSORコア

Azure Batch AI

手元でディープラーニングのテストをするとき、仮想マシンで十分
大量データがあるとき、複数の仮想マシンを設定するのは手間
-> Batch AIによる簡略化

メリット

  • クラスタをすぐ展開できる
  • クラスタのオートスケール ジョブ開始に反応してノード数を増やし、ジョブ終了でノード数を0に
  • 低優先度仮想マシン: 80%割引で仮想マシン(GPU)が使える (Batch AIとスケールセットからのみ割引が使える)
  • コンテナ利用、展開早い

キーワード(1週間前にAPI変更)

  • リソースの管理の単位はリソースグループ
  • ワークスペース(Batch AIで一番大きい単位。プロジェクト単位)
  • ワークスペースのオブジェクトとしてクラスタNFS
  • エクスペリメント: ジョブの集合体。ジョブを入れて管理する箱

ステップ

  1. Quotaの確保: Portalから引き上げ依頼(ノード数の上限が決まっている)
  2. リソースグループ、ワークスペース、Experimentを作成
  3. ストレージの作成(ここがポイント)
    • GPUについて速度は変わらない。ストレージの選択で性能が変わる
      • Azure Files: ファイルサーバのPaaS。マウントをして使う。Portalから簡単に作れるが、I/Oやスループットに厳しい条件がある
      • Blob Fuse: Blobストレージ(オブジェクトストレージ。HTTPアクセス。画像やPDFを置く。管理の単位はコンテナ)をLinuxマシンからマウント。おすすめ
      • Single Node NFS: Fuseが使えなければ、仮想で立てる
    • Blob Fuseが早い理由
      • 元データはBlobのコンテナにある。ファイルオープンでローカルキャッシュに落とす。書き込みをし、ファイルクローズではじめてストレージ側に反映する。
      • = 直接Azureのストレージに書き込まず、ローカルに差分を用意し、閉じるときにストレージに書き込むということ
      • 他方、Azure Filesは排他制御ができる。そのため遅い
  4. Dockerイメージ/OSイメージ
    • 1週間前のAPI変更まではDockerおすすめ DSVMではバージョン管理ができない
    • 変更によりOSのカスタムイメージが作れるようになった
    • Dockerイメージの保管場所: Docker HubはVMからは遠い。Azure Container Registry(従量課金) 1秒を縮めるのに使う
  5. クラスタの作成(同じサイズの仮想マシンの集合体。GPUや低優先度仮想マシン一部だけ混ぜることはできない)
    • オートスケールには10分程度ラグがある。学習時間がシビアであれば、手動でスケールする(消し忘れると課金発生)
  6. Job(JSONファイル)

参考情報

まとめ

ハンズオン

Batch AIでMNISTに取り組みました。
ハンズオン資料はこちらです。
https://github.com/DLL-BatchAI-Hand-on/Chainer/blob/master/Chainer-GPU-Distributed/cli-instructions.md

ハンズオン資料に沿ってCloud Shellで以下のコマンドを実行していきました。

  1. ワーキングディレクトリ変更
    • cd /usr/$USER/clouddrive
  2. batchai.recipesリソースグループを作成
    • az group create -n batchai.recipes -l eastus
    • リソースグループはメタ情報を管理する箱。管理されるリソースはどのリージョンにあってもいい
    • リソースグループはどこでもいいが、ワークスペースの場所は性能にとって重要(通信にかかる時間)
  3. BatchAI ワークスペースを作成
    • az batchai workspace create -g batchai.recipes -n recipe_workspace -l eastus
  4. GPUクラスタ作成(低優先度仮想マシン指定)
    • az batchai cluster create -n nc6 -g batchai.recipes -w recipe_workspace -s Standard_NC6 -t 2 --generate-ssh-keys
      • -tでつくるノード数
      • --generate-ssh-keys sshキーをストレージに保管
    • エラーが出た場合
      • バッチで検索 -> クオータの確認
    • 低優先度仮想マシンだと費用を抑えられるということだったので、指定しました(オプションに気づかずリソースグループごと消して作り直しました)
    • 仮想マシンが起動している間(アイドル状態も含む)は課金される
  5. ストレージアカウント作成(nikkie20180627dllabとして作成3)
    • az storage account create -n nikkie20180627dllab --sku Standard_LRS -g batchai.recipes -l eastus
    • ストレージアカウント名は全世界で一意にする必要がある(小文字と数字のみ、大文字や記号は使えない)
    • ストレージはクラスタと同じリージョンにつくる(Azureのデータセンターの構成はリージョンに閉じている)
    • ストレージはVMとは別で課金される永続的なもの
  6. 学習スクリプトの取得
    • wget https://raw.githubusercontent.com/chainer/chainermn/v1.3.0/examples/mnist/train_mnist.py
  7. Blobコンテナ作成、学習スクリプトデプロイ
    • az storage container create -n scripts --account-name nikkie20180627dllab
    • az storage container create -n data --account-name nikkie20180627dllab
    • az storage blob upload -f train_mnist.py -n chainer/train_mnist.py --account-name nikkie20180627dllab --container scripts
      • -> scriptsとdataはコンテナの名前の指定(この後、job.jsonで指定する)
    • BlobストレージはオブジェクトがURLをもつ
    • URL中に/の区切りを入れることでディレクトリのようになる
    • Azure Filesはログの吐き場所としてのみ利用する
      • az storage share create -n logs --account-name nikkie20180627dllab
  8. Experiment作成
    • az batchai experiment create -g batchai.recipes -w recipe_workspace -n chainer_experiment
  9. job.json書き換え
    • 取得: wget -O job.json https://raw.githubusercontent.com/DLL-BatchAI-Hand-on/Chainer/master/Chainer-GPU-Distributed/job.json
    • <AZURE_BATCHAI_STORAGE_ACCOUNT><Storage Account Name>: ストレージアカウント名(nikkie20180627dllab)にする
    • <Container Name (For Script)>: scripts(先のaz storage account create -nコマンド)
    • <Container Name (For Data)>: data(先のaz storage account create -nコマンド)
    • <Storage Account Key>: 以下のコマンドの結果参照
      • az storage account keys list -g batchai.recipes --account-name nikkie20180627dllab
  10. Jobの実行
    • az batchai job create -n distributed_chainer -c nc6 -g batchai.recipes -w recipe_workspace -e chainer_experiment -f job.json --storage-account-name nikkie20180627dllab
  11. 実行中のJobの監視(ブログ末尾参照)
    • az batchai job file stream -j distributed_chainer -g batchai.recipes -w recipe_workspace -e chainer_experiment -f stdout.txt
  12. モデルの確認
    • az batchai job file list -j distributed_chainer -g batchai.recipes -w recipe_workspace -e chainer_experiment -g batchai.recipes -d MODEL
    • または az batchai job show -n distributed_chainer -g batchai.recipes -w recipe_workspace -e chainer_experiment --query jobOutputDirectoryPathSegment

参考情報

  • おまけ: Batch AIの裏のVMSSHする

  • Keplerは空いているので低優先度で使いたい放題とのこと

感想

Azureの売り(強力なインフラ、GPUインスタンスの充実)の話が聞けたのが、一番ありがたかったです。
Cloud Shellからリソースつくると管理がラクな印象です。積極的に使っていこう
BatchAIから使う低優先度仮想マシン、今後kaggleのコンペに取り組む際に選択肢に上るかもしれません。
ハンズオン込みの充実したセッションをどうもありがとうございました。

参考: 実行中のJobの監視の様子

==========================================
Num process (COMM_WORLD): 2
Using GPUs
Using hierarchical communicator
Num unit: 1000
Num Minibatch-size: 100
Num epoch: 20
==========================================
Downloading from http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz...
epoch       main/loss   validation/main/loss  main/accuracy  validation/main/accuracy  elapsed_time
1           0.22513     0.107383              0.933267       0.9664
   18.5095
2           0.0754279   0.0671796             0.9765         0.9774
   30.0267
3           0.0478487   0.0705339             0.984834       0.9778
   40.7548
4           0.0314334   0.0904751             0.9896         0.9764
   51.4043
5           0.0229979   0.0666332             0.992967       0.9813
   62.6438
 : <省略>
16          0.00927721  0.0899814             0.997167       0.9825
   182.325
17          0.00889213  0.0872269             0.9973         0.9819
   192.866
18          0.00727136  0.0930194             0.9975         0.9821
   202.713
19          0.00774408  0.1048                0.997367       0.9819
   212.526
20          0.0097215   0.11702               0.9973         0.977
   222.365

脚注


  1. スライドに出てくるHPCはHigh Performance Computingの略のようです。

  2. 単精度は浮動小数点数の話だそうです。他に倍精度や半精度という言葉も耳にしました。Wikipedia 半精度

  3. ハンズオン終了でリソースグループごと消したので、「今は、もう、ない」です。az group delete -n batchai.recipes -y

イベントレポート | 第29回 Pythonもくもく会 〜AzureにDockerイメージがBuild, Ship, Runできずハマりました。。〜 #mokupy

はじめに

だんないよ、nikkieです。
mokupyでDocker触ってきました。(そしてAzureとの絡み?で絶賛ハマっています 苦笑)

勉強会の概要

第29回 Pythonもくもく会 - connpass

主にPythonに関するやりたいことを各自持って来て、進めていく感じのゆるい会です。 もくもく開発をして情報共有したり、交流を深めることができればと思っています。 是非お気軽にご参加ください。(Python初心者の方でも大歓迎です!)

ゆるい感じが持ち味のもくもく会です。今回はデータ分析に取り組まれている方が多かった印象です。

取り組んだこと

FlaskのアプリケーションをDockerでデプロイする方法を身につける!

動機

  • もくもくする中でAzureのWebApps(Windows OS)にFlaskアプリケーションをデプロイする知見がたまってきたのですが、ロックインを感じるようになりました。-> Dockerイメージでデプロイしてみたくなったので今回取り組みました。
  • DockerFileのCMDにpython app.pyを指定する手順を多く見かけるのですが、これだと本番サーバではないというWARNING1が出るので、本番サーバとして動かす方法が知りたかったというのもあります。

以下に取り組みました。

  1. Hello WorldするだけのFlaskアプリケーションを本番サーバで動かすDockerイメージ作成
  2. 上記のDockerイメージをAzureにデプロイ

Hello World Dockerイメージ作成

Flask Mega Tutorialを参考に進めました。
The Flask Mega-Tutorial Part XIX: Deployment on Docker Containers - miguelgrinberg.com

Mega Tutorialを参考に作ったDockerfile2

# もととなる公式イメージ
FROM python:3.6-alpine

# アプリケーションを実行するためのユーザを作成(rootで実行するのはよくないとのこと)
# -Dオプションはデフォルトの設定
RUN adduser -D microblog

# アプリケーションがインストールされるデフォルトディレクトリ(microblogユーザのホームディレクトリを使っている)
WORKDIR /home/microblog

# Mega Tutorial作成者の好み(#7のコメント。python3とpip3というコマンドを使わなくてよくなる)
COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn

COPY app app
COPY microblog.py boot.sh ./
RUN chmod +x boot.sh

ENV FLASK_APP microblog.py

RUN chown -R microblog:microblog ./
USER microblog

EXPOSE 5000
ENTRYPOINT ["./boot.sh"]

立ち入れていないですが、gunicornなるものでサーバを動かしているようです。

Hello WorldするだけのFlaskアプリケーションのファイル一式はこちら。
https://gist.github.com/ftnext/0d578da76d3d3d0adb60e18f5c02ddb9

docker run --name microblog -d -p 8000:5000 --rm microblog:latest実行後、http://localhost:8000へのアクセスでHelloWorldが確認できました。

DockerイメージをAzureにデプロイ

Web App on LinuxにDockerイメージをデプロイしました。

イメージをDockerHubにプッシュ。
https://hub.docker.com/r/ftnext/flask-azure-practice/

これを使ってWeb App on Linuxインスタンスを作ったのですが、
アクセスしてみると「Service Unavailable」_| ̄|○ il||li
(DockerのウリのはずのBuild, Ship, Runはいずこに。。。)

Kuduからログを見てみたところ./boot.sh: no such file or directory

2018-06-24 05:57:41.630 ERROR - Container start failed for nikkkie-flask-docker-practice_0 with System.AggregateException, One or more errors occurred.
InnerException: Docker.DotNet.DockerApiException, Docker API responded with status code=BadRequest, response={"message":"OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\"./boot.sh\\": stat ./boot.sh: no such file or directory\": unknown"}

ローカルで実行できているのにAzureで実行できない理由がわからず、現在進行系でハマっています。。
原因がどこにあるかも切り分けられていないので、試してみたいことを書き出しておきます。(一部はもくもく会中で試しました)

  • 別の端末(Mac)で同じイメージをdocker pullしても発生するのか? それともAzureでのみ発生?(AWSでは?)
  • boot.shの実行の仕方に問題がある? -> (ENTRYPOINT ["boot.sh"]ではローカルで動かず(デプロイせず)、ENTRYPOINT ["/home/microblog/boot.sh"]ではAzureで動かず)
  • macOSLinuxの違いによる? ローカルにvagrantLinux環境構築したら今回のイメージは動く?
  • gunicornのDockerfileのサンプル探して見比べてみる
  • CMDにpython app.pyを指定しない方法でFlaskアプリケーションを動かすことがやりたいので、gunicorn以外の手段を探す

感想

Docker使っているのに、デプロイ先で動かないとは思いませんでした。
DockerのウリのはずのBuild, Ship, RunできなかったことでAzureに手を噛まれた感が否めませんが、
スキマ時間にちょこちょこ取り組んでみます。(解決したら一本LTできるでしょうし)
お昼の時間、FlaskとDjangoの違いの話が聞けたのが参考になりました。

運営者・参加者の皆さま、1日ありがとうございました。

脚注


  1. WARNING: Do not use the development server in a production environment.

  2. adduser -D が調べた範囲では出てこなかったのですが、adduserコマンドとuseraddコマンドはCentOSでは同じものだそうです 参考: https://hydrocul.github.io/wiki/commands/adduser.html

イベントレポート | カイゼン・ジャーニー 著者による本読みの会 第1部完結編 第08話の後半編「二人で越境する」#kaizenJ

はじめに

だんないよ、nikkieです。
カイゼン・ジャーニー本読みの会8話のメモと感想です。

勉強会の概要

カイゼン・ジャーニー 著者による本読みの会 第1部完結編 第08話の後半編「二人で越境する」 - DevLOVE | Doorkeeper

「著者による本読みの会」 では、著者2人がカイゼン・ジャーニーを1話ずつとりあげて、内容を解説したり、深掘りしたり、脱線したりします。カイゼン・ジャーニーってどんな本なの?あの話のことをもっと聞いてみたい!という方、耳を傾けてみてください。
6/15の放送では収まりきらなかった後半部分、最後の山場を放送します。

江島の解説の後から

  • 氷山モデル ピーター・センゲ氏
  • メンタルモデル: 心の奥深くに根ざした価値観(その人にとっての当たり前) 認知バイアス
    • 企業文化にもメンタルモデルがある 転職すると分かる
      • 例「出張」泊まらないと出張でないという定義 別の環境では「外出」と理解される
    • ストーリー: 一人で見つけられないことも二人では気づけている(江島&片瀬)
      • -> 一人のメンタルモデルを越える

それぞれの持ち場で、がんばれ

  • みんなどうにかしたいと思っていたことがわかった
    • 一歩踏み出した江島への称賛、勇気づけられた
  • やってみた人が強い 言葉に重みが出る
  • 場は勝手にできたわけでなく、誰かが意志を持って作った(石神さんが気づかせた: 称賛の拍手)
  • 懇親会
    • 情報の共有(感動を伝えたい)
    • 情報を咀嚼しようとする
    • アルコールの力で口がなめらかになる
  • 神戸橋さん「変な生き物を見る目」->「俺もなんかしたい」
    • 市谷さんの実話: 社内イベントの場ではなかったが、神戸橋さん的な人に後日言われた
  • 行動を起こしている人の引力/重力を人は感性で感じる
    • 新井さんは小さなアクションを重ねている(ゆらぎを起こす) -> まわりも意外と見ている事がわかる
    • リスクを考えずにやってみて
    • 派閥(レーン)から外れる=変なレッテルを貼られる を考えてしまうことはあるかも <- (感想)気にするかしないかの違いなのかな?
  • 問い=存在価値 石神さんは向き合わなければならないことを知っている
  • 一部 一人でやっていて何度も石神さんに教えてほしかった
    • 怒られると分かっていて「どうしていったら良いんでしょう」(思いが溢れ出た)
    • イベントでもっとやれるとわかった
    • 孤独だった自分の気持ちを抑えきれなかった
  • 「それぞれの持ち場で、がんばれ」市谷さんの実話
    • 市谷さんが言われた言葉はそのままでは使えないので、表現を変えている
    • 言葉との出会い & スルーせずにキャッチ
    • 同士 違う現場だけどつながっている
  • 蔵屋敷さん ソフトウェア開発の楽しさを教えてくれた人(4話) タスク管理丁寧
  • 褒めてくれると思いきや冷水
  • 第一部大団円と思わせて全否定
    • 江島のキャラが分かっているがゆえの発言
  • 【裏話】一部最後「酔いが一気に覚めた」(初稿) -> 削った(蔵屋敷さんのセリフで止めた)
    • 読者のイメージ 活字のよさ

感想

神戸橋さん=同じこと3回言う人(爆)

一部が終わりということで、市谷さん、新井さんの方でもいったん振り返り、今後の展開を考えるとのこと。
お二人のお話やチャットを見て、一人で読んでの理解を超えられるように感じていたので、もっと聞いていたかったです。
振り返りの結果、どんな形になるのか、楽しみに待ちたいと思います。(自分で週次で一話ずつまとめるみたいなこともできるかも)

結構アニメを見るのですが、気に入った作品は何度も映画館に通ったり、スタッフの制作裏話を収集した上で見たりします。
これまで気づけなかったことに裏話を聞いて気づいたり、この部分は監督のこういう経歴を反映しているのかなと妄想したりして楽しんでいます。
好きなアニメと同じように『カイゼン・ジャーニー』にもアプローチしてきました。
心に響いた部分は、日々の業務にソロで実践してみています。
本読みの会は気づけなかったことに気づける機会と考え、参加してきました。
カイゼン・ジャーニー』本読みの会は、『カイゼン・ジャーニー』を気に入った人が集まって、ここがよかったなど共有できる(『カイゼン・ジャーニー』ガタリができる)素敵な機会だったと感じています。

本読みの会に気づいたのが遅く、後半の方しか出られていませんが、
市谷さん、新井さん、参加者の皆さま、これまでありがとうございました!

イベントレポート | PythonでLINE botを作ろう!! ITわいわい!! サポーター参加 #nipponrick

はじめに

だんないよ、nikkieです。
6/16にLINE Bot ハンズオンにサポーター参加してきました。そちらのレポートです。

勉強会の概要

PythonでLINE botを作ろう!! ITわいわい!! - connpass

■ご案内
IT技術者同士のつながりの輪を広げたい思いからわいわい交流会が始まりました。 第2回目となる今回は、『PythonでLINE botを作ろう』をテーマにハンズオンを実施致します。
Pythonに興味はあるけど一人ではなかなか先へ進めない方など、この機会にPythonに触れてみませんか。

講師のFumiさんとは3月のサポーターズ勉強会で知り合い、
次回ハンズオンでお手伝いさせてくださいと申し出たところ、今回の機会をいただきました。 イベントレポート | 【サポーターズCoLab勉強会】Python勉強会(LINE Botハンズオン)#spzcolab - nikkie-ftnextの日記

微力ながら次回はメンターや運営の手伝いなどお手伝いしたいと思いますので、お気軽にお声がけください。

LINE Bot作成

資料は以下に公開されています。(第1回目の内容をベースに、4択クイズ機能が追加された内容です)
Python勉強会(#002) 『PythonでLINE botを作ろう!!』公開資料 – Python勉強会

コードに関しては以下のような手順で手を入れていきました。

  • GitHubのline-bot-sdk-pythonのサンプルコードをベースにする
  • 接続確認でエラーにならないように修正
    • サンプルコードのエンドポイントが存在しないので、存在するエンドポイントに修正(スライド87)
    • 接続確認では返信先がないことによるエラーが出ないように修正(スライド90)
  • 4択クイズBotに機能追加

感想

  • ほとんどの人が4択Botを動かせたようでよかったです。機能追加する際はコードを少し変えて動かして挙動を見て、理解を深めていくような感じでしょうか。気になる箇所をprintしてもよさそうです。
  • LINE Bot SDKはFlaskで動いているようです。AzureのWebAppsの知識と掛け合わせたところ、オウム返しBotをWebAppsで動かせました!ざっくりとした手順1
    • WebAppsインスタンス作成(Python3.6を使うように設定2)
    • GitHubのline-bot-sdk-pythonのサンプルコードについて以下を行う(main.pyとして保存する)
      • 上記の「接続確認でエラーにならないように修正」2点
      • YOUR_CHANNEL_ACCESS_TOKEN,YOUR_CHANNEL_SECRET環境変数から読み込むようにする(os.getenv())
    • WebAppsで動かすために必要なファイルを追加 参考: https://github.com/ftnext/python-docs-hello-world
      • .skipPythonDeployment
      • ptvs_virtualenv_proxy.py
      • web.config
      • requirements.txt
    • WebApps側に環境変数設定

▼動かしてみた様子はこちらから

  • 懇親会でサポートのしむどんさんがPyNyumonのテキストを作られたことを知りました。あのテキストは何度も参照しました。今回は私一人では解決できない部分をフォローしていただきありがとうございました!
  • 事前に調べたり、当日対応したりして環境構築について少し理解が進みました。(PyNyumonでメンターのみなさんが何と戦っているかその一端を垣間見た気がします)

ハンズオン参加者の皆さま、運営の皆さま、どうもありがとうございました。
質問に答えることで理解を深められましたし、いろいろな方とつながれた素敵な時間でした。

脚注


  1. 再現性を担保するべく、近日中にソースコード公開して記事にまとめます。

  2. 不要かもしれないですが、Python3.6を境にjson.loads()の動きが変わっていたことで1週間ハマりました ToTの経験からバージョンは揃えると心に決めています

イベントレポート | Azureもくもく会@新宿 No.20 Azure Database for MySQLのSSLの調査、WebAppsでFlaskの循環importが発生しないようにする方法調査 #あずもく新宿

はじめに

だんないよ、nikkieです。
1時間ほどもくもくしてきたので、成果発表をベースにブログに残します。

勉強会の概要

Azureもくもく会@新宿 No.20 - connpass

みんなで集まって、Microsoft Azureに関する作業をする会です。
新しい機能を試したり周りと相談したりしてAzureを楽しみましょう。

20回記念の今回のテーマは「みんな好きなことをやろう!」でした。
業務でWebApps × Flask × Azure DB for MySQLを使っているのですが、調べきれていないところを調べる時間にしました。

調査事項

  • Azure DB for MySQLSSL設定
  • Web Apps × FlaskでDBを使うときのベストプラクティス?を調べる

Azure DB for MySQLSSL設定

MySQLWorkbenchやFlaskのアプリケーションでのSSL接続の方法を調べる時間的猶予がなく、
SSL接続を無効にして使ってきました。気になっていたので調べました。

以下のドキュメントを参考にするとよさそうです。
https://docs.microsoft.com/ja-jp/azure/mysql/howto-configure-ssl:tilte

  • ドキュメント中のリンクからSSL証明書を取得
  • MySQLWorkbenchから接続する場合
    • SSL CA Fileを設定する
  • Flaskのコードから接続する場合(Flask-SQLAlchemy使用)
    • 接続文字列にssl_ca=として取得したSSL証明書のパスを取得すればよさそう1
    • イメージ: mysql+pymysql://user:password@host/dbname?ssl_ca=ssl/ca_file/path

Web Apps × FlaskでDBを使うときのベストプラクティス?を調べる

気になっていたこと: 循環import
https://twitter.com/ftnext/status/1006188837519814656

Azure WebApps x Flaskの組合せで少しつまづいた。
wfastcgiはmain.py (1)をimportしているらしく、循環import (2)が発生した
(1)app.run するファイル(ローカルサーバ立てるのに走らせる)
(
2)main.py でappを作ってからSQLAlchemyのdbを作る(続

https://twitter.com/ftnext/status/1006189297639100416

循環import続き
main.py でSQLAlchemyのdb使ったモジュールimportしにいく →そのモジュールではmain.py からdbをimportする必要があるで循環発生
「SQLAlchemyのdb使ったモジュール」をmain.py の先頭から使っている関数の先頭に移したらエラーは消えた

ご助言いただきました。誠にありがとうございます!

教えていただいたThe Flask Mega-Tutorial Part IV: Database - miguelgrinberg.com
以前触ったことがあった2. Flaskチュートリアル — study flask 1 ドキュメントをもとに試行錯誤していました。

今回できたもの:https://gist.github.com/ftnext/63279bed7b1d0dbe0ab5015682fb78c0

感想

  • 既存の Azure App Service と Azure Database for MySQL の接続 | Microsoft Docsに「方法 1 - すべての IP アドレスを許可するファイアウォール ルールを作成する」とあるのを発見。元も子もない解決策のような。。
  • もしかしたらDockerでFlaskサーバを動かす方法確立しちゃうほうが早いかも(WebApps利用はベンダーロックインされるように思えてきた。。)←AKS調査の成果発表の影響もあるかも
  • CustomVisionServiceで物体検知が可能になっていることを知った(サッカーの試合シーンからサッカーボールを検知するデモ)。機械学習の結果がAPIからどんどん利用できるようになってるな〜。学習済みのモデルが返すJSONには精度順に検出した物体情報が含まれるとのことで、APIの仕様、気になります。

Azureの最新情報も収集でき、成果発表の機会もいただき、どうもありがとうございました。皆さまお疲れさまでした。

脚注


  1. 未検証です。今回調べた限りでは動作するのだろうと期待しています. http://docs.sqlalchemy.org/en/latest/core/engines.html#sqlalchemy.create_engine

  2. <add key="WSGI_ALT_VIRTUALENV_HANDLER" value="main.app" /> https://github.com/Azure-Samples/python-docs-hello-world/blob/master/web.3.4.config#L4 の部分のことです。main.pyのappはこれでimportできるようなのですが、app/__init__.pyのmyappはどう書けばimportされるのでしょうか?(宿題事項)

イベントレポート | (第89回)Python mini Hack-a-thon : Flaskのロギングの調査、LINE Botを少しだけ触る #pyhack

はじめに

だんないよ、nikkieです。
6/9の pyhack 成果発表をもとにブログにしました。
今回はMarkdownで書いているので、いつもと体裁が異なります。

勉強会の概要

(第89回)Python mini Hack-a-thon - connpass

スプリントのゆるい版みたいな感じで各自自分でやりたいことを持ってきて、勝手に開発を進めています。

取り組んだこと

成果

  • Flaskのログ出力について疑問は解決できた
  • LINE Botでオウム返しできた

Flaskのログ出力から書いていきます。

疑問

Flaskインスタンスをrunしているファイル(app.py)では以下のようにしてdebug.logにログ出力ができます。1
app.pyにimportしているファイル(logtest.py)のログをdebug.logに出力するにはどうすればいいのか調べてみました。

# app.py
import logging
from logging.handlers import RotatingFileHandler
import os

from flask import Flask

from logtest import fabulous_message

app = Flask(__name__)
formatter = logging.Formatter(
    '%(asctime)s %(levelname)s: %(message)s '
    '[in %(pathname)s:%(lineno)d]'
)
debug_log = os.path.join(app.root_path, 'debug.log')
debug_file_handler = RotatingFileHandler(
    debug_log, maxBytes=100000, backupCount=1
)
debug_file_handler.setLevel(logging.INFO)
debug_file_handler.setFormatter(formatter)
app.logger.setLevel(logging.INFO)
app.logger.addHandler(debug_file_handler)

@app.route('/')
def hello():
    app.logger.info('GET Access')
    message = fabulous_message()
    return message


if __name__ == '__main__':
    app.run()

わかったこと

  • ロガーの子孫構造を使う
  • 子孫構造を使わない場合、ロガーを設定して使えばよさそう(ロギング設定ファイルも導入したい)

ロガーの子孫構造を使う2

# logtest.py
import logging


logger = logging.getLogger('__main__.'+__name__)

def fabulous_message():
    logger.info('fabulous message create start')
    return 'Hello, World!'
2018-06-09 15:30:34,008 INFO: GET Access [in app.py:25]
2018-06-09 15:30:34,009 INFO: fabulous message create start [in /Users/.../logtest.py:21]

ロガーの子孫構造について https://docs.python.jp/3/howto/logging.html#loggers

たとえば、名前が foo であるロガーがあったとして、 foo.bar, foo.bar.baz, foo.bam といった名前のロガーはすべて foo の子孫になります。

ロガーの子孫構造を使っているため、logtest.pyの中でロガーの設定は不要と理解しました。
app.loggerは標準モジュール logging のロガーを使っていると確認できました。3
python app.pyと実行したとき、app = Flask(__name__)__name____main__が入るため、
logtest.pylogger = logging.getLogger('__main__.'+__name__)としたことで子孫構造が設定できました。4

logtest.pylogger = logging.getLogger(__name__)としたところ
debug.logにはログ出力されませんでした。(子孫構造が設定されていないためと考えています)

ロガーを設定して使う

以下のようにロガーを設定しても、importしたファイルからdebug.logにログ出力できました。5
(これだと「他のファイルにも同じように書かないといけないじゃん!」と思い、同じようなコードを繰り返さない方法を探して、子孫構造に至りました)

# logtest.py
import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger(__name__)
formatter = logging.Formatter(
    '%(asctime)s %(levelname)s: %(message)s '
    '[in %(pathname)s:%(lineno)d]'
)
debug_file_handler = RotatingFileHandler(
    'debug.log', maxBytes=100000, backupCount=1
)
debug_file_handler.setLevel(logging.INFO)
debug_file_handler.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(debug_file_handler)

def fabulous_message():
    logger.info('fabulous message create start')
    return 'Hello, World!'
2018-06-09 15:58:07,321 INFO: GET Access [in app.py:25]
2018-06-09 15:58:07,323 INFO: fabulous message create start [in /Users/.../logtest.py:21]

ロギング設定ファイル

importするファイル全てに書くのは大変そうなので、ロギング設定ファイルを使ってみようと思います。(宿題事項)

https://docs.python.jp/3/howto/logging.html#configuring-logging

ロギング設定ファイルを作り、それを fileConfig() 関数を使って読み込む。

動作環境

LINE Bot でオウム返し

f:id:nikkie-ftnext:20180610105316j:plain:w400

感想

takanoryさんから「Logging HOWTO — Python 3.6.5 ドキュメント」を教えていただき、ロギングの理解を深めることができました。教えていただきありがとうございました!
次の1週間を乗り切る準備ができたかなと思います。(勤務先でソロでPython使い続けるために毎週末に翌週の準備をしています。例外は直近では使わなさそうだから、またの機会に調べよう)

今回ははじめて来られた方がいつもより多かったと思います。
先日の #PyNyumon から来られた方もいて、メンターにトライした身として嬉しかったです。
来月は合宿ということで、私も思い切って飛び込んでみようと思います。(申込みました!)

脚注


  1. ロギングは次のコードを参考にしています。 http://study-flask.readthedocs.io/ja/latest/07.html#logging

  2. StackOverflowの次の回答を参考にしています。 https://stackoverflow.com/a/39863901

  3. http://flask.pocoo.org/docs/0.12/api/#flask.Flask.logger

  4. python app.pyの実行ではない本番環境で子孫構造が想定どおり働くかは検証の必要があります。

  5. RotatingFileHandlerに'debug.log'と直に渡しているのが気になるので、pathlibのPathを使うやり方に今後アップデートします。(ソフトウェアデザイン2018年2月号を参考にします)

イベントレポート | Chainer x Azure ML Hackathon CV編 #dllab

はじめに

だんないよ、nikkieです。
「Chainer x Azure ML Hackathon CV編」に参加してきました。

nikkieのレベル感

  • Azure ML Studioで機械学習(特にレコメンド)は業務で数ヶ月の経験あり
  • 深層学習について、用語は聞いたことがあるが、手を動かしたことがない

深層学習に踏み出したかったので参加しました。

勉強会の概要

いよいよ、ディープラーニングをエンジニアが使いこなす時代がやってきています。柔軟性が高く直感的な記述が可能なDeep Learning Framework Chainerと機械学習プロジェクトをEnd to EndでサポートするAzure Machine Learningを使って、画像認識、画像分類のExampleを作るハッカソンを行います。様々なデータセット(CIFAR10/100, ImageNet, MNIST, ResNet, YOLO)を使って、データ準備、モデル構築、モデルデプロイまでを行います。ExampleはDLLABのGitHubで公開します。今後も継続的にやっていきますよ!
ハッカソンと銘打っていますが、ハンズオンに近そうな印象を受け、初学者でもいけるだろうとエントリーしました。
各自でやることを決めて取り組む形式だったので、もくもく会の趣でした。

取り組んだこと

深層学習のイメージは、GPUと画像分類チュートリアル(CIFAR10など)でした。
そこで、AzureにGPUインスタンスを立てて、チュートリアルをやることにしました。

AzureにGPUインスタンスを立てる:DSVM
Chainerの名を冠するイベントなので、Chainerを使おうとWindows OSのData Science VMを作成。
(Data Science Virtual Machine - Windows 2016のNC6。月9万円程度)

Azure での Windows データ サイエンス仮想マシンのプロビジョニング | Microsoft Docs

Linux OSの方が慣れているのですが、UbuntuCentOSもドキュメント中にChainerの文字がありませんでした。
 そのため、Chainerが構築時から入っているWindows OSを使うことにしました)
 
Azure ML Workbenchからアクセスを試みる
Machine Learning 実験を作ってWorkbenchからアクセスを試みたところ認証でハマりました。(認証中から先に進まない状態になりました。。)
サインインすると、Workbench によって Azure サブスクリプション内で検出された最初の実験アカウントが使用され、
今回使ったアカウントにはいくつかのディレクトリが紐付いています。
Workbench側が全然関係ないディレクトリの認証情報入力を求めてきたので
虱潰しに検出するものなのかと入力したのですが、それ以降進まなくなりました。
後述のRDPという代替手段を見つけたので、深入りしませんでしたが、
トラブルシューティングのドキュメントを参考に、キャッシュファイルをクリアするとWorkbenchを復旧できるそうです。

DSVMにアクセスする
最初はSSHでつなごうとしたのですが、タイムアウトでうまくいきませんでした。
(ネットワークセキュリティグループの受信規則にSSHを追加したのですが、解決しませんでした。。)
リモートデスクトップ(RDP)ってMacからはできないものと思いこんでいたのですが、
上記ドキュメントのリンクから入手したアプリであっさり接続できました。

チュートリアルのための環境設定

DSVMにRDPしてJupyterでチュートリアルを進めることにしました。

チュートリアルを進めるに当たり、DSVMのChainerをv4にバージョンアップする手順がアナウンスされました。
コマンドプロンプトから以下を順に実施しました)
  • pip uninstall chainer
  • pip uninstall cupy
  • pip install chainer
  • pip install cupy-cuda90

DSVMはハッカソン後に消えるので、仮想環境は使わず、OSデフォルトのPython3.6.3とpipで進めています。

MNIST

ビギナー向けチュートリアル(上記リンク)のMNISTを進めました。
▼成果物
https://gist.github.com/ftnext/cd763fc4cec9f44373ad330443cad5aa
「全結合層のみからなる多層パーセプトロン」のGPUを使った学習まで進めたところで時間切れとなりました。

MacからRDP接続するとUSキーボードになったので苦労しました。

Mac からのRDP 接続で日本語キーボードを設定する

時間が限られていたので、以下のサイトをもとに読み替えて進めました。

USキーボードと日本のキーボードの違い

()はShift+9,0だったり、:はshift+;だったり、=はShift+^だったりとだいぶ混乱したので、設定をしたほうが作業が進んだかもしれません。

 

成果物のダウンロード

ファイル共有設定をすることで、DSVMで作成したnotebookがmacにダウンロードできました。

MacからWindowsにリモート接続する際のファイル共有 | ITBeginner

「ファイル共有」ということは、事前にmacでnotebookを用意することで
お高いDSVMの稼働時間を削減できそうです。(ファイルを送るか、コピペをする想定)

感想

深層学習に一歩踏み出しました!
今回進めたチュートリアルはわかりやすく、「エポック」や「ミニバッチ」などの用語をつかめた感触があります。

ただ、chainerのコードは呪文状態なので、勉強することはまだまだたくさんあります。
dllabさんからは手を動かす機会を定期的にいただけそうなので、今後もチェックしたいと思います。

chainerはscikit-learnみたいな書き方をするんだなと気づきました。
機械学習フレームワークはどれもオブジェクト指向で書いているのかも)

RDPははじめて触ったのですが、驚くほど使いやすかったです。

平日ハードワークのためか寝過ごしてしまい、午後からの参加でした(お恥ずかしい限りです)。
遅刻対応していただけて本当にありがたがったです。
「かたじけない、この御恩は必ず」という思いです。

あと、以下の質問をしたところ、バラバラだったAzureのサービスがつながり、
Azureを触っている身として進むべき方向が見えた気がします。
咀嚼しきれていないところもありますが、Azureについて学習するモチベーションが上がりました!

質問:Azure ML StudioとAzure ML Serviceの違いはなにか?

Azure ML Studioは触ったことがある。(ブラウザでGUI機械学習できるツール)
Azure ML Serviceは言葉だけ聞いているが、Studioとの違いが今ひとつわからなかった。

回答:

  • StudioはJupyterと同等
  • ServiceはJupyterの限界を取り払った(IoTやHololensまで広がる世界 & 自動化)

Studioは大量データの扱いに限界がある
StudioにはDeep Neural Networkがない
StudioはCPUで動く
StudioはAPIのデプロイが数クリックでできる

WorkbenchはPython + Dockerでできている。(※Serviceの主要構成要素としてWorkbenchがあると理解しました)
日付や文字データであればpandasのdatasetとしてデータ加工してくれる
トレーニング環境の使い分けができる(ローカル、GPU(DSVM)、Azure Batch(GPUインスタンスが複数立ち上がる)、Spark)
WorkbenchはモデルをBlob Storageに保存。モデルのマトリックス(ハイパーパラメタ × エポック数)からモデルを選抜すればよい
データ加工、学習、デプロイ全てでCLIを提供→自動化を見据えている

IoTHubからデバイス(ラズパイ)を指定して、モデルを流せる。(Dockerを使う。Azure Container Registoryに保存)
 buildではデバイスのツールキットを発表。今は1000円程度だが、このコストは今後激減すると見込まれる
Windows間ではモデルはONNX形式でやり取りできる。→Hololensに渡せる

 

以上です。
ハッカソン関係者と参加者の皆さま、どうもありがとうございました。1日お疲れ様でした。