2018年 PFN夏季インターンシップのコーディング課題公開

楠本充
エンジニア

2018-07-18 11:32:38

PFN 2018夏季インターンシップの選考で用いたコーディング課題を github 上で公開しました。

https://github.com/pfnet/intern-coding-tasks

PFN の楠本です。PFN では毎年8,9月前後に2ヶ月間の長期インターンシップを行っています。コーディング課題はその選考で応募者のプログラミング能力や問題解決能力を見るために出題させて頂いているものです。PFN のインターンシップでは機械学習をはじめとする幅広い分野で応募を行っているため、今年は「機械学習・数理」「バックエンド」「フロントエンド」「プロセッサ/コンパイラ」「Chainer」の5種類のコーディング課題を用意し、応募者の希望するテーマに応じてこのうちのいずれかを解いていただく形にしていました。

今年は去年を大きく上回る数の応募を国内外双方からいただくことができました。それに伴い、インターン生の受け入れ人数も去年よりもさらに拡充する形になりました。

今年の問題は以下のような構成になっています。

  • 機械学習・数理課題: ニューラルネットワークの敵対的入力(Adversarial Example)のアルゴリズムを実装し、性能を報告するためのレポートを記す課題。
  • バックエンド課題: 与えられたログファイルを分析するツールを作る課題。
  • フロントエンド課題: セミナー発表のような動画に対して、発表内容のアノテーションを行うウェブサービスのプロトタイプを作る課題。
  • プロセッサ/コンパイラ課題: 行列積コードの最適化と、行列積回路の設計を行う課題。
  • Chainer 課題: モデルの学習を行うコードを Chainer で実装する課題。

コーディング課題では毎年、出題者が趣向を凝らした問題を作成しています。これらの課題が、興味のある分野を実践的に学ぶための練習問題になれば幸いです。

私は今年の機械学習・数理課題の出題に携わりました。少し余談になりますが、課題を作る際に意識していたことについて書きたいと思います。他の課題ではまた話が違ってくるかもしれませんが、共通しているところもありそうです。

  • 前提知識があまり無くても解けるようにする: PFN では幅広い分野の方々を募集しています。そのため、機械学習そのものの経験や知識が無くても課題を一通り解けるように問題を設定したり、問題文を記述するようにしています。また、特定の知識を持っている人が有利になりすぎるということがあまりないようにも配慮しているつもりです。
  • 実際の研究に近いような設定にする: 深層学習のような分野の研究では「何か良いテーマを見つけて手法を考える → 実装する → 出てきた結果をまとめ、考察を与える」という過程を繰り返しますが、このうち「実装して考察する」という流れを短期間で一通り辿れるような設定にしています。大学の授業の課題のような感じに近いかもしれません。
  • できるだけ興味深いテーマを問う: 機械学習・深層学習の分野では日々研究が進んで面白い結果が次々に出ているので、それに少しでも触れられるような課題を設定しているつもりです。今回の課題である Fast Gradient Signed Method という手法は、シンプルな手法でありながらランダムよりも遥かに強い攻撃手法であるという点で興味深いものだったと思います。
  • 時間が掛かりすぎないようにする: 学業に支障が出ると良くないので、実力が十分あれば1~2日程度で終わるような分量にすることを目標にしています。

提出されたコードは様々な観点から評価するようにしています。単に実装されたコードが正しいのかどうかだけではなく、コードが読みやすいものになっているか、単体テストなどの検証のためのコードが適切に書かれているか、他人がコードの追試をしやすいようになっているか、といった要素も考慮するようにしています。
実験ではコードを書いて動かしたら終わりではなく、手法がどの程度うまくいったのかを評価し、なぜそのような結果になったのかを考察するのが重要になります。特に、複数人で一つの課題に取り組む際にはそれら(評価・考察)を他のチームメンバーに共有することも大事になるでしょう。レポートでは結果の評価と考察ができているかを評価するようにしています。

これらの課題を見て PFN に興味を持っていただけた方は、ぜひ来年のインターンシップへ応募することを検討していただければ幸いです。また、PFN ではフルタイムの採用も通年で行っておりますので、こちらもご検討をよろしくお願いします。

分散深層学習を支える技術:AllReduceアルゴリズム

kfukuda

2018-07-10 11:49:43

本記事は、2017年インターンシップを経て現在はアルバイトとして勤務されている上野さんによる寄稿です


みなさんはじめまして。Preferred Networksの2017夏季インターンに参加し、現在アルバイトをしている上野裕一郎です。普段は東京工業大学でHigh-Performance Computingに関する研究を行っており、分散・並列計算に興味があります。

今回は、分散深層学習を行う際に使用されるAllReduceという通信パターンについて調査・実装・評価を行いましたので、それについてご説明いたします。

分散深層学習とは

現在、ディープニューラルネットワークを用いた学習には長い時間がかかることが知られています。そして、様々な種類のモデルや、大量のデータを組み合わせて学習を試すためには、学習にかかる時間を短縮する必要があります。そのために、多数のプロセスに分散して計算を行うことで、学習にかかる時間を短縮することを目的とするのが分散深層学習です。分散深層学習の詳細については、Preferred ResearchのChainerMN 公開に関する記事[1] をご参照ください。

弊社では、深層学習の研究開発や関連技術の迅速な実用化のために、スーパーコンピュータ MN-1 を運用しています。これは、民間企業のプライベートな計算環境としては国内最大級で、NVIDIA(R)製 Tesla(R) P100 GPUを1,024基、Mellanox(R) InfiniBand FDRを搭載しています。これを用いて、ImageNetの画像分類データセットを利用したResNet-50の学習を15分で完了することができました[2]。

しかし、このような多数のGPUを用いて効率的に計算を行うのは多くの困難が伴います。そのうちの1つとして、データ並列型分散深層学習において、GPU同士の通信にかかる時間がボトルネックとなっていることが挙げられます。

