Aidemy Tech Blog

機械学習・ディープラーニング関連技術の活用事例や実装方法をまとめる、株式会社アイデミーの技術ブログです。

人材採用から人材管理まで AI×HRのサービス10選!

 

こんにちは、たくやです。

今週はニュースからちょっと離れて、AIがHR(Human Resourse, 人事)にてどのように利用されているのか、また利用されようとしているのかについて、いくつかのサービスをご紹介させていただきたいと思います。

これからHRにAIを導入しようと考えている方、また、AIが具体的にどのようなメリットをもたらすのかに興味がある方が読みやすい構成にいたしました。

これまで人事は上司の好き嫌い、経験や勘、飲みニケーションなどの不透明な条件下で行われていましたが、そういったものを画一的に体系化、数値化することで、従来よりも効率的に業務改善などの業務を達成できることが期待されています。

 

<チャットを利用した個人の仕事適正判定サービス >

1、株式会社フォーラムエンジニアリングの「Insight Matching 」

Watson のテクノロジーを活用した人材マッチングシステム。

実際にユーザーとのテキストチャット形式を通し、対話履歴書のみでは知ることが難しかった趣味や性格などの人間的な側面も分析し、独自のアルゴリズムを用いて適正を数値化してくれます。

例えば、設計士を募集する企業があったとします。その企業にとって適合性の高いエンジニアを提案する際に、エンジニアとの対話から得た情報をそれぞれ数値で表します。具体的には、数値上では電話営業のスキルが35点だったとしても、設計士を募集する企業の事業領域とのスキルやモチベーションにおける適合性が90点なので、クライアント企業とエンジニアの適合性は 70点。エンジニアと企業の適合性が十分に高いとし、人材コンサルタントに提案するといった仕組みです。

IT領域から自動車関連など、多岐に渡るエンジニアが約5000人登録しているそうです。

www.youtube.com

 

 

 

<テキストのパフォーマンス分析サービス>

2、Textio

機械学習と自然言語処理を駆使し、候補者の作成したレジュメや求人広告に利用されている文言やレイアウト、オファーメール、応募効果(ニーズにあった人材の獲得ができたか、獲得までに要した時間)などを解析し、候補者の属性によって効果的な、またはネガティブにとらえられる可能性の高い文言や文章を割り出だしてくれます。

2014年にシアトルで設立したスタートアップ企業です。

TwitterMicrosoft、スターバックスが利用しています。 

textio.com

 

<求職者データベース検索サービス>

3、Connectifier

2012年に元Google社員のBen McCann氏とJohn Jersin氏が創業したカリフォルニアの企業です。

求職者情報をデータベース化し、人事担当者がキーワードやロケーションなどの条件を入力すると、データベースから潜在的な候補者を含む、適合性の高いターゲットを迅速にピックアップしてくれます。

なんと、4億人を上回る求職者情報をデータベース化しています。

具体的なアルゴリズムは公開していないものの「AIを活用する」とコーポレートサイトに明記されており、AI×HRのスタートアップとしてかねてより注目が集まっていました。

2016年2月、Connectifier は LinkedInに買収されました。

 

4、AI人事部長

チームメンバーや応募者が用意しているアンケートに答えることによって、その人の強みや特徴を視覚化。チームがどういう状況なのか、または応募者がチームにフィットするかなどを分析してくれます。

できることは

チームメンバの個人単位でのサポート

  • プロファイリング分析:メンバーがどういった価値観を持っているか。
  • メンタルパワー分析:各人のストレス耐性や感情統制力などの評価。
  • 個性活用マニュアル:それぞれが好む対応やNGワードなど。モチベーションを上げるために必要な事項などの提案。

面接のサポート

「こういった人材が欲しい」というのを社内のメンバーから選択すると事前に応募者に行ったアンケートから面接より前にAIが応募者の特性を分析し、その人がチームが求める人材かを分類してくれます。

 特筆すべきは”無料”という点。これならすぐにでも使い始めることができます。

WORKUP AI人事部長

 

 

<SNSなどから自動で情報を収集し、データベース化、マッチングするサービス>

5、Gild

サンフランシスコにある企業で、エンジニア採用向けのサービスを提供しています。

一般的なSNSだけではなく、エンジニアが利用するGithubやStack Overflowなどのプログラミング技術に関するコミュニティサイトや個人ブログなど、Webサイトをクロールして大量のデータを収集し、データベース化してくれます。(”スクレイピング”という手法を用いていると推測されます。)

エンジニアの実力は履歴書や面接だけでは、適切に評価することは難しいものですが、常に最新化されるビッグデータを独自のアルゴリズムで解析することで、エンジニアのレベルを可視化することができます。

さらにGild Spotlightという求職者として顕在化していないエンジニアが転職をしたくなるタイミングも推測して企業の人事担当者に推薦することができるサービスも提供してくれます。

Facebook、trip advisorなどの企業がGildのサービスを利用しています。

glid.com

 

6、Entelo

Enteloはサンフランシスコの企業で、人事担当者がエンジニアとデザイナーをWEB上から検索できるサービスを提供しています。

サービスの仕組みはGlidと似たようなもので、それにデザイナーの採用がプラスされたものです。

応募があった候補者のデータを簡単に管理・分析できるインバウンド向けのEntelo Stackと、自ら検索して候補者を探すアウトバウンド向けのEntelo Searchがあります。

Entelo Stackは、応募があった数多くの候補者のレジュメに対して、あらかじめ設けた基準と照合し、最良の候補者が優先的にリストアップできるサービスを提供しています。
人事担当者が自社にマッチした候補者を優先順に目を通せるため、選考プロセスや選考スピードの効率化につながります。

Entelo Searchは、膨大なデータベースから、ニーズにあった候補者を検索することが可能なサービスです。

候補者の転職検討タイミングの推測、ビジネススキル・人種・軍隊経験までわかる多様な検索軸、優秀な候補者のレコメンドなど多彩な機能があります。

Microsoft、Znefits、Facebookなどの企業がサービスを利用しています。

www.entelo.com

 

7、Talent Base

日本がリリースしているサービスになります。

お気に入りの人材をプールし一括管理することができます。また、作成した人材プールや行動履歴を解析して、各社に最適な人材を自動で発掘してくれます。

企業別にソーシャルでの影響度をランキングしたり、ゲームをすると勝手に友達を評価する「評価ゲーム」など、面白い独自コンテンツが入っています。

talentbase.io

 

 

<社員のエンゲージメントを数値化して評価してくれるサービス>

8、IBM Kenexa

「どんな特徴が社員の生産性にどう影響を与えるのか?」という曖昧なテーマに対し “既に学習済みのデータベース” を用いて、導き出された仮説に対して、即時「こうしたらいいのでは?」という提案までくれます。 

主に行われることは3つ

  • 設問ライブラリから5問程度を選択。オンラインで意識調査を実施。
  • 得られた回答を解析。WatsonAnalyticsの持つビックデータを活かし仮説を構築。
  • 数値をグラフィカルに明示しつつ、具体的な改善方法や対応策を提案。

世界の優良企業をランキングするフォーチュン・グローバルのTOP10企業の内8社までもが導入する、とても有名なツールとなっています。

www-01.ibm.com

 

9、HRMOS

日本の会社であるビズリーチが提供するサービスです。

できることは3つ。

  • 社員の成果、成果に対する上長コメントなどの言語解析。
  • 出退勤データや経歴データのディープラーニング。
  • 上記をベースとした『その企業が伸びるために採用するべき人材像』の明確な見える化。

IBM Kenexaに比べて、その会社の雰囲気を明確化するというところまで踏み込んでいるのがユニークな点です。

hrmos.co

 

10、Fronteo Kibit

こちらは上記二つとは趣旨が違い、”離職を防ぐ”を目的として作られたサービスです。

Fronteoは日本の会社で、AI業界ではなかなか有名な会社です。

従業員のメールをチェックして、

「離職しそうな可能性がある。」

「正当な評価を受けていないことをストレスに感じている可能性がある。」

「特定のリーダーからパワハラを受けている可能性がある。」

といったことをアラートで通知してくれます。

Watsonよりも安価で実装でき、過去にはわずか5件の教師データのみでユーザーボイスの感情判別を98%超の正答率で処理した実績もあるというAIです。

www.fronteo.com

 

・まとめ

最近のHRの流行はAI×ソーシャルデータという、技能をさらに詳しくみるだけでなくだけでなく、個人の特性や感情まで組み込んだ人事に移ってきているということが読み取れましたね。

 

参照

http://studyhacker.net/vocabulary/hr-tech

https://www.ibm.com/think/jp-ja/watson/cognitive-staffing/

https://www.hrpro.co.jp/agora/4272

https://bita.jp/dml/ai_hr

 

