Amazon EC2 P3インスタンスにおけるPose Estimation速度向上検証

はじめに

皆さんこんにちは。AIシステム部・AI研究開発グループの李天琦(leetenki)です。

先日Amazon EC2 P3インスタンスがリリースされるに伴い、11月9日にアマゾン東京本社にて、「Amazon EC2 GPU インスタンス 祭り」というイベントが開かれました。それに先駆けて、弊社AIシステム部では特別に先行でP3インスタンスを使用させて頂き、速度性能の評価を行いました。また、イベントでのお客様企業による登壇セッションでもその内容について発表させて頂きました。本記事でその評価結果について紹介しようと思います。

AWS_AI1.png

Amazon EC2 P3インスタンスとは

Amazon EC2 P3は、NVIDIA Tesla V100世代のGPUを搭載した最新のインスタンスです。GPUベースの並列コンピューティング機能を兼ね備え、CUDAやOpenCLを使用するGPGPUコンピューティング用途向けに設計ています。特に高い浮動小数点演算処理能を必要とする機械学習、Deep Learning用途に最適化されています。

2017年11月時点において、Amazon EC2で提供されているオンデマンドタイプのGPUインスタンスのうち、P3シリーズのインスタンスは下記の3種類です。全てTesla V100モデルのVoltaアーキテクチャのGPUを搭載しています。GPUの数やGPUメモリサイズ、CPUの数やCPUメモリサイズ等の細かい違いがあります。

GPUs GPU Memory CPUs Main Memory
p3.2xlarge 1 16 8 61
p3.8xlarge 4 64 32 244
p3.16xlarge 8 128 64 488

検証環境

今回速度性能評価を行う上で、比較をシンプルにするために、以下の1GPUのみのp3.2xlargeタイプのインスタンス、及びこれに対応する1世代前のp2.xlargインスタンスを使用しました。

GPUs GPU Memory CPUs Main Memory
p2.xlarge 1 12 4 61
p3.2xlarge 1 16 8 61

また、OS及び各種ライブラリ環境はどちらも以下のように統一させました。

OS Ubuntu16.04
CUDA 9.0
cuDNN 7.0
chainer 3.0.0
cupy 2.0.0

検証用モデル

自分はAIシステム部内ではComputer Visionチームに所属しているという事もあり、今回は普段から業務で使っているCNN(Convlutional Neural Network)について速度検証させていただきました。具体的には、以下に述べるVGG19及び、Pose Estimationのネットワークを使用しました。

VGG19速度比較

Computer Visionのタスクを解く上で、よく使われるCNNモデルにVGG19というのがあります。これは元々、画像認識の世界的なコンペティションであるILSVRC2014において、Classification Taskの分野で世界一の精度を記録したモデルです。最近ではClassification Taskだけでなく、様々な高度なCNNモデルのベースの特徴抽出器としても使われています。そのモデル構造は非常にシンプルで、下図のように3×3のConvolution層及びPooling層のみから成り立っています。

AWS_AI2.png

Architecture of the two-branch multi-stage CNN (Cao, et al., 2017)

今回VGG19の計測を行うために、元々p2インスタンス上で動かしていたコードをそのままp3インスタンスに持ってきて速度比較を行いました。本来ならば、Tensorcoreを発動させるのにp3用にソースコードをFP32からFP16に書き換えるのが望ましいですが、今回はChainerの開発ブランチが上手く動作せず、そちらについては断念しました。

以下が、p2及びp3上におけるVGG19モデルの動作速度の比較になります。このグラフでは、VGG19を1回推論処理するのに必要な平均時間を示しています。 AWS_AI3.png

VGG19を1回推論処理するのに、p2インスタンスでは5.7[msec]かかっていたのが、p3インスタンスでは0.62[msec]と約9〜10倍高速化される結果となりました。 なぜTensorcoreを発動せずともこのように高速化できたのかについて、詳しく調べるためにNVIDIA Profilerを使ってプロファイリングしてみました。

まずp2インスタンスについて、下図のように、処理中はGPU使用時間の約70%をimplicit_convole_sgemmというcuda関数が占めています。これは簡単に言えば、cudaを使ったconvolution層の畳み込み演算を行う関数です。 AWS_AI4.png

一方で、p3インスタンスの処理結果を見てみると、同じようにconvolution処理を行なうのに、implicit_convole_sgemmではなく、winograd3 × 3Kernelというcuda関数が呼び出されています。 AWS_AI5.png

このwinogradが何かと言うと、convolutionのカーネルサイズが小さい時(3 × 3等)に、畳み込み演算を高速化するアルゴリズムです。VGG19のモデルでは全てのconvolution層のカーネルサイズが3 × 3となっているので、このwinogradアルゴリズムにより大幅に高速されたという訳です。しかし、このwinogradアルゴリズムは実はKepler世代より前のGPUには対応していないため、今回はp3インスタンス上でのみ発動し、このwinogradアルゴリズムの差、及び元々のGPUパワーの差が効いて、9倍高速されたと推測できます。

Pose Estimation速度比較

次にPose Estimationについて速度比較を行います。このPose Estimationという技術を簡単に説明すると、RGBの2次元動画像から、映っている人の細かいPoseを推測する技術です。下図のように、実際に我々が開発を進めているスマートショップというプロジェクトでもこの技術を活用しています。

movie_result.gif

アルゴリズムの詳細については元論文を参照して頂ければと思いますが、このアルゴリズムのモデル構造は非常にシンプルです。下図にあるように、ネットワーク構造は1 × 1、3 × 3、7 × 7のConvolution 及びPooling Layerのみで構成されています。

AWS_AI6.png

Architecture of the two-branch multi-stage CNN (Cao, et al., 2017)

入力画像を、まずはVGG19とほぼ同じ構造のCNNに通して、解像度を8分の1に圧縮した特徴マップを抽出します。その後段で2つのブランチに分岐し、1つはConfidence Mapsと呼ばれる、体の各key pointをheatmap形式で予測するネットワークです。下図のように、key pointの種類ごとに1channelの出力で予測します。

AWS_AI7.png

Part Confidence Maps (Cao, et al., 2017)

もう一つのブランチが、PAFs (Part Affinity Fields) と呼ばれる、各key point間の繋がりうる可能性を表すベクトルマップを予測するネットワークです。

AWS_AI8.png

出典: Part Affinity Fields (Cao, et al., 2017)

これら2つのブランチでConfidence Maps及びPAFsをそれぞれ予測した後、さらに予測した結果に最初のVGG19で抽出した特徴マップをconcatして、これを再度同じ構造のネットワークに繰り返し入力していきます。この繰り返しのネットワークをstageと言い、stageが進むほど精度があがる仕組みです。

このPose Estimationのモデルに関してはstageごとに推論速度の比較を行いました。以下が比較結果になります。 AWS_AI9.png

こちらの比較結果を見ると、最初のVGG19の処理部分では、p3インスタンスのほうが約8〜9倍高速化できている事がわかります。また、その次のstage1でも、p3インスタンスのほうが約7倍高速化されています。しかし、stage2以降では差が縮まり、約2.3倍しか高速化されない結果となりました。

これについてもプロファイリングしてみたところ、winogradアルゴリズムが関係している事がわかりました。先ほど説明した通り、winogradというのはconvolutionのカーネルサイズが小さい時(3 × 3等)に、畳み込み演算を高速化するアルゴリズムです。今回使用したPose Estimationのモデルでは、最初のVGG19及びstage1の部分では全てカーネルサイズが3 × 3のconvolution層で構築されているため、p3インスタンスのほうでwinogradが発動して7〜9倍高速化された訳です。しかし、stage2以降ではほとんどのconvolution層がカーネルサイズ7 × 7に置き換わるため、p3でwinogradを発動させる事ができず、GPUパワーの違いのみで、そこまで大きく速度差が開かなかったと考えられます。

Batch処理の速度比較

以上のpose estimationの推論速度の比較を行ったところ、winogradが発動しない場合はGPUパワーのみの違いで約2〜3倍しか差が開かない事がわかりました。しかし、GPU使用率を見てみると、p2インスタンスではGPU使用率100%といっぱいいっぱいなのに対し、p3インスタンスではGPU使用率が34%とまだかなり余裕があるように思えます。

そこで、Batch処理を行って、どちらもGPU使用率を100%まで使い切った状態で速度比較を行いました。下図が、batchサイズを増やした際のp2インスタンス及びp3インスタンスの推論処理時間になります。 AWS_AI10.png

batch size 1の時ではp3インスタンスのほうが処理速度3.7倍(stage 2までのトータル処理速度)だったのに対し、batch sizeを大きくしていけば行くほど処理速度の差が開いていく結果になりました。グラフにあるように、p2インスタンスではbatch sizeを32倍にすると処理速度もそれに比例して約30倍ほど遅くなるのに対し、p3インスタンスではbatch sizeを32倍にしても処理速度は約8〜9倍しか遅くならないという結果となりました。倍率で言うと、batch size 32で処理した場合はwinogradの発動しないstage2以降でも、p3インスタンスのほうが8倍以上高速化可能という事になります。

ちょうど、今までp2インスタンス上でリアルタイムのPose Estimationを行うのに約3〜4FPSとフレームレート的にカクカクだったので、これをp3インスタンスに置き換えれば30FPSと完全にリアルタイムで処理できるという事になります。

訓練速度比較

ここまで推論の話を書いてきたので、訓練についても速度比較を行ってみます。ここでは、Pose Estimationのモデルをフルスクラッチで訓練させ、1回の順伝搬及び逆伝搬にかかったイテレーション時間を計測します。なお、batch sizeはGPUメモリの都合上どちらも16とします。

以下が訓練における速度比較結果になります。p2インスタンスでは1回のイテレーションを行うのに9.8秒かかったのが、p3インスタンスでは1.3秒と約7.5倍高速化された結果となりました。ちょうど今までp2インスタンスでの訓練に1週間ほどかかっていたのが、1日で完了するので実用的にはかなり嬉しいですね。

速度
p2インスタンス 9.8[sec/iter]
p3インスタンス 1.3[sec/iter]

コストパフォーマンス比較

今回速度比較に用いたp2.xlarge及びp3.2xlargeインスタンスについて、東京リージョンの価格を比較してみます。

価格
p2.xlarge $1.542/hour
p3.2xlarge $5.243/hour

このように、コスト面ではp3.2xlargeのほうが約3.4倍高くなっています。しかしこれまで説明した通り、p2インスタンス上で動いていたコードに特に変更を加えなくとも、そのままp3インスタンスに持って行けば約7〜9倍高速化できるので、値段の割にコスパはかなり良いと思います。そして今回は残念ながら触れられませんでしたが、Volta世帯のGPUの目玉機能であるTensorcoreが発動するようコードを修正すれば、更に10倍速以上の高速化が期待できますので、機会があればそちらにもチャレンジしてみようと思います。

おまけ

おまけですが、今回p2及びp3インスタンスの速度比較に使用したPose Estimationのソースコードについて、こちらでオープンソース公開していますので、皆さんもし良かったら試してみてください。

参考文献

・Zhe Cao and Tomas Simon and Shih-En Wei and Yaser Sheikh. Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields. In CVPR, 2017. arXiv:1611.08050 [cs.CV].

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

Chainerを用いたRealtime Multi-Person Pose Estimation実装

はじめに

皆さんこんにちは。DeNAのAI研究開発エンジニアの李天琦(leetenki)です。今日はChainer Advent Calendar 2017の初日エントリという事で、Realtime Multi-Person Pose Estimationの実装について解説させて頂きます。

movie_result.gif

pose estimationの実行結果

背景

Realtime Multi-Person Pose Estimationとは、CVPR2017でCMUが発表した、RGBの2次元画像のみから複数人のPose情報を検出するアルゴリズム (Cao, et al., 2017) です。特徴は、1枚の画像から複数人のPoseを検出するために、それまで主流であったBounding Boxを検出した後に各Boxに対してPose検出するというトップダウン方式を取らずに、ボトムアップかつワンショットに複数人のPoseを推定してしまう点です。画像に映ってる人数に関わらず1回の推論でPose推定を行うので、Realtimeに処理できるほど高速という訳です。また、1回の推論でPoseまで検出できるので、Bounding Boxから検出するトップダウン方式に比べると誤差の蓄積がなく、精度も著しく向上しています。事実こちらのアルゴリズムは2016 MSCOCO Keypoints Challengeで優勝し、この時点においてのstate-of-the-artを記録しています。

CMUのオリジナル実装はCaffeをベースにしたopenposeというライブラリで公開されています。TensorFlowやPyTorchによる再現実装も有志で行われているようですが、Chainer実装で公開されているものはなかったので、今回はこれをChainer化していこうと思います。コードはこちらを参照してください。

モデル解説

実装の話に入る前に、まずはモデルの構造を簡単に説明しておきます。

詳細は元論文を参照して頂ければと思いますが、このアルゴリズムのアーキテクチャ自体は非常にシンプルです。以下のモデル図にあるように、ネットワーク構造は1 × 1、3 × 3、7 × 7のConvolution 及びPooling Layerのみで構成されています。

Chainer-1.png

Architecture of the two-branch multi-stage CNN (Cao, et al., 2017)

入力画像を、まずはVGG19とほぼ同じ構造のCNNに通して、解像度を8分の1に圧縮した特徴マップを抽出します。その後段は2つのブランチに分岐しており、1つはConfidence Mapsと呼ばれる、体の各key pointをheatmap形式で予測するネットワークです。下図のように、key pointの種類ごとに1channelの出力で予測します。

Chainer-2.png

Part Confidence Maps (Cao, et al., 2017)

もう一つのブランチが、PAFs (Part Affinity Fields) と呼ばれる、各key point間の繋がりうる可能性を表すベクトルマップを予測するネットワークです。繋がりが定義されているkey point間を結ぶ線分上(正確には一定の幅を持つ領域)の全てのピクセルにおいて、一定の長さを持つ方向ベクトルが定義されます。このベクトルはxとyの2枚チャンネルのheatmapによって表現されます。下図の例では、オレンジ色となっている部分が、肩から腕にかけての方向ベクトルのマップです。

