2021年12月22日水曜日

Thank you for reading

I published 60 articles a year for 4 consecutive years.
I wrote 61 articles this year in 2021 as well.
(61 / 365 = 0.167)

Thank you for reading.

I will take a break for a while.

I hope you all have a wonderful New Year's holiday season.
Winter scenery of Mt. Rishiri, the northernmost beautiful mountain in Japan 
(The mountain is steeper than expected, so winter climbing will be difficult for general climbers.)
The photos shown here are taken from:
http://www.town.rishiri.hokkaido.jp/rishiri/

2021年12月21日火曜日

生成AIによるDeepFakesの倫理に関する授業資料

【what is this】最新のDeep Learningで作られたFake(偽物)DeepFakesは、ポジティブ、ネガティブの両面を持ちます。以下のチュートリアルは、「Artificial Intelligence with MIT App Inventor」の第9弾(beginner level)です。簡単なスマホアプリ作成「Make Your Own Fake Voice!」から始めて、現代のDeepFakesの利用や問題点を議論し、社会に与える影響と将来の姿を考えさせます。主に生徒向けに作られたものですが、一般の大人にも有用な情報が含まれているかと思います。

簡単なFake Voiceアプリの作成
 第一ステップでは、MIT App Inventorを利用した簡単なFake Voiceアプリを作成します。音声認識と音声合成を使いますが、本当の”DeepFakes”ではありません。音声合成の際に、音のpitchとrateを適宜変更するという単純なものです。出来上がったアプリのブロック図は、図1のとおりです。こんな簡単なものですが、それでもFake Voiceの体験ができます。

 例えば、図1のスマホ画面にある「方丈記」の一節「ゆく河の流れは絶えずして、... 」をこのアプリが読み上げます。その際、デフォルトの音声合成よりも、pitchとrateをかなり低くした方が、この随筆にマッチしていて、趣があります。これは、Fake Voiceのポジティブな応用と考えたい。

 一方、例えば、「おれだけど。ちょっと風邪引いてさあ。声が変なんだけど。実わあ...電車の中に鞄を…」をこのアプリで(低pitch、低rateに設定して)電話をかけるとすれば、これは悪用でしょう。

最新AIによるDeepFakesを概観する
 第二ステップでは、最新のDeepFakesはどのように作成され、利用されているかを、ビデオで学びます。適用分野として、音声、音楽、映像、画像、テキスト、などの生成がありますが、ここでは、音声を中心に以下の6件を取り上げてみます。

(1)合成された故ケネディ大統領の声で幻の演説を聴く
 故ケネディ大統領は、凶弾に倒れる前に、ある演説の原稿を用意していました。実現されなかったその演説を、大統領自身だと思えるような声で実現させたプロジェクトがあります。彼が実際に行った831件の演説の録音を元に、AIと音響工学を駆使して、特有の間合いや強調のしかた、それにボストンアクセントも反映させた、彼らしい音声を合成したのです。下記のビデオでそれを聴いてみましたが、なかなかの出来栄えだと思います。“In a world of complex and continuing problems, … America’s leadership must be guided …
 ●President Kennedy Deepfaked
 https://www.youtube.com/watch?v=wZF59wIIBLI

(2)月面着陸に関する「別のバージョンの歴史」
 1969年、米国は人類初の月面着陸に成功しました。しかし、その任務は非常に危険だったので、悲惨な結果になった場合を想定した大統領談話原稿が用意されていました。もちろん、月面着陸はうまくいき、そのスピーチは行われませんでした。しかし、2020年に、MITのチームは、当時のニクソン大統領が沈痛な面持ちでそのスピーチを行う、ディープフェイクビデオを作成しました。これにより、「別のバージョンの歴史」を体験できることを示しました。これがどんなん意味を持ち、どんな影響を与えるかは議論があるところでしょう。
 ●Moon Disaster
 https://moondisaster.org/film

(3)音声データバンクが声を失った人々を救う
 スコットランドのSpeakUnique社は、病気(運動ニューロン疾患)で発声できなくなった人のために、その人らしい声でテキストを読み上げることができるFake voiceを設計製作しています。蓄積された膨大な音声サンプルを利用し、きめ細かく、好みや特性を考慮した調整を行い、個人向けのユニークな高品質音声を作ってくれます。AndroidやiOS向けのアプリとしても、それを提供しています。
 ●Voice Banking Helps People with Motor Neuron Diseases
 https://vimeo.com/403687789

(4)人に代わって美容院やレストランを予約
 米国でも、小規模な店の約60%はネット予約システムを持たずに、電話受付けしているそうです。Googleでは、DeepFake voice(Google Duplex Assistant利用)が美容院やレストランへ予約電話をかけてくれるサービスを始めるとのことです。
 以下のデモビデオでは、客に代わって電話したDeepFake Voiceが、店側の人間から混雑状況を知らされて、最初の希望時間を変更して予約を取っていました!人が発する自然言語をも理解していたのですから、誰しも驚きます。店員は、人間が電話してきたと思っているようでした。(個人向けには需要はなさそうですが、社用で定常的に顧客接待で会食予約する場合などは、人間のコスト削減に繋がるかも。)
 ●Haircut appointment or Restaurant reservation
 https://youtu.be/D5VN56jQMWM

(5)銀行強盗(詐欺)に使われた例
 英国のあるエネルギー会社の従業員は、会社のCEOから、遠く離れた会社に243,000ドルを送るようにという電話を受けました。その従業員は、CEOの声だと信じて、送金してしまいました。その声はFake voiceでした!下記のこのビデオは、このような事件がどのようにして起こるかを説明しています。
 ●Fake Voices Pull a Bank Heist
 https://www.youtube.com/watch?v=EGEID-_XWCM

(6)金融犯罪、金融危機を引き起こす可能性
 以下の短いビデオは、将来、(音声だけでなく、ビデオやドキュメントを巧みに偽造した)ディープフェイクが起こす金融犯罪、さらには金融危機の可能性について、イラストを用いて分かりやすく説明しています。
 ●Could AI-Powered Videos Cause an Economic Collapse?
 https://youtu.be/YE0i7IpqVfk

DeepFakesの適用分野や社会へのインパクトについて考察
 最後の第三ステップでは、ここまでの情報にもとづき、各グループ毎に、DeepFakesの適用分野や将来の可能性について議論させます。さらに、全体会合で、他のグループの見解も聞き、さらに議論を深めるようにしています。指導者に対して、図2のような指針が示されています。(ここでは省略しましたが、もう少し詳しくブレークダウンした指針もこのカリキュラムユニットの資料に含まれています。)


2021年12月19日日曜日

画像の深層学習はどのような領域に着目しているのか

【what is this】ディープラーニングを用いた画像認識は、小学生による体験から実用レベルまで、利用が広がっています。そうなってくると、次の段階は、「どうやって認識しているのか」が気になるはずです。それに答えるのは簡単ではありませんが、少なくとも「画像のどこに着目して認識しているか」を示してくれれば、かなり良いです。簡単な原理でそれを実現する(子供向けの)Scratchプロジェクトがありました。大人でも試してみると楽しい!

■ 認識対象の例とTeachable Machineによる深層学習 
 画像認識の対象として、図1に示した4種の木製の小さな置物を取り上げます。それぞれを300枚程度、Webカメラの位置を変えたり、傾けたりしながら撮影します。それらにラベルをつけて学習させることは容易です。例えば、Google Teachable Machineを利用すれば誰にでもできます。
 その学習結果のモデルに対して、別途撮影した画像を入力した場合、それが4種類のどれであるかは、どの置物でも、99%程度の確かさ(conf = cofidence)で判別できます。