日本語版最速!? jupyter notebookをgoogleが神改造 colaboratoryについてまとめてみた。

こんにちは、たくやです。

最近すっかりニュース担当として定着してしまいましたね。

今回はgoogle が公開した教育と研究のための研究ツールである Colaboratory について解説していきたいと思います。

ざっと検索してみたところ英語版でしかまだ記事が出ていないようでしたので、日本語版最速と題させていただきました。

 

目次

・ニュース概要

・そもそもJupyter notebookとは

・Colaboratoryを使うメリット、デメリット

・実際に申し込みをしてコードを動かしてみた。

・おまけ Colaboratoryの気になるFAQ 

                                      

・ニュース概要

  • ColaboratoryはJupyter notebookを基盤としたオープンソースプロジェクト。
  • 現在、ColaboratoryはChromeのデスクトップ版でのみ動作する。
  • 優れたユーザーエクスペリエンスを提供するために、当初はノートブックの作成や編集へのアクセスを制限している。そのため、利用するには申し込みをしなくてはいけない。
  • ColaboratoryノートブックはすべてGoogleドライブに保存される。
  • 既存のJupyter / IPythonノートブックをColaboratoryにインポートできる。
  •  Colabは長年にわたりgoogle内部で使われるツールであったため依然として内部で使用されるPython 2.7のみをサポートしている。しかし、今後、Python3やRなどにも対応させていきたいとgoogleは考えている。
  •  Colaboratoryを使用すると、Jupiterのノートブックを他の人と共有し、ブラウザ以外のコンピュータでダウンロード、インストール、または実行することなく、共有することができる。
  • Portable Native Client(PNaCl)を使用しているため、安全に共同研究室はネイティブスピードで動作する。よって、新規ユーザーはjupyter notebookを以前より速く使用できるようになる。

PNaClとは

ウェブブラウザ上のウェブアプリケーションをネイティブアプリケーション(端末内の演算装置が直接に演算処理を行うタイプのアプリ)に近い速度で実行することなどを主な目標とした、機械語で書かれたコードを安全に実行できるシステムのこと。

 

                                      

・そもそもJupyter notebookとは

ブラウザ上で使えるプログラム実行環境です。ノートブックと呼ばれるドキュメントを作成し、プログラムの記述と実行、メモの作成、保存と共有などをブラウザ上で行うことができます。

以下Jupyter notebookのどこが魅力を箇条書きで書きます。

  1. Jupyter notebookの最大の特徴は”セル”と呼ばれる単位でコードを書いていける。複雑で冗長なコードも分割して実行することが可能。
  2. コードの実行が簡単。shit+Enter で簡単にコードが実行できる。
  3. 各言語のライブラリを使うことで出力結果を様々な形で表現することができる。例えばPandas というライブラリを使えば表の状態で結果を出力できる。
  4. 「保存・共有・再現」の利便性からデータ分析と非常に相性が良い。 

 

Jupyter notebookのインターフェイス

f:id:meteoputi:20171110004553p:plain

 

Colaboratoryのインターフェイス

f:id:meteoputi:20171110003310p:plain

実際に二つを見比べてみても、とても似ていることがわかると思います。

Colaboratoryのほうが、ちょっとオシャレな感じがしますね。

 

                                      

・Colaboratoryを使うメリット、デメリット

最後に、冒頭で述べたニュース概要から、ColaboratoryがJupyter notebookに比べて、どこが改良されたのかを簡単にまとめます。

  • 実行が早い
  • 異なるスキルセットを持つ人同士での”コラボレーション”が同じツール上で可能となる。
  • ノートブックを複数人で同時に編集することができる。
  • jupyter notebookとよく似ているが、jupyterのようにセットアップが必要ない。

Colaboratoryという名の通り、従来のJupyter notebookに比べて、共有能力が強化されているようです。

しかし、逆にデメリットも存在します。

  • 現状ではPython2.7 にしか対応していない。
  • 最新すぎて公開されている情報が少なすぎるため、困った際に検索しても解決策が出てきにくい。
  • 現段階では申し込みをする必要があり、即時使用はできない。

 

これからデータ分析、AI関係などで開発をする人にとってはとても心強いツールになりそうですね。

早く多言語に対応してくれるのを待つばかりです。

 

                                      

・実際に申し込みをしてコードを動かしてみた。

f:id:meteoputi:20171110044731p:plain

どうやらnumpy は入っているようでしっかり動きました。

 

f:id:meteoputi:20171113194828p:plain

乱数もしっかり発生させることができました。

 

 

f:id:meteoputi:20171113195531p:plain

また、pandasもしっかり使えるようです。

 

f:id:meteoputi:20171110044812p:plain

しかし、kerasは入っていないようです。
(!pip install keras と書いてインストールすることによって動くようです。)

 

f:id:meteoputi:20171110044755p:plain

少し見にくいですがエクセルの読み込みもうまくいきませんでした。

(こちらも!pip install xlrd と書くことによって正常に動くそうです。)

コメントくださった方、ありがとうございました。

 

最後に実際にcolaboratoryを使うと処理が早くなるのかを検証してみます。

・jupyter notebook の結果

f:id:meteoputi:20171110044844p:plain

 

・colaboratory の結果

f:id:meteoputi:20171110044835p:plain

残念ながら、colaboratoryの方が手元のjupyter notebookよりも倍以上時間がかかるという結果になってしまいました。

手元のPCは特段データ解析/ゲーム用に特化していない普通のノートPCなので、うーん。。。という感じですね。

まだまだ、ツールとしては不完全な上に、理論通りにはうまく動いていないのかもしれません。

実際に便利なツールとなるにはもう少し時間がかかりそうです。

                                      

・おまけ Colaboratoryの気になるFAQ

Q. コラボレーションノートを検索するにはどうしたらいいですか?
A. ドライブの検索ボックスを使用します。ノートブックビューの左上にあるColaboratoryロゴをクリックすると、ドライブ内のすべてのノートブックが表示されます。また、最近開いたノートブックを[ファイル] - > [最近開いたもの]を使って検索することもできます。

 

Q. 私のコードはどこで実行されますか?ブラウザのウィンドウを閉じると、実行状態はどうなりますか?
A. コードはあなたのアカウント専用の仮想マシンで実行されます。仮想マシンは、しばらくの間アイドル状態になるとリサイクルされ、システムによって最大限の有効期間が強制されます。

 

Q. データを取り出すにはどうすればよいですか?
A. これらの手順やColaboratoryのファイルメニューからGoogleドライブから作成したColaboratoryノートブックをダウンロードできます。 Colaboratoryノートブックはすべて、オープンソースJupyterノートブック形式(.ipynb)で保存されています。

 

https://research.google.com/colaboratory/faq.htmlk

から引用させてもらいました。

 

参照

https://research.google.com/colaboratory/faq.html

https://deepage.net/machine_learning/2016/12/13/jupyter_notebook.html

Deep Learning を使って背景イラストを生成した話

お疲れ様です.まっくす @minux302 と申します.

話が長いのでまずはブツを見せます.キャラクターに馴染むような背景イラストを Deep Learning の技術を使って生成していきます.ちょっと長いですがお付き合いいただければ幸いです.

 

f:id:minux302:20171110123021j:plain

秘められた力で背景写真を自分に馴染むように変換したと勘違いしている女の子のイラスト

 

1 背景と提案

1.1 背景

絵,描けるようになりたいですよね.

背景画,憧れますよね.

よく絵描きの方々が描く,アンニュイな表情した女の子が廃墟や浜辺に佇んでるやつ,描けるようになりたいですよね.

  

.......

 

描けないですよね....

 

 

趣味でちょこちょこキャラ絵とか描いたりするんですが背景画は全然描きません (描けません).

背景画を描く際には,キャラとはまた違った知識や技法とかが必要になってきます (多分).あと大変です.めっぽう大変です.

もうね,描く量が多い.そしてある程度はパースなりなんなりを意識して描かないと変な感じになっちゃう.

そんな僕でもやっぱりキャラに背景画を付け加えたい時があります.そういう時は写真を使います.もうすでにブツは描いてあるし,パースも完璧.最高.

案外写真でも,加工してうまいこと使えばかなりキャライラストに映えます.フォトショやクリスタでガシガシうまいことやれば,かなりいい感じになる(らしい).完璧じゃん.

blog.nest-online.jp

 

1.2 問題点

でもやっぱり加工した写真の中にキャラクターを立たせても浮いてしまうんですよね.技術不足などもあるでしょうが以下の点あたりが自分は気になります.

  • 色合い
  • 質感

そのままバンとキャラをのせても,彩度とか色相とか全然違ったりして浮いちゃいますよね.