Chainer-3.png

出典: Part Affinity Fields (Cao, et al., 2017)

これら2つのブランチでConfidence Maps及びPAFsをそれぞれ予測した後、さらに予測した結果に最初のVGG19で抽出した特徴マップをconcatして、これを再度同じ構造のネットワークに繰り返し入力していきます。この繰り返しのネットワークをstageと言い、stageが進むほど精度があがる仕組みです。

モデルの実装

では実装の解説に入っていきましょう。MSCOCO Keypoints Challenge 2016で訓練済みの重みパラメータファイルがこちらで公開されていますので、今回まずこれをChainer用に変換して、推論の処理を実装して行きます。

先ほど説明したように、このアルゴリズムのネットワーク構造自体は非常にシンプルで、1 × 1、3 × 3、及び7 × 7のConvolution Layerのみで構成されています。ゆえに、chainer.links.caffe.CaffeFunctionを使えば簡単にcaffemodelを読み込む事ができます。ただし、CaffeFunctionを使ったcaffemodelの読み込みは非常に時間がかかるので、毎回使い回す事を考えて、一旦自前でChainerのLayer定義を書いて、これに重みパラメータを代入した状態でnpzファイルに書き出します。

ChainerのLayer定義ファイルはこちらです。以下のconv11からconv44_CPMの部分が最初のVGG19を使った特徴抽出器です。VGG19と同じ構造で、全て3 × 3のConvolution Layerとなっています。これによって画像サイズが8分の1に圧縮されたFeature mapが出力されます。

# cnn to make feature map
conv1_1=L.Convolution2D(in_channels=3, out_channels=64, ksize=3, stride=1, pad=1),
conv1_2=L.Convolution2D(in_channels=64, out_channels=64, ksize=3, stride=1, pad=1),
conv2_1=L.Convolution2D(in_channels=64, out_channels=128, ksize=3, stride=1, pad=1),
conv2_2=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv3_1=L.Convolution2D(in_channels=128, out_channels=256, ksize=3, stride=1, pad=1),
conv3_2=L.Convolution2D(in_channels=256, out_channels=256, ksize=3, stride=1, pad=1),
conv3_3=L.Convolution2D(in_channels=256, out_channels=256, ksize=3, stride=1, pad=1),
conv3_4=L.Convolution2D(in_channels=256, out_channels=256, ksize=3, stride=1, pad=1),
conv4_1=L.Convolution2D(in_channels=256, out_channels=512, ksize=3, stride=1, pad=1),
conv4_2=L.Convolution2D(in_channels=512, out_channels=512, ksize=3, stride=1, pad=1),
conv4_3_CPM=L.Convolution2D(in_channels=512, out_channels=256, ksize=3, stride=1, pad=1),
conv4_4_CPM=L.Convolution2D(in_channels=256, out_channels=128, ksize=3, stride=1, pad=1),

その後に続く以下のような2分岐されたConvolution Layerが、各StageにおけるPAFs及びConfidence Mapsの計算部分になります。ここではL1とついてるのがPAFsで、L2がConfidence Mapsになります。そして、stage1ではカーネルサイズ3 × 3のConvolution Layerで構成されていますが、stage2以降ではreceptive fieldを広げるために7 × 7のConvolutionに置き換わっています。stage3以降のネットワークも全てstage2と同じ構造となっています。

# stage1
conv5_1_CPM_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_2_CPM_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_3_CPM_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_4_CPM_L1=L.Convolution2D(in_channels=128, out_channels=512, ksize=1, stride=1, pad=0),
conv5_5_CPM_L1=L.Convolution2D(in_channels=512, out_channels=38, ksize=1, stride=1, pad=0),
conv5_1_CPM_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_2_CPM_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_3_CPM_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=3, stride=1, pad=1),
conv5_4_CPM_L2=L.Convolution2D(in_channels=128, out_channels=512, ksize=1, stride=1, pad=0),
conv5_5_CPM_L2=L.Convolution2D(in_channels=512, out_channels=19, ksize=1, stride=1, pad=0),
# stage2
Mconv1_stage2_L1=L.Convolution2D(in_channels=185, out_channels=128, ksize=7, stride=1, pad=3),
Mconv2_stage2_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv3_stage2_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv4_stage2_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv5_stage2_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv6_stage2_L1=L.Convolution2D(in_channels=128, out_channels=128, ksize=1, stride=1, pad=0),
Mconv7_stage2_L1=L.Convolution2D(in_channels=128, out_channels=38, ksize=1, stride=1, pad=0),
Mconv1_stage2_L2=L.Convolution2D(in_channels=185, out_channels=128, ksize=7, stride=1, pad=3),
Mconv2_stage2_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv3_stage2_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv4_stage2_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv5_stage2_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=7, stride=1, pad=3),
Mconv6_stage2_L2=L.Convolution2D(in_channels=128, out_channels=128, ksize=1, stride=1, pad=0),
Mconv7_stage2_L2=L.Convolution2D(in_channels=128, out_channels=19, ksize=1, stride=1, pad=0),

次に、caffemodelをChainer用に変換します。変換用コードはこちらです。重みパラメータの代入部分は以下のようになります。

exec("chainer_model.%s.W.data = caffe_model['%s'].W.data" % (layer_name, layer_name))
exec("chainer_model.%s.b.data = caffe_model['%s'].b.data" % (layer_name, layer_name))

Convolution Layerの場合、W.dataとb.dataのみ代入すれば済みますので、これを全てのLayerに対して繰り返すだけです。

推論の実装

ネットワークの推論の実装はこちらです。実際にCNNの処理を行っている部分はこれだけです。

h1s, h2s = self.model(x_data)

RGB画像をCNNに通して、PAFsとConfidence Mapsの出力を得るだけですね。ただ、このアルゴリズムのミソはその後処理部分で、得られたPAFsとConfidence Mapsからスケルトン情報を再構築する部分が最も複雑です。では順を追って説明していきます。

① PAFsとConfidence Mapsのサイズ拡大
ネットワークから出力されるfeature mapは幅も高さも8分の1に圧縮されているので、まずはこれをresizeしてオリジナルの画像サイズに引き伸ばします。Chainer2.0からはchainer.functions.resize_imagesというFunctionが定義されたので、これを使うとVariableのまま計算できます。

② Confidence Mapsをガウシアン平滑化
8倍サイズに引き伸ばした直後のConfidence Mapsは、peak周りがデコボコしていて、山がハッキリしないので、これにガウシアンフィルタをかけてpeakを一定に平滑化します。scipy.ndimage.filters.gaussian_filterを使えば簡単に実装できるのでオススメです。以下がガウシアン平滑化の計算部分になります。

heatmap = gaussian_filter(heatmaps[i], sigma=params['gaussian_sigma'])

下図の左がガウシアンフィルタをかける前で、右がかけた後です。 Chainer-4.png

ちなみに、これをVariableのままGPUを使って計算したい場合、chainer.functions.convolution_2dを使って、ガウシアンカーネルを手動で定義してあげれば実装できます。

③ Confidence Mapsからkey point座標を求める
ガウシアンフィルタをかけた後のConfidence Mapsは下図(右)のようになります。ここから、peakの(x, y)座標を求めます。実はこのConfidence Mapsからpeakの座標値を求める処理が意外に計算コストが高いのです。 Chainer-5.png

実際にConfidence Mapsからpeak座標を求める処理は以下の部分になります。

map_left = xp.zeros(heatmap.shape)
map_right = xp.zeros(heatmap.shape)
map_top = xp.zeros(heatmap.shape)
map_bottom = xp.zeros(heatmap.shape)
map_left[1:, :] = heatmap[:-1, :]
map_right[:-1, :] = heatmap[1:, :]
map_top[:, 1:] = heatmap[:, :-1]
map_bottom[:, :-1] = heatmap[:, 1:]

peaks_binary = xp.logical_and.reduce((
    heatmap >= map_left,
    heatmap >= map_right,
    heatmap >= map_top,
    heatmap >= map_bottom,
    heatmap > params['heatmap_peak_thresh']
))

ここでは効率良く計算するために、Confidence Mapsを上下左右に1ピクセルずつずらしたheatmapを4枚用意します、オリジナルのConfidence Mapsと上下左右のheatmapを比較して、その全てより値が大きいピクセルをkey pointとして座標抽出するようにしています。

④ key point間のPAFsを積分
key pointが全て求まった後、関係あるkey pointだけをグルーピングして人のスケルトンを構築する必要があります。論文では、2種類のkey point間の考え得る全てのconnectionの組合せを実際に繋げてみて、その間のPAFsの積分値で同じグループか否かを判別します。ちなみに、そもそもなぜこのPAFsの積分を行うのかと言うと、訓練時に、関係あるkey pointの間には一定の方向ベクトルが定義され、関係ないkey point間ではゼロベクトルが定義されるので、推論する時にはこれを手掛りにkey point間のベクトルの方向及び大きさの合計を見れば、2つのkey pointが関係あるか否か判別できるのです。

PAFsの積分は元論文に書いてある通り、2点間を結ぶ線分上の各ピクセルにおいて、その水平方向ベクトルと実際の推論で求まったベクトル値の内積をとって、全部足し合わせるという手法です。

Chainer-6.png

single limb with groundtruth positions (Cao, et al., 2017)

これを実際に実装しているのが以下の部分になります。params[‘nintegpoints’]というのは、2点間を何分割するかというハイパーパラメータで、今回は10に設定しています。

vec_unit = vec / vec_len
integ_points = zip(
    np.linspace(joint_a[0], joint_b[0], num=params['n_integ_points']),
    np.linspace(joint_a[1], joint_b[1], num=params['n_integ_points'])
)
paf_in_edge = self.extract_paf_in_points(paf, integ_points)
inner_products = np.dot(paf_in_edge, vec_unit)

⑤ connectionの選択
以上の④までで、各点間の候補となるconnectionはPAFsによって重み付けられた積分値を得る事ができました。最後はこれを使って有効なconnectionを選択していきます。本来であれば2種類のkey point間で考え得る全パターンの組合せを作り、そのトータルのPAFs積分値が最大となる組合せを選択すべきですが、これを愚直に実装すると人数が増えるにつれて計算量がO(n^2)で増えていきます。なので、今回はgreedy法を採用し、PAFs積分値を大きい順にソートして上から順に選択していきます。そしてそれ以上選べるkey pointがなくなった時点で打ち切るようにしています。以上の処理はcompute_connectionsという関数で実装しています。

推論処理の実装は以上です。モデル訓練の話はData AugmentationやPAFs生成と長くなりそうなので、また次回のパートⅡで書こうと思います。

実行結果

ではてきとうな画像を使って推論を試してみましょう。

Chainer-8.png 完璧にPose認識できていますね。

Chainer-7.png

人が増えても、遠くにいても問題ないですね。 ※ちなみに推論処理のスケールについて、entity.pyというファイル内で以下のように定義しているハイパーパラメータがあります。

'inference_scales': [0.5, 1.0, 1.5]

これは画像を0.5倍、1.0倍、1.5倍のスケールでそれぞれ推論し、その結果を平均するという意味です。速度と精度のトレードオフだと思いますが、この値を調整すればいろんなスケールに対して高精度にPose検出する事ができます。

今回、chainerで実装したRealtime Multi-Person Pose Estimationのコードは全てこちらで公開していますので、皆さん興味があればぜひご自分の環境で動かしてみてください。

参考文献

・Zhe Cao and Tomas Simon and Shih-En Wei and Yaser Sheikh. Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields. In CVPR, 2017. arXiv:1611.08050 [cs.CV].

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

KDD2017に参加してきました

はじめに

こんにちは。AIシステム部研究開発グループの春日です。当グループではCV/NLP/RLといった技術領域を中心に研究開発を行い、実際のサービスへの活用を行っております。近年では会社として次の柱とすべくオートモーティブ事業へも注力しており、ここで活用される機械学習技術も当グループで開発を担っています。そこで、KDDというデータマイニング分野でのトップカンファレンスを聴講しにいき、オートモーティブ事業関連で活用されている技術についてキャッチアップしてきました。今回はその内容についてお伝えしていきたいと思います。

KDDとは

KDDの正式名称は「International Conference on Knowledge Discovery and Data Mining」です。今回は23回目の開催であり、1990年代にデータマイニングという研究分野が明確に確立されてから現在も盛んに研究発表がなされています。開催期間は8/13-17の5日間でした。初日はTutorial Day、2日目がWorkshop Dayという特定のテーマに沿った発表です。3-5日目がMain KDD Conferenceで、採択率約10%で採択された優秀な論文が発表されます。

開催場所

開催場所は、カナダ・ハリファックス (Halifax, Nova Scotia - Canada) です。日本からだと直行便がなく、最短で約17時間はかかる場所です。小さい町ですが港町として栄えており、非常に過ごしやすい場所でした。

kdd-image7.png

[ 会場のHalifax World Trade and Convention Centre]

さすが、港町というだけあって平然とロブスターが大量に叩き売りされています。

kdd-image8.png

[ロブスターの陳列]

近年のデータサイエンスブームの波を受けたこともあり、過去最多の1143本が投稿され、Main Conferenceに採択されたのは100本、Posterに採択されたのは116本でした。

セッションの様子

投稿された論文のうちMain Conferenceに採択されると口頭での発表ができます。カテゴリごとに複数の会場があり、各会場とも300人程度のキャパシティがあります。人気なところは立ち見になることもあります。Google社の講演 TFX: A TensorFlow-Based Production-Scale Machine Learning Platform (Denis Baylor et al.) は大変盛況でした。

kdd-image19.jpg

[Main Conferenceでの発表の様子(KDD2017での講演より)]

一方で、Posterに採択されると、19:00-22:00の夜の時間帯で会場に自身の研究内容をポスターで展示し、参加者からの質疑応答に応える形式で発表がされます。