分散深層学習では、どのような通信が発生し、なぜ時間がかかるのか、もう少し詳しくご説明します。

分散深層学習におけるAllReduceの重要性

データ並列型分散深層学習では、異なるデータでモデルのパラメータでの損失関数の勾配を求めたあと、プロセス間で勾配の平均を求め、求めた平均を得られた勾配とみなして、モデルに適用を行います。この勾配の平均を求める操作として、多対多の通信を行う集団通信アルゴリズム:AllReduceが用いられています。

このとき、最もよく用いられているのが、NVIDIA社が提供しているNCCL[3] (NVIDIA Collective Communications Library)です。NCCLは、並列・高性能計算の分野の標準であるMPIと比較して、圧倒的に高速な通信を実現しています。前述のImageNet15分実験においても、NCCLが実現する高速通信は、記録の達成には不可欠なものでした。現在、ChainerMNでデータ並列型分散深層学習を実行するにあたっては、NCCLは必須のライブラリとなっています。

さて、NCCLの高い性能の秘密はどこにあるのか、社内でも多くのリサーチャーやエンジニアが興味を持ちました。今回は、実験的にAllReduce通信プログラムを作成し、最適化することによって、NCCLの性能にどこまで迫れるかを試してみました。

AllReduceのアルゴリズム

では、分散深層学習のスループットに大きな影響を与えるAllReduceについて詳しく見ていきます。
AllReduceとは、すべてのプロセスが持っている配列データを集約(Reduce)したうえで、すべてのプロセスがその結果を等しく取得する操作です。まず、総プロセス数を \(P\), そして、それぞれのプロセスには\(1\)から\(P\)までの番号\(p\)がついているとします。そして、各プロセス\(p\)が長さ\(N\)の配列\(A_{p}\)を持っているとしましょう。さらに、プロセスpが持つi番目のデータを \(A_{p,i}\) とします。このとき、最終的に得られる配列を \(B\)とすると、

$$ B_{i}~~=~~A_{1,i}~~Op~~A_{2,i}~~Op~~…~~Op~~A_{P,i} $$

となります。ここで、\(Op\) は2項演算子で、SUM(合計)、MAX/MIN(最大値/最小値)などがよく用いられます。つまり、ここでいう集約(Reduce)とは、配列の要素 \(A_{p,i}\) を、\(p=1,…,P\)までの全プロセスにわたって \(Op\)を用いて畳み込み計算することになります。分散深層学習においては損失関数の勾配の平均が必要であるため、勾配の要素ごとにSUMを用いて合計を計算します。以降では、集約操作に用いる演算はSUMだと仮定します。図1に、\(P=4\), \(N=4\)のAllReduceを実行する模式図を示しています。

図1. AllReduceの模式図

このようなAllReduce処理を実装する方法として、複数の方法が考えられます。

例えば、最も単純な方法として、代表となるプロセスを1つ決め、そこに全ての配列を集め、そのプロセスが全てのReductionを行い、計算結果を全プロセスに配布する、というアルゴリズムを考えることができます。しかし、このアルゴリズムは、プロセス数が増えると代表プロセスの通信量、Reduceの計算量、メモリ使用量がそれに比例して増え、処理量に不均衡があります。

このようにプロセス間の処理量に不均衡が存在しないよう、うまく通信や計算を全てのプロセスに分散させたアルゴリズムが提案されています。代表的なものとして以下のものが挙げられます。

  • Ring-AllReduce
  • Rabenseifnerのアルゴリズム[4]

本稿では、Ring-AllReduceアルゴリズムについて紹介します。NCCLも、Ring-AllReduceを用いて実装されています[5]。

Ring-AllReduce

まず、総プロセス数を\(P\), そして、それぞれのプロセスには\(1\)から\(P\)までの番号がついているとします。そして、各プロセスが図2のようにリングを構成するとしましょう。

図2. リングの構成例

ここで、プロセスpに着目して処理の流れを見ていきます。

まず、プロセスpは、自分の配列をP個に分割し、この分割された配列のp個目をチャンク[p]と表記するとします。そして、プロセスpは、チャンク[p]を次のプロセスp+1に送信します。この時、同時にプロセスp-1はチャンク[p-1]の送信を行っているので、プロセスpはこれを受信することができます(図3)。

図3. 各プロセスpがチャンク[p]を送信する

そして、プロセスpは、受信したチャンクに自分のチャンク[p-1]を足し込み(Reduceし)、計算結果を次のプロセスに転送します(図4)。

図4. 各プロセスがReduce後のチャンク[p-1]を送信する

これをP-1ステップ繰り返すことで、それぞれのプロセスが、Reduce済みのチャンクを1つ手に入れることができます(図5)。

図5. P-1ステップの繰り返しが終了し、Reduce済みのチャンクを1つ手に入れる

言い換えれば、各々のプロセスが、リングの上をまわるチャンクに、自分のチャンクを少しずつ足しこんでいきます。そして、チャンクがリングに沿って全プロセスを1度ずつ訪問した時点で、そのチャンクは、全てのプロセスのチャンクの集約の結果になっています。つまり、最終的には、それぞれのプロセスが、チャンクごとの集約の結果を1つ保持していることになります。

そして、それぞれのプロセスが持つ集約済みチャンクを、さらにリング上で一周回すことで、全てのプロセスが集約済みチャンクを全て取得でき、AllReduceが完了したことになります。

では、このアルゴリズムの通信量を、先程挙げた単純なアルゴリズムと比較してみましょう。

単純なアルゴリズムの場合、代表プロセスが受信するデータの量は、代表プロセスでない全てのプロセスからデータを受信する必要があるので、\((P-1) * N\)となります。その後、代表プロセスでない全てのプロセスにデータを送信する必要があります。これは、Pに対して代表プロセスの受信量が比例しています。