もう一つは質感(や描き込み量).写真は本当に細かいところまで描いてあるし,色の塗り方(?)も全然違う.絵描きの方はキャラを描いてるのと似たような筆で,似たような塗り方で背景画を描いたりしているので,いい感じにキャラが浮かず馴染んでいるように思います .

 

1.3 提案

そこで,加工した背景写真からキャラが浮いちゃう問題を Deep Learning ってやつでなんとかしたいと思います.今回は 画風変換 の技術を使いました.一時期話題になったので皆さんも多分ご存知だと思います.ゴッホの絵のスタイルを写真に反映させました!って画像をよく見ましたよね. 

 

f:id:minux302:20171110094342p:plain

本家の人たちのHPから引用した図(https://deepart.io/).1の背景写真に2のゴッホのスタイル反映させ3を生成している

 

 今回のブログは,この画風変換の技術を使って,自分が描いたキャラクターの塗りのスタイルを写真に反映させて,キャラクターに馴染んだ背景写真を生成しよう!と言うお話です.

上図のゴッホの場合のように,キャラの質感を風景写真に反映させたらキャラが浮かないような背景画像が生成されるのでわ?という目論見です.

画風変換については以下のページがとてもわかりやすくまとめられています.

画風を変換するアルゴリズム

Neural Style Transfer: Prismaの背景技術を解説する

 


2 画風変換について

2.1 画風変換の流れ

画風変換の技術では,画像を"コンテンツ"と"スタイル"に分けて考えます.コンテンツとは,物体を物体として認識するための情報,つまり輪郭などのことです.スタイルはテクスチャなど,質感のことです.以下,画風を変換させたい画像をコンテンツ画像,反映させたいスタイルを持っている画像をスタイル画像とします.

画風変換は何をしているかというと,コンテンツ画像において,コンテンツを保ちながらスタイルを弱めて,スタイル画像のスタイルと入れ替えてしまおう,ということをしています. 

そうなってくると,

1. どのようにしてコンテンツを保ちながらスタイルを弱めるか

2. スタイルをどうやって獲得するか

ということが必要になってきます.

 

2.2 画風変換の大雑把な中身 

2.2.1 どのようにしてコンテンツを保ちながらスタイルを弱めるか

下図は画像認識に用いられる Deep Learning の中身です(VGGモデル).Deep っていうくらいなので深いです.深いってのは図のように層が何層にも重なってるという意味です.左から画像が入力され,だんだんと層を経て右側から値が出力されます.

このVGGモデルはもともと画像認識のタスクに使われていたモデルです.画像認識とは,猫の画像を入力した時に,それが猫の画像であると判定できるようなタスクです.

このモデルに画像を入力すると,物体を認識するのに必要な情報だけ抽出されるように画像が変換されていきます.物体を認識するのにどんな情報が必要かと言われれば,物体の輪郭などが考えられます.反対に質感などはあまり必要ありません. 

 

f:id:minux302:20171110101213p:plain

VGG モデル


このVGGモデルに画像を入力することにより,コンテンツを保ったままスタイルを弱めることができます. 

実際に画風変換の論文 A Neural Algorithm of Artistic Styleh から引用した図を下図に載せます.下方の家の写真では,実際にVGGモデルに画像を入力して,各層から得られる情報から画像を再構成しています.なんとなく深い層の部分では画像の質感等が失われて,輪郭だけが残るようになってるように見えませんか?.

 

f:id:minux302:20171110100236p:plain

VGGモデルの途中の層から得られる情報から画像を再構成

2.2.2 スタイルをどのように獲得するか

次にどのようにして画像のスタイル(質感)を獲得するのか,ということについて述べます.まず何かを獲得するには相手を見定めなければなりません.つまりどのようにスタイルを定義するか,ということです.

VGG の途中の層からは何枚かの画像データが取得できます.この論文では,それらの画像間での関係性(相関)によってスタイルを定義しています.詳しいことは数式を用いないの説明できないのですが,これを用いることによって画像の色,線の太さやテクスチャなどの情報が獲得できます.

この定義によって定められたスタイル情報を元に画像を再構成した結果が上図の上方の図です.各層からゴッホの絵のスタイルが再構成できているように見えますね.

 

2.2.3 どのように学習するか

次にどのように学習していくかという話をします.

Deep Learning では"損失関数"というものを定義して,それを最小化するような学習を行います.損失関数はどれだけ欲しいものが得られているかの指標となります.この値が小さいほど,欲しいものが獲得できていることになります.

今回は,生成された画像が

  • どれだけコンテンツ画像のコンテンツを持っているか (\mathcal{L_{contents}} とします)
  • どれだけスタイル画像のスタイルが反映されているか (\mathcal{L_{style}} とします)

ということが指標となります.生成された画像がコンテンツ画像と同じコンテンツであれば \mathcal{L_{contents}} = 0であり,コンテンツ画像からコンテンツが離れるほど \mathcal{L_{contents}} の値は大きくなります.\mathcal{L_{style}} についても同様のことが言えます.

指標が二つあるので和をとり以下のように損失関数 \mathcal{L_{total}} が定義されます.

\mathcal{L_{total}} = \alpha \mathcal{L_{contents}} +\beta \mathcal{L_{style}}

\alpha, \beta はどれだけコンテンツ,スタイルの差を損失関数に反映させるかを決める重みです.これらのパラメータは人間が決める必要があり,そのようなものをハイパーパラメータと言います.後々出てくるので覚えておいてください.

今回はこの \mathcal{L_{total}} が小さくなるような画像を生成するように学習が進んで行きます.VGGの重みは固定で,入力となる生成画像がどんどん更新されていきます.

 

以上が画風変換の大雑把な流れとなります.

 

3. 実験

3.1 環境

OS: Ubuntu 16.04, CP: Intel Icore 7, Memory: 16G, GPU: GForce 750Ti

今回は以下のリポジトリのものを使用しました.画風変換(Neural Style Transfer)をTensorflowで実装したものです.嬉しいことに --preserve-colors のオプションをつけることで元画像の色を保持できます.

github.com

 

3.2 とりあえず動かす

今回はコンテンツ画像として次の写真を使いました.香川に1人旅に行った時の夕焼けがとても綺麗だったので撮りました.

 

f:id:minux302:20171110110713j:plain

コンテンツ画像

まずは試しにゴッホの絵をスタイルとして画像を生成します.うん,いい感じで吐けてる.

 

f:id:minux302:20171110111011j:plain

ゴッホのスタイル画像を使った時の生成画像


次にいらすとやさんの背景画像をスタイルとして使ってみます.

 

f:id:minux302:20171110113632j:plain

スタイル画像(風景画)

以下が生成結果です.なるほど.ちょっと角ばった感じの質感になってますね.

f:id:minux302:20171110113748p:plain

いらすとやの風景画をスタイルとして使った場合の生成画像


次に,キャラ画像をそのままスタイルとして使います(野蛮).

 

f:id:minux302:20171110111135p:plain

スタイル画像(キャライラスト)

 

あいや,変になってしまった.やっぱりキャラ画像をそのまま使うのは野蛮だったか?

 

f:id:minux302:20171110114000p:plain

いらすとやのキャラ画像をスタイル画像として使った場合の生成画像


 

3.3 適切なハイパーパラメータを探す

Neural Style Transfer: Prismaの背景技術を解説する にも述べられていたんですが,用いる画像によって適した \alpha, \beta の値が異なるらしいです.諦める前にこの写真とキャライラストの組み合わせにあったハイパーパラメータを探索して行きます.

探索にはグリッドサーチという手法を用いました.あらかじめ \alpha, \beta ( この実装の場合は content_weight と style_weight)の値をいくつか決めておき,それらの組み合わせを全部試していくという手法です.

今回辛いのが定量評価ができないということ.損失関数の値が小さいからといって実際の画像がいい感じにスタイルが反映されたものにはなってないんですね.\mathcal{L_{contents}}\mathcal{L_{style}} の散布図などを書いたりしましたが,良い生成画像の傾向などはあまり見られませんでした.(強いて言うなれば\mathcal{L_{contents}}\mathcal{L_{style}} の比率が,値が小さい時に1:3くらい,値が大きい問いに3:1になってるくらいだったが,ここら辺はあまり詳しくは見ていません.)

色々試した結果,以下の場合が一番いい感じになってると思いました.

content_weight = 0.001, style_weight = 0.1 で500イテレーションで生成しています.実行コードに追加で --content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors のオプションを付け加えています.

キャラ画像のそのままの使用でも,塗りの感じとか割といらすとやっぽいものが反映されているように見えませんか??

 

f:id:minux302:20171110092636p:plain

content-weight = 0.001, style-weight = 0.1 500イテレーションで色を保持した場合に生成された画像

 

先ほどのキャラ画像と合わせて少しいじるとこんな感じ.まぁまぁなんでないでしょうか.

 

f:id:minux302:20171110123021j:plain

合わせた画像

 

4. 反省と今後の展望

今回は思いつきでとりあえず試してみるかという感じでやりましたが,やっぱり余白が結構あるキャラ画像を無理やり使うのは自分でもかなり野蛮だと思っています.キャラのスタイルをキャラに反映するならまだいいですが,キャラのスタイルを風景写真に反映させるのはちょっと無理があったように思います.スタイル画像もこの場合はたまたまいいものが生成できましたが,割とうまくいかない場合が多かったです.(下図のようにだいたい画像が壊れた感じになる).このスタイル画像としてのキャラ画像の扱いの仕方を工夫していきたいです.あと以下のように新しい画風変換の技術もあるのでそこらへんも試していきたいです.

 

f:id:minux302:20171110105643p:plain

うまくいかなかった例



 

github.com

 

 

5. まとめ

画風変換を使って,キャラのスタイル反映したような背景画像の生成を試みた.ハイパーパラメータおじさんになればなんとなくうまくいってるように見える場合もある.正直キャラ画像をそのままスタイル画像として風景写真のスタイル変更に使うのはあんまりよくなさそう.

 

良い所

GPUを持っていてパラメータチューニングを頑張れば,キャライラストに馴染みそうな背景画像が生成できる(かもしれない)(ちなみに500iteration 18枚生成とかで1.5hくらいかかった)

 

悪い所

背景画を描く練習をしないので,一生描けるようにならない.ネコと和解せよ.にゃーん.

 

 

おしまい

 

おまけ

いらすとやの風景画を

--content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors

で動かした時のもの.色が暗くなっていて見にくいですが,ビルの塗りの筆の感じなど,かなりいらすとやっぽいと個人的に思う.

 

f:id:minux302:20171110114541p:plain

 

自分が過去に描いたイラストで試した.

--content-weight 0.001 --style-weight 0.1 --iteration 500 --preserve-colors

で動かした.微妙.

 

f:id:minux302:20171110114932p:plain

 

6. 参考文献

https://deepart.io/

https://elix-tech.github.io/ja/2016/08/22/art.html

https://research.preferred.jp/2015/09/chainer-gogh/

https://arxiv.org/pdf/1409.1556.pdf

http://www.irasutoya.com/

 

 

【初心者】でもわかる、最近巷で有名な"AlphaGo Zero"の仕組み

こんにちは、たくやです。

今回はちょっと旬を逃してしまった感はありますが、とても話題となったAiphaGo Zeroの仕組みについてプログラミング初心者にもわかるような解説をしていきたいと思います。

 

・ニュース概要

  • AlphaGoが過去のAI囲碁ソフトと違うところは、人間のうち筋をデータとして与えなかったこと。
  • 自身が相互対戦することで最善手を学習する手法を3日間に500万回繰り返させることで棋力を向上させた。
  • AlphaGo Zeroはトップ棋士を打ち負かして驚かせた「AlphaGo」に対して100戦全勝、その改良版である「Alphago Master」にも100戦中89勝した。

 

natureのAlphaGo Zeroに関する論文である"Mastering the game of Go without human knowledge"(人間の知識なしに碁を制する。)

https://www.nature.com/articles/nature24270.epdf?author_access_token=VJXbVjaSHxFoctQQ4p2k4tRgN0jAjWel9jnR3ZoTv0PVW4gB86EEpGqTRDtpIz-2rmo8-KG06gqVobU5NSCFeHILHcVFUeMsbvwS-lxjqQGg98faovwjxeTUgZAUMnRQ

を簡単に噛み砕いて説明していきたいと思います。

複雑な数式や専門用語などはできるだけ取り扱いません。

 

まず、これほどまで圧倒的な強さを手に入れたAlphaGo Zeroが前のバージョンであるAlphaGo Lee12やAlphaGo Fanと異なる点をもう少し技術的な面から説明していきます。

あげられる点は以下の4点。

 

  1. 人間のデータを監督したり使用したりすることなく、ランダムプレイから始まる自己再生強化学習のみによって訓練される。
  2. 移動確率を出力するPolicy Networkと位置評価を出力するValue Networkを別々にするのではなく、単一のニューラルネットワークで使用する。(前バージョンではPolicy NetworkValue Networkという二つのディープニューラルネットワークを使用していた。)
  3. 迅速な改善と正確で安定した学習をさせるために、訓練ループ内にルックアヘッド検索を組み込んだ新しい強化学習アルゴリズムを導入した。
  4. モンテカルロ法のロールアウト(その盤面から全ての打ち方を試して、その結果どの打ち方がいいのかを判断する方法)をやめ、モンテカルロ木探索のみにした。(このことが使用するマシンパワーの圧倒的削減に貢献している。)

 

これらについて、解説していきます。

 

AlphaGoZeroが学習時に基本的にやっていることはモンテカルロ木探索です。

*モンテカルロ木探索とは

例えばAとBという場所のどちらに石を置くかを考えるとき、Aに石を置いたとき、Bに石を置いた時、それぞれ、その先対局を続けていった時に何パーセントの確率で勝てるのかを評価することでA,Bどちらに石を置くかを決定する手法です。

                              f:id:meteoputi:20171103124137p:plain


 

ただし、そのモンテカルロ木探索にディープニューラルネットワーク(DNN)を組み合わせてあります。

ディープニューラルネットワークがわからない方はこちらをお読みください。

今話題のディープラーニングって一体なんなの? 文系から見た人工知能

 

つまり、石の配置履歴を取り込んで、自己対戦により移動確率を出力するPolicy Networkを、モンテカルロ木探索を使用して求めた次に打たれる可能性のあるそれぞれの手に対する評価値(仮にそこに石を置いた場合の勝率の確率)に反映します。なぜ、最初から自己対戦による移動確率だけで次に打たれる手を考えないのかというと、モンテカルロ木探索を用いることで、より良い一手が発見される可能性があるからです。

それとほぼ同時に、自己対戦の終局図から勝敗を判定し、位置評価を出力するValue Networkの教師として反映します。

Policy(どこに石を置くか)← モンテカルロ探索木

Value(盤面の評価値)← 試合の勝敗

 

よって取り扱われるデータは、

・Policy(移動可能性)

・Value(位置評価)

・最後にわかるどちらが勝ったかというデータ 

の3つだけになります。

                     f:id:meteoputi:20171103123642p:plain

 

*モンテカルロ木探索を用いるのはあくまで学習時だけで、実際に対局する際はニューラルネットの出力のみで判断するので、本番での計算速度が向上しました。

 

さらに詳しくみていきましょう。

AlphaGo Zeroのモンテカルロ木探索は3つのステップに分けることができます。

(次にどこに石を置くかを決める段階なので、まだ実際に石は動かしていません。)

  1. 選択
  2. 拡張と評価
  3. バックアップ

1の ”選択” では一番最初の配置からある程度、ゲームを進めていった配置まで、評価値が高いところに石を置いていきます。

2の ”拡張と評価” では1の操作でゲームが終了しなかった場合、その最後の時の盤面をDNNにインプットして、その時点で勝てる確率と、その次の手の確率分布を計算します。(AlphaGo Zero ではモンテカルロ木探索で1600回のシミュレーションを行ったため、一手を考えるのに0.4秒かかりました。)

3の "バックアップ " では2の最終盤面で得られた評価値の平均を元々の盤面に反映します。それの平均値が元々の盤面の新しい評価値となります。

 

1〜3のステップを通して導き出した最良の手を選択します。

 

しかし、ここで「教師となるデータもないのに、どのデータを元に学習をさせているんだ」という疑問が生まれると思います。

従来のAlphaGoではここに人間のプロ棋士のうち筋を用いていました。

しかし、AlphaGo Zeroでは自己対局を繰り返すことによってデータを作り出しているのです。

最初はもちろん、全てランダムで行うために、文字通り”ゼロ”からの成長になります。

 

今まで説明してきたことを図にしてまとめます。

f:id:meteoputi:20171103142800p:plain

 

最後にこのAlphaGo Zeroのすごさを端的に表している画像があるので紹介します。

f:id:meteoputi:20171103135436j:plain

上の画像は横軸に何日AlphaGo Zeroをトレーニングしたか。

縦軸に、強さを数値化したものを取っています。

3日トレーニングした時点でもう既に2016年元世界チャンピオンのイ・セドル氏を倒したAlphago Leeの強さのレベルに達していることわかります。

f:id:meteoputi:20171103140107p:plain

しかも消費するマシンパワーはAlphaGo LeeやAlphaGo Fanに比べて圧倒的に低いことがこの図からもわかります。

 

人類はこれまで4千年もの時をかけて、数百万の碁の試合をし、それをパターンとして色々な本にまとめてきました。しかし、AlphaGo Zeroはそのほとんどの知識を発見し、それに加え斬新な戦略までも見つけ出しました。

中には、将来、AIが人間よりも優れた発明能力を身につけてしまうのではないかと恐れる方もいるかもしれません。しかし、局面が変わるに従って変化する戦略をどのように数値化し、反映させるのかプログラムするのは、あくまで人間なのです。このAIの圧倒的な自己学習能力を人間がうまく使うことで、人間の能力を拡張させるツールとして使うこともできるのです。

 

参照

http://toyokeizai.net/articles/-/194179

http://blog.livedoor.jp/yuno_miyako/archives/1068350228.html

https://www.slideshare.net/suckgeunlee/alphago-zero

超♪人♪気♪リズムゲーム『デレステ』『ミリシタ』『バンドリ』を自動化してみたよ♪♪

f:id:namahoge:20171029130717g:plain

(↑教師データ。あと、自動化したのはゲームの認識部分です)

はじめまして。なま @namahoge です。

人工知能の勉強をはじめて半年ほどのひよっこです 🐣

Aidemyの研修の一貫でブログを書くことになったので、とりあえず、最近勉強したばかりの簡単な人工知能を使ってリズムゲームの認識部分を自動化してみました。Pythonを使います。

(ね、念のために言っておきますが、自動ロボットを作って学校行ってる間もプレイしてもらおうとか、イベントでランキングTop100に入りたいだとか、そっ、そんなやましい考えは全然一切これっぽっちもありませんよっ!)



どんなシチュエーション?

ロボットが主人(?)の端末を借りて、ゲームの内容をカメラで認識し勝手にプレイする様子をイメージしています。

なので今回は、端末の内部にアクセスしたりはせず、カメラを使って外部からゲーム画面を取得します。

音符を探せばいいんでしょ?簡単じゃん?? と思われるかもしれませんが(いやごもっともではありますが)、それが地味に難しいんです。バンドリのキャプチャ画像がそれをよく示していたので↓

f:id:namahoge:20171029224815p:plain

f:id:namahoge:20171029224957p:plain

このように音符がまるで影分身しているように見えたり、エフェクトで音符が隠れたり、長押しの部分が背景に同化していたり、、、という感じです。

ごりごりの画像処理で自動化しようとすると、ノイズや背景、エフェクトに対して処理を行ったり、各色の音符について代表的な音符の画像を用意したり、様々なことをしなければなりません。

ところが、最近はやりの人工知能を使うと、教師データさえ用意すれば難しいことは考えなくても勝手に自動化できるそうではありませんか......!(茶番)

しかも人工知能による自動化プログラムは汎用的で、いろいろなリズムゲームがあっという間に自動化できる、ということらしいです(恐らく)。

ということで今回は人工知能と呼ばれるプログラムを書いて自動化にチャレンジしていくことにしました。

どんな人工知能使うの?

今回はCNNと言う人工知能(より正確には深層学習手法)を使い、学習器を作りました。

CNNを超噛み砕いて素人なりにがんばって説明してみます。。

例えば、あるポスターを渡されて、CNNがそれをリゼロのポスターだと判定する流れはこんな感じです。

与えられた画像(エミリア(銀髪)、レム(青髪)、ラム(桃髪)、スバル(黒髪)を並べた画像)

f:id:namahoge:20171030021836p:plain

  1. Convolution
    与えられた画像に対し、端から、エミリアっぽさ、レムっぽさ、ラムっぽさ、スバルっぽさをスコアリングする。この作業を Convolution という。この作業によって、画像から部分領域ごとに注目すべき特徴量を抽出できる。↓はスバルっぽさを調べているところのイメージ。 f:id:namahoge:20171030031106p:plain
    Convolution の結果データ(紫がエミリア、青がレム、赤がラム、黒がスバル)
    f:id:namahoge:20171030142339p:plain
    ○で囲ったデータが示すように、それぞれのキャラクターがいる場所にしっかり反応しています。
  2. Pooling
    データをいくつかに分割し、それぞれのブロック内で、それぞれの特徴量の最大値を抽出する。この作業を Pooling という。この作業によって、興味のないデータを捨ててデータを圧縮する。
    f:id:namahoge:20171030033851p:plain
    Pooling の結果データ
    f:id:namahoge:20171030031855p:plain

  3. Dense
    Poolingの結果残ったデータから、総合的に真偽を判断する。 今回は、上のデータから画像の中にまんべんなくリゼロのキャラクターがいることがわかるので、 与えられた画像はリゼロのポスターであると判断を下す。

このようにCNNを使うと、画像の中の特徴量をある程度の位置情報を残しながら高い情報量密度で抽出できます。

実際にCNNを使う際には、キャラクターの顔を探せばいいことや、リゼロのキャラクターはどんな顔なのか、またPooling結果からどう総合判断するか、などは最初は学習器はわかりませんが、これらは学習器が誤差逆伝播法(という数学チックな手法)などで勝手に学習してくれます。

今回はわかりやすさのためにCNNがいきなり顔っぽいものを探す様子を書きましたが、実際に使われるCNNの多くは、初めに与えられた画像から「直線」や「角」といった低次元の特徴量を探しだし、その特徴量の分布から「輪郭」や「凹凸」といった少し高次元の特徴量を抽出、最後に「顔」を認識する、という感じでもう少し長い過程を必要とします。

今回抽出したいのは流れてくる音符(?)という比較的低次元の概念のものなので、単純な学習器で良いと考え、Convolution、Poolingはともに1回だけの簡単な学習器を作りました。

準備

まずはデレステの自動化に挑戦していきますっ!

import cv2
import numpy as np

映像データを作る

ゲームの映像の取得はウェブカメラでできます。以下のサンプルを適当に使ってください。

ウェブカメラを使う

cap = cv2.VideoCapture(0)
while(True):
    ret, frame = cap.read()
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) == 27:
        break