■ 深層学習では画像のどの領域に着目しているか 
 こんなに高いconfidenceで認識されても...  深層学習は画像のどの部分に注目して判断しているのでしょうか?それを調べるための簡単な原理が、Scratch3のプロジェクト「Explainable AI」に示されています。これは、子供向けのAIを開発しているML4K (Machine Learning for Kids) が公開しているものです。

 さっそく試してみましょう。図2(a)はAppleですが、適当なサイズの(紫色の)ブロックで、適当な領域を隠して撮影しています。「へた」の部分を隠した画像に対しての認識では、confidenceはほとんど変わらず99.5%でした。ところが、「中央」を隠した場合は、confidenceが50.1%まで大幅に低下しました。この観察から、「へた」よりも「中央の膨らみ」の方が、より重視されていると推定されます。


 図2(b) は、Salmonですが、「口先」よりも、「エラと腹部」が重要のようです。


 図2(c) は、Bearですが、「尻」よりも、「頭部」が重視されていることが分かります。これは、人間の感性からも納得できます。

■ 注目領域を自動的に検出して表示する 
 ここまでは、画像を隠す小さなブロックの位置を適当に手動で移動させながら調べました。それをもっと組織的にやってみましょう。そのやり方もこの「Explainable AI」に示されていますが、基本的には、手動で調べたのと同じ原理です。

 画像をメッシュにして、その各ブロック部をひとつづつ隠して行き、confidenceの低下を調べます。低下の度合いが大きい(すなわち、重要であった)部分ほど明るくすればよいのです。図3は、Bearの場合ですが、手動で調べた図2(c) のとおり、「目と耳の領域」を最も重視して認識していることが分かりました。こんな簡単な方法なのに素晴らしい!

子供向けのScratchプロジェクトだが、学生などにも有用 
 上に述べたとおり、この方法は図4のScratchプロジェクトで実現されています。主に子供を対象としたものですが、かなり高度な内容と言えそうです。実際、図3を眺めていると、自然言語処理などでも注目されているアテンション(Attention)に通ずるように思います。

 この「Explainable AI」では、TensorFlowをラップして使いやすくしたTeachable Machineの学習結果を取り込みます。そして、それを使った予測(prediction)のための基本的なブロックが用意されていますので、図3のような解析と表示が簡単にできるようになっています。学生や大人にも十分有用だと思います。


2021年12月15日水曜日

タイタニック号データも球面SOMで分析してみる

【what is this】以前、MLB投球の機械学習に関して、球面SOMを用いた分析を行いました。今回は、タイタニック号の乗客データについて、同様に球面SOMで分析しました。技術的なことは別として、SOMの素晴らしさを改めて感じられると思います。

■ タイタニック号の乗客の「生死」の自動分類 
 タイタニック号のデータの詳細は、前の記事をご覧下さい。その記事で扱ったFeatured Dataset には、全部で1,043人乗客データ(生還415名、落命628名)があります。それぞれに、9項目(9の特徴量)の値が記載されています。そして、各人に、「生 / 死」のラベルが付与されています。

 このデータから、乗客の生死を球面SOMで自動分類させるのです。ここで注目すべきことは、球面SOMは、「生 / 死」のラベルは全く利用せずに、(9項目から成る)入力データを何らかのクラスタに分類してくれます。すなわち、ラベル無し(教師信号なし)に機械学習してクラスタを作ります。その結果の一例を図1に示します。

 
 これをみると、何種類かのクラスタにデータが分類されていることが分かります。そして、驚くべきことに、この分類結果に、元々あったラベルをあてはめてみると、この図では、"生"と"死"にほぼ分類されていることが分かります。"生"も"死"も一つではなく、何種類かのクラスタに分かれているようですが、この図では、赤い太線が生死の強い境界線になっているようです。

 なぜ、「生 / 死」のラベルを利用せずに、9次元のベクトルデータをこのように分類できたのでしょうか?不思議にも思いますが、それがこの技術の素晴らしさだと思います。

 さらに詳しくみてみましょう。図2と図3は、図1の場合よりも、ニューラルネットワークのニューロンの個数を増やした場合です。図2は、正面の半球面が、幸いなる「生還者」の世界であることを示しています。。一方、図3は、図2の球面の裏側ですが、そこは恐ろしい死の世界となっています。



2021年12月13日月曜日

機械学習でのFeature Engineering(特徴量設定)体験

【what is this】ディープラーニングでは、「必要な特徴量は自動的に見つけてくれる」とも言われますが、多くの場合、人間による慎重な特徴量設計が必要([1], [2])となるでしょう。この分野の定番MNIST(手書き数字認識)と同様に有名なものとして、「タイタニック号の乗客の生死」に関するデータセット([3], [4])があります。今回はこれに関する機械学習を行うえで、どのように特徴量を設定すべきかを、参考資料[3]に従って体験しました。

■ タイタニック号の乗客のデータの機械学習 
 本稿は、Gant Laborde氏による書籍[3]第9章の解説の追体験記になります。乗客のデータは、図1「(1)原データ」にあるとおり、全部で12種の特徴量(12カラム)からなります。氏名、年齢、性別などの他に、Survived(生/死)が含まれています。整数値、実数値、文字列などの値が含まれています。

 総計1,309名分ありますが、機械学習の観点から、train用891名分、test用418名分に分けられています。そして、目的は、Survived(生/死)をラベル(教師信号)として、train用データを学習させ、その学習結果を使って、test用データ(validation用データとも呼ぶ)の乗客のSurvived(生/死)を予測させ、正解率を計算することです。

■ 機械学習のために、適切に特徴量を設定(Feature Engineering)
 図1(1)原データにおいて、上記の機械学習にとって、寄与度が低いと考えらるものは除外した方がよいです。ここでは、「(2)不要カラム削除」にあるとおり、4要素を除外しました。これを元に、以下の2つのデータセットを作りました。

NaiveDataset
 一つでも空白の(値の無い)セルを含む行を削除します。さらに、SexEmbarkedの値が文字となっているので、これをカテゴライズして、整数値(0,1,2など)に変換します。

FeaturedDataset
 NaiveDatasetに対して、Sexを削除して、新たに2つの特徴量としてmalefeamaleを追加します。さらに、年齢層(10歳未満、40歳未満、40歳以上)を表すAgeBucketを追加します。そして、各特徴量の値を、MinMaxScalerで、0〜1の間の実数値(両端値を含む)にスケーリングします。
 この3つの特徴量を追加した理由は、図2にあります。実は、この悲劇の事故は映画化されたのですが、その中で、多くの乗客が、"Women and children first!"と叫んでいるそうです。図2をみると、それが事実だったことが分かると思います。すなわち、男に比べて女の生存率が圧倒的に高い!また、子供の生存率も大人よりもかなり高いのです。


 この事実は、機械学習に大きな影響を与えるはずです。上で、3つの特徴量を新設したのは、この事実をより強く反映させるためです。maleとfemaleはそれぞれone-hot型にしました。AgeBucketは、3段階に区分けしました。

■ 特徴量の設定の機械学習への効果
 上記のとおり、不要のカラムを削除しただけの「NaiveDataset」と、特徴量を新たに設定した「FeaturedDataset」を用意しました。これらを、図3に示すNeural Network(TensorFlow.js使用)で学習させた結果を示します。


 図3の上段にあるとおり、Validation Accuracyの比較では、FeaturedDatasetに対する正解率0.89は、NaiveDatasetに対する正解率0.83に対して、意味のある向上が得られていると言えます。また、Train AccuracyよりもValidation Accuracyが高くなっていることは、over fittingになっておらず、好ましい学習が行われたことを意味します。つまり、原データにある特徴量をそのまま使うのではなく、データの特性を考慮して特徴量を設計する必要があることを体験できたと思います。