対して、Ring-AllReduceにおける1プロセスあたりの送信(受信)したデータの量は、以下のように求めることができます。最初に、P個に分割した配列をReduceしながらP-1回送信しました。そして、全プロセスにそのReduce済みチャンクを配布するために、P-1回送信しました。よって、1プロセスあたりの送信量はこの合計である \(2(P-1)/P * N\)となり、1プロセスあたりの送信量はPに関して定数であることが分かりました。

よって、2つのアルゴリズムを比べると、Ring-AllReduceは代表プロセスに集中していた送信・受信量を各プロセスにうまく分散させたアルゴリズムになっていることが分かります。このような特徴から、多くのAllReduceの実装でRing-AllReduceアルゴリズムが用いられています。

実装と最適化

Ring-AllReduceのアルゴリズムそのものは、GPU対GPUの通信を行う送受信関数を用いれば、簡単に実装することができます。Baidu社によるbaidu-allreduce[6]は、MPIのライブラリ上で実装済みの MPI_Send, MPI_Recv関数を用いてこれを実現しています。

今回は、MPIではなく、InfiniBandを直接扱うことができるInfiniBand Verbsを用いて実装し、より進んだ最適化を試みました。まず、InfiniBand、GPU、CPUのそれぞれのハードウェアリソースのアイドル時間を可能な限り削減して性能を引き出すために、アルゴリズムの処理をRegistration, Send, Reduction, Receive, Deregistrationなどのステージに分割し、パイプライン化を行っています。ここで、Registration, Deregistrationは、メモリ領域をDMAを用いて転送する際に必要な前処理、後処理を表しています。これらは、MPIを用いて実装すると、 分割してパイプラインに組み込むことができません。
さらに、配列を分割したものであるチャンクを、パイプラインの粒度をより細かくするために更に分割しました。また、メモリ確保は低速であることが知られているので、メモリプールを導入してコストを隠蔽しています。

性能評価

本稿で実装したプロトタイプ(PFN-Proto)の性能を、他の既存実装(詳細は付録に記載)と比較しました。比較対象を、スーパーコンピュータで広く用いられている通信ライブラリであるOpen MPI[7]、Baidu社によるbaidu-allreduce[6]、NVIDIA社によるNCCL[3]です。

なお、今回の我々のプロトタイプ実装は、ノード間通信に焦点を当てて開発しており、ノード内でのGPU間のDMA通信や共有メモリを使った通信最適化は実装されていません。実験では、1ノードに1プロセスを実行する条件でのみ測定しています。また、Open MPIについては、最新シリーズであるバージョン3.xではGPU Directに関係するバグがあり、弊社内ではまだ導入していないため、2.1.3を測定対象としています。

総プロセス数を8として、1ノードに1プロセスを起動することとし、256MBの配列のAllReduceをそれぞれ10回ずつ実行して測定を行いました。実験環境は、MN-1を用いています。実験環境の詳細は付録「実験環境」をご参照ください。図6に性能評価の結果を示します。

図6. AllReduceの実行時間の評価

この棒グラフは実行時間を示しており、低いほうが良い結果を示します。各棒は、それぞれのライブラリの10回の実行時間の中央値、エラーバーは実行時間の95%信頼区間を表しています。各実装の名前の意味、バージョンなどは、付録「比較対象ソフトウェア」をご参照ください。

まず、実行時間の中央値について見てみましょう。一番右側に示されているPFN-Protoが、最も高い性能を示しています。これは、ompi, ompi-cuda, Baidu, NCCLと比較して、それぞれ約82%, 286%, 28%, 1.6% 高速となっています。なお、グラフ上には示されていませんが、10回試行中の最速は、baidu-allreduceで0.097 [s] となりました。

次に、実行時間の分布について見てみましょう。中央値を基準にした実行時間の最大値と最小値は、PFN-Protoが +/-3%、NCCLが+/- 6%以内に収まっています。一方、baidu-allreduceは最大値が中央値の7.5倍という大きな数字となりました。これは、初回実行時に大幅に時間がかかるためです。なお、初回の試行を除いた最大値も中央値の+9.6%となっており、依然としてNCCLおよびPFN-Protoよりもばらつきが大きいことがわかります。

MPI、およびMPIをベースにした実装でこのように性能にばらつきが出る原因としては、MPIが内部で行っているメモリ領域の扱い方に関連していると推測しています。MPIは、InfiniBandによる送受信に必要となるメモリ領域の確保とRegistrationなどを抽象化したインターフェイスを提供しています。これにより、Ring-AllReduceの実装から、それらの発生タイミングを精密に制御することができないため、性能にばらつきが出ると考えられます。

関連研究

今回は、分散深層学習の中のAllReduce操作の高速化についてご説明しました。それ以外にも、分散深層学習の通信部分を高速化する方法として様々なものが考えられています。例えば、

  • 勾配の送受信を1イテレーション遅延させて、Forward, Backwardと通信をオーバーラップする方法(例:ChainerMNにおけるDouble Buffering[8])
  • データの浮動小数点精度を下げることによって通信量を削減する方法(例:ChainerMNにおけるFP16通信[8])
  • 勾配の値の重要度によって送受信するデータを間引いて通信量を削減する方法[9]

などがあります。特に、InfiniBandを持たないような環境(例えばAWS)では、このようなテクニックを用いることで学習を高速化することができます。

まとめ

本記事では、分散深層学習を支える技術である、AllReduceという通信パターン、特にRing-AllReduceという通信アルゴリズムについて説明しました。

そして、このアルゴリズムを実装し、今回の実験環境・実験条件では、NCCLと同等の性能まで最適化することができました。そのためには、InfiniBand Verbsを使用し、徹底的なパイプライン化を行うことが必要であったことが分かりました。これにより、高いハードウェアの性能と並行性を十分に活用することができました。これからも、より高速で、高い信頼性を持つ通信にはどのようなアルゴリズムやチューニングが最適か、調査・開発を進めていきたいと考えています。