cap.release()
cv2.destroyAllWindows()

動画を撮影

def record():

 movie = []
 cap = cv2.VideoCapture(0)

 for i in range(1000):
     ret, frame = cap.read()
     movie.append(frame)
     cv2.imshow('frame', frame)
     if cv2.waitKey(1) == 27:
         break

 cap.release()
 cv2.destroyAllWindows()
 return np.array(movie)

動画を保存

def save(movie, name):
    # nameには 'hoge.mp4' などを渡す

    result = name
    fps    = 30.0
    height = movie.shape[1]
    width  = movie.shape[2]
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
    out = cv2.VideoWriter(result, int(fourcc), fps, (int(width), int(height)))

    for i in range(movie.shape[0]):
        out.write(movie[i])
    out.release()

動画の読み込み

def read(name):
    # nameには 'hoge.mp4' などを渡す
    
    movie = []
    cap = cv2.VideoCapture(name)

    for i in range(1000):
        ret, frame = cap.read()
        frame = cv2.resize(frame, (160, 120))
        movie.append(frame)
        cv2.imshow('frame', frame)
        if cv2.waitKey(1) == 27:
            break

    cap.release()
    cv2.destroyAllWindows()

    return np.array(movie)

動画を numpy.ndarray 形式でそのまま保存、読み込み