kdd-image12.jpg

[Poster発表会場の様子(KDD2017でのポスター展示より)]

注目の論文

今回KDDに参加した中で、オートモーティブドメインにおいて注目すべき論文を取り上げて紹介します。

  • The Simpler The Better: A Unified Approach to Predicting Original Taxi Demands on Large-Scale Online Platforms (DiDi Chuxing)

こちらは中国の配車最大手「DiDi Chuning」による論文 The Simpler The Better: A Unified Approach to Predicting Original Taxi Demands on Large-Scale Online Platforms (Yongxin Tong et al.) です。DiDiはUber Chinaを350億ドルで買収したことで一大ニュースとなった有力企業です。そのDiDiが主力事業としているタクシー配車におけるタクシー需要のオンライン予測システムに関する論文です。UOTD(Unit Original Taxi Demand)とは、下図で示すようにそれぞれのPOIや時間ごとのタクシーの需要を意味します。ここでは1時間ごとのZhongguancun Software Parkにおけるタクシー需要の予測値を示しています。

kdd-image18.png

[タクシー需要のオンライン予測 [1]]

特徴的なのが、DeepLearningを代表とする複雑なネットワークモデルを用いて予測するのではなく、以下の式で示すような単純な線形回帰モデルで予測している点です。これにシンプルな正則化項を加えただけのモデルです。

kdd-image9.png

[需要予測に用いているモデル [1]]

ただし、特徴量は合計で2億次元以上という非常に大規模なものを用いています。これには、時間や天気、POIといった様々な特徴を組み合わせたものも含みます。

kdd-image10.png

[大規模な特徴量構成 [1]]

このようなモデルを用いている背景にはビジネス観点があります。それは法規制等の環境の変化に伴って、新たな特徴が加わるごとに、モデル自体を見直すのは非常に高コストであるからという考えです。DeepLearningのようなモデルは、入力が変化する度にハイパーパラメーターチューニングに非常に時間やリソースがかかってしまうため、モデルは線形回帰と固定して特徴量だけ再設計することで、新たな予測をするということです。サービスから得られた実データを用いた実験では、NNやGBRTといった手法より高精度で予測できています。 近年では、AI = DeepLearning という認識が広まりつつあるのですが、ビジネスへの活用という観点ではこのような古典的かつシンプルな線形回帰で十分なバリューを発揮するという意味で非常に面白い論文です。

[1] The Simpler The Better: A Unified Approach to Predicting Original Taxi Demands on Large-Scale Online Platforms (Yongxin Tong et al.)

  • A Taxi Order Dispatch Model based On Combinatorial Optimization (DiDi Chuxing)

同じくDiDiによる論文ですが、こちらはタクシー配車におけるDispatchを扱ったものです A Taxi Order Dispatch Model based On Combinatorial Optimization [Lingyu Zhang et al.] 。Dispatchとはタクシードライバーと顧客の配車オーダーの割当を意味し、これをどのように最適化するかという問題です。まず前提として、顧客が配車オーダーを出した段階で、ドライバーにリクエストが送信されます。ドライバーはそれを承諾するか拒否するかという行動をとることができます。よって、どのオーダーをどのドライバーに割り当てれば承諾の成功確率(=SR)を最も高くできるかを考えなくてはなりません。単純には、配車オーダーがあった地点から最も近い地点のドライバーを割り当てるといった方法が考えられます。

kdd-image15.png

[オーダーとドライバーの位置関係の例 [2]]

DiDiの提案手法では、まずドライバーの承諾確率をモデル化します:pij=p(y=1|oi,dj) oiはオーダーに関連するETAやPOIのカテゴリーといった特徴量、djはドライバーに関連する過去の承諾率や営業エリアといった特徴量です。さらに曜日や時間といった特徴も加えて、承諾確率pijをモデル化します。ここではLogistic Regressionが用いられています。 この承諾確率を用いてSRの平均を最大化するオーダーとドライバーの割当の組み合わせを以下に式に従って最適化します。

kdd-image16.png

[Order Dispatch Problem [2]]

この際、Hill-climbing Algorithmを用いて最適解を求めます。北京市内の実データに適用実験した結果、SRがベースラインモデルの80%から84%に向上したということです。

kdd-image17.png

[実験結果 [2]]

DiDiは自社にどんどん蓄積される豊富なデータを用いて、より効率的なモデルの独自開発を行っており、今後も注目すべき企業だといえます。 [2] A Taxi Order Dispatch Model based On Combinatorial Optimization [Lingyu Zhang et al.]

  • Planning Bike Paths based on Sharing-Bikes' Trajectories (Microsoft Research)

こちらは最近日本進出でも話題となったMobikeのデータを用いた自転車専用レーンの設計計画に関するMicrosoft Researchの論文 Planning Bike Paths based on Sharing-Bikes' Trajectories [Jie Bao et al.]

kdd-image14.png

[Mobikeユーザーの走行軌跡データ(KDD2017での講演より)]

中国では大気汚染や交通渋滞の解消のためにシェアバイクが急速に普及しています。しかし、自転車専用レーンが整備されていないため、安全性が不十分という問題があります。そこで、予算という制約のもとで、いかに効率的に専用レーンを建設すべきかが今回の目的です。 各ユーザーの走行軌跡に対して建設した専用レーンのスコアをscore(,)=ssegs()s.ls.lと定義します。これを合計したスコアTscore(,)を最大化するように専用レーンを建設する計画を立てます。 方法はシンプルで、①開始点を抽出する ②Greedy Network Expansionによって道路リンクを繋いでいく というステップで最終的に建設する道路ネットワークを抽出・可視化します。 ①の開始点の抽出ですが、単純には最も頻繁に使われる上位数点を用いるといったことが考えられます。そうすると、頻繁に通る道はたいてい近い場所にあることが多いので、かなり近い範囲で開始点が定まってしまうことが問題です。そこでSpatial Clusteringを行うことで、空間的な広がりも考慮しながら開始点を定めるというところが本手法のコアです。これによって、下図で示すように、地図上で広がりのある道路ネットワークを可視化できていることがわかります。 ②のGreedy Network Expansionでは、①で決めた開始点を繋ぐように貪欲に道路リンクを探索していきます。もちろん予算という制約があるので、出来る限りの開始点を繋げるように道路リンクを広げていきます。

kdd-image11.png

[Spatial Clusteringを用いた結果 [3]]

[3] Planning Bike Paths based on Sharing-Bikes' Trajectories [Jie Bao et al.]

KDD Cup 2017

最後に KDD Cup というデータ分析コンテストについて共有します。KDD Cup では提供されたデータセットに対して課題が設定され、その課題におけるモデルの精度を競うコンペティションです。世界的にも権威と歴史がある大会で、トップクラスのデータサイエンティストが競い合います。今回のテーマは、''Highway Tollgates Traffic Flow Prediction" でした。課題設定は2つあり、①Travel Time Prediction ②Volume Prediction です。ここでは、①Travel Time Predictionについて取り上げます。

kdd-image13.png

[Highway Tollgates Traffic Flow Prediction [5]]

このタスクは交差点から料金所の旅行時間を予測するというものです。例えば上図でいうと、IntersectionAからTollgate2の区間での車両の通過時間を意味します。用いるデータセットは各区間の車両軌跡データ・該当エリアの天気・道路ネットワークです。評価指標は移動時間予測タスクにおける一般的な指標であるMAPE(Mean Absolute Precentage Error) です。優勝チームであるTeam Convolutionは、MAPE=0.1748でした。このチームが優勝したポイントはモデル・特徴・データという3つのレベルでのアンサンブル学習にあります。モデルレベルではXGBoostやMultilayer Perceptron等のモデルを用いたアンサンブル学習とします。特徴レベルでは異なる減衰係数やスムージング係数等を用いて算出した特徴量を組み合わせたものをアンサンブル学習させます。データレベルでは異なる滑走窓の値や分割数でのデータによりアンサンブル学習させます。このように3つのレベルでたくさんアンサンブル学習させることにより汎化性能を上げ、MAPE = 0.1748という精度を得られています。かなりテクニカルではありますが、基本的には複雑なモデルを用いずに、BoostingやMLPといった古き良き古典的なモデルを用いている点が面白いです。実際のビジネスの場でも最新の複雑なモデルではなく、広く一般的に使われているモデルを用いる場面も多々あります。

[5] KDD Cup 2017

全体の感想