ただし、今回の実装は、社内のクラスタを使用して開発・最適化しており、社内のクラスタのみに最適化された実装になっている可能性があります。それに対してNCCLは、幅広い環境で安定して利用できる高速な集団通信ライブラリであり、依然として、NVIDIA製GPUを用いて分散深層学習を行うためには、NCCLを使用するべきであると考えています。

謝辞

最後に、インターンの頃からメンターの方々やチームの方々には手厚いサポートをしていただきながら、大量の計算資源のもとでプロジェクトを進めることができており、非常に貴重な経験をさせていただいています。本当にありがとうございます。


おまけ:メンターより

上野さんのインターンシップメンターを務めています、PFN 大規模分散計算チームの福田(@keisukefukuda) です。今回は、NCCLの高い通信性能はどのように実現されているのだろうか?という疑問からスタートした実験的なプロジェクトでしたが、上野さんの高い技術力によってNCCLに近い性能を出すことに成功しました。

PFNでは、機械学習/深層学習そのものの研究だけでなく、ソフトウェアからハードウェアまで、広い分野で研究開発を進めています。

HPC・高性能計算に興味を持っている学生の皆さんは、ぜひ来年のPFNインターンシップへの応募をご検討ください(このブログ記事の公開時点では、残念ながら2018年の夏季インターンの募集は終わってしまいました)。

また、もちろん中途・新卒の人材募集も通年で行っています。興味のある方はぜひご検討ください!PFNの人材募集のページはこちら https://www.preferred-networks.jp/ja/jobs です。

参考文献

[1] 分散深層学習パッケージ ChainerMN 公開
[2] Akiba, et al., “Extremely Large Minibatch SGD: Training ResNet-50 on ImageNet in 15 Minutes”
[3] NVIDIA Collective Communications Library
[4] Rabenseifner, “Optimization of Collective Reduction Operations”, ICCS 2004
[5] Jeaugey, “Optimized Inter-GPU Collective Operations with NCCL”, GTC 2017
[6] baidu-allreduce
[7] Open MPI
[8] ChainerMNのクラウド環境向け新機能とAWSにおける性能評価
[9] Tsuzuku, et al., “Variance-based Gradient Compression for Efficient Distributed Deep Learning”, In Proceedings of ICLR 2018 (Workshop Track)

付録

比較対象ソフトウェア

Implementation Version Note
MPI (ompi) Open MPI 2.1.3 CPUメモリからCPUメモリへの転送
(他の実装はすべてGPUメモリからGPUメモリへの転送)
CUDA-aware MPI Open MPI 2.1.3
baidu-allreduce (baidu) A customized version of baidu-allreduce, based on commit ID 73c7b7f https://github.com/keisukefukuda/baidu-allreduce
NCCL 2.2.13

実験環境

  • Intel(R) Xeon(R) CPU E5-2667 x 2
  • Mellanox(R) ConnectX(R)-3 InfiniBand FDR (56Gbps) x 2
  • NVIDIA(R) Tesla(R) P100 GPU (with NVIDIA Driver Version 375.20)

Emergence of Locomotion Behaviors in Rich Environment の追試

Manabu Nishiura

2018-06-29 10:48:38

1.内容紹介

はじめまして。PFNでSummer Internship 2017に続き、アルバイトをしている東京大学の西浦です。現在は駒場2キャンパスの先端研で神経科学・循環器系の数理モデルの研究をしています。

さて、2017年の春頃、DeepMindから”Emergence of Locomotion Behaviours in Rich Environments”[1]という論文が公開され、その動画が話題になりました。しかし、この論文では公開されている情報が限られており(深層学習分野でよくあることなのですが)、実験環境の設定、ネットワークの構成や学習に必要なパラメータで不明なものが多く、論文の結果を再現するためには不明な部分を推定するために多くの組み合わせを試す必要がありました。そのため、このような実験の再現は深層学習の実践的な知識と学習のための大規模なリソースが必要とされ、個人で行うのはなかなか難しいと思います。今回はその論文をChainer FamilyのひとつであるChainerRLを利用して再実装し追試を行い、その結果として様々な知見が得られましたのでご報告させていただきます。

Emergence of Locomotion Behaviors in Rich Environmentsの元動画

2.元論文の概要

強化学習のパラダイムは、原理的には単純な報酬のみから複雑な振る舞いを学習することができるようになっています。しかし実際は、意図した振る舞いを学習させるためには、報酬関数を慎重にチューニングすることが一般的です。この論文では、報酬はなるべく直感的な構成で固定してしまい、学習に使う環境(タスク)を様々な種類用意して、エピソードごとにランダムにその環境を変更するというアプローチが採用されています。これにより、様々な環境に対してロバストで、複雑な行動を獲得させようということをモチベーションに実験が行われています。

アルゴリズムとしては、方策勾配法(Policy Gradient)をベースにして、現在の方策に近い方策へと徐々に更新していくProximal Policy Optimization(PPO)[3]を用いています。PPOは論文公開当時では一番性能の良い強化学習のアルゴリズムだったのでそれが採用されていて、論文には同じく性能のよいTrust Reigion Policy Optimization(TRPO)[4]との比較もされています。

3.アルゴリズム、実験手法の解説

前提知識

まず強化学習のフレームワークについて説明します。強化学習では環境とエージェントというのがあり、エージェントが環境に対して行動をし、環境はそれを受けてエージェントに対して観測と報酬を返すという枠組みになっています。エージェントは、報酬に基づいて行動を決定するためのルール「方策(Policy)」を学習していきます。この論文では、ロボットなど連続値の行動を扱いやすい方策勾配法を採用しています。方策勾配法ではActor-Criticモデルという、エージェントをActor(行動器)とCritic(評価器)でモデル化し、例えばそれぞれをニューラルネットワークで表現します。また、エージェントがActor-Criticモデルだと、例えば、Actorのネットワークを決定しているパラメータが方策に該当します。Criticは、現在の方策の元である状態がどれだけの価値を持つかを表す価値関数(ある状態以降の報酬の期待値に割引率をかけたものが一般的)でモデル化されます。

 