np.save('hoge.npy', movie)
movie = np.load('hoge.npy')

最後に

np.save('deresute_X', movie)

教師データを作る

どんなふうに教師データを作ってもいいのですが、映像を1フレームずつ見ながらデータを入力していきたかったので、↓のコードを書きました。 デレステの教師データは、各フレームに対し、5つのボタン、その間の4箇所、どこもタップしない、の計10種類のラベルに分類したものとしました。 リズムゲームは同時に複数箇所タップしないといけなかったりするので、一つのフレームに正解ラベルがいくつもある、ということが起こりますが問題ありません。

movie = read('hoge.mp4')

num_train = 100 #何フレームに教師ラベルをつけるか
t0 = 25 #何フレーム目から教師ラベルをつけるか
labels = []

for t in range(t0, t0+num_train):
    cv2.imshow('frame', movie[t])
    cv2.waitKey(100)
    while True:
        label = np.array([int(y) for y in (input("%d > "%t)).split()])
        #配列の大きさを整えるため、各フレームに与えるラベルの数を決めておく。
        if label.shape[0] == 4: break 
    labels.append(label)
    cv2.waitKey(100)
cv2.destroyAllWindows()
labels = np.array(labels)

#0-1のデータに変換する
n = 10 #デレステの場合 n=10、ミリシタの場合 n=12、バンドリの場合 n=14
labels = [np.sum(np.eye(n)[label], axis=0) for label in labels]
labels = np.array(labels)
labels = np.where(labels > 1, 1, labels)

最後に

np.save('deresute_T_25-124.npy',labels)