■ Tensorflow.jsについて
 ここで参考にした書籍[3]は、TensorFlow.jsプログラムをNode.jsサーバで動かす例題を示しています。しかし、小生のMac環境では、Nodeを正常に動作させることができなかったので、独自に、通常のWebサーバで実行できるように改変しました。その過程で、TensorFlow.jsの詳細を学ぶことができました。
 また、入力データの様々な加工には、Python環境でのPandasに相当するDanfo.jsを使うことができました。このDanfo.jsの利用によって、上記で述べたFeaturedDatasetの作成を効率的に行うことができました。

参考資料
[1] 
ディープラーニングは自動で特徴を抽出してくれる?
https://www.hellocybernetics.tech/entry/2019/06/23/010201
[2] 機械学習に欠かせない、特徴量とその選択手法とは
https://ainow.ai/2020/07/14/225092/
[3] Gant Laborde:"Learning TensorFlow.js - Powerful Machine Learning in JavaScript", O'Reilly, 2021-05-07.
[4] codexa増田秀人,ウイリアム・スタイメル:"機械学習のプロセス徹底解説-タイタニック号から生還できるのは誰?", 日経ソフトウェア, 2019年1月号, pp.6-27.

2021年12月7日火曜日

Tensorflow.jsのimportなどで遭遇したエラーの対処

【what is this】多くの場合、Tensorflowは、Python環境で使われているようです。しかし、いくつかの理由から(その一例はここにありますが)、JavaScriptで動かすTensorflow.jsへも注目が高まっているようです。本記事は、Tensoflow.jsの基礎を解説したテキスト[1]の例題で発生した、幾つかのエラーに対処した時のメモです。推奨すべき対処法かどうかは分かりませんが、取りあえず正常に動かすための備忘録です。

■ テキスト「Learning Tensorflow.js」
 このテキスト[1]は、今年5月に刊行されたばかりです。Tensorflow.jsの利用に関する基礎知識を与えるものです。例題の解説も分かりやすいです。全部で12章ありますが、8章までは、通常のWebサーバの元で、第9章以降はNode.jsサーバで動かす例題があります。



 第8章の例題を、Visual Studio Codeの環境で実行していて、次のようなエラーメッセージがでました。他の人にもよく起こる?ようであり、対処方法に関する記事をたくさんでていました。それらを参考に対処してみました。

 

■ Tensorflos.jsの例題実行で発生したエラーへの対処
(1)importに関するエラー

例えば、あるJavaScriptファイルindex.jsの中の以下のimportです。
import * as tf from "@tensorflow/tfjs";

これを実行すると以下のエラーが発生しました:
Uncaught SyntaxError: Cannot use import statement outside a module

ネットで調べると、以下のようにすれば良い、という説明がありました:

Add "type": "module" to your package.json file.
{
 // ...
 "type": "module",
  // ...
}

でも、その通りにしても、相変わらずエラーのままです。そこで、以下のようにしてみました。
このimportを削除する。(コメント化して残す。)
htmlの<body>の中に以下を挿入する:
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.0.0/dist/tf.min.js"></script>

以上にようにして、このhtmlファイルをVisual Studio CodeのOpen with Live Serverで起動させたところ、正常動作しました!

(2)moduleに関するエラー
 例えば、あるJavaScriptファイルindex.jsの中にある以下の3つのimportです。
import * as tf from "@tensorflow/tfjs";
import "core-js/stable";
import "regenerator-runtime/runtime";

これに対して、以下のエラーメッセージが出ました:
Uncaught TypeError: Failed to resolve module specifier "@tensorflow/tfjs". Relative references must start with either "/", "./", or "../".

以下のように対処しました:
3行とも削除する。(コメント化して残す。)
さらに、(1)の場合と同じく、htmlの<body>の中に以下を追加。
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.0.0/dist/tf.min.js"></script>

このように改変した結果、正常動作となりました!

(3)Danfo.jsに関するエラー
 Danfo.jsは、PythonのPandas相当の機能を使えるようにするものです。これも、上記(1)、(2)の場合と同様に、JavaScriipt内でのimportに失敗する場合は、htmlのタグで指定すれば正常に使えました。
これをコメント化する-> import dfd from "danfojs-node"
さらに、htmlの<body>の中に以下を追加。
<script src="https://cdn.plot.ly/plotly-1.2.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/danfojs@0.3.4/lib/bundle.min.js"></script> 

なお、Dataframe object dfを使って、各カラム毎の統計値を計算できるのですが、その際、非数値(あるいはnull項目)のカラムを取り除いた後に、df.describe().print() を実行する必要があります。

■ 第9章以降の例題の実行
 以上で、第8章までの例題は問題なく動作するようになりました。Mac miniでもLet's NoteでもOKでした。第9章以降では、Node.jsサーバを利用する例題があります。Node.js環境がうまく設定できない場合には、通常のWebサーバで動くように改変しようと思います。

参考資料
[1] Grant Laborde, "Learning Tensorflow.js - Powerful Machine Learning in JavaScript", O'Reilly, 2021-05-07.

2021年11月30日火曜日

MLB主審が誤審したと思われる「ストライク」の球面SOMでの表示

【what is this】前回の記事では、MLB投球の球種分析を球面SOM(自己組織化マップ)[1]で行いました。今回は、主審が誤審して「ストライク」コールしたと思われる投球について、球面SOMで可視化して眺めてみました。(信憑性に欠けるか、誤った論述になっている部分があると思いますが、後日、自分のための何らかのヒントになり得ると考えて書き留めます。)

■ 主審が誤審したと思われる「ストライク」309球の球面SOM表示
 以前の記事で、MLBでの多数の投球判定[2]のうち、主審が誤って「ストライク」コールしたと思われる309球の分析を示しました。「誤審」と思われる根拠についても、その記事で述べました。

 今回は、その309球のデータ(5features = 5成分から成る)を球面SOMで分析しました。図1をご覧下さい。これは、各成分毎に(各成分を軸として)この309球のデータをクラス分けした(はずの)図です。簡単な場合から行きます。例えば、成分5は、左打者か右打者かの2値を取ります。誤審したストライクを、左打者、右打者毎に分離してもいびつにならない(明瞭にクラス分け可能)。すなわち、そのように分離しても、類似性の高いデータ(5次元ベクトル)同士は近くに集まって表示される。図はそれを示しているようです。右打者の方が数が多いので、奥のキノコ状の球面が大きいようです。

 また、ストライクゾーン面を通過したx座標とy座標である、成分1と成分2についても、大きなキノコ状の球面2つがほぼ明確に分かれています。これは、ストライクゾーンの左右方向(成分1)と上下方向(成分2)に関して、誤審されたストライク球のデータをほぼ明瞭にクラス分けできることを示しているようです。


 これらに反して、成分3(ストライクゾーンの上辺の高さ)と成分4(ストライクゾーンの下辺の高さ)に着目した場合は、明瞭に区分けすることが困難なようです。すなわち、分離しようとしたクラスが複雑に混じり合っている。こうなると、主審も判断に迷う場合が多いはず。これは打者(の姿勢)によって、ストライクゾーンの高さ方向が変化することに起因するはずです。

■ まとめ
 ここまでを纏めると、かなり乱暴ですが(また適切な表現かどうかも分かりませんが)、以下のように言えそうです。
  • 横方向に関する誤審の多くは、主審の確信犯的な判定によるようである。(実際、例えば、2ストライク後は、投手に有利な方向でストライク判定される傾向があるとの調査結果もあります。)
  • 一方、縦方向の誤審は、ストライクゾーン縦方向の見極め自体が難しいことで起る場合が多いのではないか。
 このことは、(以前の記事で示した)以下の図2が裏付けているようです。緑の枠線は、打者毎に変化するストライクゾーン(主に縦方向)を示しています。たくさん重なっています。赤丸は、主審がストライクコールしたのですが、それは誤審と考えられる投球を示しています。

参考資料
[1] 大北正昭、徳高平蔵、藤村喜久郎、権田英功:自己組織化マップとそのツール、シュプリンガージャパン、2008年12月