実験環境としては、物理エンジンのMuJoCo [2]と強化学習のフレームワークであるOpenAI Gym [5]を用いています。代表的なものとしては、Planar walker(またはWalker2d)と呼ばれる二次元平面内でエージェントに二足歩行を行わせるモデルが挙げられます。Planar walkerの場合、それぞれのエージェントは各関節を曲げるトルクにより行動を表現することになります。また、エージェントが環境から受けとる観測は、大きく内部状態と外部状態に分けられ、各関節の角度、角速度、位置、接触、トルクセンサ情報などを内部情報、地形の高さ情報を外部情報として受け取っています。報酬はPlanar walkerの場合だと以下のように設計されており、基本的には前に進むと報酬がもらえ、それに加えて姿勢のペナルティー(負の報酬)などが含まれています[1]。

Planar walker [4]

今回追試したアプローチでは、方策を決定するネットワークは内部状態と外部状態を別々に処理して最後に合わせて処理して、行動の次元個分、平均と分散の組を指定した正規分布を確率的方策としてを出力する構成になっています。

アルゴリズム

ここで、追試で使ったTRPOとPPOの二つのアルゴリズムについて解説します。まず、ベースになっている方策勾配法は、目的関数(原則としては現在の方策による期待値を用いる)を方策のパラメータに関して微分し、得られた勾配方向にパラメータを更新する方法です。目的関数を計算するために、現在の方策で行動して、その系列データを貯めること(一般化方策反復)を行います。しかし、方策の更新には慎重になる必要があり、一度方策が劣化してしまうと、それから後に得られるサンプル系列も悪化してしまい、持ち直すのが難しくなるという問題があります。

そこでTRPOは、方策の更新に制限をかけながら更新していきます。具体的には、KLダイバージェンスを使って信頼領域(trust region)を定義して、その信頼領域を超えないように、制約条件つきの最適化問題を解くことにより方策のパラメータを更新します。これにより方策の分布として大きな変化を抑制することができて、方策の大きな劣化を防ぐことができます。TRPOが二回微分を計算するので、計算量が多いことを踏まえ、PPOはTRPOの制約条件を目的関数に含めて非厳密化することで、TRPOより単純で軽い計算量でそれなりの性能を発揮するアルゴリズムになっています。

具体的には、方策を \(T * N\) time steps走らせて(Nはスレッドの数)集めた \(s_t\) ,\(a_t\), \(r_t\) を用いて \(A_t\)(アドバンテージ)を計算し、\(L^{CLIP} \)を前の方策と新しい方策の比率を \(\pm \epsilon\) 内にクリップして勾配方向にパラメータを更新していきます。方策のネットワークと価値関数のネットワークでパラメータを共有する(最後の出力層のみそれぞれのパラメータを使う)なら、方策と価値関数のネットワークを独立に更新できないので、目的関数に価値関数の誤差項を加え、探索の幅を増やしたければ、エントロピーボーナスを加えることもあります。(最終的な目的関数は \(L^{CLIP+VF+S} \))ここで登場するアドバンテージとは、収益(報酬の期待値)からベースラインを引いたもので、勾配の推定値の分散を減らすためのテクニックです。それぞれの計算式を以下に示します[3]。

元論文ではPPOをさらに分散版にしたものを使っています。追試としては、PPOで方策ネットワークと状態価値関数にLSTMを含んだものと、TRPOを用いましたが、1スレッドの場合では、TRPOの方がかなり性能がよかったです。したがって、以下の結果は全てChainerRLのTRPOで学習させた結果となります。

実験手法

追試としては2通りの環境で訓練しました。一つ目は元論文の動画に近い3種類のタスクがある環境で、もう一つは地形の凸凹の状態がランダムに変わるものです。

元論文に近い環境では、Planar Walkerを①箱を飛び越えるタスク、②穴を飛び越えるタスク、③浮いている板を避けるタスクの3種類の環境で順番に訓練した後、3種類の環境(タスク)がランダムにエピソードごとに切り替わる環境で訓練します。

地形の凸凹の状態がランダムに変わる環境では、エピソードごとにすべての地形が変わる中で訓練します。

4.結果

学習し始めのエピソードごとにランダムに地形が変わる中で試行錯誤している様子

学習後歩いている動画

こちらでは、学習初期段階からランダムに地形を変更していたためか、とにかく脚を高く上げて、どんな障害物でも越えられるような動きになってしまったようです。

動画に示した歩行行動を獲得するまでの学習曲線を上に示します。10,000ステップごとに10エピソード走らせて評価を行なっており、青のrewardは10エピソードの平均累積報酬で、上下の灰色の線は10エピソード内での最小値最大値になっています。200万ステップほどで収束していることが分かります。

 

元論文に近い環境で学習後歩いている様子

障害物によって頭を下げたり、ジャンプする高さが変わったり、動きが変わっていることが見て取れます。一つ目と二つ目の動画ではPlanar walkerの関節の減速比のパラメータが違っていて、このような微妙な差でも獲得される動きに違いが出てしまいます。

 動画に示した歩行行動を獲得するまでの学習曲線を上に示します。歩く動作は120万ステップほど、穴を飛び越える動作は800万ステップほど、浮いている板を避ける動作は400万ステップほどで学習が収束していることが分かります。

タスクによって報酬の平均がそこまで変動していないものもあり、歩く動作を獲得した状態から箱を飛び越える動作の獲得にはそれほど学習が必要ではないが、箱を飛び越える動作を獲得した状態から穴を飛び越える動作を獲得するのと、箱を飛び越える動作を獲得した状態から浮いている板を避ける動作を獲得するためにはかなり学習が必要であることが分かります。