データ作成の様子

f:id:namahoge:20171030124138p:plain

出来上がった教師データ

f:id:namahoge:20171030124741p:plain

学習

今回は、3フレーム分未来のタップ位置を予測する学習器を作りました。

import tensorflow as tf
from sklearn.utils import shuffle

# 乱数のシード値の設定
rng = np.random.RandomState(2525)
random_state = 39

X_data = np.load('deresute/deresute_X.npy')
Y_data = np.load('deresute/deresute_T_25-124.npy')
print(X_data.shape, Y_data.shape) # -> (1000, 120, 160, 3) (100, 10)

train_X = ((X_data[22:122] -X_data.mean())/X_data.std())
train_Y = Y_data # <- 120:220 # 3フレーム分未来の予測をする

train_X には、規格化(平均を引いて標準偏差で割る)を施していますが、そうすることで学習速度が向上します。

まずはCNNに使われるいくつかの作業を記述したクラスを宣言します。

これらはどんなCNNプログラムにも使えるので一度他で使ったことのあるものを使いまわしています。

Conv

class Conv:
    def __init__(self, filter_shape, function=lambda x: x, strides=[1,1,1,1], padding='VALID'):
        # Xavier Initialization
        fan_in = np.prod(filter_shape[:3])
        fan_out = np.prod(filter_shape[:2]) * filter_shape[3]
        self.W = tf.Variable(rng.uniform(
                        low=-np.sqrt(6/(fan_in + fan_out)),
                        high=np.sqrt(6/(fan_in + fan_out)),
                        size=filter_shape
                    ).astype('float32'), name='W')
        self.b = tf.Variable(np.zeros((filter_shape[3]), dtype='float32'), name='b') # バイアスはフィルタごとなので, 出力フィルタ数と同じ次元数
        self.function = function
        self.strides = strides
        self.padding = padding

    def f_prop(self, x):
        u = tf.nn.conv2d(x, self.W, strides=self.strides, padding=self.padding) + self.b
        return self.function(u)

Pool

class Pooling:
    
    def __init__(self, ksize=[1,2,2,1], strides=[1,2,2,1], padding='VALID'):
        self.ksize = ksize
        self.strides = strides
        self.padding = padding
    
    def f_prop(self, x):
        return tf.nn.max_pool(x, ksize=self.ksize, strides=self.strides, padding=self.padding)

Flatten

class Flatten:
    def f_prop(self, x):
        return tf.reshape(x, (-1, np.prod(x.get_shape().as_list()[1:])))

Dense

class Dense:
    def __init__(self, in_dim, out_dim, function=lambda x: x):
        # Xavier Initialization
        self.W = tf.Variable(rng.uniform(
                        low=-np.sqrt(6/(in_dim + out_dim)),
                        high=np.sqrt(6/(in_dim + out_dim)),
                        size=(in_dim, out_dim)
                    ).astype('float32'), name='W')
        self.b = tf.Variable(np.zeros([out_dim]).astype('float32'))
        self.function = function

    def f_prop(self, x):
        return self.function(tf.matmul(x, self.W) + self.b)

こっそり Flatten なるものを追加しましたが、これは Pooling で得られたデータを一次元配列に変換するだけの作業です。

ネットワークの構築

layers = [
    Conv(filter_shape=[28,28,3,5], function=tf.nn.relu, strides=[1,4,4,1]), # 120x160x3 -> 34x24x5
    Pooling(ksize=[1,2,2,1], strides=[1,2,2,1]), # 34x24x5 -> 17x12x5
    Flatten(),
    Dense(17*12*5, Y_data.shape[1])
]

x = tf.placeholder(tf.float32, [None, 120, 160, 3])
t = tf.placeholder(tf.float32, [None, Y_data.shape[1]])

def f_props(layers, x):
    for layer in layers:
        x = layer.f_prop(x)
    return x

y = f_props(layers, x)

cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=t))
train = tf.train.GradientDescentOptimizer(0.02).minimize(cost)

valid = tf.cast(tf.rint(tf.sigmoid(y)),dtype=tf.int32)

学習

n_epochs = 100
batch_size = 10
n_batches = train_X.shape[0]//batch_size

init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for epoch in range(n_epochs):
    train_X, train_Y = shuffle(train_X, train_Y, random_state=random_state)
    for i in range(n_batches):
        start = i * batch_size
        end = start + batch_size
        sess.run(train, feed_dict={x: train_X[start:end], t: train_Y[start:end]})
    pred_Y, valid_cost = sess.run([valid, cost], feed_dict={x: train_X, t: train_Y})
    _W = sess.run(layers[0].W)
    _W = ((_W - _W.min()) * 255 / _W.max()).astype(np.uint8)
    cv2.imshow('w1', _W[:,:,:,0])
    cv2.waitKey(50)
    if epoch%10 == 0:
        score = np.sum(np.abs(pred_Y - train_Y.astype(np.int32)))
        print(score, end=' ')
        print('EPOCH:: %i, Validation cost: %.3f' % (epoch + 1, valid_cost))

学習の様子

f:id:namahoge:20171030131724p:plain

結果(まぁまぁうまくいったよっ)

教師データがない部分も含めて予測を行います。

一度に大きいtestデータを作るとパソコンのメモリがパンクするので、いくつかに分割します。

for i in range(10):
    test_X = ((X_data[100*i:100*(i+1)] - X_data.mean())/X_data.std())
    pred = sess.run(valid, feed_dict={x: test_X})
    np.save('deresute_pred' + str(i) + '.npy', pred)

pred = np.zeros([0,Y_data.shape[1]], dtype=np.int32)
for i in range(10):
    pred = np.append(pred, np.load('deresute_pred' + str(i) + '.npy'), axis=0)
print(pred.shape) # -> (1000, 10)

学習結果の視覚化

def overlay_(x, y, points):
    img = x.copy()
    for k in range(1,y.shape[0]):
        if y[k] == 1:
            cv2.circle(img, (points[k-1,1], points[k-1,0]), 20, (255,0,0), 3)
    return img

def overlay(X, Y, points):
    imgs = []
    for t in range(X.shape[0]):
        img = overlay_(X[t], Y[t], points)
        imgs.append(img)
    imgs = np.array(imgs)
    return imgs

bandori_points = np.zeros((13,2)).astype(np.uint16)
bandori_points[:,0] = 210
bandori_points[:,1] = np.arange(22, 297, 320/14)
deresute_points = np.zeros((9,2)).astype(np.uint16)
deresute_points[:,0] = 184
deresute_points[:,1] = np.arange(42, 281, 238/8)
mirisita_points = np.zeros((11,2)).astype(np.uint16)
mirisita_points[:,0] = 184
mirisita_points[:,1] = np.arange(42, 281, 238/10)
mov1 = overlay(movie[3:1000],pred[0:997], mirisita_points)

こんな感じになりました↓

 (冒頭の約6秒を教師データとして使いました。)

youtu.be

場所によって正解率が悪かったり長押しの精度が微妙だったりはしますが、だいたいの音符に一応反応できている感じはするかなというレベルでした。

ただ、今回はたった6秒分しか教師データを用意していなくてここまでできたので、十分な長さ(3曲分とか?)の教師データを作れば、全ての曲でフルコンボがとれるようになるのではないのかなぁと思っています。。

ここからが本題

さて、人工知能(今回は深層学習手法)のスゴイところはその汎用性という話だったので、他のリズムゲームでもやってみましたっ

ミリシタの教師データ

youtu.be

ミリシタの全予測

youtu.be

バンドリの教師データ

youtu.be

バンドリの全予測

youtu.be

ちょっと微妙な感じではありますが、学習したんだなというのは伝わってきます(よね)。十分な数の教師データがあればどのゲームでも自動化できそうです。

最後に

CNNを使えば簡単に自動化ができそうだということがわかってもらえたと思います、が、一応注意書きしておくとゲームの完全な自動化は恐らく全てのゲームで利用規約に反してしまいます。。。

例えばバンドリの利用規約には

第6条(禁止事項)
(19)(中略)BOT、チートツール、その他技術的手段を利用してサービスを不正に操作する行為
(26)その他当社が不適切だと判断する行為

とあるので、ゲーム操作まで自動化してはいけませんよ〜(“真面目に”頑張ってる他のプレーヤーにとってもあまりよくないですしね、たぶん(?)。(自分に言い聞かせてる))


github リポジトリ載せときます!

いろいろデータを入れてあるので、jupyterでエンター連打するだけで実行できます♪

深層学習や予測データの可視化までできるようにしてありますっっ

github.com


最後まで読んでくださってありがとうございましたっっ!!

(精一杯小声で…面白かったらいいねくださいっ♪)

参考1:リゼロの画像
https://pbs.twimg.com/media/Cik8sVYUgAIgO00.jpg