KDDという学会は扱う分野がかなり幅広いのですが、今回は主にオートモーティブ事業関連について取り上げました。他にもClusteringやGraphなどの理論寄りに関する研究から、Medical DataやRecommendationといった実務寄りの研究まで多様な研究が発表されていました。ご興味ある方はこちらのAccepted Paperからご覧下さい ( http://www.kdd.org/kdd2017/accepted-papers ) 今回の学会参加を通して、最先端のオートモーティブ事業で取り組まれている技術についてキャッチアップできたことはもちろん、参加者の方々とのネットワーキングができたことも大変刺激的で良い勉強になりました。 DeNAでは国際学会派遣制度というものがあり、私のような新卒1年目でも積極的に学会に参加することができます。こういった制度を活用してスキルアップできる環境は素晴らしいと思います。一緒に働いてみたいと思われた方は是非ご一報下さい!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

Google機械学習活用勉強会レポート

はじめに

AIシステム部・AI研究開発グループの森と申します。この4月にDeNAに転職し、現在は主に画像や音声に関するDeep Learningの研究開発に従事しています。

DeNAでは、機械学習・人工知能(AI)技術を積極的に事業活用していく方針が全社的に打ち出されており、その一環として、エンジニアを対象にしたGoogle社様による勉強会が定期的に開催されています。

8月に行われた1回目の勉強会では、

  • Googleの機械学習プロジェクト
  • 機械学習をビジネスに応用する際のポイント
  • Google Cloud Platformで提供されている機械学習APIの概要

などをGoogle Cloud ソリューションアーキテクトの中井悦司さんに講義していただきました。

リンク:Google機械学習系API勉強会レポート https://engineer.dena.jp/2017/08/googleapi.html

2回目である今回の勉強会では、前回同様に中井悦司さんにお越しいただき、Google Cloud Platform (GCP) が提供する機械学習サービスをより実践的な面から講義していただきました。本勉強会には、DeNAのエンジニアを中心に約80名が参加しました。

IMGP2658.JPG

勉強会の様子

GCPが提供する機械学習サービス

1回目の勉強会では、Cloud Vision API、Cloud Speech API、Cloud Natural Language APIなど学習済みモデルのWeb APIが中心的な話題でした。

google_ai_api5.pngのサムネール画像

講演資料より

今回は、学習済みモデルのAPIではなく、TensorFlowとCloud Machine Learning (ML) Engineを用いて、データからオリジナルモデルを学習し、新しいAPIをデプロイするまでの流れを一通り解説していただきました。以後、演習で使用した各サービスを簡単にレポートします。

End_to_End_Process_of_Machine_Learning_with_Structured_Data.png

講演資料より

データ

BigQueryで公開されているOpen Natality Datasetを使いました。母親のさまざまな属性(人種、年齢など)と生まれた赤ちゃんの体重に関連する表形式のデータです。このデータを用いて母親の属性から赤ちゃんの体重を予測する回帰モデルをGCPのサービスを組み合わせて実現するのが目的です。

Cloud Datalab

Cloud Datalabは、データの探索、分析、可視化、機械学習モデル構築を行うためのインタラクティブツールです。Pythonのデータ分析環境として有名なJupyter Notebookと同じユーザインタフェースでGCP上のさまざまなサービスと連携することができます。今回は、BigQueryからのデータ収集、可視化による統計分析、データ前処理、機械学習モデル構築まですべてCloud Datalab上で実行しました。

datalab.png

演習に用いたノートブック

BigQuery

BigQueryは、ペタバイト級のデータを格納できるデータウェアハウスサービスです。講義ではOpen Natality Datasetの公開データベースからSQLを使って500万件のデータを収集しました。BigQueryの検索結果は、Pythonのデータ解析ライブラリであるpandasのDataFrame形式に変換できるため高度な統計分析や可視化が簡単にできます。

Cloud Dataflow

Cloud Dataflowは、パイプライン処理によってデータ前処理ができるサービスです。今回は、BigQueryから収集したデータに対して、(1) 属性の変換 (2) 訓練データとテストデータへの分割 (3) CSV形式でCloud Storageに格納という一連のパイプラインを実行しました。

dataflow.png

講演資料より

Cloud Dataflowは、処理するデータ量によって自動的にインスタンスが立ち上がるオートスケールに対応しており、何も意識することなく高速にデータ処理ができます。実際に背後でGoogle Compute Engineのインスタンスが自動的に立ち上がる様子も確認できました。

TensorFlow

TensorFlowは、Googleが提供している機械学習ライブラリです。DeNAのAI開発部でも多くのエンジニアが日常的に活用しています。

今回の勉強会では、カテゴリ変数(母親の人種など)と量的変数(母親の年齢など)を組み合わせたモデルを作るために tf.contrib.learn.DNNLinearCombinedRegressor (Wide & Deep Model) を使いました。このような複雑なモデルもTensorFlowのhigh-level APIを活用すると簡単に書けます。

tensorflow.png

講演資料より

Cloud Machine Learning Engine

Cloud DataLab上では小規模データによるテストまで行い、本番の大規模データによるモデル学習は、Cloud ML Engineを使いました。

Cloud ML Engineは、TensorFlowで構築したモデルの訓練、訓練したモデルのデプロイ、APIの提供までGCP上でシームレスに実行できるサービスです。Experiment APIを用いてモデル・訓練データ・テストデータ・評価指標を設定することで分散環境で高速にモデル学習ができます。

学習経過のログはCloud Storageに保存されるため、Cloud DataLabからTensorboardを呼び出すことで学習経過を可視化することもできます。

tensorboard.png

Tensorboardの出力例

学習済みモデルも同様にCloud Storageに保存されます。この学習済みモデルはCloud ML EngineのWebインターフェイスまたはgcloudコマンドを使うことで簡単にデプロイできます。デプロイしたモデルは、Web APIとして提供されるのでアプリケーションからjson形式のリクエストを送ることで利用できます。Cloud ML Engine上ではリクエストの頻度などAPIの使用状況も確認できます。

Google App Engine

Google App Engineを使うことで、デプロイしたWeb APIを利用するWebアプリケーションが構築できます。今回は、母親の情報から赤ちゃんの体重を予測するアプリケーションを作成しました。

application.png

完成したWebアプリケーション

ハンズオン

後半のハンズオンでは各参加者にGCPプロジェクトのアカウントが配布され、前半の講義で習った内容を実際に手を動かして体験することができました。弊社のインフラ基盤チームとGoogleエンジニアによるサポートやSlackでの情報交換により演習を円滑に進めることができました。

まとめ

今回の勉強会では、Google Cloud Platform上で、機械学習アプリケーションを構築する流れを一通り体験することができました。

これまでオンプレミス環境でWebサーバを立てて、モデルをアップロードして、アプリケーションを書いてという流れは一通り経験していましたが、これらをすべてクラウド上でかつ簡単な操作で実現できることに驚かされました。

現在、AIシステム部では、さまざまな機械学習・AI案件に取り組んでおり、迅速なサービス開発・デプロイが求められることが多くなっています。今後は、Google Cloud PlatformとCloud ML Engineを積極的に活用して効率的にサービス展開していきたいと考えています。

より深く理解するために

講師の中井さんからGCPをより深く理解するためのリソースをご紹介いただきました。

GoogleCloudPlatform / training-data-analyst https://github.com/GoogleCloudPlatform/training-data-analyst
今回の演習で使ったGithubのリポジトリです。今回の演習では blogs/babyweight を使いました。

データサイエンスに関する初心者向けの参考書 http://enakai00.hatenablog.com/entry/2017/02/20/124112
中井さんのブログ記事です。

Data Engineering on Google Cloud Platform https://www.coursera.org/specializations/gcp-data-machine-learning
Courseraが提供している有料のコースです。今回の勉強会の内容をすべて含んでいます。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

第1回 SHIBUYA SYNAPSE が開催されました

はじめに

AIシステム部の西野剛平です。AIシステム部ではAI研究開発グループに所属しており、Computer Visionの技術を中心に研究開発を行っています。

8/30にAI技術に関するイベントSHIBUYA SYNAPSEの第1回目を弊社内にあるSakuraCafeにて開催し、そこで現在私が関わっている「スマートショップ実現に向けた取り組み」に関してご紹介させて頂きました。 今回は、エンジニアブログという事もあり、イベントで発表した内容のうち、特に技術的な内容について紹介したいと思います。

IMG1.JPG

IMG2.JPG

SHIBUYA SYNAPSEとは

昨今のAI技術は深層学習を中心に目まぐるしく進化しており、それとともにビジネスへの適用も着実に行われてきております。SHIBUYA SYNAPSEは、このような環境において、企業×大学や、プランナー×エンジニアといった異なるバックグラウンドを持つ参加者の有機的なつながりにより、価値あるサービスの共創の場を提供することを目的に設立されました。より詳細な情報に関してはSHIBUYA SYNAPSEのホームページをご覧いただければと思います。

今回は、SHIBUYA SYNAPSEの記念すべき第1回目で、東京大学の山崎俊彦准教授をメインスピーカーにお招きし、山崎先生からは「魅力」の予測や解析に関してのご紹介をして頂きました。また、イベントの最後には懇親会もあり、AIに対して様々な携わり方をしている方同士での意見交換が広く行われるなど、大盛況のうちにイベントを終わる事ができたのではないかと思います。

IMG3.JPG

IMG4.JPG

スマートショップの実現に向けた研究

インターネット上でのサービスにおいては、お客様に合った最適なコンテンツの配信、ログ情報からお客様の行動を解析して迷わない導線に改善するなど、日々サービスを快適にご利用頂く工夫が行われております。しかし、リアルな店舗においてはそのような最適化はあまり行われていないため、快適なサービスを提供するという点では、まだまだ改善の余地があるのではないかと考えております。 私たちは、AI技術を活用することで、リアルの店舗においても一人一人のお客様の状況に合わせた接客やリアルタイムの商品推奨など、今までにないショップ体験の提供ができないかを考え、将来のスマートショップの実現を見据えた研究開発を行っています。

IMG5.png

姿勢推定技術を活用した同一人物の再認識

スマートショップの実現のためには、店内でのお客様の状況を把握する技術の確立が不可欠です。その第一ステップとして、定点カメラからの映像を元に、深層学習ベースの姿勢推定技術を活用した、同一人物の再認識技術の開発を行いました。

本手法は、人物の検出と検出された人物の同定を繰り返し行っていくというのが大枠の流れとなっており、この人物の検出タスク部分に姿勢推定技術を利用したのは、高精度であるというのが一番の理由ですが、その他にも将来性を考慮したいという意図があります。姿勢推定では一般的な検出器で検出される人の矩形情報を得られるだけでなく、各体のパーツを表す器官点情報までも同時に検出することができます。これらの情報は非常に有用で、今後別のタスクを解く必要が発生した場合でも、有益な情報として利用できる可能性は高いと考えています。今回紹介する人物同定の技術においても、この器官点情報を利用する事により、高精度でリアルタイムに同一人物の再認識を実現しています。

一般的なトラッキングにおける問題点

例えば、粒子フィルタをベースとしたような一般的な物体追跡においては、フレーム間の画像変化を基に追跡を行うため、フレーム間隔が長い場合(フレームレートが小さい場合)はフレーム間の画像変化量が大きくなってしまい、追跡は極めて困難になってしまいます。

IMG6.png

また、正確な検出器を前提とした場合は、ある時刻tで検出された人と次のフレーム時刻t+1で検出された人の対応付けを行う事により同一人物判定をする事ができます。 例えば、簡易にトラキングを実現する方法として、Intersection over Union(IoU)の結果を利用する方法が考えられ、それぞれのフレームで検出された人の矩形(BoundingBox)同士、各々の組みでIoUを求め、その値が大きいもの同士を同一の人物とします。

IMG7.png

IMG8.png

ただし、この場合もフレーム間での人の移動量が大きい場合には、IoUの値が0となってしまい追跡が破綻してしまいます。

実サービスを見据えた場合、コスト対効果を意識しなければいけないため、限られた計算リソースで実行する事を想定する必要があります。その上で、リアルタイムに処理するとなると、フレームレートが低くなってしまうというのは、ある程度は前提事項として許容しなければいけない事でないかと考えています。(実際、紹介しているリアルタイムデモ映像のフレームレートは1.7fps程度となっています。)したがって、前述したようなフレームレートが低い場合に発生してしまう問題に対応できるような人物追跡手法を設計する必要があります。

今回紹介する手法は、こういった低いフレームレートやオクルージョンが発生するケースを特に意識しており、姿勢推定によって得られた器官点情報を上手く利用することで、そのような状況下においてもロバストに同一人物の再認識を行えるなるような手法を考案しました。

デモ映像

弊社SakuraCafe内で行ったリアルタイムデモ映像になります。

姿勢推定技術によって検出した人物を矩形で囲っています。その上に表示されている番号はその人物を識別するためのIDで、同じ番号の場合は同一人物と認識されています。また、今回技術の詳細は紹介しませんが入店と退店のタイミングや、年齢および性別の推定もリアルタイムに行っております。赤色の線が入店、青色の線が退店を表し、顔が正面を向いた際に表示される矩形に年齢と性別の推定値を表示しています。

全体の構成

本手法は下記の要素で構成されています。

  1. フレーム画像から人物の器官点の検出
  2. 1つ前のフレームで検出された人物と今回検出された人物の同じ器官点同士で色の照合
  3. 1つ前のフレームで検出された人物と今回検出された人物の位置の照合
  4. 2と3の結果から総合的に判断し、人物の同定

1から4の手順を動画の各フレームに対して逐次行っていくことで、連続的に同一人物の再認識を実現しています。

姿勢推定技術に関して

まずは、姿勢推定技術を使って、フレーム画像中から人物、および器官点の検出を行います。器官点は複数人数の器官点を同時に検出し、検出されたそれぞれの器官点はどの人物のどの体の部分に対応しているかを認識します。下の写真は検出された、鼻、首、左肩、左手、右肩、右手、左腰、左足、右腰、右足の10個の器官点になります。

IMG9.png

色差の計測

各器官点の色を取得します。各器官点を中心とした局所領域からピクセルのRGB値を取得し、それをL*a*b*色空間に変換した後、CIE2000で色差を計測します。色差は1つ前のフレームで検出された人物と今回検出された人物の同じ器官点同士での計測になります。

IMG10.png

色差を類似度に変換

色差を色の類似度として扱いたいので、色差dを1.0 〜 0 の定義域に射影する下記の関数を導入し、それを類似度S(d)とします。

IMG11.png

この関数自体はただのシグモイド関数で、係数αやバイアスΒのパラメータ値は、おおよそ下記の要件に合うように調整しています。

IMG12.png

色の類似度の計算

色差の計算方法、およびそれを類似度に変換する式を説明しましたが、もう少し具体的な例で説明したいと思います。時刻tのフレームでPersonAという人を検出、時刻t+1でPersonBという人を検出したと仮定し、これらに対し「色の類似度」を求める手順を示します。

IMG13.png

各器官点毎にL*a*b*色空間に変換した後、CIE2000色差を計算し、類似度を求めます。各器官点毎の類似度が全て求まったら、それらの平均を取り、最終的にその値をPersonAとPersonBの「色の類似度」とします。上記はその計算過程をイメージした表になります。見切れや隠れなどにより検出されなかった器官点がどちらか一方にでもある場合は、類似度50%となるようにしています。(これは、その器官点を使用しない場合に比べ、器官点1つあたりの類似度への寄与率が高くなり過ぎないようにするための措置です。)

位置の尤度

追跡中の人物は最初の検出フレームからその移動の軌跡をすべて保持しています。したがって、これまでの移動情報を基にその人物が次のフレームにいる位置をガウス分布でモデル化する事ができます。これを尤度関数とし、実際に次のフレームで人が検出されたら、その位置情報をそれぞれの尤度関数にあてはめることにより、尤もらしさを求める事ができます。ちなみに、実際のデモ映像では人に対して相対的にブレが少ない首の器官点位置を利用しています。

IMG14.png

上記は、追跡中の3人の軌跡情報を基にガウス分布でモデル化したイメージ図になります。次のフレームでの各人の予測位置は赤色で書かれている部分で、これまでの移動量が大きいほど次フレームでの予測位置は遠くに、分散は大きくなります。

総合尤度の算出

色の類似度、および位置の尤度から総合尤度を計算し、その値から同一人物の判定を行っていきます。例えば、前のフレームでPersonAとPersonBの2人を追跡しており、現在のフレームでPersonCとPersonDとPersonEの3人を検出した場合について考えてみます。

IMG15.png

前のフレームと現在のフレームで検出された全ての人の組み合わせに対し、色の類似度および位置の尤度を計算し、その積を総合尤度とします。この例では下記のようになります。

IMG16.png

これを総合尤度の高い順で並べ替え、ある閾値以下(ここでは0.02を利用)のものを除外すると下記のようになります。

IMG17.png

これを上から順に人物同定していきます。「前フレーム」欄か「現在のフレーム」欄のどちらかに既出の人物が含まれる場合、その行は無視します。これを最後の行まで行い最終的な結論を出します。この例においては下記のような結果となります。

PersonA と PersonDは同一人物である

PersonB と PersonEは同一人物である

PersonCは新たに検出された人である

これを動画の各フレームに対して連続的に行っていく事で、高精度な同一人物の再認識を実現しています。

最後に

SHIBUYA SYNAPSEの開催当日は、このブログに書かせて頂いた内容をご紹介しつつ、会場内でリアルタイムにそれを体験できるデジタルサイネージのブースも用意しました。

IMG18.JPG

発表している内容をその場で実際に体験できるという事で、参加された方々にも興味を持っていただき、非常に良い試みだったと思っています。 SHIBUYA SYNAPSEは今後も2回3回と続いていく予定なので、このブログを読んで興味を持って頂ければ幸いです。是非、次回のご参加を検討して頂ければと思います!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

CVPR2017に参加してきました

はじめに

みなさんこんにちは、AIシステム部AI研究開発グループの李天琦 (@TianqiLi)です。普段は主にComputer Visionの研究開発を行っています。

DeNAのAIシステム部では、カメラの映像解析をはじめとする多くのプロジェクトでDeep Learningの技術を活用しています。Deep Learningの世界は変化が激しく、毎日追い続けても追いきれないほど日々新しい技術論文が発表されています。そこで、最新の技術トレンドをキャッチアップするため、今年(2017年)7月にハワイで開催されたConputer Visionに関するトップカンファレンスの一つである「(CVPR2017」)に参加してきました。その内容について紹介したいと思います。

cvpr2017_1.jpg

CVPRとは

CVPRの正式名称は「Computer Vision and Pattern Recognition」です。Compuer Visionというのはロボット(コンピュータ)の視覚を指し、広義では画像処理、映像処理の技術分野全般を意味しています。そのComputer Visionの分野において世界で最も権威ある学会の一つがこのCVPRです。そして近年ではDeep Learningを始めとするAI技術の飛躍的な進歩により、あらゆるComputer Vision分野でDeep Learningを使う事が当たり前になってきているので、CVPRはDeep Learningに関するトップカンファレンスの一つだとも言われるようになりました。

cvpr2017_2.png

今年の開催期間は7/21〜7/26の6日間です。初日と最終日は特定のテーマに絞って集中的に行うTutorial & Workshopが開かれました。他の4日間が、幅広い分野のセッションが行われるMain Confernceです。また、Main Conferenceの4日間では、Expoと呼ばれるスポンサー企業の展示会も並行して行われ、世界トップのIT企業たちが最新の研究成果や製品などを展示しました。

開催場所

今年の開催地はハワイのオアフ島です。海と自然に囲まれた最高のリゾート地でした。

cvpr2017_3.jpg

[ 会場のHawaii Convention Center ]

近年のDeep Learning人気の影響を受けて、CVPRの参加者は年々増加し、今年は採択論文数も参加者も過去最高でした。統計によれば、今年の投稿論文は2680本で、採択は783本でした。そして今回のCVPRの参加人数は6000人以上にものぼっています。

cvpr2017_4.jpg

[ オープニングセレモニーの様子 ]

cvpr2017_5.jpg

[ 採択論文の統計 ]

セッションの様子

CVPRに採択された論文のうち、評価の高かったものはOralやSpotlightと呼ばれるプレゼンテーション形式のセッションで発表されます。その場で大掛かりなデモを行うものもあります。それ以外は、Posterと呼ばれるセッションで展示され、質問すると論文の作者が直々に解説してくれます。

cvpr2017_6.jpg

[ Oral セッションの様子 ]

cvpr2017_7.jpg

[ Poster セッションの様子 ]

Expoの様子

Main Conferenceと並行して行われるExpoでは、各企業が独自の技術Demoを展示しています。今年最も多かったのはやはり自動運転で、TOYOTA、Tesla等の大手車メーカー以外にも、多数の自動運転ベンチャーが展示していました。

cvpr2017_8.jpg

[ Googleのリアルタイムポーズ推定のデモ ]

cvpr2017_9.jpg

[ 完全無人運転のDemo ]

cvpr2017_10.jpg

[ 無人運転の映像解析Demo ]

展示企業によっては最新の製品の販売も行っていて、今回の目玉商品はIntelが新たに販売する予定の「Movidius Neural Compute Stick」でした。これは簡単に言えばDeep Learning専用の外付け小型計算機です。これまで、Deep Learningは非常に計算コストが高いため、GPUを積んだ大型マシンが必要というのが常識でしたが、それを小型のエッジデバイス上で実現させたのがこのIntelのStickです。日本での発売予定日はまだ三ヶ月以上先ですが、今回の学会で一部の研究者向けに先行販売を行うとの事でしたので、DeNAでも研究開発用にと一部確保してきました。CVPRでも数百個しか販売されていなく半日で売り切れたので、かなり貴重です。

cvpr2017_11.jpg

[ Movidius Neural Compute Stick ]

懇親会への参加

カンファレンス期間中、毎晩のようにビーチやナイトクラブで懇親会が行われていました。そのほとんどがクローズドなもので、特定の企業のメンバーもしくは招待状を受けとった人しか参加できないようになっています。ACCV(アジア地域で開催されるComputer Visionの国際学会)のメンバーの懇親会では、AIの世界的な権威者であるTakeo Kanade先生やFei-Fei Li先生のスピーチに会場が沸きました。

cvpr2017_12.jpg

[ ACCV懇親会でのTakeo Kanade先生のスピーチ ]

注目の論文

今回CVPRで発表された論文の中で、特筆すべきものをいくつか紹介します。

- DenseNet

まず、今年のBest Paperに選ばれた2本の論文のうち、1つがこちらのDensely Connected Convolutional Networks (Gao Huang et al.)です。

cvpr2017_13.png

[ Dense blockの構成 ]

この論文が最初に発表されたのは2016年の8月頃で、当時Image-Classificationタスク(画像に映った物体の種類を分類する問題)におけるState-Of-The-ArtだったResNetのSkip Connection構造を取り入れた密な結合構造「Dense Block」を提案しています。各層の入力に、それより以前の全ての層の出力を結合した結果を使うというシンプルなネットワークアーキテクチャです。汎化性能が高く、パラメータ数の少なさと精度においてResNetを上回る性能を示しています。

- SimGAN

2本のBest Paperのうち、もう1本がこちらのLearning from Simulated and Unsupervised Images through Adversarial Training(Ashish Shrivastava et al.)です。

cvpr2017_14.jpg

[ SimGANの展示ポスター ]

こちらは、GAN(Generative Adversarial Nets)の手法を用いて、シミュレータから生成されたCGデータを現実画像に見えるように変換して、現実の画像と見分けづらくさせる手法です。そもそもなぜこれが重要かと言うと、Deep Learningの世界では訓練データの多さがそのまま計算結果の精度に直結するため、データが多くあればあるほど有利です。しかしリアルのデータを集めて、それにラベルを付けていく事は非常に大変なので、これをシミュレータから無限に生成できないかというアプローチです。シミュレータから生成された画像は通常、リアルの画像と比べてどうしても不自然さが生じますが、その不自然さをなくす事に成功したのがこちらの論文です。

Loss Functionの設計が特徴的で、シミュレータのデータにリアリズムを付与するAdversarial Lossと、元々のアノテーション情報を失わないようにするためのSelf-regularization Lossという2つのLossを定義しています。この仕組によって、一部のUnsupervisedなリアルデータさえあれば、シミュレータから無限に教師データを生成できる画期的な手法です。

- YOLO9000

今回のCVPRではBest Paperとは別に、Best Honorable mention awardという特別賞のPaperも2本ありました。そのうちの1本がこちらのYOLO9000: Better, Faster, Stronger(Joseph Redmon et al.)です。

cvpr2017_15.png

[ YOLO9000のポスターセッション ]

YOLO9000は、画像内から特定の物体の位置と種類を含めて検出する「一般物体検出」の手法に関する論文です。従来の手法よりも遥かに高速、高精度かつ多種の物体を検出できるようにしたフレームワークを提案しています。 YOLO9000自体の技術Demoも凄いですが、それ以上に今回展示されたポスターが独特すぎると話題を呼びました。通常であれば学会に出すポスターは論文の解説ポスターと相場が決まっているところを、原則を完全無視して広告的な意味でのデザインポスターを展示してくるあたり、さすがすぎるとツイッター等のSNSで一時期話題となりました。 ちなみにこちらのYOLO900の論文は、自分のほうで部分的に再現実装したYOLOv2 Chainerバージョンというリポジトリをオープンソースで公開しています。皆さん興味あればぜひ使ってみてください。

- Polygon RNN

2本の特別賞のPaperのうち、もう一本がこちらのAnnotating Object Instances with a Polygon-RNN(Lluis Castrejon et al.)です。

cvpr2017_16.png

[ Polygon-RNNのツール画面 ]

こちらの論文では、Semantic Segmentationの教師データを作る際のアノテーションコスト削減の仕組みを提案しています。通常であれば、セグメンテーション用の教師データを作るのに、物体のピクセル領域全域を細かく塗りつぶす必要があったところを、こちらの論文では複数の頂点によって構成された多角形の頂点推測問題に置き換えています。アノテーターは物体の外接矩形であるBounding Boxを与えてあげれば、RNNの仕組みで内部のオブジェクトに対して自動的に頂点候補を生成してくれます。生成された頂点がズレている場合は、アノテーターは最低限の頂点修正作業のみ行えば済みます。これによって従来の4〜7倍もの作業効率を実現できるという画期的なフレームワークです。 ちなみにアノテーション効率化に関するPaperは、このPolygon-RNN以外にもTraining object class detectors with click supervision(Dim P. Papadopoulos et al.)というのがありました。こちらは、Bounding Boxのアノテーション作業をワンクリックで行えるようにしたという画期的な手法を提案しています。

全体の感想

今年のCVPRはやはりというべきか、CNNをベースとした論文がほとんどでした。また、その多くが、計算のパイプラインを複雑化する事で高い精度を達成できたという、手法的な新規性に関するものでした。私たちの研究チームでもこれから学会に技術論文を発表していく予定なので、良い参考にはなったと思います。 今回のCVPRで発表されたOralやSpotlightのプレゼンは基本的に、こちらのYouTubeですべて動画で見られますが、実際に行ってみると論文の気になる点を作者に直に聞けたり、あとネットワーキングもできる等のメリットがあります。自分は今回がCVPR初参加でしたが、技術的な収穫はもちろん、ネットワークも広がって凄く良い刺激になりました。

cvpr2017_17.jpg

[ おまけ:Fei-Fei Liとの写真 ]

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

DeNAにおけるOpenStack Upgrade

はじめに

こんにちは。IT基盤部でOpenStackの運用をしています酒井です。
弊社では先日社内のOpenStackのアップグレードを行いました。今回は弊社で実施したアップグレード手順についてできるだけ詳しく紹介させていただきます。

なぜアップグレードするのか

OpenStackのリリースサイクルはこちらにあるように約半年ごとに新しいバージョンがリリースされ新機能が追加されます。弊社ではkiloとlibetyを利用していましたが、mitakaで導入された新しい機能を使いたいため、ひとまず両環境をmitakaにアップグレードすることをターゲットとしました。また、弊社ではSDNとしてBig Cloud Fabric(以下BCF)を使用していますが、BCFのサポートするOpenStackバージョンが決まっているため、OpenStackをアップグレードしないとBCFをアップグレードできない、という事情もありました。

OpenStackの構成

弊社のOpenStackの構成としては以下の通りです。

OSUbuntu 14.04
OpenStack Versionkilo/liberty
OpenStack ComponentKeystone, Glance, Nova, Neutron, Cinder, Ironic
HypervisorKVM
Cinder BackendCeph
Neutron mechanism_driversopenvswitch, bsn_ml2, networking_bigswitch_l3_pe
(l3-agentは無し)

OpenStack環境が2環境あり、それぞれkiloとlibertyを利用していました。kiloからmitakaへのアップグレードは一度には行わず、kiloからliberty、libertyからmitakaと2回に分けてアップグレードしました。これは当時使っていたBCFのバージョンではkiloとlibertyのみをサポートしており、mitakaをサポートしているバージョンのBCFではkiloをサポートしていなかったため、このような段階的なアップグレードをする必要があったためです。

アップグレード手順

基本的な手順としては以下のようになります。

  1. 事前準備
    1. 新バージョンのController Nodeを新規で構築する。(DB, rabbitmqはController Node上で動作する構成)
  2. メンテナンス期間: 各コンポーネント毎に以下の作業を行う
    1. 旧バージョンのController Nodeのサービス停止
    2. DBを新バージョンに対応させるためマイグレーション
    3. 新バージョンのController Nodeのサービス起動
    4. 動作確認
    5. DNS更新してエンドポイント切り替え
    6. Compute Node上で動作するサービスがあれば(弊社のケースではNovaとNeutron)新バージョンにアップグレード

各コンポーネントのAPIの停止を伴うため、社内の関係者と調整しメンテナンス期間を設けてアップグレード作業を行いました。コンポーネントのアップグレードはKeystone, Glance, Nova, Neutron, Cinder, Ironicの順に行いました。各コンポーネントごとの詳細な手順を以下に説明します。なお、kiloからlibertyへのアップグレードとlibertyからmitakaへのアップグレードでは手順はほぼ同様でしたが、一部異なる箇所がありましたのでそこは個別に説明します。

Keystone

旧バージョンのController Nodeのkeystoneを停止します。

service apache2 stop

次にkeystone DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 keystone > keystone-db-backup.sql
mysql -uroot -h$NEW_DB_SERVER -p -f keystone < keystone-db-backup.sql
sudo su -s /bin/sh -c "keystone-manage db_sync" keystone

新バージョンのController Nodeでサービス再開します

service apache2 start

以下のような動作確認をします。

# 35357ポートの確認
TOKEN=$(openstack --os-url http://$MY_IP:35357/v2.0 token issue -f json | jq -r .id)
openstack --os-url http://$MY_IP:35357/v2.0 --os-token $TOKEN user list
# 5000ポートの確認
openstack --os-url http://$MY_IP:5000/v2.0 token issue

問題なければDNSを更新してendpointを新バージョンに切り替えます。

Glance

旧バージョンのController Nodeのglanceを停止します。

stop glance-registry
stop glance-api

次にglance DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 glance > glance-db-backup.sql
mysql -uroot -h$NEW_DB_SERVER -p -f glance < glance-db-backup.sql
sudo su -s /bin/sh -c "glance-manage db_sync" glance

旧バージョンのController Node上に保存されているimageファイルを新バージョンのController Nodeにコピーします。

rsync -av $OLD_CONTROLLER_NODE:/var/lib/glance/images/
/var/lib/glance/images/

新バージョンのController Nodeでサービス再開します

start glance-api
start glance-registry

以下のような動作確認をします。

MY_IP=`hostname -i`
# glance image-listの確認
glance --os-image-url http://$MY_IP:9292/ image-list
# glance image-createの確認
echo dummy | glance --os-image-url http://$MY_IP:9292/ image-create --disk-format raw --container-format bare --name dummy_image
# glance image-downloadの確認
glance --os-image-url http://$MY_IP:9292/ image-download <新規イメージのID> > dummy_image
cat dummy_image # dummyと表示されればOK
# glance image-deleteの確認
glance --os-image-url http://$MY_IP:9292/ image-delete <新規イメージのID>

問題なければDNSを更新してendpointを新バージョンに切り替えます。

Nova(Controller Node)

旧バージョンのController Nodeのnovaを停止します。

stop nova-cert
stop nova-consoleauth
stop nova-novncproxy
stop nova-conductor
stop nova-scheduler
stop nova-compute
stop nova-api

nova DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 nova > nova-db-backup.sql
mysql -uroot -h$NEW_DB_SERVER -p -f nova < nova-db-backup.sql
sudo su -s /bin/sh -c "nova-manage db sync" nova
# mitakaへのアップグレードの場合は nova-api DBのマイグレーションも必要です。
sudo su -s /bin/sh -c "nova-manage api_db sync" nova

新バージョンのController Nodeでサービス再開します

start nova-api
start nova-compute
start nova-scheduler
start nova-conductor
start nova-novncproxy
start nova-consoleauth
start nova-cert

以下のような動作確認をします。

MY_IP=`hostname -i`
PROJECT_ID=$(openstack project show $OS_PROJECT_NAME -f json | jq -r .id)
TOKEN=$(openstack token issue -f json | jq -r .id)
curl -i http://$MY_IP:8774/v2/$PROJECT_ID/servers/detail  -H "Accept: application/json" -H "X-Auth-Token: $TOKEN"
curl -i http://$MY_IP:8774/v2/$PROJECT_ID/images/detail  -H "Accept: application/json" -H "X-Auth-Token: $TOKEN"

問題なければDNSを更新してendpointを新バージョンに切り替えます。

Nova(Compute Node)

最初にneutron-ovs-cleanupが起動していることを確認します。neutron-ovs-cleanupが停止しているとnova-compute再起動時にneutron-ovs-cleanupが実行され、インスタンスの通信が途切れてしまうためです。

status neutron-ovs-cleanup

新バージョンのaptリポジトリを追加します。kiloからlibertyへのアップグレードの場合は以下のようになります。

OLD_OS_VERSION=kilo
NEW_OS_VERSION=liberty
echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu trusty-updates/$NEW_OS_VERSION main" > /etc/apt/sources.list.d/cloudarchive-$NEW_OS_VERSION.list
mv /etc/apt/sources.list.d/cloudarchive-$OLD_OS_VERSION.list /tmp
apt-get update

まずnova, neutron, openvswitch以外のパッケージをアップグレードします。

apt-mark hold nova-compute
apt-mark hold openvswitch-common openvswitch-switch
apt-mark hold neutron-plugin-openvswitch-agent neutron-plugin-ml2
apt-get dist-upgrade

nova.confを必要に応じて修正した後、novaをアップグレードします。

apt-mark unhold nova-compute
apt-get dist-upgrade

当該Compute Nodeのnova-computeがupしていることを確認します。

nova service-list

Neutron(Controller Node)

旧バージョンのController NodeのNeutronを停止します。neutron-dhcp-agentを止める前にstate downにすることによりdnsmasqプロセスを終了させることができます。またその後state upにすることにより、新バージョンのneutron-dhcp-agentが各ネットワークに自動的にbindされるようになります。

neutron agent-update --admin-state-down $DHCP_AGENT_ID
# dnsmasqプロセスがいないことを確認した後neutron-dhcp-agentを停止する
stop neutron-dhcp-agent
neutron agent-update --admin-state-up $DHCP_AGENT_ID
stop neutron-metadata-agent
stop neutron-plugin-openvswitch-agent
stop neutron-server

Neutron DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 neutron > neutron-db-backup.sql
mysql -uroot -h$OLD_DB_SERVER -p -f neutron < neutron-db-backup.sql
sudo su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron

新バージョンのController Nodeでサービス再開します

start neutron-server
start neutron-plugin-openvswitch-agent
start neutron-metadata-agent
start neutron-dhcp-agent

以下のような動作確認をします。

TOKEN=$(openstack token issue -f json | jq -r .id)
curl -i http://$MY_IP:9696/v2.0/networks.json -H "Accept: application/json" -H "X-Auth-Token: $TOKEN"

問題なければDNSを更新してendpointを新バージョンに切り替えます。

Neutron(Compute Node)

openvswitch、Neutronの順にアップグレードを行います。 まずopenvswitchのアップグレードについてですが、kiloからlibertyへのアップグレードの場合、qvo Portのother_configに設定を追加する必要があります。以下のようにkiloではother_configが空になっているため、libertyへアップグレード後neutron-openvswitch-agentを再起動するとtagの情報が失われtagの再割り当てが行われます。その結果インスタンスの通信が数秒程度途絶えることになります。

# kiloではother_configは空になっている
ovs-vsctl --columns=name,other_config list Port qvoe97fb5a8-67
name                : "qvoe97fb5a8-67"
other_config        : {}
# libertyでは各種コンフィグが保存されている
ovs-vsctl --columns=name,other_config list Port qvoe97fb5a8-67
name                : "qvoe97fb5a8-67"
other_config        : {net_uuid="83b7bfb1-0b2f-406a-8725-fdaa7daf563f", network_type=vlan, physical_network="physnet1", segmentation_id="113", tag="5"}

これを避けるため、アップグレード前に全Portに対し以下のようなコマンドを実行し手動でother_configを設定しました。

ovs-vsctl set Port qvoe97fb5a8-67 other_config='{net_uuid="83b7bfb1-0b2f-406a-8725-fdaa7daf563f", network_type=vlan, physical_network="physnet1", segmentation_id="113", tag="5"}'

またkiloからlibertyの場合、conntrack zoneの対応もする必要があります。libertyではportごとに個別のconntrack zoneを使ってコネクションを管理するようになりました。kiloではconntrack zoneの指定はされておらず全てのportがデフォルトのzone 0で管理されていました。そのままlibertyにアップグレードするとzoneが新規に割り当てられてしまい(ソースコードはこちら)、割り当てられたzoneにはコネクションがないためそのコネクションのパケットがドロップしてしまうということがわかりました。これを回避するため、neutron-openvswitch-agentがzone 0を使い続けるよう、まず以下のようなルールを追加設定しました。

iptables -t raw -A neutron-openvswi-PREROUTING -m physdev --physdev-in $dev -j CT --zone 0

また、既存のiptables-saveコマンドのwrapperを以下のように作成しました。

cat <<EOF | sudo tee /usr/local/sbin/iptables-save
#!/bin/sh
/sbin/iptables-save "\$@" | sed 's/ -j CT$/ -j CT --zone 0/'
EOF
chmod +x /usr/local/sbin/iptables-save

vi /etc/neutron/rootwrap.conf
# /usr/local/sbin/を優先するよう以下のように修正
exec_dirs=/usr/local/sbin,/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin

この二つの対応により各portがzone 0を使い続けるようになります。

以上で準備ができましたのでopenvswitchのアップグレードを行います。openvswitch-switchパッケージインストール時にopenvswitch-switchサービスが再起動されるのですが、そのタイミングでネットワークが不通になることがありました。それを避けるためにここではopenvswitch-switchサービスを再起動しないようにしています。

# ダミーの何もしないinvoke-rc.dで本物のinvoke-rc.dを隠すことでopenvswitch-switchを再起動しないようにする
ln -s `which true` /usr/local/sbin/invoke-rc.d
apt-mark unhold openvswitch-common openvswitch-switch
apt-get dist-upgrade -s
apt-get dist-upgrade
# invole-rc.dを元に戻す
rm /usr/local/sbin/invoke-rc.d

パッケージのアップグレードが終わった後で手動でモジュール再読込を実施します。弊社の環境ではこのタイミングでインスタンスの通信が0.5秒程度途切れました。

/usr/share/openvswitch/scripts/ovs-ctl force-reload-kmod

次にNeutronのアップグレードです。まずアップグレードの前にneutron-openvswitch-agentを停止します。

stop neutron-plugin-openvswitch-agent

kiloからlibertyへのアップグレード時にはNeutronのアップグレードの前にOVSブリッジにfail_mode: secureを設定する必要があります。Neutronのバージョン7.2.0からOVSブリッジにfail_mode: secureが設定されるようになりました。fail_mode: secureでない状態でneutron-openvswitch-agentを起動するとneutron-openvswitch-agentによりOVSブリッジにfail_mode: secureが設定されるのですが、この処理にはフロー情報のクリアが伴いインスタンスのネットワーク断が発生してしまいます。 これを避けるため、事前にfail_mode: secureの設定、フロー情報のリストアを行います。

ovs-ofctl dump-flows br-ex | grep -v NXST_FLOW > br-ex.flow; ovs-vsctl set-fail-mode br-ex secure; ovs-ofctl add-flows br-ex - < br-ex.flow

Neutronのコンフィグを必要に応じて修正した後、neutronをアップグレードします。

apt-mark unhold neutron-plugin-openvswitch-agent neutron-plugin-ml2
apt-get dist-upgrade

当該Compute Nodeのneutron-plugin-openvswitch-agentがupしていることを確認します。

neutron agent-list

Cinder

旧バージョンのController Nodeのcinderを停止します。

stop cinder-volume
stop cinder-scheduler
stop cinder-api

次にcinder DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 cinder > cinder-db-backup.sql
mysql -uroot -h$NEW_DB_SERVER -p -f cinder < cinder-db-backup.sql
sudo su -s /bin/sh -c "cinder-manage db sync" cinder

弊社の場合cinder DBのvolumesテーブルのhostカラムを更新する必要がありました。このカラムには以下のようにcinder-volumeを動かしていた旧Controller Nodeのホスト名が含まれていました。Controller Nodeのホスト名が変わる度にこのカラムを更新するのは手間なので、弊社ではcinder.confにhostパラメタとして別名を定義し、その値をこのカラムに使用するようDBを更新しました。

mysql> select distinct(host) from volumes;
+-------------------------------+
| host                          |
+-------------------------------+
| CONTROLLER_HOSTNAME@ceph#CEPH |
+-------------------------------+

新バージョンのController Nodeでサービス再開します

start cinder-api
start cinder-scheduler
start cinder-volume

以下のような動作確認をします。

MY_IP=`hostname -i`
PROJECT_ID=$(openstack project show $OS_PROJECT_NAME -f json | jq -r .id)
TOKEN=$(openstack token issue -f json | jq -r .id)
curl -i http://$MY_IP:8776/v2/$PROJECT_ID/volumes/detail?all_tenants=1 -H "Accept: application/json" -H "X-Auth-Token: $TOKEN"

問題なければDNSを更新してendpointを新バージョンに切り替えます。

Ironic

旧バージョンのController Nodeのironicを停止します。

stop ironic-conductor
stop ironic-api

次にironic DBを新バージョンに対応させるためスキーマのマイグレーションします。

mysqldump -uroot -h$OLD_DB_SERVER -p --opt --add-drop-database --single-transaction --master-data=2 ironic > ironic-db-backup.sql
mysql -uroot -h$NEW_DB_SERVER -p -f ironic < ironic-db-backup.sql
sudo su -s /bin/sh -c "ironic-dbsync --config-file /etc/ironic/ironic.conf upgrade" ironic

弊社の場合nova DBのinstancesテーブルのhost/launched_onカラムを更新する必要がありました。これらには旧バージョンのController Nodeのホスト名が保存されていたのですが、以下のようにこれらの値を新バージョンのController Nodeのホスト名に更新しました。なお、cinder DBの場合と同様に別名を使うということも検討したのですが、BCF環境ではホスト名を使ったほうが安全にアップグレードが行えるということがわかり(詳細は割愛しますが)、ホスト名を使い続けることとしました。

mysql> update instances set host = '$NEW_CONTROLLER_NODE' where host = '$OLD_CONTROLLER_NODE';
mysql> update instances set launched_on = '$NEW_CONTROLLER_NODE' where launched_on = '$OLD_CONTROLLER_NODE';

旧バージョンのController Node上に保存されているtftp関連のファイルやimageファイルを新バージョンのController Nodeにコピーします。

mkdir /tftpboot
chown ironic.ironic /tftpboot
rsync -av $OLD_CONTROLLER_NODE:/tftpboot/ /tftpboot/
rsync -av $OLD_CONTROLLER_NODE:/var/lib/ironic/images/ /var/lib/ironic/images/
rsync -av $OLD_CONTROLLER_NODE:/var/lib/ironic/master_images/ /var/lib/ironic/master_images/

新バージョンのController Nodeでサービス再開します

start ironic-api
start ironic-conductor

以下のような動作確認をします。

MY_IP=`hostname -i`
TOKEN=$(openstack token issue -f json | jq -r .id)
curl -g -i -X GET http://$MY_IP:6385/v1/nodes -H "X-OpenStack-Ironic-API-Version: 1.9" -H "User-Agent: python-ironicclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: $TOKEN"

問題なければDNSを更新してendpointを新バージョンに切り替えます。 最後にaggregateに新しいController Nodeを追加、古いController Nodeを削除して終了です。

nova aggregate-add-host $AGGREGATE_ID $NEW_CONTROLLER_NODE
nova aggregate-remove-host $AGGREGATE_ID $OLD_CONTROLLER_NODE

その他

インタフェース構成の改善

一連のアップグレード作業を通じて、いくつか改善したいことが見つかりました。一つはCompute Nodeのインタフェース構成です。現状は以下の図の「現状の構成」のようにbr-exにIPアドレスを割り当てています。この構成だとopenvswitchのアップグレードに何らかの理由で失敗しbr-exがdownしたままになるとCompute Node自体が通信できなくなります。弊社ではCompute NodeはCephのStorage Nodeを兼ねているため、インスタンスのI/Oが詰まってしまうことになります。

これを以下の図の「改善案」のようにbr0というlinux bridgeを追加しそこにbr-exを接続しIPアドレスはbr0に割り当てる構成にすることを検討しています。これにより、openvswitchのアップグレードを仮に失敗したとしてもCompute Node自体はbr0のIPアドレスを使って通信できCephには影響を与えなくすることができます。linux bridgeが一つ増えることで性能面では不利になると思われますが、その辺りを検証した後に本番環境に適用していきたいと考えています。 interfaces.png

まとめ

弊社で行ったOpenStackアップグレードの手順について紹介させていただきました。弊社では6月、7月にkiloからlibertyへのアップグレードを1回、libertyからmitakaを2回行ったのですが、アップグレード作業中もその後も障害は発生していません。newton以降へのアップグレードは今のところ未定ですが、アップグレードを行った際にはまたその手順を公開したいと考えています。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

Google機械学習系API勉強会レポート

AIシステム部の奥村(@pacocat)です。AIシステム部では、AI研究開発グループに所属しており、主に強化学習を用いたゲームAIの研究開発を行っています。 DeNAでは、様々な事業ドメインのデータを実際に使いながら機械学習を使ったサービス開発を推進しており、中でもゲームは豊富なデータ・シミュレーターがあるため、最先端のアルゴリズムを動かすための環境を自前で持っているのが特徴です。

全社的にも機械学習サービスのニーズが高まっている背景の中、7/5にGoogle様による機械学習系API勉強会が当社セミナールームにて開催されました。今回は、勉強会の内容をブログでレポートしたいと思います。

Googleといえば、先日開催されたGoogle I/O 2017でも"AI first"というメッセージが改めて強調されていましたが、実際にGoogle LensやGoogle Homeなど機械学習を活用したサービス・プロダクトが次々と登場し、注目が集まっています。

[最近話題になっていた"Democratizing AI(AIの民主化)"についてなど、AI関連の取り組みについてはこちらのGoogle Cloud Next'17の動画をご覧ください]

このセミナーでは、Google Cloud, ソリューションアーキテクトの中井悦司さんにお越しいただき、

  • Googleでどのようにディープラーニングを活用しているのか
  • Google Cloud Platform(GCP)が提供する機械学習サービス
  • 機械学習のビジネス適用における考え方

といったテーマについてお話いただきました。

昨今「人工知能」を利用したビジネス期待が急激に高まっていますが、中井さんはそうした期待値と実際の機械学習ソリューション開発のギャップを適切に埋めるため、機械学習の啓蒙やGCPを使った技術支援全般を行っています。

google_ai_api2.png

セミナーの様子(100名程度の社内エンジニアが参加していました)

※以下、主にディープラーニングに関連した学習技術を含め「機械学習」という用語を使いますが、「機械学習」と「ディープラーニング」の区別が必要な場合は明示的に「ディープラーニング」と記載します。

Googleでなぜ機械学習を活用するか

そもそも、Googleではどのように機械学習が取り入れられているのでしょうか。 「1クリックで世界の情報へアクセス可能にする」という企業ミッションを耳にすることもありましたが、モバイル市場の拡大に伴い、情報へのアクセス手段もクリックに限らなくなってきました(※参考:Searching without a query)。

そうした背景のもと、音声や画像入力に対応するため、サービスを支える機械学習技術が強くなっていったのは必然的な変化だったのでしょう。実際、Googleでは様々な機械学習(特にディープラーニングを使った)技術が開発されています。セミナーでは、そうした技術の中でもホットなものを紹介していただきました。

Wavenet(DeepMind社による音声合成技術)

Wavenetは、ニューラルネットワークを使って音声のデジタルデータを直接出力するモデルです。従来の、音素に分解してつなぎ合わせるパラメトリックな手法に比べて音声生成精度が飛躍的に向上しました。いずれは、人間の発話と区別がつかなくなってくるようになるかもしれません。 また、人間の音声に限らず、楽器の音を集めてトレーニングすることで、自動作曲が出来ることも話題になりました。

google_ai_api3.png

DeepMind Technologies Limited, "Wavenet",
https://deepmind.com/blog/wavenet-generative-model-raw-audio/
(accessed: 2017-07-13)

Gmail Smart Reply

自然言語処理の分野でも新しいサービスが提供されています。現在は英語モードのGmailのみが対象となっていますが、スマホでGmailを開くとメールの文脈を理解して、返答文の候補を生成してくれるサービスです。ここにも文脈理解のためのディープラーニング技術が活用されています。
※現在はモバイルGmailアプリからの返信の20%程度で、この機能が利用されているそうです。

google_ai_api4.png

Google, "Save time with Smart Reply in Gmail",
https://www.blog.google/products/gmail/save-time-with-smart-reply-in-gmail/
(accessed: 2017-07-13)

データセンターの冷却効率改善(DeepMind社によるソリューション)

Google社内向けのソリューションも開発されています。DeepMind社は昨年、ディープラーニングと強化学習を組み合わせた技術でデータセンターの電力消費効率を最大40%削減することに成功しました。(※参考:DeepMind AI reduces energy used for cooling Google data centers by 40%
※この事例における技術の詳細は公開されていませんが、こちらに中井さんによる機械学習を使ったエネルギー効率予測についての解説があります。

他にも、Google Photosの一般物体画像認識技術など、様々な機械学習サービスが生み出されており、Google社内では機械学習のバックグラウンドを持っていないサービスエンジニアも社内トレーニングコースなどを活用して、機械学習モデルを使いこなしているそうです。

GCPが提供する機械学習サービス

さて、Googleでは一般ユーザーがこうした機械学習技術を活用できるためのサービスを提供しており、目的別に以下の二つの方向性に大別されます。

  • 学習済みモデルのAPIサービスを使う
    ⇒ ディープラーニング技術を今すぐに活用してみたい人向け
  • TensorFlowやCloud Machine Learning Engineのような環境を使って開発を行う
    ⇒ 独自モデルを作りたい人向け

google_ai_api5.png

Google社講演資料より

①学習済みモデルのAPIサービスを使う

Cloud Vision API

google_ai_api6.png

Google, "CLOUD VIDEO API",
https://cloud.google.com/vision/?hl=ja
(accessed: 2017-07-13)

Cloud Vison APIは、画像を渡すことで様々なラベル情報を取得することが出来ます。 上の例では、顔の検出だけでなく、顔が向いている方向・感情分析の結果が返ってくるAPIとなっています。

Cloud Natural Language API

Cloud Natural Language APIは、自然言語を分析するサービスです。文章の感情分析を行うことも可能で、お問い合わせメールの自動分類でカスタマーサポート業務を効率化するなど、導入事例が増えてきているそうです。

Cloud Video Intelligence API(β版)

google_ai_api7.png

Google, "CLOUD VIDEO INTELLIGENCE API",
https://cloud.google.com/video-intelligence/?hl=ja
(accessed: 2017-07-13)

現在はβ版が提供されていますが、Cloud Video Intelligence APIは、動画解析・検索が出来るサービスです。 動画のフレームを解析し、場面の切れ目を検知したり、場面ごとに何が映っているかを検出することが可能です。
※上の例では、"Elephant", "Elephants", "Animal", "African elephant"とったラベルが検出されています。

他にも様々なAPIが公開され、導入事例も増えてきているそうなので、気になる方はこちらをご覧ください。

②独自にモデルを1から作成する

上述のAPIは、既に学習が済んでいるモデルをそのまま使うパターンになりますが、自社のデータを使って独自にモデルを開発したい場合もあります。その場合は、TensorFlowのような機械学習フレームワークとCloud Machine Learning Engineのような(TensorFlowのGPU・分散学習機能に対応している)計算リソースを利用する方法があります。

③学習済みの公開モデルを利用して独自モデルを作成する

①と②を折衷したパターンです。独自モデルを作る場合、既存で提供されているAPIレベルのものを1から作るのは大変です。そこで、公開されているフレームワークや学習済みデータを活用することで独自モデルを作成する方法もあります。これは転移学習と呼ばれている手法で、既に学習されたネットワークを独自にチューニング・カスタマイズすることで、1から学習をするよりも効率的に開発が行えるメリットがあります。 セミナーでは、TensorFlow Object Detection APIを使った簡単なアプリのデモが行われていました。(※デモアプリの作成方法は、こちらの記事で公開されています。)

google_ai_api8.png

https://github.com/tensorflow/models/tree/master/object_detection
(accessed: 2017-07-13)

機械学習のビジネス適用における考え方

セミナーの後半では、機械学習を実ビジネスに適用する際、どのような点に気をつけないといけないか、リアルなプロジェクト視点で講演を行っていただきました。

まず、ディープラーニングは非構造化データ(画像・動画・音声・自然言語)に高い性能を発揮する特性がある一方で、適応領域はまだ限定的です。データが不十分だったり、まだ実証されていない事を実現する場合のハードルは高いと考えたほうがいいという話がありました。 ディープラーニングはあくまでツールの一つでしかなく、それだけで凄いサービスが作れるかというとそうではありません。あくまでビジネスの中でディープラーニングが上手くハマるところを見つけていく、という関わり方が大事という話が印象的でした。

続いて、(ディープラーニング以外の)従来の機械学習をサービスに導入する際には、データアナリストによるデータとビジネスに対する知見が必要、というポイントが紹介されました。従来の一般的な機械学習では、構造化データによる予測処理がサービス適用の中心となります。そうした予測は、一般的な統計分析(いわゆるBI)が出発点になるため、あらかじめデータを整備しサービス分析が出来ていることが前提になる、というニュアンスです。

ここで、データ分析に対する考え方を整理しましょう。データ分析のプロセスについて、次のような理解をされることがあるそうです(下図の矢印のサイクル)

  • 手元にデータが存在しており、データアナリストはそこからインサイトを得るために様々な集計や機械学習モデルの実験を繰り返す
  • そうして作られた機械学習モデルによって、未知のデータに対する予測が出来るようになる
  • データ予測がビジネスに使えないか検討する

google_ai_api9.png

Google社講演資料より

しかし、本来のゴールである「ビジネス判断」を考えると、このループを逆にたどる必要があります。

  • まず、ビジネスゴールを明確にする(一番大事な出発点)
  • ビジネスゴールを実現するために、何を予測すべきかを決める
  • 予測に必要な機械学習モデルやデータを洗い出す
  • そうしたデータを集め、分析するためにはどのような活動をしないといけないのか

当たり前じゃないかと思われる方がほとんどだと思いますが、改めて大事な視点だと感じました。

話はさらに機械学習エンジニアとビジネスのコミュニケーションにも踏み込んでいきました。 機械学習はやってみないとどれくらいの精度が出るか分からない、という不確実な要素が強い領域です。ただ、だからといって素直に「やってみないと分からない」とコミュニケーションするだけでは何も進められないのも現実です。

機械学習は実験的な要素を含んでいるんだとエンジニアとビジネスサイドで共通認識を持った上で、影響範囲を適切に見極めながら実際にサービスに機械学習を組み込んでみて、リアルに実験をしていくのが重要だというのが中井さんの主張です。そうして知見が溜まることで、機械学習をビジネスで使う勘所をサービスメンバー全体で持てるようになるのではないでしょうか。

google_ai_api10.png

Google社講演資料より

まとめ

最新の機械学習系APIの紹介から、ビジネス適用まで、様々な観点から機械学習サービスについてのエッセンスをまとめていただきました。特に後半の機械学習サービス開発の注意点については、なかなかこうした形でまとめて聞く機会も少ないので、改めて機械学習を使ったサービスについて考えるきっかけになったのではないでしょうか。AIシステム部では、様々なAI案件でビジネスメンバーと一緒にサービスをデザインして組み立てていくことが多く、機械学習に対する共通認識や社内文化の作り方など、参考になる観点が多かったように思います。

今回カバーしきれなかった内容を扱った第二回も検討されているそうなので、楽しみです!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

ICLR2017読み会を開催しました

はじめに

こんにちは、AIシステム部の内田(@yu4u)です。 大分時間が経ってしまいましたが、先日、深層学習に関する論文が多数発表された国際学術会議、International Conference on Learning Representations (ICLR'17) の論文読み会をSakuraカフェにて開催したのでその報告です。 ICLRは、オープンレビューを採用しているので、リジェクトされたものも含め全ての論文およびレビューを読むことができるので、こういう読み会には丁度良いかもしれません。

ICLR'17ウェブサイト

オープンレビューサイト

読み会のConnpass

読み会のTogetter

当日の様子

IMG_3694.JPG

懇親会の様子

IMG_3708.JPG

背景

私自身はコンピュータビジョンが専門ですが、その中で利用するニューラルネットのモデルやその学習方法、モデル圧縮等に興味があり、ICLRの論文は良く読んでいました(ICLRの論文を読むというよりは、気になる論文を読んでいたらそれがICLRの論文であるケースがあるという方が正確)。

そんな折、同僚がICLRに参加するらしいということでふと調べてみると、ICLRに関しては過去国内で読み会が開催されていない (to the best of my knowledge) ことに気づき、使命感(?)から開催を企画する運びとなりました。 Twitterで発表者を募ったところ、Connpassでは発表者の募集ができないくらい多くの方に手を上げて頂けたので、当初15時くらいから開催しようかと思っていたのですが、半日フル開催というボリュームにすることができました。

感想とか

こういう勉強会の企画・運営は初めてだったのですが、会場はもとより、コーヒーブレークや懇親会まで会社的にフルバックアップしてもらえたので、スムーズに開催することができました。あとConnpassは良いサービスですね!

発表者の方々がその道のプロばっかりだったので、発表内容のクオリティが高かったのが凄かったです。当日はずっと司会だったのですが、内容がかなり学術的であることもあり、たまに質問が途切れると専門ではない内容でも質問をしなければという使命感から、学会の座長をしている気分でした。おかげで、実はコンピュータビジョンとか個別の分野よりも、こういうより抽象的なレイヤーの研究のほうが面白いのではないかと思い始めてきました。

機会があれば、またこういう勉強会は企画してみようと思います。あと、来年のICLR読み会も開催したいと思います。

当日の発表内容

以降の内容は当日の各発表の解説です。当日何となく理解したつもりになった発表も、厳密に分かっていないところもあるので、結局元の論文を読み返したりしてしまいました。専門ではない内容も多いため、間違いがあればご指摘ください!

ICLR2017紹介

[ICLR2017読み会 @ DeNA] ICLR2017紹介 from Takeru Miyato

最初の発表では、PFNの宮戸さんにICLR2017を俯瞰できるようなご講演をして頂きました。 実は大学の研究室の先輩であるPFNの @sla さんから、宮戸さんがICLRで発表されるということを聞き、ICLRという会議自体を俯瞰できるようなご講演をお願いしたところ、ご快諾頂きました。 現場の盛り上がりを感じられる内容で、ポスター会場の混み具合はもとより、夜は企業がパーティーみたいな場を設けているということで、もはやお祭りですね。 本会議の採録率は39%らしく(去年は28%)、間口を広げる方向にシフトしているのかもしれません。来年は是非発表者として参加してみたいですね。

医療データ解析界隈から見たICLR2017

医療データ解析界隈から見たICLR2017 from RIKEN, Medical Sciences Innovation Hub Program (MIH)

次に、理化学研究所の川上さんに、医療データ解析をされている立場からICLRという会議を振り返って頂きました。 川上さんは医師免許を持っておられるお医者さんでもあり、同僚の @pacocat がICLRの現地でお会いした際に読み会に興味を持って頂けたとのことで、なかなか聞けない切り口でご講演頂けるのではと思いお願いさせて頂きました。 弊社もヘルスケア事業にも力を入れており、医療領域における機械学習の活用は非常に興味があります。個人的にはパーソナライズドな医療に期待しています。 論文の実験の再現性が低いという話があり、再現しなかったからと言って直ちに間違っているということも言えないので、なかなか新しい手法が出てきて一気に変化が起こるような領域ではないのだろうと考えさせられました。 自分の分野だと、話題の手法はあっという間に再実装や追試がされていくので、対照的だと感じました。最近だと、例えばSELUs (scaled exponential linear units) という手法が話題になって、あっという間に追試された結果が色々Twitterに流れてきたのは印象的でした。

Data Noising as Smoothing in Neural Network Language Models

ICLR2017読み会 Data Noising as Smoothing in Neural Network Language Models @Dena from Takanori Nakai

@Quasi_quant2010 さんのご発表。 これまでn-gramを用いた言語モデル (language modeling) では、Kneser-Neyに代表されるスムージングが非常に重要な役割を果たしていた。他方、RNNによる言語モデルでは、単語(列)の頻度を明示的に扱っているわけではないので、そのようなスムージングを直接的に行うことはできなかった。 そこで、n-gramから導出される確率を利用して、RNN言語モデルを学習する訓練データに対し、単語を置き換えたりするノイズを加えることで、スムージングと同様の正則化を実現することを提案し、経験的にperplexityが低下することを示した。

レビューでも経験的と言われていますが、アイディアは面白いですね。画像でいうと、ちょっと賢いData Augmentationをしているようなイメージでしょうか。 ちなみにKneserの発音は「k N AI z uh r」らしいです。

http://d.hatena.ne.jp/tkng/20100426/1272266900

On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima

170614 iclr reading-public from Katsuhiko Ishiguro

石黒さん(みらい翻訳/NTTドコモ)のご発表。 DNNは多数のlocal minimumがあり、それらの局所解はどれもglobal minimumと遜色ないと言われている。この論文では、そのlocal minimumにはsharp minimumとflat minimumがあり、大きなバッチサイズを使うとsharp minimumに、小さなバッチサイズを使うとflat minimumに収束すると主張している。 Flat minimumは、局所解から多少パラメータを変動させても、ロスがあまり増加しないような局所解であり、訓練データとテストデータの分布の違いによりロス関数がずれたとしても、あまり精度が変わらない汎化された理想的な局所解と定義される。

大きいバッチサイズと小さいバッチサイズそれぞれで得られたパラメータを結ぶ直線上にあるパラメータを内挿・外挿により求め、ロスを算出することで、sharp minimumとflat minimumを可視化しているのが面白く、説得力があります。 ちなみにその後、バッチサイズの大小ではなく、SGDのパラメータ更新回数こそが重要であるという主張の論文が出ています。

論文:https://arxiv.org/abs/1705.0874

解説:https://www.slideshare.net/JiroNishitoba/20170629

Q-Prop: Sample-Efficient Policy Gradient with An Off-Policy Critic

Q prop from Reiji Hatsugai

@Reiji_Hatsu さんのご発表。 強化学習において最適な方策を見つける手法は、直接方策をモデル化する方策ベースの手法と、状態の価値をモデル化する価値ベースの手法に大別できる。 方策ベースの手法は、現在推定している方策と学習に利用しているサンプルが同じである方策オン型であり、安定した学習が可能である一方、方策がアップデートされるとこれまでの学習サンプルが利用できないためサンプル効率が悪い。 価値ベースの手法(Q学習)は、常に価値が最大となる方策を選択するため、サンプルの方策とは異なる方策に基づく方策オフ型である。このため、任意の方策でサンプリングされたデータで学習できる一方、学習が安定しない、複数ステップ法への拡張が難しいという問題がある。 この論文では、これらの手法のいいとこ取りをするというのがポイントである。具体的には、方策勾配の関数に、criticのTaylor展開したものを加えて数式コネコネすると、actor-criticの手法に似たアップデートの式が出てきて、criticが方策オフ型で学習できるようになる。

何となく雰囲気は分かるが、導出がトリッキーなので、時間があるときにAppendix Aの数式を追ってみたいです。上記のいいとこ取りという観点では、同じくICLR'17に下記のような論文もあります。 PGQ: Combining Policy Gradient And Q-learning

論文:https://arxiv.org/abs/1611.01626

解説:https://www.slideshare.net/sotetsukoyamada/pgq-combining-policy-gradient-and-qlearning

Tying Word Vectors and Word Classifiers: A Loss Framework for Language Modeling

言葉のもつ広がりを、モデルの学習に活かそう -one-hot to distribution in language modeling- from Takahiro Kubo

@icoxfog417 さんのご発表。 機械学習である単語を表現する場合には、その単語のIDに該当する次元が1でそれ以外が0となるone-hotなベクトルが利用される。学習時のロスもこのone-hotなベクトルをベースに計算されるので、推論結果が、正解の単語とほぼ同じような単語であろうと全く違う単語であろうと同じロスが発生する。 本論文では、これに対し、単語間の類似度に基づき、正解をone-hotではなく広がりのある分布として表現し、その分布を用いてロスを計算することを提案している。 具体的には、元々のone-hotのベクトルと、単語の埋め込みベクトル間の内積により算出される類似度をsoftmax通すことで作られるベクトルの重み付き和により、この広がりのある分布を定義している。 また、one-hotのベクトルをdenseなベクトルにする埋め込み行列Lについても、出力時の射影Wと本質的に対応しているべきであり、それらを個別に学習しないような手法を提案している。具体的には、LがWの転置であるという制約を導入している。

読み会では、LとWの対応について逆行列で求めているのかという質問がありましたが、フルランクではないのでどのようにしているのかと思いましたが、論文を読むと上記のように転置であるという制約を入れているようです。

Stochastic Neural Networks for Hierarchical Reinforcement Learning

ICLR読み会 奥村純 20170617 from Jun Okumura

奥村さん(DeNA)のご発表。 迷路を解くような問題では、報酬がゴールにたどり着いた時にしか発生しない(報酬がsparse)。このようなケースでは、探索時にゴールに全く辿り着かずに学習が進まないという問題がある。これに対し、中間的なタスクを設定し、そこで汎用的なスキルを身に付けさせることで、報酬がsparseである問題を解決しつつ、身につけた汎用的なスキルを他の問題にも適用できるようにできれば嬉しいよねという問題提起。 本論文では、迷路を解く問題に対し、取り敢えず移動するというタスク(蛇のような関節モデルを想定しており、移動すらランダムだと難しい)を設定し、更に様々な方向に移動する多様性もあるように学習させるために、確率的ニューラルネットの利用と、色々な動きをした際に報酬にボーナスを与える相互情報量ボーナスを導入している。

やっていることは理解できるのですが、背景でなるべく中間タスクはhandcraftedにならないようにと言っている割に、えらくタスクに依存する手法となっているのがちょっとモヤモヤします。

Optimization as a Model for Few-Shot Learning

Optimization as a Model for Few-Shot Learning - ICLR 2017 reading seminar from Hokuto Kagaya

@_hokkun_さんのご発表。 Deep learningは大量の訓練データが存在する場合には威力を発揮するが、例えば鳥というクラスの中で細かい鳥の種類を分類するようなfine-grainedなタスクなどにおいて、各クラスに十分な訓練データが準備できないケース(few-shot learning)がある。そのようなケースでも高精度な認識をするための手法。 SGDの更新式ってLSTMのセルの更新式に似ているよねという発想から、SGDのパラメータの更新の方法をLSTMで学習するというメタ学習を提案している。

枠組みとしては通常の学習でも活用できそうな気がしますが、自動的にドメイン特化した更新式を獲得する枠組みがポイントなので、ドメインが決まっている通常の学習では単に学習率とかを色々単純に試したほうが良いかもしれません。 つまり、問題設定として、メタ学習データでメタ学習を行い、メタテストデータで先ほど獲得した学習方法を利用して学習を行う(ややこしいがメタテストデータに学習データとテストデータがさらに存在する)という前提があり、そもそも学習データで学習率を調整できない(ドメインが変わるので意味がない)のでこのようなアプローチが重要になるのだと思います。

Autoencoding Variational Inference for Topic Models

@nzw0301 さんのご発表。 Latent Dirichlet Allocation (LDA) をNeural Variational Inference (NVI) で行う(明示的にDirichlet分布は利用していないのでLDAと言うのは語弊がある?)。VAEではガウス分布のパラメータをニューラルネットが出力し、そのガウス分布からサンプルを生成する。この際、backpropができるような計算グラフを構築するreparameterization trickを利用する。LDAでは、ディリクレ分布のパラメータを生成し、多項分布(トピック分布)を生成したいが、そのままでは上記のtrickは利用できない。そこで、事後分布をガウス分布で近似するLaplace近似を利用し、ガウス分布からのサンプルにsoftmax(σ())を適用することで、多項分布をサンプルすることを可能とする。 上記のトピック分布θとトピック毎の単語生成確率行列σ(β)との積によって、最終的な文書の単語分布が得られる。ここで、σ(β)は、トピック毎の多項分布であり、最終的な単語分布はそれらのθによる重み付き和となる。このようなケースでは、生成される単語分布は、トピック毎の単語分布よりシャープにならず、幾つかのトピックにおいて主観品質の悪い結果をもたらすことがある。これに対し、本論文では、得られる単語分布をσ(βθ)とするProdLDAを提案している。この場合、βは多項分布であるような正規化がされていないため、上記の問題を解決できるとしている。また、学習方法もBNとDropoutを利用するなど工夫しているらしい。

とても勉強になりました。σ(βθ)としてしまうのは乱暴なようだけど、この定式化でもσ(β)はちゃんとトピック毎の単語性生成行列になるのですね。下記の論文のように、reparameterization trickにもいろいろな種類があって面白いです。

https://arxiv.org/abs/1611.00712

Variational Lossy AutoEncoder

@crcrpar さんのご発表。 VAEでは、潜在変数の事前分布p(z)を正規分布に、事後分布p(z|x)をガウス分布とすることが多い。このような単純な分布は表現能力が低く、真の事後分布にうまくfitしない問題が発生する。この問題に対し、Normalizing Flow、Inverse Autoregressive Flow (IAF) といった、より複雑な事後分布を生成できる手法が提案されている。これらの手法では、単純な分布を徐々に複雑な分布にする可逆変換を利用している。本論文では、IAFで事後分布を複雑な分布にするのではなく、Autoregressive Flow (AF) を用いて事前分布を複雑な分布にすることを提案し、AF事前確率とIAF事後確率のエンコーダ処理は同一であることを示した。

AFを事前確率に入れるほうがIAFを事後確率に入れるより表現能力が高いという主張が良く分かりませんでした。事前知識が足りず、normalizing flow辺りの論文から理解しないといけないですね。

Semi-Supervised Classification with Graph Convolutional Networks

Semi-Supervised Classification with Graph Convolutional Networks @ICLR2017読み会 from 英爾 関谷

関谷さん(DeNA)のご発表。 隣接行列で表現される重み付き無向グラフが与えられ、各ノードには特徴信号が紐付いている。一部ノードにはクラスラベルも付いており、残りのノードにはクラスラベルは付いていない。このような前提で、クラスラベルの付いていないノードのクラス分類を行う、graph-based semi-supervised learningの問題をグラフ畳み込みネットワークで解く手法。 グラフに対する畳み込みは、各ノードの特徴信号を並べたベクトルに対し、グラフラプラシアンの固有ベクトル行列を利用してグラフフーリエ変換を行うことでフーリエドメインに変換し、そこで畳み込みカーネルとの要素積を行い、最後に逆フーリエ変換する処理として定義される。 上記の処理は行列演算と固有値分解の計算量が大きいため、畳み込みカーネルをグラフラプラシアンの固有値の関数と定義し、1次までのチェビシェフ近似を用いることでノード数に線形なグラフ畳み込みを行うことを提案している。

チェビシェフ近似の辺りから、何でそれで良いのか理解が難しいです。ちなみに特徴ベクトルは独立に周波数ドメインに変換されて畳み込みが行われるようですが、次元間の関係をうまく捉えるような拡張とかできないかな、と思いました。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

Google I/O 2017 ショートレポート

昨年よりHRをやってますtachikeiです。

ちまたのI/O熱が冷めた頃合いを狙ってHR観点でショートレポートを投下します。

次回 DeNA TechCon のネタ探しも含めて Google I/O 2017へ行きました。
プロダクトや技術的なトピはたくさんの方が書かれているので、それ以外で。

IMG_3881.jpg

持ち帰ったのは以下2点。
・Google I/Oはトッププライオリティのアジェンダ
・おもしろい技術でおもしろいモノを作る、以上

1点目は
・トップが語る
・IOにリリースをあわせる
・ムーブメントを起こす
エンジニアが好きにやってるカンファレンスじゃなくて全体がそこに向かっている印象です。

2点目は
物作りの会社。おもしろい技術でおもしろいものを作ろうと。テクノロジーとプロダクト。
エンジニアが本来やりたいのは、これだと思います。

当然利益は出さなければならないと思いますが、
ここのシンプルな点の追求こそが競争力のベースになっているように感じました。

それ以外の点としては
・物作りに集中できる環境作り
・AIの応用スピード早い
・オフィスアワーのAIニーズ高い
・ライブ配信、メディア対応手厚い

以上です。
必要なものを組織にジワジワとインストールしたいと思います。
早速、ラズパイ用のマイクロフォンを買いに行きましたとさ w

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る