元論文では適切に実験設定が考えられていて、カリキュラムラーニングになっていたために、タスクに応じて行動をうまく切り替えられるようになっていましたが、ただ単に地形やタスクをランダムに変えるだけでは、どんな環境にも対応するような方策を獲得してしまうようです。

5.考察

問題点の一つに、初期条件を注意深く設定しないと意図した学習結果になりづらいという問題があります。今回の場合も初期の状態変数の分散や、地面とMuJoCoのモデル(Planar walkerなど)との高さ方向の相対的な位置は学習の様子をみながら調整することが必要でした。具体的に注意した点としては以下のような点が挙げられます。

  • ある程度初期状態に分散がないと、分散の範囲で実現できる行動になってしまう。(逆に分散が大きすぎても学習がうまく進まないことがある)
  • 環境をリセットした時に何ステップ分フレームをスキップしてから指令を出し始めるか、によって獲得されるモーションが変わってくる。(例えばMuJoCo環境内で、完全に地に足が着いてから指令値を出すようにした、など)
  • 歩行を獲得させる場合、学習の過程で最初に獲得されるのはその場に立っているという方策なので、初期位置の周辺はなるべく平らな方がよさそう。

その他にも、下記の記事[6]に現状の深層強化学習の課題はよくまとまっているので、ぜひ読んでいただきたいです。(方策を更新していくために特定のアルゴリズムを採用しても、報酬関数、方策を表現するネットワークのパラメータなどは自分で任意に決定する必要があり、設定する報酬によって獲得される方策がかなり変わってしまうという問題など。)

 

失敗例の動画

けんけんを獲得している動画(初期化した時の相対的な高さの問題で、片足を前に出す方策を獲得できなかった例、初期状態の分散はうまくいった例と同じ)

6.PFNインターンの感想

ある仮説を検証するのに、「ある実験系でやってみて上手く行かなければもっと単純化した系でやってみる。」という、研究の基礎的なプロセスの体験ができたのはとてもよかったです。また、ロボティクス関係の様々な研究を知ることができ、そこで研究している人たちとの繋がりができたのは一番大きな収穫だったかもしれません。最後に、情報交換の重要性も強く意識することができました。有名なライブラリやパッケージの使い方(インストールで苦戦するものなど)や、こういう手法を試したけどいまいちだった、ハイパーパラメータの情報など、公開されていなけど実験をしていく中では欠かせない情報などを共有できる環境が、とてもありがたいなと感じました。

元論文の情報が結構少なく、なかなか学習が進まず進捗が出ずに精神的に辛い時期もありましたが、様々な方に積極的に相談するようになってからは比較的スムーズに乗り切ることができたように思います。最後になりましたが、ご指導いただいてるメンターの皆様をはじめ、社員の方々に感謝を表して報告を終わらせていただきたいと思います。

参考文献

[1] “Emergence of Locomotion Behaviours in Rich Environment” https://arxiv.org/abs/1707.02286v2

[2] MuJoCo advanced physics simulation http://mujoco.org/

[3] “Proximal Policy Optimization Algorithms” https://arxiv.org/abs/1707.06347

[4] “Trust Reigion Policy Optimization” https://arxiv.org/abs/1502.05477v5

[5] OpenAI Gym https://gym.openai.com/docs/

[6] “Deep Reinforcement Learning Doesn’t Work Yet” https://www.alexirpan.com/2018/02/14/rl-hard.html

 

実センサを搭載したロボットカーの深層強化学習による自律制御

Megumi Miyashita

2017-12-12 12:24:19

はじめに

はじめまして。PFNで夏季インターンに続き、アルバイトをしている宮下恵です。普段は東京農工大学大学院で強化学習に関する研究をしており、ものづくりやロボットに興味があります。

「実センサを搭載したロボットカーの深層強化学習による自律制御」について報告させていただきます。

 

続きを読む »

2017年 PFN夏季インターンシップのコーディング課題公開

Kosuke Nakago

2017-07-27 09:54:00

* English blog is also written here.

PFNでは毎年8、9月に学生の方を対象とした2カ月間の長期インターンシップを実施しています。

今年も2017年のPFN 夏季インターンを募集したところ多数の応募をいただき、先日無事に選考が終了しました。

PFN 2017夏季 インターン募集

それに伴い、今回PFNのインターンコーディング課題をgithub上で公開しました。

https://github.com/pfnet/intern-coding-tasks

 

続きを読む »

深層強化学習による自動駐車の実装

Shiba Shintaro

2017-03-22 19:15:13

初めまして! PFN でアルバイトをさせてもらっている芝慎太朗です。普段は東京大学大学院で行動神経科学の研究をしています。僕が去年取り組んでいた、「車が自ら駐車場に向かい停止する」自動駐車プロジェクトについて報告します。まずはこちらのアニメーションをご覧ください。(アニメーションがうまく再生されない場合は画像をクリックしてください)

We implemented self-driving car that parks itself using deep reinforcement learning. The English slide is available at SlideShare!

背景

深層強化学習は、2015年から非常に注目され始めた人工知能技術であり、深層学習と強化学習を組み合わせたものです。深層強化学習によって、それまでできなかったような複雑なタスクにおいてもコンピューターが人を上回り始めました。プロ棋士を破ったことで一躍話題になった Google DeepMind による囲碁の人工知能 AlphaGo もこの技術を使っています。最近では スマッシュブラザーズにおいても威力を発揮し 話題になりました。

深層強化学習は制御タスクとの相性がよく、実際に PFN でもぶつからない車の自動運転ドローンの制御などに成功してきました。

PFN が CES 2016 で展示した自動運転(参照)では、アルゴリズムとして深層強化学習ブームの火付け役となった Deep Q Network(以下DQN)を用いています [Mnih et al., 2015]。ニューラルネットワークへの入力は、LIDAR(wikipediaによる解説)を模した近接物への距離と角度センサー、直前の行動、現在の車のスピードとステアリング(ハンドルの曲がり具合)でした。

しかし自動運転技術を現実に応用することを考えると、一般に距離センサーよりもカメラの方が安価という特徴があります。一方で、距離の計算が必要になるためカメラ画像の方が制御は難しくなると考えられます。実際、つい最近も ブラウザ上で動作するような簡単な自動運転デモ が公開されたばかりですが、これも距離センサーを使用しており、使用しているニューラルネットは3層程度の簡易なものです。
距離センサー・カメラそれぞれに得意・不得意な状況や利点・欠点があるので一概にどちらを用いるべきとは言えませんが、いずれにせよ、距離センサーに頼らずカメラ画像のみを用いて車を制御するようなアルゴリズムの研究開発は非常に重要です。

本プロジェクト

このプロジェクトでは、距離センサーではなく、車に取り付けられたカメラによる主観的な画像の入力によってend-to-endのアルゴリズムで車を制御できないか、ということに挑戦しました。具体的なタスクとして選んだのは駐車です。すなわち、車を駐車スペースに移動して停止させます。

アルゴリズムとしては DQN の改善版である Double DQN を使用しました。Double DQN は行動価値の見積もり値である Q 値の過大評価を防ぎ、ニューラルネットの発散を防ぐことで学習を安定させるという特徴があります [Hasselt et al., 2015]。詳しくは解説スライド(この投稿の最後にリンクが貼ってあります)や元論文をご覧ください。

まずは環境の定義です。今回は実機や既存のシミュレータを使用せず、簡単な車の物理シミュレータを自分で実装しました。このシミュレータはアクセル、ブレーキ、ハンドルの曲がり具合を受け取り、牽引力、空気抵抗、転がり抵抗、遠心力、制動力、コーナリング力を計算し、車の位置、速度、加速度を更新します。車や駐車スペースの大きさと、車が探索できる地面の範囲なども定義しました。次の図は、シミュレーションされた環境を上から見た俯瞰画像です。黒い長方形が駐車スペース、赤と黄色の長方形が車(黄色が前)になります。


次にエージェントへの入出力を定義します。エージェントは環境の状態を入力として受け取り、アルゴリズムにしたがって適切な行動を選択します。現実世界に例えるなら車に乗っている人に相当するでしょう。行動はアクセル、ブレーキ、ハンドルを左右に曲げることの組み合わせで全部で9種類用意しました。状態としては、環境を車から見た主観画像と、現在の車のスピードとステアリング(ハンドルの曲がり具合)を使用しました。つまり、車の現在位置や駐車スペースまでの距離を直接知ることはできません。

主観画像は、車を中心に3方向または4方向に設置されたカメラ画像を用意し、車の周りをぐるりと見渡せるようにします。次の画像はカメラが4台の場合の主観画像です。画像の大きさはニューラルネットに入力する直前で 80 x 80 に縮小します。わかりやすいように中心に先ほどと同様の俯瞰画像を載せました。


エージェントは、画像の入力に合わせて適切な行動を選択し、車を駐車スペースに導いてそこで停車することが求められます。状態がカメラ台数分の画像と、画像でないパラメータ(現在の車のスピードとステアリング)からなるため、ニューラルネットの構造を工夫して以下のようにしました。この図はカメラが3台の場合に使用されたニューラルネットワークです。図中の Convolution とは、画像を処理するための畳み込みニューラルネットを示します。


最後に報酬を定義しておきます。「車が駐車スペースに向かい、その中で停止する」、すなわち「車ができるだけ長く駐車スペースの内側にいる」ことを学習するような報酬の与え方を考えます。いろいろな設定を試しましたが、最終的に

  • 車が駐車スペースの内側にいる場合、+1
  • 車が地面の外にいる場合、-1
  • その他の場合、0.01 – 0.01 * ゴールまでの距離

というふうに設定してみました。
その他の細かい設定や、他に試した報酬の設計などは末尾のスライドをご覧ください。

結果

GeForce GTX TITAN X 上で約一週間ほど学習を回し続けた結果、冒頭で示したように、車が自動で駐車スペースに向かい停止するように学習できました。次のアニメーションは冒頭と同じもので、左が車の軌跡、右が実際にニューラルネットワークに入力された画像です。

しかしながらやはりタスクの難しさもあって、このまま学習を続けていくと車が地面をぐるぐる回り続けたり、パラメタによっては学習途中でニューラルネットの出力が発散してしまったりという場合もありました。こちらも詳細はスライドを見ていただければと思います。


考察

深層強化学習を用いて、主観画像の入力から自動駐車を学習できました。画像を入力して車を制御するのは、距離や角度のセンサーよりも一段階難しいタスクです。実は、このプロジェクトも距離などを入力にして学習させるところから始めました。距離を直接入力した場合には安定してすぐに学習できたものの、主観画像では Q 値の発散や、うねうねと動き続ける車が誕生したりとなかなか安定しませんでした。

原因として考えられることの1つに、畳み込み層で車や駐車スペースの場所がうまく検出しきれていない可能性があります。先にCNNから位置を回帰するような事前学習をおこなってその重みを初期値として使うことや、一度 CNN 部分の出力を可視化してみることも有用でしょう。

また学習を安定させるために、アルゴリズムの変更も効果的かもしれません。例えば A3C [Mnih et al., 2016] や TRPO [Schulman et al., 2016] を使ってみたり、モンテカルロ法と組み合わせた学習などは試す価値があると考えられます。

実際にはいきなり始めから主観画像を入力したわけではなく、上で少し述べたように、簡単なタスクから徐々に難しくしていました。また、報酬の設計を変更しつつ、駐車スペースの位置や車の初期設定を変えながらカリキュラム学習をしたりと細かい実験を試しています。これらの詳細が知りたい方は上記のスライドを見ていただければと思います。

まとめ

本プロジェクトの結果はまだ様々な状況で完全に対応できるものではありませんが、深層強化学習によってカメラ画像のみで自動駐車が実装できる可能性を示したものだと言えます。今後の方向性としては、学習アルゴリズムを変更して学習を安定させたいです。シミュレーションだけではなく、実機でも実現できれば非常に面白いと思います。

僕は現在も他のプロジェクトに取り組みながらアルバイトを続けています。初めからプログラミングや強化学習ができたわけではなく、自分で勉強しつつ、わからないところをメンターに教えていただきながら、大変恵まれた環境で進めることができたプロジェクトでした。学生の皆さんも興味があればアルバイトやインターンに積極的に飛び込んでいってみてはいかがでしょうか。

2016年夏季インターンシップ開催報告

大野 健太
エンジニア

2016-10-28 18:41:49

PFI・PFNでは今年8, 9月に夏季インターンとして14名の方に来て頂き、機械学習・深層学習に関する様々なプロジェクトに取り組みました。このブログエントリでは、PFI・PFNのインターンシッププログラムの概要と、今年のインターンシップ、特に最終成果発表会についてを紹介します(写真は中間発表のポスター発表の様子です)。

2016%e3%82%a4%e3%83%b3%e3%82%bf%e3%83%bc%e3%83%b3%e4%b8%ad%e9%96%93%e7%99%ba%e8%a1%a8

PFI・PFNのインターンプログラムについて

PFI, PFNでは、2010年からインターンシップを実施しています(PFNは2015年から)。夏季のインターンシップは毎年行っており、また毎年ではありませんが、春季にもインターンを実施しています。PFI・PFNのインターンシップの特徴として、8, 9月の2ヶ月間と比較的長期であること、インターンで行うプロジェクトのテーマに精通している社員がメンターにつき一緒にプロジェクトを進めていくこと(大抵の場合1人の学生に対してメンター2人)、インターン中の成果は論文やOSSなどの形で可能な範囲で公開できることなどが挙げられます。

準備に関しても4月から募集要項の作成を進めており、春季インターンも含めると、1年のうち半分以上はインターンに関して何らかのプロジェクトが動いていることになります。PFI・PFNがここまでインターンシップに力を入れている理由として、インターンを行った後に社員としてPFNに来ている方がメンバーとして活躍していること、社員の側もインターンで来ていただく学生の方々から最新の研究について学んでいること、インターンでのプロジェクトが学生の方の研究・学業にも直接的・間接的に役に立っているという自負があることなどが挙げられます。

選考は書類審査・コーディング審査・面接審査で実施しております(選考方法に関しては今後変更になる可能性は十分あります)。コーディング試験に関しては別のブログエントリにて、過去の選考で出題した課題を公開しておりますのでご参照ください。選考では、本人の興味・研究分野・得意な技術などを考慮し、指導できるメンターとの間でマッチングを行います。幸いなことに、PFI・PFNでのインターンを希望していただける方は多く、また、皆さん優秀な方が多いので、毎年選考には頭を悩ませています(そして、大体毎年想定以上の人数を採用してインターン期間中はてんやわんやになります)。今年の募集要項は過去のNewsをご参照ください。

今年の夏季インターンについて

PFNが事業を拡大し、人数面・設備面でキャパシティが増えたことで、今年の夏季インターンでは14人と例年以上に多くの方に参加していただきました(倍率としては例年と同等程度でした)。今年4月にオフィスを本郷三丁目から大手町に移転した時には空席がたくさんあると思っていたのですが、実際にインターンを開始したら、危うく席が足りなくなりそうになり、若干ヒヤヒヤしました。

インターンシップの募集する際に、大まかなテーマは設定していますが、具体的にどのようなテーマで行うかは採用後にインターン生とメンターとの間で議論を行い、プロジェクトの方向性を決めていきます。今年のテーマは以下の通りです。どのプロジェクトでも関しても異常検知・強化学習・深層生成モデルなどに関する最先端のテーマに取り組んでいただきました。

  • 対話における商品の営業
  • Automatically Fusing Functions on CuPy
  • Generation of 3D-avatar animation from latent representations
  • Response Summarizer: An Automatic Summarization System of Call Center Conversation
  • Imitation Learning for Autonomous Driving in TORCS
  • 3D Volumetric Data Generation with Generative Adversarial Networks
  • DQN with Differentiable Memory Architectures
  • Anomaly Detection by ADGM / LVAE
  • Multi-modal Deep Generative Model for Anomaly Detection
  • CNN based robotic grasping for randomly placed objects by human demonstration
  • Bayesian Dark Knowledge and Matrix Factorization

今年の新しい試みとして、中間発表・最終発表を従来の口頭発表形式から、ポスター形式に変更しました。また、最終発表は一般公開し、外部の方も参加していただけるようにしました。発表をポスター形式にしたことで、インターンの学生の方たちがPFI, PFN社員やお客さんと双方向の議論が出来たのはよかったのではないかと思います。最終発表会は当初2時間を予定していましたが、終了時間が過ぎても活発に議論が続いていました。最終発表会当日のポスターはリンク先のconnpassページにまとめておりますので、是非ご覧になってください(発表資料は順次追加していきます)。

今後のインターンシップに関して

PFNでは(私がPFN所属なのでこのような主語を置きます)来年以降も夏季インターンシップを実施する予定で、募集要項は4月頃に掲載する予定です。また、PFNでは、春季インターンなどの通年インターンシップやアルバイトも随時実施しております(通年でのインターンシップはまだ仕組みが整備されていないため、受け入れられる数が限定されていますが、HPへの募集要項の掲載などの準備を進めています)。PFI・PFNでのインターンシップやアルバイトに興味のある方は是非ご一報いただければと思います。