[2] Predicting balls and strikes using TensorFlow.js
https://medium.com/tensorflow/predicting-balls-and-strikes-using-tensorflow-js-2acf1d7a447c

2021年11月29日月曜日

MLBでの7,000投球の球種の機械学習と球面SOMによる可視化

【what is this】MLBでの投球に関する機械学習の続編です。今回は、投球7,000球のそれぞれに球種ラベル(2-seam, 4-seam, sinker, など7種)が付与されたデータを機械学習させ、その結果を使って、テスト用に用意された700投球で球種を予測させました。さらに、その700球の球種を、球面SOM(自己組織化マップ)で可視化してみました。

■ MLB 7,000投球のデータ
 MLBの公開データのうちに、7,000投球について、以下に示す球速等と左右投手の識別子のデータセットがあります。そして、その各投球に球種ラベルが付与されて、参考文献[2]で解説されています。
投球データのfeatures(特徴量8要素);
 ball velocity (vx0, vy0, vz0)
 ball acceleration (ax, ay, az)
 starting speed of pitch
 whether pitcher is left handed or not

球種ラベル(pitch_code 7種)
    2-seam, 4-seam, changeup, curveball, slider, cutter, sinker
(プルグラム中では、0〜6の整数で表される)

 これらのデータの具体例を示します:
(投球データの次は、左(1)/右(0)投手を表す。最後は球種ラベル。)
 vx0, vy0, vz0, ax, ay, az, start_speed, left_handed_pitcher, pitch_code
 7.699, -132.225, -6.583, -22.508, 28.311, -16.585, 91.1, 0, 0
 6.680, -134.215, -6.355, -19.660, 26.703, -14.343, 92.4, 0, 0
 2.565, -135.398, -2.916, -14.784, 27.808, -21.573, 93.1, 0, 0
  . . .

■ 投球のデータの機械学習
 これらのデータを教師付き機械学習させるプログラム概要も[2]に示されています。それは、Tensorflow JSを使って、Node.jsのサーバで動かすものです。しかし、当方の環境でNode.jsをうまく稼働させることができなかったので、自分で通常のWebサーバで稼働させるように修正して学習させました。その結果(球種毎の正解率)を以下に示します。

 2-seam   => training:0.822, validation:0.701
 4-seam   => training:0.899, validation:0.618
 changeup => training:0.841, validation:0.718
 curveball=> training:0.970, validation:0.804
 slider   => training:0.864, validation:0.607
 cutter   => training:0.900, validation:0.591
 sinker   => training:0.811, validation:0.443

 上記で、"training"は、学習に用いた7,000件についての、そして、"validation"は、これとは別に用意したテスト用のデータ700件についての球種予測(prediction)の正解率です。 "validation" では、cutterやsinker正解率は低めですが、投球の複雑な物理現象を考えれば、全般的には、かなりよく球種を予測できていると思います。

■ 球面SOM(自己組織化マップ)による球種の可視化
 このように、ある程度良い学習結果が得られましたが、ちょっと物足りません。つまり、正解率の数値だけでは、頭の中に具体像が得られません。球種を何らかの形で可視化したい。そこで思い付いたのが、自己組織化マップSOMです。SOMについては、10年以上前に、少し勉強しただけで、その後はご無沙汰していたのですが、その当時使っていた書籍[1]を思いだし、それに添付のSOMツールを使ってみました。古いツールですが、何とか稼働させることができました!

 以下に、その結果の一部を示します。細かいので、拡大してご覧下さい。SOMは、教師ラベル無しでデータを学習して、類似性の高いデータ同士を近い場所に配置してくれます。下図は、球面SOMによる結果です。ここでは、最初に述べたTensorflowJSを使った機械学習とは別の方法での学習ですが、同様に妥当な結果が得られていると思います。

 例えば、図1では、"sinker"となるべきベクトル(ここでは8次元ベクトル)が、中央付近に集まっています。また、"2-seam"同士も、その左側や上側に集まっているのが確認できます。小生は野球データに関しては全くの素人なので、間違っているかも知れませんが、sinkerと2-seamは、共に速球で沈むという共通点があり、それらの集団が隣接しているのも納得できそうです。(なお、右上ブルーで囲まれた球面は、大きい球面の裏側です。)


 図2では、"curve" が中央から右にかけて集まっています。そして、中央の斜め下方向に強い区分けの赤線があります。その赤線に隣接する左下方向には、"cutter" が集まっています。curveとcutterは共に曲がるという特性がある一方、球速が大幅に異なることから、この強い区分け線ができているようです。

 以上、2つの方法での機械学習は、いずれも、8種の特徴量(8次元ベクトル)で、球種をある程度予測できることを示しています。特に、球面SOMの結果は、頭の中に、具体的なイメージを定着させてくれると感じます。

参考資料
[1] 大北正昭、徳高平蔵、藤村喜久郎、権田英功:自己組織化マップとそのツール、シュプリンガージャパン、2008年12月
[2] Node.jsを使用して野球の投球の種類を予測する
https://www.tensorflow.org/js/tutorials/training/nodejs_training?hl=ja

2021年11月20日土曜日

「強化学習」の新刊が届きました

 書評みたいなことは書きませんが、小生がじっくり読んで学んだ「強化学習」の参考書は以下の2点でした。

[1] 中井悦司, ITエンジニアのための強化学習理論入門, 技術評論社、2020-7-30初版

[2] 伊藤 真, Pythonで強化学習を学ぶ, 日経ソフトウェア2021年7月号, pp. 24-39

 本日(2021-11-20)、Amazonに予約してあった下記の新刊が到着しました!
上記[2]の記事を書かれた伊藤真氏による新著です。また、学ぶ楽しみが増えました。

[3] 伊藤 真, 「強化学習」を学びたい人最初に読む本, 日経BP, 2021-11-22初版

 本書は、タイトルは控えめになっていますが、かなり高度な内容も含まれます。しかし、そこを一歩一歩丁寧に叙述しているのが最大の特徴のようです。
 Q-Learningにおいて、Qテーブルをダイナミックプログラミングで(厳密解を)求解するという基本線はもちろんです。それに加えて、ニューラルネットワークを利用する近似解法とその性能検討、さらにその向上策にも、じっくり取組んでいます。

 中井氏の[1]と伊藤氏の[3]は、ともに、丁寧な叙述で、かなり高度なところまで導いてくれる素晴らしい本だと思います。具体的なコードもフォローしやすく、広範な読者層に向いていると思います。

 これら以外にもいくつか強化学習の和書や訳本は出版されていますが、小生の知る限りでは、内容がやや古かったり、最新技術に言及しているがやや理論寄りだったり、難解な感じで少しとっつきにくいものが多いように思っていました。そのなかで、[1][3]が出版されたのは非常に喜ばしいところです。

補足:
 上記[1], [2]を学んで自分で確認したり、再構成したり、応用アプリにしたりの記事をこのブログに数編づつ書いて来ました。今回の新著[3]についても、学んだあと、同様に、自分なりの確認や応用について書ければよいと思っています。


2021年11月18日木曜日

MLB(メジャーリーグ)主審の判定結果を学習してストライク判定(3)