アイデミーでIoT×AIハッカソン開催。3名の審査員の投資予算の配分は...!? 

こんにちは!Aidemyでインターンをしている、なかむーと申します。
巨大化した台風が刻々と迫る10/22(日)。そんな荒れ狂う天気の中、
我が社では活気よくIoT×AIハッカソンを開催しました!

f:id:nakamura_t_21:20171022233119p:plain

どんな感じで開催したの?

以下の概要で開催いたしました!

  • 開催期間は一日(10:00~18:00)
  • 参加人数は11人(3チーム)
  • チームはランダム編成
  • ラズパイと各種センサ、機械学習手法を用いる
  • テーマは自由
  • 審査員の方(3名)はそれぞれ仮に10億円の投資予算を配分するとしたらどうするかを審査

審査員紹介

審査員として三名の方にお越しいただきました!

  • 株式会社クラウドワークス 取締役COOの成田さん
  • 株式会社東京大学エッジキャピタル(以下UTEC) 代表取締役社長の郷治さん
  • 元MERY創業者/エンジェル投資家 の中川さん

f:id:nakamura_t_21:20171027084832p:plain

流れ

  1. 各チームでアイデア練り
  2. ひたすらひたすら実装
  3. 10分程のチームの成果発表
  4. 審査員からのレビュー

ラズパイと機械学習を使い何かを作るといったお題でしたが、どのチームも
生活で起きる問題点を解決するプロダクトを考えていました。
f:id:nakamura_t_21:20171022233918p:plainf:id:nakamura_t_21:20171022233922p:plain

どんなものを考えたの?

(1)通知を読み上げるシステム

携帯の画面に現れる通知は、いちいち携帯の画面を開き確認するのは面倒ですよね?こちらの班は、その通知を音声で読み上げてくれるシステムを考案・制作しました。イヤホンをつけていない状態では、通知は通常通りですが、イヤホンをつけている状態では、通知の内容を読み上げてくれるシステムです。読み上げシステムにwavenetのような機械学習式音声生成システムを考えていました。
f:id:nakamura_t_21:20171027083143p:plain

(2)正しいゴミ分別をさせるゴミ箱

社内の燃えるゴミのゴミ箱に、ペットボトルが捨てられていることがあることから、間違ったごみ捨てがされた場合、それを検知し、捨てた人を注意するゴミ箱を計画、制作しました。あらかじめゴミ箱の中の画像を取得しておき、捨てた後の画像と差分をとり、ゴミを検出します。YOLOやSSDでゴミ付近の領域を検出し、ゴミを切り出します。その画像をVGG16を転移学習させたモデルで、捨てられたものが適切か認識し、正しい分別でなければゴミ箱が怒るといった流れです!

f:id:nakamura_t_21:20171023000617p:plain

(3)社内の飲料水を自動補充してくれるツール

我が社にはクリスタルガイザーが常備されています。ですが、減ってきたら誰かが注文しなければなりません。そこで、クリスタルガイザーの貯蓄の様子をカメラで撮影し、ある程度減ってきたのをCNNで検知し、自動でアマゾンで注文してくれるツールになります!水のペットボトルの検知アルゴリズムは、時間の制約上、学習済みモデルであるVGG16の「waterbottle」を利用したようです。
f:id:nakamura_t_21:20171023002214p:plain
f:id:nakamura_t_21:20171023002324p:plain

各審査員の評価は??

各審査員に10億円(仮)の投資予算を配分をしていただきました! 結果は以下の通りになりました。

審査員 1班 2班 3班 審査員コメント
成田さん 1 5 4 確かにゴミ箱の分別がキチンとされていないケースが多く、着目した課題に共感できた。
中川さん 0 3 7 ハッカソンという短い間で、カメラ認識から自動補充スクリプトまで作り上げたのは素晴らしい。
郷治さん 5 1.5 3.5 「音声」というテーマはホットで、今後伸びていく市場。引き続き注目したい。
累計資金調達額 6 9.5 14.5 ---

優勝は、14.5億円(仮)を資金調達した3班となりました!
短い間で完成度の高いプロダクトを作成できたことが大きな理由だったようです。

まとめ

様々なトラブルがあり少ない時間でのハッカソンとなりましたが、満足のいくハッカソンだったように思います。
自分も普段の業務から離れ、一から開発をすることにより良いリフレッシュになりました。

次回は、「FPGA×ML」テーマなどでハッカソンをやってみる予定です。
Aidemyでは社内で豊富な勉強会やイベントを開催していきます。

なお、Aidemyではフルタイムコミット正社員/インターン生や、ハーフコミット副業エンジニア/インターン生といった形態で、フロントエンドエンジニア(React)、バックエンドエンジニア(Node.js)、インフラエンジニア(Azure)、機械学習エンジニア、デザイナーを募集しています。

興味のある方は、代表の石川まで、TwitterでDMください!

twitter.com

説明できますか?CPUとGPUの違い

こんにちは。たくやです。

今週はリクエストがありました、GPUとCPUの違いについて説明したいと思います。

目次

GPUとCPUの違い

GPUの起源とディープラーニングのボトルネック

現在、世界一強力なクラウドで使えるGPUインスタンスの性能

おまけ 浮動小数点演算とは

 

                                  

GPUとCPUの違い

GPUとCPUの違いはなんなのか。

みなさんは答えることができますか?

 

 

 

 

 

答え合わせです。

GPUもCPUも本質的には計算をするという点で同じです。

ただ、GPUとCPUはその構造が全く違っているのです。

GPUはCPUよりもはるかに多くのコアを搭載しており、コアの数は同時に対応できる

処理の多さを表しています。

GPUは同じ処理を同時に複数のコアに投げることができるのです。

一方でCPUは一つ一つの処理を一つずつ行うような作業に強いです。

このGPUとCPUの違いを視覚的、感覚的に理解できる有名な動画が存在するので載せておきます。

www.youtube.com

この動画は前者のスプレーガンをCPU、後者のスプレーガンをGPUに見立てています。

前者のスプレーガンが一つ一つ、丁寧に処理をするのに対し、後者のスプレーガンを一気に同じ処理を並列して行います。

 

もう少し詳しく具体的な例をあげて説明したいと思います。

Xeon E5-2680 v2 CPUは10コアで、各コアでAVX2を使えば、単精度浮動小数点の積和演算を8個並列に実行でき、2演算(積と和)×8並列×8コア=128演算を実行できます。一方、NVIDIAのK20x GPUは2演算×192並列×14コア=5376演算を並列に実行できます。Xeon E5-2680 v2のクロックは2.8GHzであるのに対して、K20x GPUは0.732GHzであり、CPUの方が3.825倍のクロックであることを考慮しても、5376/(128×3.825倍クロック)=10.98で、ピーク演算性能でいうと、Kepler GPUの方が11倍以上速いということになります。

浮動小数点とは何かは下に解説があります↓

おまけ 浮動小数点演算とは

 

これだけでも違いはわかると思いますが、

2017年のmac proでも最大でCPUのコア数が8なのに対し、Tesla V100 GPUにはなんと5000コア以上が詰まっています。

どうでしょうか。

GPUとCPUのコア数が文字通り桁違いに違うのを感じていただけましたか?

その計算速度の違いは火を見るより明らかでしょう。

しかし、一方でCPUは連続的で複雑な処理を得意とします。

分岐予測機構や、スーパースカラ(スーパースケーラ)という、命令処理を実行する回路を複数持つことで、複数の命令処理を同時に実行する仕組みや、Out-of-order実行という機械語プログラム中の命令の並び順に依らず、データなどの依存関係から見て処理可能な命令について逐次開始・実行・完了させる機構を兼ね備えたCPUは1サイクルに1.5命令程度は実行できると考えられますが、そのような機構を持たないGPUコアは、条件分岐が多い複雑な処理をする場合には、1サイクルに0.1~0.2命令しか実行できないと思われます。

これだけ見ても10倍程度の差がありますが、クロックという1サイクルを回すための時間がCPUの方がGPUよりも4倍速いので(GPUの具体例を参照して)その差は40倍にもなり、CPUの処理の方がGPUよりも圧倒的に速いことが伺えます。

*サイクル(クロックサイクル)とは CPUはクロックという基準の信号にテンポをあわせて動作します。ただし、ひとつの命令が1クロックで終わるわけではありません。
命令の実行には、1)メモリからの命令取り出し、2)解釈、3)実行、4)結果のメモリーへの書き戻し、と4ステップで行われます。各ステップには数クロックから数十クロックが必要です。そして、1命令を完了するのにかかるクロック数をクロックサイクルといいます。

まとめると

GPU 大量の単純な計算をするのに優れている。

CPU 複雑な処理をするのに優れている。

という違いがあります。

なのでGPUはゲームなどのグラフィックに使われることが多いです。

(たとえば「アイテムを落としたら、落ちる」とか「服に風があたったらなびく」といったような、つねに答えが同じになるような単純な処理の高速の繰り返しであるためです。そもそもGPUはGraphics Processing Unit の略なのです。)

 

これまで説明してきたGPUとCPUの違いをプログラミング言語を用いて例えると

GPU  『for』が得意

GPUは、難しい処理ができる大きいものではなく、演算器だけ取り出したものを何百個と並べ、1度に処理するものです。

もしfor文のループを100万回繰り返すなら、それを10000個の演算器で等分して処理してやれば処理速度は大幅に上がります。

 

CPU 『if~else~』が得意

CPUは、OSのように複雑なプログラムを動かすことを念頭において作られてきました。従ってフレキシブルにプログラムを動かせますが、演算器の間でメモリをシェアする仕組みなので、コアの増加に伴い性能が頭打ちになってしまうことが欠点です。

メモリを階層化するなど、互いに邪魔せずに処理できるよう工夫はされていますが、それでも限界はあります。

連続的な細かく条件をとって処理していく問題を得意としています。

 

次にGPUとディープラーニングの関係性を探るために

GPUの起源とディープラーニングのボトルネックをみていきたいと思います。

 

 

                                  

GPUの起源とディープラーニングのボトルネック

GPU はNVIDIAという会社によって開発された、ゲームを快適に行うため、CPUの演算を補助するための装置で、FPUという浮動小数演算処理装置に、画像表示装置をくっつけたものでした。

なぜ、整数ではなく浮動小数なのでしょうか。

なぜなら、ゲームではグラフィックの大量の演算を処理する際、座標は小さなものはミリ以下の単位から広いシーンはキロメートル単位までの値が混在し、ピクセルの明るさは6桁程度は優に変わるので、固定小数点の数字の範囲にうまく収まるように注意して計算する必要があり、面倒だったからです。その手間を省けるのが浮動小数点演算という手法であり、それを扱うためにさらに膨大な計算を瞬時に行えるGPUの開発が進んでいったのです。

当初、ビデオボードと呼ばれていたGPUはその名の通り、ゲーマーしか手を出さないニッチを狙った商品で、今日のように科学計算に使われてはいませんでした。それには理由があり、GPUはその単純な仕組みにより、全ての計算を正確に行う訳ではなかったのです。当時、GPUはあくまでゲームのグラフィックのために使われていたため、ピクセル数が少しずれていても大して問題ではないため、わざわざ全ての計算を正確に行う必要もありませんでした。

その一方でCPUは正確な値を返してくれるため、科学計算の中心は当時、まだまだCPUでした。

しかし、ここでNVIDIAが動きました。市場拡大を狙って、ECC(Error Correction Code) という計算エラーを自動で検知し、修正する機能などの充実させその計算精度を科学計算にも使えるレベルにまで引き上げたのです。その圧倒的な演算処理能力により科学計算の中心はGPUに移っていきました。

そのころ、ディープラーニングは特徴量の抽出に際して必要になる膨大な計算処理によって学習にとても多くの時間がかかり、モデルの構築→学習→調節→学習のサイクルが高速で回せないことがディープラーニング発達のボトルネックとなっていました。

しかし、GPUの一度に同じ処理を行うことができる仕組みが、ディープラーニングの膨大な行列演算の処理と非常に相性がよく、ディープラーニングにGPUが使われだした頃からディープラーニングは大きな発展を遂げることになります。

今でも複雑なモデルの学習をする時は膨大な計算処理がボトルネックとなりますが、GPUの登場がディープラーニングの発達に大きく貢献したのは疑いようがありません。

 

最後に、今、機械学習の学習速度にお悩みの人には朗報かもしれないニュースを紹介します。

 

                                  

現在、世界一強力なクラウドで使えるGPUインスタンスの性能

今週のニュース

AWS(Amazon  Web Service) が強力な新インスタンスをリリースです。

*インスタンス  物理的な一台のコンピュータ上で、ソフトウェアとして実装された仮想的なコンピュータを起動したもの。

ニュース概要

  1. アマゾンはクラウドコンピューティングサービスE3で、新しいインスタンスP3の提供を開始。
  2. このインスタンスは、NVIDIAの「Tesla Volta」アーキテクチャに基づく GPU「Tesla V100」を使用しており、機械学習モデルのトレーニングを劇的に高速化できる。
  3. 利用できるインスタンスは、使用されるTesla V100 GPUの数が1基のもの、4基のもの、8基のものの3種類で、それぞれ「Intel Xeon E5 Broadwell」ベースのカスタムCPUを8基、32基、64基搭載している。
  4. 新インスタンスは、米国東部(バージニア北部)、米国西部(オレゴン)、欧州(アイルランド)、アジアパシフィック(東京)の各リージョンで利用できる。

この新インスタンス、GPUの搭載数によって

1基  p3.2xlarge

4基  p3.8xlarge

8基  p3.16xlarge

という名前をつけているのですが、それぞれ

Instance Size GPUs - Tesla V100 GPU Peer to Peer GPU Memory (GB) vCPUs Memory (GB) Network Bandwidth EBS Bandwidth
p3.2xlarge 1 N/A 16 8 61 Up to 10Gbps 1.5Gbps
p3.8xlarge 4 NVLink 64 32 244 10Gbps 7Gbps
p3.16xlarge 8 NVLi 128 64 488 25Gbps 14Gbps

https://aws.amazon.com/jp/ec2/instance-types/p3/

上記のような性能の違いがあります。

料金は一番性能のいいp3.16xlarge で一時間あたり41.94ドルで1ドル114円で換算すると一時間あたり約4781円と高額になっております。(東京での使用を想定)

 

少し前のインスタンスである、16 個の NVIDIA K80 GPU、64 個の vCPUを搭載したp2.16xlargeのインスタンスのオンデマンド利用料が1時間当たり24.67ドル=2812円なのを考えるとその値段はおよそ倍。

p3.16xlargeを一日つけたままにすると約11万5千円

一ヶ月付けっ放しにすると約350万!

この先はちょっと考えたくありませんね・・・・。

 

ちなみにp3.2xlargeは5.24ドルで597円/時、p3.8xlargeは20.97ドルで2390円/時です。

そんな半沢直樹ばりの料金をとる今回のp3.16xlargeの性能はいかほどのものなのでしょうか。

p2.16xlarge が単精度浮動小数点演算を一秒間に70兆回できるのに対し、

p3.16xlargeでは、なんと単精度浮動小数点演算を125兆回できます。

値段が倍になった分、ちゃんと処理速度も倍になっているんですね。

 

とはいえ、値が大きすぎてGPUが過去と比べてどれだけ成長したのかわかりにくいと思います。

そこでマイクロプロセッサの歴史を振り返って、1977年に発売していたIntel 8080Aチップを搭載したMITS Altairを考えてみます。2MHzクロックで秒間832回の乗算が可能でした。しかし、それから40年がたちました。p3.16xlargeは約1500億倍も高速です。言い換えると、過去40年かけてAltairが行なった計算に比べ、100倍以上の計算を1秒に実行することが可能となっているのです!

この計算処理速度の爆発的増加がディープラーニングのこれまでの発達の屋台骨となっていた訳です。

 

 

                                  

おまけ 浮動小数点演算とは

ところで浮動小数点演算ってなんなんだ、というツッコミが入りそうなので、

そこも最後に解説していきたいと思います。

浮動小数点数から解説していきます。

浮動小数点数とは指数形式で表された数字のことです。

例えば1230であれば浮動小数点数で1.23×10^3で表されます。

昔はコンピュータごとに処理の仕方が異なりましたが、それでは不便なので共通のルールがIEEE754という組織によって作成されました。

それがIEEE規格で状況によって求められる精度が違うことを考慮して、

32桁バージョン(単精度)と

64桁バージョン(倍精度)があります。

この浮動小数点数の状態で演算を行うと通常の演算に比べて処理に時間がかかる上にコンピュータにとって都合がいいので、コンピューターの性能を評価するベンチマークに使われることが多いのです。

つまり今回行われた単精度浮動小数点演算は

32桁の浮動小数点数の演算だったということがわかりました。

 

 参照

https://japan.zdnet.com/article/35109459/

https://aws.amazon.com/jp/ec2/pricing/on-demand/

https://aws.amazon.com/jp/blogs/news/new_amazon_ec2_instances_with_up_to_8_nvidia_tesla_v100_gpu_p3/

http://wa3.i-3-i.info/word15851.html

https://www.gizmodo.jp/2016/06/cpugpu.html

https://bita.jp/dml/sony-neural-network-console-interview