【what is this】MLB(前回記事(2)で示したアプリにより、メジャーリーグ主審のストライク/ボールの判定状況を観察しました。その結果、学習をもとに作成されたAI主審の判定を利用すれば、メジャーリーグ主審の誤審がある程度分かるのではないかと考え、検討しました。

■ MLB主審とAI主審の判定結果の相違
 MLBでの実際の5,000投球に対するMLB主審とAI主審(=学習済みニューラルネットワーク)の判定結果は以下のとおりでした:

  • 5,000球のうち4,539球(約91%)で、両者の判定結果が合致した。
  • 残りの461球(約9%)は両者の判定は逆転した。
  • 学習条件を種々変更しても、これ以上は両者は合致しない。
 このことから、この相違9%の主因は、MLB主審の誤審によるのではないか。すなわち、AI主審の方が、約5,000球の学習の結果、(確信はありませんが)人間よりも的確に判定しているのだろう。それを裏付ける例を、図1で確認します。(機械測定によるストライクゾーンとボールの直径は、ともに実物を同一縮小率で縮小して表示しています。)図1左は、MLB主審の判定は「ボール」ですが、ストライクゾーンに触れているので、AI主審のとおり「ストライク」のはずです。図1右の例も同様に、AI主審の方が正しいように見えます。

■ 両者の相違の詳細分析
 上では、相違例を2例だけ示しましたが、5,000投球の全てについての状況を、図2と図3に示します。図2は、相違のあったうちの、「MLB主審はボールで、AI主審はストライクだった152球すべてを表示しています。図2右には機械測定によるストライクゾーン(打者により変動するので重なっています)この図を見ると、MLB主審の「ボール」判定(青丸)の何割かは、ストラークゾーンに入っているか接しているので、ストライクとすべきだった誤審と思われます。

 一方、図3は、相違があったうちの、「MLB主審はストライクで、AI主審はボールだった309球すべてを表示しています。これを見ると、このうちのかなり多くは、ストライクゾーンから外れており、MLB主審による誤審であり、AI主審の判定(ball判定)の方が正しいように見えます。


 かなり乱暴な言い方ですが、以上の観察から、MLB主審とAI主審による相違461球のほぼ9割くらいは、MLB主審による誤審のように思えます。つまり、MLB主審は全判定の8%(= 0.9 x 461/5000 = 0.08)ほどを誤審した、と言えるのではないでしょうか。

■ MLB主審のストライク/ボールの誤審率は実際にどのくらいか?
 気になる、MLB主審のストライク/ボールの実際の誤審率はどんなものでしょうか。探してみたところ、参考資料[1][2]に、上記の結論を裏付けると思われる、次のような記載がありました!
  • 例えば、2018年のMLB Bad Call Ratioは、9.21%だった。⇒上で示した8%に近いので、納得できたような気がする。
  • 主審は、特定の状況下ではバッターよりもピッチャーに有利な判定をする。⇒図2と図3の結果と合致する。すなわち、ボールなのにストライクと誤審する場合の方が(その逆よりも)圧倒的に多い。
  • 2ストライクのときは、次の球がボールでもストライクと誤審することが多い。⇒今回の検討では、この点は分からない。

参考資料:
[1]
Gigazine「メジャーリーグ11シーズン・400万球分の投球データを分析して審判がどれだけ正しくジャッジできているのかを分析した結果」
https://gigazine.net/news/20190423-analysis-how-many-mistakes-umpires/

[2] A new study of MLB pitch calls makes a strong case for robotic umpires
https://techcrunch.com/2019/04/08/a-new-study-of-mlb-pitch-calls-makes-a-strong-case-for-robotic-umpires/


2021年11月15日月曜日

MLB(メジャーリーグ)主審の判定結果を学習してストライク判定(2)

【what is this】MLB(前回記事(1)では、メジャーリーグ)の主審によるストライク/ボールの判定結果(5,000投球)を学習させて、約90%以上は同じ判定をするニューラルネットワーク(AI主審)を構成できました。今回は、これをスマホで楽しみながら、判定確認するためのアプリを作りました。「ストライクゾーン」の縦方向の範囲は、打者によって変化するわけですから、その即時の見極めの難しさ(というか醍醐味)が少し分かった気がします。

MLB主審とほぼ同じ判定をするAI主審スマホアプリ
 このアプリは、Tensorflow.jsを利用して、5,000投球を学習させたモデルを、スマホに取り込んで作動させます。実行結果を以下に示します。テストに使った入力は以下のとおりです。

ランダムに100投球のデータを入力する。各データは、以下の5項目から成る。

  • ストライクゾーンの正面の平面に触れた時のx座標値、y座標値
  • 打者で決まるストライクゾーンの縦方向の範囲の上限値、下限値
  • 左打者か右打者かのフラグ

 図1に、左打者と右打者に対するストライク判定例を示します。下図左は、ストライクゾーンに僅かにボールが触れたと判定され、ストライクです。一方、下図右は、微妙ですが、触れていないとの判定でボールです。これには文句は付けられない!


 図2は、テスト用100投球に対する判定です。図中に、MLB主審とAI主審の判定結果に関する混同行列を示しています。このテストでは、両者の判定が93%合致したという結果となっています。下図の、赤丸(ストライク)、青丸(ボール)は、MLB主審による判定結果です。


 それにしても、ストライクゾーンの縦方向の範囲はずいぶん変化するものです。図1、図2の緑枠は、機械測定に基づくストライクゾーンです。上下に振れるので、枠線がたくさん重なって、分かり難いですが。

 ちょっと物足りない。
 その通りです。このデータは、左右の打者、打者の身長(ストライクゾーンの高さに関係する)などがランダムに含まれています。ですから、ストライクゾーン縦方向の範囲がほぼ同じものを集めて、そのグループ毎にストライク/ボールの判定結果を学習すればもっと明解な知見が得られるように思います。ですが、本稿はここまで。

2021年11月12日金曜日

MLB(メジャーリーグ)主審の判定結果を学習してストライク判定(1)

【what is this】MLB(メジャーリーグ)の主審(アンパイア)によるストライク/ボールの判定結果が公開されています。これを学習させれば、MLBの平均的な主審と同じ能力を持つ判定ロボットが作れそうです。実際、5,000投球のデータを学習させた結果、人間の主審と比べて、約95%は同じ判定をするニューラルネットワークができました。これは、多次元データの2値分類問題ですので、技術的には特に新鮮味は無いのですが、MLBの実際のデータを使った結果なので現実感があります。

続編(2)はこちらです。

■ ストライクゾーンと投球の判定
 ストライクゾーンについて、筆者が調べた結果は、図1右側に示したとおりです。ストライクゾーンは、ホームプレートを底面とする5角柱の立体です。ただし、高さ方向の範囲は、図のとおり、打者(とその構え)で変化します。つまり、プロット図の中の緑の長方形の枠は、平均的な打者のストライクゾーンを示したものであり、打者によって異なります。

 図1のプロット図は、主審が判定した、ストライク(オレンジ色)とボール(青色)を示しています。投球された球が僅かでもストライクゾーンに触れた場合はストライクです。球の直径はMLBの場合約7.5cmですから、ストライクゾーンの外でもストライクの場合が多いようです。中には、正面からはストライクゾーンに触れなくても、球筋が変化して、立体のゾーンの側面や底面に触れてストライクになる場合もあります。もちろん、誤審でストライクにした場合も含まれるでしょう。


 ここで確認ですが、上のプロット図の緑枠のストライクゾーンは、機械測定によるものであり、主審が判断したストライクゾーンとは必ずしも一致しません!

■ 
投球データを利用した学習
 上記で用いた投球データは、図2に示すように、5つの特性値からなっています。すなわち、球がストライクゾーンの正面の面を無限に拡大したと考えた場合に、その面に触れた時点のx座標値とy座標値、さらに、打者に依存するストライクゾーンの縦方向の上限値と下限値、そして、左打者か右打者かのフラグです。
 この5つの特性を持つ個々の投球を、主審の判定による2値ラベル(ストライクかボールか)に対応づけてあります。これを、機械学習させるわけです。


■ ニューラルネットワークの構成
 この機械学習は、参考文献[1][2]で行われていることを参考にして実行しました。具体的なニューラルネットワークの構成は以下のとおりです。2つの隠れ層をもち、それぞれの隠れ層の後にdropout層を挿入しています。
___________________________________________
 Layer (type)                 Output shape    Param #   
 ====================================================
 dense_Dense1 (Dense)         [null, 24]      144       
 ____________________________________________________
 dropout_Dropout1 (Dropout)   [null, 24]      0         
 ____________________________________________________
 dense_Dense2 (Dense)         [null, 16]      400       
 ____________________________________________________
 dropout_Dropout2 (Dropout)   [null, 16]      0         
 ____________________________________________________
 dense_Dense3 (Dense)         [null, 2]       34      
 ====================================================
 Total params: 578
 Trainable params: 578
 Non-trainable params: 0

■ 学習の結果
 学習用のデータは、上に示したように、5,000個です。評価用にも、これと同じデータセットを用いました。10エポックの学習(毎回ランダムに構成したバッチサイズ50のミニバッチを100個を学習)結果、正解率0.959が得られました。すなわち、このニューラルネットワークは、MLBの標準的な主審の判定結果と約95%合致(学習条件により若干変動)する結果を与えるものとなりました。つまり、投球のストライク/ボールの判定に関しては、理論上、MLB主審を努められそうな結果です!
epoch 1 ,  steps= 100 , loss= 0.339  ,acc= 0.879
epoch 2 ,  steps= 100 , loss= 0.281  ,acc= 0.839
epoch 3 ,  steps= 100 , loss= 0.332  ,acc= 0.859
 . . .

epoch 8 ,  steps= 100 , loss= 0.235  ,acc= 0.899
epoch 9 ,  steps= 100 , loss= 0.206  ,acc= 0.879
epoch 10 , steps= 100 , loss= 0.129  ,acc= 0.959
baseball.js:95 training done !

■ 感想
 プロ野球に限らず、他のスポーツでも、判定や採点の機械化の方向があるようです。しかし、プロ野球の場合、機械あるいはAIが主審の代役となることが望ましいのでしょうか。スポーツの人間味っぽいところが好きな人も多いはずです。投手、打者、審判とも、一瞬にして見極める技術を向上させているはず。また、観客も、「あれ、誤審じゃないの」とか、「あの主審は低めに厳しいよなあ」などと言い合いながら観戦するのも捨てがたい気もします。もちろん、判定で揉めた場合のリクエスト(現在でも実施されていますが)に対応するための、最新測定機器やAIの出番はもちろん増えるでしょうが。

参考文献
[1]
Nick Kreeger, Visualizing ML training using TensorFlow.js and Baseball data
https://observablehq.com/@nkreeger/visualizing-ml-training-using-tensorflow-js-and-baseball-d

[2] Predicting balls and strikes using TensorFlow.js
https://medium.com/tensorflow/predicting-balls-and-strikes-using-tensorflow-js-2acf1d7a447c

2021年11月5日金曜日

スマホでニューラルネットワーク(ml5JS/TensorflowJS利用)その2

【what is this】引き続き、「スマホでニューラルネットワーク」にこだわります。以前の記事 [1]では、Q-Learning(強化学習)をニューラルネットワークで行うための基本手法を検討し、実装しました。今回は、さらにそれを深めた手法である「Experience Replay + Target Networks」があることを知り、それをTensorflow.js (JavaScript環境)で構築し、妥当なQ値が得られるまでPCで学習させました。さらに、その学習済みモデルをスマホへ格納し、スマホのアプリとして、Q-Learningを用いた2Dグリッドの経路探索課題を解きました。

■ ExperienceReplay+TargetNetworksによるQ-Learningスマホアプリ
 この手法によるQ-Learningの結果を先に示します。課題は参考文献[1]で扱ってきた、2Dグリッドでの経路探索です。Fig.3にあるように、ロボットが壁や障害物を避けて宝石(緑色の球体)に最短距離で到達するように学習させます。その学習結果を、スマホアプリで示したのがFig.3です。この例では、ロボットが障害物(黒色の正方形)を避けてうまく宝石に到達するルートを学習したことが分かります。

■ ExperienceReplay+TargetNetworksの概要
 
強化学習は一般に、「教師付き学習ではない」と言われています。強化学習では、固定した正確なラベル(目標)を設定すること自体が困難です(というよりも、それ自体が求める解なのですから)。しかし、刻々変化するラベルを対象として、ニューラルネットワークで「教師付き学習」させる方式があります。それが、文献[1]で検討したものです。

 しかし、この方法には、2つほど欠点があります。一つは、「ある状態に対してある行動を取った場合」の一組づつしか学習できない。つまり、ニューラルネットワークで本来の性能を発揮するためのミニバッチ処理(多数の入力の一括処理)ができないことです。第二は、もっと本質的な問題ですが、この方法では、「状態と行動」が強く結合した学習となってしまい、多様な入力(状態)に対する学習が収束しずらいか、振動してしまう可能性が高いことです。

 これを解決すべく登場したのが、今回の「Experience Replay + Target Networks」なのです。小生の場合、参考文献[2][3]を読んでその概要を学びました。Fig.1に示すPseudo codingは文献[2]から引用したものです。これに従って、独自にJavaScript(Tensorflow.js使用)でそれを試作することができました。


 大雑把に言うならば、上図において、ExperienceReplayは、ミニバッチによる教師付き学習を可能にするために、replay memory Dに「状態と行動に関する観測結果」を蓄積していきます。そして、TargetNetworksの方は、上に述べた「状態と行動の関連性」を解消すべく、学習用のニューラルネットワークとは別に用意された、予測(prediction)用のニューラルネットワークです。すなわち、2つの分離されたネットワークを使います。TargetNetworksは、定期的に、学習用のネットワークの重みで置き換えられて、新しくなって行きます。このため、学習と予測のネットワークに時間差が生じますが、これが実は求めるべきQ値の推定を安定させることに繋がる。そのように考えられます。

■ Tensorflow(Python)よりもTensorflow.js(JavaScript)を使った理由
 この手法の実装における、「出力値とラベルの差(誤差)」の最小化を図るには、やはりTensorflowの学習関数(fit)を使うのが便利です。Pythonでやってももちろん良いのですが、今回は、JavaScript上のTensorflow.jsを使いました。その理由は、スマホアプリとの相性が良いことによります。
 ただし、学習済みモデルは、スマホ(あるいは外部の)webサーバに配置する必要があります。スマホ用のwebサーバーはいくつも公開されていますので、手軽に使えます。Fig.2はその一例です。この例では、学習済みモデルは2つのファイル(ネットワークトポロジー等の.jsonと重みの.bin)が、スマホのwebサーバに配置されています。スマホのアプリ側では、このモデルを(JavaScriptプログラムで)ロードして、予測に使うことができます。


■ 留意点:ExperienceReplay+TargetNetworksをTensorflow.jsで行う場合
(1)Tensorflow.jsは非同期関数
 Tensorflow.jsは非同期関数の仕様になっているので、その使用は、非同期関数(先頭にasync付き)の中で行う必要があります。そして、学習用のfit関数等を呼び出す場合は、awaitによって、fit関数の実行終了を待つ必要があります。そうしないと、思わぬところで別のコード部が実行されたりしますので、注意が必要です。

(2)モデルのsaveとloadの方法
 上に述べたように、学習用のネットワークtrain_netの重みを、定期的にTatget Networksへloadする必要があります。その際に、Tensorflow.jsは、非常に使いやすいsave/loadの仕組みを提供しています。つまり、以下のように、ブラウザのメモリにsaveできる、localstorageスキームを使うことができます。
    // target_netのモデルを更新するため、train_netのモデルをsave
    await train_net.save('localstorage://2dgrid_model');
    // train_netのmodelをtarget_netへロード
    target_net = await tf.loadLayersModel('localstorage://2dgrid_model');

 一方、これとは別に、train_netの学習済みモデルを外部へ取り出して利用したい場合には、downloadsスキームによって、save/loadを行うことができます。以下はその例です。
    // 学習済みモデルのダウンロード
    await train_net.save('downloads://2dgrid_model');
    // 学習済みモデルをmodelフォルダに配置してそこからload
    train_net = await tf.loadLayersModel('./model/2dgrid_model.json');

  なお、loadした学習モデルを単に予測に使うだけなら、これOKですが、さらにそれを学習させる場合は、以下のように、再度、最適化関数を同じものに設定してコンパイルする必要があります。
    train_net.compile({loss: 'meanSquaredError', optimizer: 'sgd'});

(3)学習関数fitへ与える入力データの形式
 PythonでのTensorflowでは、fit関数の引数となる訓練データとラベルデータは、pandas array形式ですが、Tensorflow.jsでは、通常配列をtensor2dで変換して与えます。

【注】上記の(1), (2)は、Tensorflow for JavaScriptの下位レベルAPIであるCore APIを使った場合です。そうではなく、上位レベルAPIであるLayers APIを使う場合には、非同期性を考慮しなくても使える関数が用意されています。

■ ニューラルネットワークの構成と学習性能
 上に述べた2つのニューラルネットワーク(学習用と予測用)の構成は以下のようにしました。試行錯誤の結果、これに落ち着きました。隠れ層は1層よりも2層の方が良い。また、隠れ層1層目のノード数はやや多い方が良い(ここでは128とした)などが分かりました。活性化関数は、隠れ層ではreluに、出力層ではlinearに設定しました。
_______________________________________________________
Layer (type)                 Output shape              Param #   
=================================================
dense_Dense1 (Dense)     relu    [null, 128]                512       
_______________________________________________________
dense_Dense2 (Dense)     relu    [null, 32]                 4128      
_______________________________________________________
dense_Dense3 (Dense)     linear  [null, 4]                  132       
================================================
Total params: 4772
Trainable params: 4772
Non-trainable params: 0
_______________________________________________________
(各隠れ層の後にdropout層を挿入した場合も試しましたが、この問題に関しては、特段の効果は確認できませんでした。)

 Fig.3に示した4x4グリッドについて、学習したモデルを次回の学習の初期モデルにしてさらに訓練を続けるというやり方で(ε-Greedyのεの値はその度に一定比率で減少させて)学習させました。その結果を使って、状態(宝石の位置、障害物の位置、ロボットの位置)をランダムに100組み生成して、ロボットが宝石に最短距離で到達できるか否かをテストしました。その成功率は以下の通りでした。
・1回目:0.97
・2回目:0.95
・3回目:0.97

■ 感想
 「不正確なラベル」を使って「近似的な解法」を実行して行くという、この(一見確信を持てないような)手法ですが、実際にやってみると段々にラベルが正確な値に近づき、正しい答えを出すようになるのは不思議な気もします..
 この手法で学習させた結果は、上記のとおり、かなり満足のできるものでした。従来のベルマン方程式に基づくQ-tableを構築しながら学習させる方法では、ほぼ確実に厳密解に到達できました。これに対して、今回のニューラルネットワークを用いた上記のExperience Replay + Target Networksでも、95%程度の正解率を得ることができました。そして、問題規模がさらに増大した場合は、Q-tableによる学習は明らかに破綻するので、今回の手法の有効性が高まるものと感じます。

 この実装は、ほとんどFig.1の情報だけから出発して(参考文献[2]や[3]に載っていたPytonコードを見ずに)、自分で考えながら具体化し、Tensorflow.jsを使って実現しました。どこか間違っているかも知れないという不安は残っていたのですが、上記のとおり95%の正解率を得ることができたので、恐らく、妥当な作りになっているだろうと思います。

参考文献
[1] Running Q-Learning on your palm (Part3)
[2] Jordi TORRES.AI, Deep Q-Network (DQN)-II
Experience Replay and Target Networks, Aug.16, 2020

[3] Ketan Doshi, Reinforcement Learning Explained Visually (Part 5): Deep Q Networks, step-by-step
A Gentle Guide to DQNs with Experience Replay, in Plain English, Dec 20, 2020


2021年10月17日日曜日

利尻山 初冠雪

本日(2021-10-17)北海道北部で、今季初の積雪が観測されたとのことです。さっそく、北海道最北端の名山、利尻山(利尻岳)の様子をライブカメラで確認してみました。冠雪というよりも、かなりたくさんの積雪がみられました。これから長い厳冬になります。

http://www.town.rishiri.hokkaido.jp/rishiri/ 
ライブカメラから引用(15:00ころ)

同(翌朝 07:00ころ)

同(翌日 15:00ころ)

2021年10月5日火曜日

スマホでニューラルネットワーク(ml5JS/TensorflowJS利用)その1

 【what is this】分類問題等で保持しているデータを使って機械学習させ、その結果を利用して、未知のデータを予測(分類など)したい場合があります。最近では、Tensorflow/Kerasなどを使えば、それは比較的楽に実現できます。ここでは、学習結果をスマホアプリに組み込み、スマホで利用することを行いました。Javascriptから使えるTensorflowJSML5JSを利用しました。

■ 例題:1700万種の彩色を9種に分類する
 R、G、Bそれぞれ、0〜255まで取る場合の可能な色彩の種類は約1700万になります。それを9種(緑系、桃色、橙系、青系、茶系、赤系、黄系、紫系、灰色)に分類したいとします。そのためには、以下のようにします。参考資料[1]にあるML5.JSの例題Color_Classifierを利用させていただきました。定番の手書き数字認識MNISTばかりではなく、この例題も魅力的ではないでしょうか?
  • ラベル付きの色彩データ(R:81, G:183, B:155→緑系、など)5,600組を用意
  • これをPC上の、下図の画面にあるようなニューラルネットワークで学習(各層へのバイアスの表示は略しています。)
  • 数十秒で学習は完了(スマホでも実行は可能と思われるが)
  • 学習結果のモデル(ネットワーク構造と重みデータ)をsaveしておく

■ 学習結果のモデルをスマホで利用する
 上記でsaveしておいた学習モデルを、スマホへloadします。それを利用するスマホアプリをMIT App Inventorで作成しました。すなわち、約1700万種の彩色のどれを与えても、的確に9種のいずれかに分類できます。下図に、実行例(緑系、紫系、桃色など)を示します。第2候補も示しています。



 ちょっとデザインに凝ってみます。以下の画面設計は如何でしょうか?こちらの方が、ニューラルネットワークでpredictionを行っているというrealityがあると思います。下図左側は、[紫系= 0.90, 青系 = 0.04]、右側は、[橙系 = 0.84, 黄系 = 0.12]という結果でした。どちらも納得できます。

 時間のかかる学習をPCやクラウドで実行させ、学習済みモデルをスマホへloadしてアプリケーションを作成するという一般的な方法ですが、実際にやってみると適用範囲が広そうなことを実感できます。

■ なぜスマホで?
  • MIT App Inventorを使うのですが、それに搭載されているWebViewerは強力なJavaScriptエンジンなので、Tensorflow.jsやml5.jsを活用できる。
  • デザインが楽しい。上図のように、好みの画面設計がとても容易にできる。
  • ニューラルネットワークを使う機械学習にもっと親しめる。

(補足)
  • スマホ上で、ML5JSやTensorflowJSを使うには、スマホ上にWebサーバを立ち上げ、ドキュメントルートを設定し、そこへ学習済みモデルファイルと、関連コード一式を配置する必要があります。この辺りが少し面倒ですが、分かってしまえばあまり苦になりません。
  • 別の問題として、最近のAndroid OSでは、このように立てたwebサーバに対しても、セキュリティが厳しくなっていて、いくつかのpermissionsが必要になるようです。また、どのWebサーバを使うかにもよります。例えば、Pixcel3a (Android 11)の場合は、比較的新しい"Serve:HTTP Server"と、古めの"KWS"サーバは共にOKですが、古いAndroid OS(Android 8.1)で利用可能だった"KSWEB"サーバは、403 Forbiddenのエラーが発生して使えませんでした。
参考資料
[1] ml5.js examples search, https://examples.ml5js.org

2021年9月25日土曜日

Running Q-Learning on your palm (Part3)

Japanese summary 本シリーズのPart1Part2では、スマホ向けのQ-Learningアプリを開発し、それを簡単な例(直線の廊下でロボットが宝石を得る)に適用しました。今回は、このアプリを改訂し、2次元グリッドでロボットが行動できるようにしました。そして、グリッドサイズが大きくなるにしたがい、これまでのQ-tableを保持してQ値を更新する方法は、メモリ量と処理量の急増により破綻することを確認しました。それに変わる有望な方法として、Neural Networkの利用を検討し、それを(スマホではなく)PC上のPythonで実現した結果を示します。

Abstract
In Part 1 and Part 2 of this series, I developed a Q-Learning app for smartphones and applied it to a simple example (a robot gets a gem in a straight corridor). This time, I revised this app so that the robot can act on the 2D grid. However, as the grid size increases, the traditional method of holding the Q-table and updating the Q value becomes difficult due to the increase in memory capacity and processing volume. As a promising alternative, I considered using a neural network. And here's the result of doing that with Python on a PC (not a smartphone).

 Revised version of the Q-Learning app
In the revised version of the smartphone app, as shown in Fig. 1(a), the robot is trained to reach the gem while avoiding barriers on the 4x4 grid. The Q-Learning algorithm is basically the same as last time. There is one gem and one barrier, and their positions change randomly for each play (every episode). The robot also starts from a random position. After sufficient training, the robot can always reach the gem in the shortest route. On the other hand, if not well trained, the robot often gets lost and hits a wall, as shown in Fig. 1 (b).


 Memory capacity required for Q-Learning
The size of the Q-table required for this learning can be calculated according to the grid size and the number of gems and barriers. See Fig.2. The number of Q-table entries (i.e., the number of keys) is the total number of possible states, which in Case 1 (4x4) is 3,360. At this level, it can be held sufficiently even on a smartphone, and the amount of calculation is within an acceptable range. However, in Case2 (5x5), the total number of states increases sharply to over 6,000,000, even though only one gem and one barrier have been added. In this situation, regardless of whether it is a smartphone or a PC, processing is almost impossible due to both the amount of memory and the amount of calculation.

 Calculate Q-values with neural network (without holding Q-table)
For cases like Case2 above, you can think of a way to calculate the required Q-value with a neural network without holding the Q-table. To do this, transform the Q-value update formula for the neural network, as shown in Fig.3. This makes it possible to compare output and target  ([1]). It can be used to solve this problem with common supervised machine learning. This machine learning iteration allows the output to be closer to the target and, as a result, the Q-value to be closer to the exact value.

Fig.4 clearly shows how to use this neural network in the case of Case1. Note that in this example, the action "W (west)" is taken in the current state S. In this way, one learning is done only for one action in one state. This learning should be repeated for as many actions as possible, in as many states as possible.

 Calculation example of Q-value by neural network
I implemented a learning method using such a neural network in Python and executed it on a PC. This program is based on the Python program (using Tensorflow / Keras) published by Dr. Makoto Ito in reference [1]. Fig.5 shows the learning process for Case1 (4x4). It shows the situation where 10000 episodes were randomly trained. In the upper graph, the average sum of rewards per episode has reached about 0.8. On the other hand, when the neural network is not used, as shown in the figure on the right of Fig. 1(a) (although the characters are small and difficult to see), it is 0.8305, so both results are almost the same. The lower graph shows that the average number of steps a robot takes to reach the gem is about 2.9. This value is also valid considering the situation in Fig.1.


I have omitted the details, but in the case of Case2 (5x5), I was able to train well with this neural network as well. It took only about 3 minutes to run on a general PC, so I was able to confirm the usefulness of this method. This time I've only used the most basic neural networks, but for more complex problems (for example, if you need to remember the location of an object), you may need other neural networks such as LSTMs.

Acknowledgments
I was able to create a Q-value calculation program using a neural network by referring to the Python program published in the reference [1]. I would like to thank Dr. Makoto Ito, the author of this article.

References
[1] Makoto Ito's Blog Article: M-note Program and Electronic Work (in Japanese)
     http://itoshi.main.jp/tech/

2021年9月12日日曜日

Running Q-Learning on your palm (Part2)

 Japanese summary 前回の記事では、スマホ向けのQ-Learningアプリを開発し、それを簡単な例(ロボットが宝石を得る)に適用しました。今回は、ロボットの行動にいくつかのバリエーションを与えてみました。その場合でも、新しい行動の記述を追加する以外は、このスマホアプリをほとんど変更していません。今回の例題でも、Q-Learningによる学習の結果、ロボットは宝石を得るための最適な手順を自ら発見できました。

Abstract
In the previous article, I developed a Q-Learning app for smartphones and applied it to a simple example (a robot gets a gem). This time, I gave some variations to the behavior of the robot. Even so, I haven't changed much of this smartphone app, except to add a new behavioral description. In this example as well, as a result of learning by Q-Learning, the robot was able to discover the optimal procedure for obtaining the gem.

# For the case where the robot moves on the 2D grid, please see this revised version.

 New examples (two cases)
As in the last time, as shown in the figure below, the task is for the robot to move the corridor and get the gem. The actions that the robot can take are different from the last time, but learning the best steps to successfully acquire a gem is the same.



Consider the following two cases regarding robot behavior and its rewards. In both cases, an episode ends when a "Take" is performed (regardless of success or failure) or the robot deviates from the corridor boundary.

Case1:
  • Take: Take the gem (reward = +5 if successful, otherwise -1)
  • Forward: Move forward one block in the corridor (reward = -1)
  • Jump: Move forward two blocks in the corridor (reward = -1)
Case2:
  • Take: Take the gem (reward = +5 if successful, otherwise -1)
  • Back: Go back one block in the corridor (reward = -1)
  • Skip2: Skip two blocks in the corridor (reward = -1)

 Learning results in Case1 and the robot moving example
As a result of fully executing Q-Learning for Case1, we obtained a highly accurate Q-table. Using it, the robot was able to discover the optimal procedure for obtaining the gem, as shown in Fig.1. In the initial state of this example, the positions of R (Robot) and G (Gem) are expressed as "R . . G . .". The corresponding maximum value of Q-table is given by "Forward" and "Jump" (where, both values are 3.0.). Whichever is adopted, it will be the same after all, but here, "Jump" was taken. At the transition destinations after this, the action that maximizes the Q-table value was also taken, so the gem was successfully acquired. This is the best procedure.


 Learning results in Case2 and the robot moving example
The robot's actions possible in Case2 is different from Case1, but similarly, the robot was able to discover a procedure for obtaining the gem. The situation is shown in Fig.2. In the initial state of this example, the positions of R (Robot) and G (Gem) are expressed as "R . G . . .".  This procedure is optimal by combining "Skip2" and "Back".


Here's another slightly more complicated example in Case2. See the Gif animation below. In this example, the robot found the best steps to get the gem:

“R . . . G .”  →Skip2BackBackSkip2Take[success]

 Setting rewards according to purpose
The reward values shown above can be changed depending on the purpose. For example, unlike the above, let's say you want to get the gem in the best way, even if the robot starts at any position. In such cases, change the reward design of Case 2 as follows and name it Case 3.

Case3:
  • Take: Take the gem (reward = +5 if successful, otherwise -1)
  • Back: Go back one block in the corridor (reward = -1 if it is in the corridor after moving, otherwise -2)
  • Skip2: Skip two blocks in the corridor (reward = -1 if it is in the corridor after moving, otherwise -2)

This reward design will serve your purpose, as in the examples below: