2021年6月28日月曜日

梅雨の合間の小さな生き物

 このコロナ禍、気軽に旅行にも行けません。暫し、近所のちょっとした水場を散策する日々です。そんな時に出会った小さな生き物たち、何か安らぎを与えてくれます。以下の写真は、ニホンアマガエルとハグロトンボと思われます。

こんな石柱を登って何処へ行くの(厚木市郊外にて)
おーい、そんな高い所まで行ったら、降りられないぞ。


いつの時代からこんな華麗なスタイルに(厚木市郊外にて)
翅を開くもまたよし


2021年6月20日日曜日

A list of my articles about MIT App Inventor apps

I have written about 300 posts on this blog, including articles on computer science and smart phone applications. Most of them are written in Japanese. However, some of them on MIT App Inventor were written in English, so that people outside Japan can also read them.

Here is a list of articles about MIT App Inventor written in English. I would be very happy if people who are going to use App Inventor to develop new apps can refer to them.

# Various apps using App Inventor 

Make a mini calendar app for Android, celebrating the New Year

Beautiful mountain view comes automatically to your smartphone 

Finally arrived! Beautiful mountain photos that were automatically recognized!

Supporting social dilemma experiments with App Inventor 

Voice Calculator: well-crafted AI tutorial 

Using the MIT App Inventor FaceExtension (for Facemesh) 

Identify the position from the key point number in Facemesh

Enjoy finding out Hamiltonian Cycles

Enjoy Reinforcement Learning in Tic-tac-Toe 

Enjoy live cameras from across the world on your smartphone 

Timer Overhead(in MIT App Inventor)

Firebase GPS demo made with ThunkableX (common to Android & iOS)
(Note: This app uses ThunkableX, not MIT App Inventor)

# Using the App Inventor Extensions (JSON, AWS, etc.)

A JSON Decoding Extension for App Inventor (1)  

A JSON Decoding Extension for App Inventor (2) 

Another example using JSON Decoding Extension

Decoding JSON by using new Dictionary Blocks 

A good example of Extension for App Inventor 

Using MIT App Inventor AWS AI Services Extension 

Creating my own extension blocks for App Inventor

# Linking App Inventor and micro:bit 

Cooperation between micro:bit and MIT App Inventor with Eddystone signals (No.1)

Cooperation between micro:bit and MIT App Inventor with Eddystone signals (No.2)

Cooperation between micro:bit and MIT App Inventor (No.3)

# Using JavaScript in App Inventor

Make MIT APP Inventor more powerful with JavaScript 

Writing formulas in both AppInventor and JavaScript 

# More App Inventor resources

Rapid Prototyping Using App Inventor in Information and Computer Sciences Course

Empowering Students to Develop Mobile Applications by Using App Inventor for Android

2021年6月18日金曜日

ちょっと惹かれるPython1行コード(その2)

 【what is this】前回に引き続き、短くて美しい1行コードを検討します。参考文献[1]を参考にしています。Pythonの初心者が中級へステップアップするのに適しています。小生もこれに該当しますので、個人的な忘備録でもあります。

■例題:漁獲高の平均を上回る漁港をリストアップする
 今回データ分析の対象とするデータ(参考文献[2]を参考とした)を以下に示します。Python numpy配列であるFHには、主要な漁港名9つを格納しています。そして、別のnumpy配列Vには、この漁港の順に、2014年〜2018年の5年間の漁獲高(水揚げ量)を万トン単位で格納してあります。

【解くべき問題】
 上記データ45件(=9漁港x5年)の平均値を一回でも超えた漁港を示すこと。
【解答プログラム】
 以下の1行コードが解答プログラム(出力込み)です!
答えは、"銚子"、"釧路"、"焼津"の3漁港でした。

■一行コードの分解 ...
 上記1行コードをすぐに理解できる人は少ないかもしれません。そこで、その中身を分解してみます。最後には、「なるほど、素晴らしい!」となるでしょう。

(1)平均値を求める
 これは下図のように、簡単です。

(2)平均値を超えるか否かを真偽配列で表す
 この真偽の配列は、下図のように生成することができます。numpyのbroadcastが働いています。

(3)"True"の位置のインデックスを求める
 上図の真偽配列において、'True'となる位置のインデックスを下図のように求めます。ここで、numpy関数nonzeroが使われていますが、'nonzero'は、Pythonでは、'True'に対応することに注意します。全45件のうち、13件が'nonzero'であり、その位置のインデックスは、下図のように2次元配列で表されます。
 例えば、上段の'0'と下段の'0'のペアは、銚子漁港の最初(2014年)のデータが、平均直を超えていることを意味します。また、釧路漁港(上段インデックス4)は、3回平均値を超えたことが分かります。

(4)漁獲高の絶対値はここでは不要
 上図は、2次元配列になっていますが、ここでは、漁港名に対するインデックスだけわかれば良いので、最初の1次元配列だけを取り出します。下図で、'[0]'がそれを実現します。

(5)インデックスのリストを配列に与える
 次に、このインデックスを漁港名に変換するのですが、以下のように、インデックスのリストを配列FHに与えることができます。

 
 これに従って処理を続けると、以下のように、漁港名のリストが得られます。

(6)最後は集合(set)で仕上げ
  最後に、漁港名の重複を除去するため、set関数を適用します。完成!

■補足(Excelファイルを使う)
 上記のnumpy配列FHとVの設定に、以下のようなエクセルファイル(fishVol.xlsx)を利用しても良いでしょう。(pandasを使いますが、別途openpyxl, xlrdのインストールを要します。)

[参考文献]
[1] Christian Mayer, "Python One-Liners", No Starch  Press, 2020.
[2] 図録 主要漁港別水揚げ高(日本地図)とその推移, 2020.https://honkawa2.sakura.ne.jp/7400.html

2021年6月11日金曜日

ちょっと惹かれるPython1行コード(その1)

【what is this】誰でも、短くて美しいコードに憧れます。参考文献[1]には、Pythonによる1行コード(Python One-Liners)の考え方と実例がたくさん載っています。それを参考に1行コードを2つほど書いてみました。

■例題:キノコの毒性に関するデータの学習と学習結果による予測
 機械学習の分類問題として、キノコを有毒か無毒かに分類することをやってみます。図1には、キノコの色(赤、青、黄)、笠の形(丸、角)、柄の長さ(長、短)、場所(地面、樹木)の特性によって、それが有毒か無毒かのデータ(参考文献[2]から引用)があります。これを機械学習によって学習させ、さらに、その学習データが正しく分類(予測)されたかどうかを確認します。

(注)上記データは現実のキノコにそのまま当てはまるものではなく、あくまで機械学習を学ぶために用意された仮想データです。従って、実際のキノコの毒性判定には利用しないでください。

■
SVMとRandomForestの一行コード(学習と予測)
 2つの手法(SVM-サポートベクタマシンとRandomForest)によるPython1行コードとその予測結果を示します。図2は、SVMの場合です。Python numpy配列のスライシング(特性データと正解レベルを分離するため)を行い、学習(.fit)結果を予測(.predict)へ接続しています。確かに、素早く簡潔なコーディングとなりました。学習に用いたデータに対する予測結果は、正解率89%でした。9件のうち1件のみが誤まった判定となりましたが、こんな少ないデータでも良く予測できることが確認できました。


 次は、RandamForestによる場合です。こちらの結果は正解率100%でした。素晴らしい!やり方は、SVMの場合と同様です。


 なお、図1での特性データは数値で与えたが、日本語で与えたい場合は以下のようにして、別途用意した辞書型変数Dを使い、map(lambda式を使う)処理を施せばよい。以下の実行結果は、図3での実行結果と同じになります。


 上図の変数Yの計算は、以下のどちらでも良いでしょうが、2番目の方がちょっとだけ分かりやすいかもしれません。
 Y = np.array(list(map(lambda i : list(map(lambda j : D[j], i)), X)))
 Y = np.array(list(map(lambda i : [D[j] for j in i], X)))

■何のために1行コードを書くのか
 さて、参考文献[1]の最後に、以下のような叙述がありました。納得ですね。
Don't cram everything into a single line of code just to show off your one-liner superpower. Instead, why not use it to make existing codebases more readable by unraveling their most complex one-liners?
(単に何でもかんでも1行に詰め込むのではなく、複雑なコードを読みやすくするために!)

[参考文献]
[1] Christian Mayer, "Python One-Liners", No Starch  Press, 2020.
[2] 黒橋禎夫, "改訂版 自然言語処理", 放送大学教育振興会, 2020.

2021年6月9日水曜日

「強化学習理論入門」の最終章は深層学習だった

 【what is this】強化学習理論入門を書籍[1]で学んできましたが、その最終章(第5章)は深層学習でQ-Learningを行うものでした。ここでその技術を述べることはできませんが、最後の例題「あるけあるけゲーム」でその魅力に浸りたいと思います。

■DQN(Deep Q Network)
 これまでに、行動ポリシーπについて、状態価値関数Vπ(s)や、行動-状態価値関数qπ(s, a)を計算して、最善の行動ポリシーを求めることをやってきました。しかし、状態(s)の数が非常に大きい場合などは、全ての状態についてこれらの関数値を保存しながら利用することは困難となります。(例えば、囲碁の場合、盤面の状態の数は10の172乗というとてつもない数になると言われています。)
 そういう状況で、状態価値関数や行動-状態価値関数の近似値を、ニューラルネットワークを利用して計算するというのが、この書籍[1]の最終章のテーマです。特に、先に述べたQ-Learningをニューラルネットワークで行うのが、DQN(Deep Q Network)です。また、この実行性能をさらに高めるために、「モンテカルロ・ツリーサーチ」の基本(実行時の一歩先読み)についても取り上げられています。

■DQNによる「あるけあるけゲーム」
 ここでとりあげる「あるけあるけゲーム」の規則は、図1の右側の説明にあります。キャラクターは障害物(および自分の辿った場所)を避けて、できるだけ長く歩く、というものです。何の方策もなく歩くと、図1の結果のように、長さ(Length)5程度で短く終わる場合が多いです。自分の軌跡に戻ってしまってゲーム終了となる場合も多いです。


 これに対して、DQNで一定程度学習した後に歩かせると、図2のとおり、長さ20程度まで伸びる場合が多いです。


 このDQNでの学習結果を使って、実行時にさらに一歩先読みする方法(モンテカルロ・ツリーサーチの考え方に基づく)によれば、図3のとおり、著しく長く歩くことができます。なかなか素晴らしい結果だと思います。


■上記DQNの構成と実行時間
 このゲームを、如何にしてベルマン方程式に結びつけるか(アクション、報酬、状態の設計)、そして、さらにどのようにニューラルネットワークで学習させるのか、それを学べるのが、この書籍の第5章なのです。図4はその最終的な結論としてのDQNのネットワーク構成です。詳細を掴むにはこの書籍を読んで戴く必要がありますが、画像認識で多用されている畳み込みフィルター(conv2d層)が使われている点がポイントの一つです。これは、別々のレイヤーに置かれたキャラクタと障害物の位置関係を把握するためです。


 畳み込みフィルタ(5x5を8種)、隠れ層2層(2,048ニューロンと1,024ニューロン)などが含まれているので、辺の重みやフィルタ値など合計で約500万個のパラメータを最適化することになります。そのため、Google Colab(GPU利用)で、図2に示した学習に約30分を要しました。しかし、パラメータ数は膨大のようにみえますが、上記のゲーム場面のすべての状態数よりははるかに少ないです。

■本書[1]で学んだ感想
 基礎から始めて高度な強化学習理論が実に丁寧に説明されており、最後まで挫折せずに読めました。書籍によっては、最初は緻密な説明がなされていても、途中から杜撰な叙述になったり、急に飛ばしはじめたりする場合もあるのですが、本書は全くぶれることなく、最後まで緻密な説明で貫かれています。Pythonのコードの説明も、同様に非常に詳しく、読者にとってとてもありがたい。完全に理解したとは言えないかも知れないが、この強化学習理論の専門書(5章構成、全283ページ)を丸々一冊読み上げたということで、力がついた気がします。
 なお、著者自身によって、この書籍全体を要約解説したスライド50枚も公開[2]されており、(本書を読み終わった後に)知識を整理するのに大いに役立つと感じました。

■本書に関する小生のブログ記事
 実は、この書を読みながら、自分のメモとして、これまでに、以下の記事をこのブログに書いて来ましたので、よろしけばご参考にされたい。

[第1章] 強化学習のゴールと課題
[第2章] 環境モデルを用いた強化学習の枠組み
[第3章] 行動ポリシーの改善アルゴリズム
[第4章] サンプリングを用いた学習法
[第5章] ニューラルネットワークによる関数近似
 ・「強化学習理論入門」の最終章は深層学習だった(↑今回の記事)

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月
[2] 中井悦司:60分で学ぶ「強化学習理論入門」、2020/09/04
https://speakerdeck.com/enakai00/60fen-dexue-bu-qiang-hua-xue-xi-li-lun-ru-men?slide=50

2021年6月4日金曜日

強化学習:モンテカルロ法とQ-Learning

【what is this】強化学習に関するさらなる続編です。前回のレンタカーショップ問題とは異なり、環境モデルが分からない場合の例としての迷路問題をとりあげます。そして、その解法としての、モンテカルロ法とQ-Learningの性能を観察します。

■迷路問題とレンタカーショップ問題
 先のレンタカーショップ問題では、ある状態Sにおいて行動aを取った場合に、得られる報酬rと次の状態S'が起こる条件付き確率が分かっている(計算できる)必要がありました。しかし、現実の問題ではそれを満たさない場合も多いです。以下に述べる迷路問題(開始点から終点までの最短経路を求める)もその一つです。

■モンテカルロ法とQ-Learning
 ここでは、迷路問題に対する解法として、モンテカルロ法とQ-Learningなどを検討しています。本記事は、実際のところ、これまでと同じく、中井悦司著[1]の第4章を学んだ成果を簡単に書いたものです。
 モンテカルロ法では、上に述べたような条件付き確率に頼るのではなく、シミュレーションによって、行動aに対して得られる結果の情報にもとづいて学習を行います。この方法では、シュミレーションのエピソード(episode:開始点から終了点に達する)が完了した情報が必要です。これに対して、Q-Learningと呼ばれる方法は、エピソードの完了を待たずに、1ステップ分の新しい情報を使って学習を進められる点が特徴です。

 手法の詳細は、参考文献[1]などをお読みいただきたいのですが、ここでは結果だけを示して、さらに知識を深める手掛かりとしたいと思います。図1は、両方法による迷路の最短経路の探索結果です。開始点(S)からゴール(G)を目指して、壁(#)を避けながら、上下左右のいずれかへ進みます。両方法で辿ったパスは違っていますが、ともに最適解になっているはずです。注目すべきは、学習に要した時間です。Q-Learningの方が圧倒的な高性能を示しました。


 これらの性能をさらに明確に示しているのが、図2です。学習中にどれだけの長さのepisodeを得たかを比較しています。モンテカルロ法では、初期の段階では、非常に長いepisodeを取得しながら学習しています。つまり、長いパスをさまよってなかなかゴールへ辿り着かない状況となっています。これに対して、Q-Learningでは、開始まもなく、急激に短いパスとなり、効率的に学習が行われていること示しています。


■感想
 冒頭に述べた中井悦司著[1]では、今回の第4章(Q-Learningあたり)がクライマックスと言えましょう。しかし、書籍全体の約6割を占める第3章「環境が分かっている場合」の状態価値関数による(ベルマン方程式に基づく)統計学的な厳密解の求め方までで、それに必要な基礎は出来上がっています。つまり、第3章まで熟読すれば、第4章はスムーズに理解できるはずです。この書では、非常に丁寧な叙述が特色であることを強く感じます。また、確認のためのPythonコードについても詳しい説明がついていますので、少なくとも、Pythonの初級を終えていれば、理解にはほとんど困らないと思います。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月

2021年5月28日金曜日

レンタカーショップ問題(強化学習での行動ポリシー最適化)

    【what is this】強化学習における「状態価値関数」をとりあげてきましたが、今回もその続編です。理論と手法の詳細は参考文献[1]を熟読戴くことにして、ここでは、「レンタカーショップ問題」と呼ばれる複雑な問題がこれに基づいて解けることを楽しみたいと思います。

■レンタカーショップ問題(Jack's Car Rental)
 この問題は著名なSuttonの著作[2]にありますが、簡潔に1ページに纏められており、そこから自分でプログラムを作るのは難しそうです。しかし、中井悦司著[2]では、実に丁寧にこの問題の設定と具体的な解法(Pythonプログラム付き)が解説されており、非常に有用です。このブログ記事は、それにしたがって学んだ結果を小生なりにまとめたものです。

 図1に、この問題の設定条件を示しました。2つの店Aと店Bを持つオーナーが、車貸出しによる利益を最大にするために取るべき行動(戦略)を求めます。その行動とは、営業終了後の夜間に、2つの店の間で適当な台数の車を移動させることです。両店の貸出し/返却の台数の発生確率が異なるため、翌日の営業に備えて、両店の車の台数を調整する必要があるのです。ただし、車を移動することで一定の損失(余分なガソリン代など)が発生します。


 両店の貸出し/返却の台数の発生確率は、ポアソン分布に従っており、その期待値は図1の説明文にあるように分かっているとします。図2に示すような確率分布となります。


■マルコフ決定過程における確率的な状態遷移
 この問題を解くためのベースとなる状態遷移を図3のように定めます。ある時点の状態は、店Aと店Bに現在残っている車の台数のペアとします。営業終了時(午前中は貸出しのみ、午後は返却のみ)の状態をSとします。それに対するアクションa(行動a)は、夜間に店Aから店Bへ|a|台の車を移動させることを意味します。逆向きの移動ではaの値は負値になります。その行動が終わり、さらに翌日の営業が終了した時点の状態をS'とします。つまり、状態Sにアクションaを適用した結果の状態がS'です。

 状態S'では、車の移動による損失と、貸出しによる利益が確率から計算されています。貸し出し/返却台数は乱数で決まるので、図3の遷移は、確率的な状態遷移を含むマルコフ決定過程といえます。この状態遷移をもとに、先の記事でも述べたベルマン方程式を作ることができます。ベルマン方程式を解くことは、各状態の価値(状態価値関数)を計算することになります。

 そして、状態価値関数はアクションaによって決まるわけであり、どの状態に対しても最も大きな状態価値観数値を与えるアクションを求める方法があります。その一つが、ここで使われている価値反復法と呼ばれるものです。

■価値反復法によるレンタカーショップ問題の最適解
 この方法は(詳細はここには書けませんが)、行動-状態価値関数計算とGreedyポリシーの更新と状態価値関数の更新をセットとして、全ての可能な状態(店Aと店Bに残っている台数のあらゆる組合せ)について行います。それを、すべての状態について変動がなくなるまで反復します。反復一回あたり計算量(可能なあらゆる台数についての確率計算を含む)は相当に大きくなりますが、種々の効率化手法がとられます。最終的には、比較的少ない反復回数(数十回程度)で収束解(最適解)が得られるようです。図4は、収束の途中の解(行動ポリシー)を示しています。


 そして、図5は、収束した最適解(最適行動ポリシー)の拡大図です。一つのマスは、一つの状態(店Aと店Bに残っている台数のペア)です。マスの中の数値は、店A→店Bへ|a|台の車を移動するという行動を意味します。この結果を眺めてみて、十分納得ができるように思います。

 全体としては、残っている台数が両店間で偏っている場合は、それを補正する方向になっています。ただし、両店の貸出し台数の期待値(ポアソン分布の)の違いを反映して、店Aから店Bへの移動が多くなっています。
 例えば、店Aに15台、店Bに2台残っている状態では、限度いっぱいの5台を店Bへ移動すべきとなっています。これは、店Bの方がポアソン分布の期待値が大きいことを反映しています。逆に、店Aに2台、店Bに15台残っている状態では、店Bの方が期待値は大きいものの、店Bから1台を店Aへ(少し損失は生ずるが)移動した方が全体の貸し出し数は増えるという判定となっています。


 図5の最適行動ポリシーによる状態価値関数の値を図6に示します。両店にともに車が多く残っている方が、翌日の営業での利益を大きく期待できることを示しており、これも納得できます。

■感想
 冒頭に述べた中井悦司著[1]は、全体で5章の構成、本文全276頁です。今回の話題は、そのうちに第3章(全体の約6割)までの集大成と言えます。つまり、状態遷移を表す条件付き確率が全て計算できる「環境が分かっている」場合の基本的な強化学習理論の結論であると言えましょう。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月
[2] Richard S. Sutton and Andrew G. Barto, "Reinforcement Learning : An Introduction", second edition, The MIT Press, 2018.

2021年5月22日土曜日

MIT App Inventor Summer Appathon(ハッカソン)のご紹介

すでにご存知の方も多いと思いますが、簡単にご紹介致します。


このハッカソン(Appathonとなっていますが)、名称の通り、MIT App Inventorを利用します。この開発環境には、各種Webサービス連携、データベース機能(CloudDB, FirebaseDB等)、種々の組込みセンサや外部ボードとの連携(シリアル、BLE等)、豊富なGUIやメディア機能、JavaやJavaScriptの呼び出し、等々が標準装備されています。さらに、多彩なExtensions(特に機械学習関係、Unixコマンド使用、等々)も続々提供されています。

大学でのセミナーや卒研レベルにも有用かと思います。下記の通り、混成チームもありですから、この沈みがちな時世に、教員と学生が絆を深める(強める)機会として共同で挑戦と言うのもありそうです。

他のコンテストなどと同様に、創造的発想が重視されますが、それを実現したスマホアプリの提出が必須です。審査員は、提出されたソースコードを可能な限りビルドして動作を確認するようです。もしも、使用される外部デバイスなどを用意できない場合は、(提出必須の)ドキュメントと動作ビデオでも審査されるようです。

ハッカソンなので、開発期間はテーマ開示後2週間です。(ただし、昨年度のテーマや入賞作品を参考に、事前準備はある程度可能でしょう。)子供/大人、個人/グループ(子供大人混成含む)などのトラックがあります。例年、世界各国からかなり多数のエントリがある一方、最終的に完全な提出まで漕ぎ着ける人はそれほど多くはないようです。かなりキツそうですが、それだけにやり甲斐があるでしょう。当然ながら、未発表作品に限られます。

入賞作品はMITのサイトに大きく掲載され、世界中の人に認めてもらえるという、本来の姿の栄誉を受けられます。(入賞賞品は特にありませんが)純粋に創作活動を讃える場のように思います。

(補足)--------------
えっ、冒頭の説明があってもなお、App Inventorではもの足りない? (^^ゝ
Really? Then you are a true professional. But don't you find the following few applications that work with Java and JavaScript helpful? :-)

●例1→かなり複雑な計算を含む処理にはJavaを使う。
既存のJavaコードをブロックから呼び出す例は以下にあります。
App Inventor for Android で SVM(サポートベクトルマシン)分類

●例2→自分好みの新たなブロックをJavaで自作する。
JSONのデコード用の新たなブロックをJavaで作った例です。
A JSON Decoding Extension for App Inventor (1)

●例3→JavaよりもJavaScriptを使いたいのならば。(基本編)
Make MIT APP Inventor more powerful with JavaScript

●例4→もっとJavaScriptを活用する。(学習済みモデルの利用)
MIT App InventorとGoogle Teachable Machine2を連携させた例です。

●例5→Eddystone信号でmicro:bitと連携する。
Cooperation between micro:bit and MIT App Inventor with Eddystone signals (No.1)

2021年5月17日月曜日

利尻岳(北海道)五月の風景

  最近になって、北海道にも新型コロナウィルスに関する緊急事態宣言が発令されました。現地へ出かけることはできませんが、利尻町のホームページで公開されているライブカメラで利尻岳(利尻富士とも呼ばれる日本百名山の一つで標高1,721m)の様子を楽しむことができます。最近そこで閲覧した、残雪の美しい山の風景を以下に載せたいと思います。


●利尻町ホームページ
(注)上記写真掲載は、上記の「利尻町ホームページへのリンクを希望される方へ」の利用ガイドラインに沿って行っています。

2021年5月15日土曜日

トランザクションデータのグループ化(JavaとPython)

    【what is this】トランザクションデータなど、複数のカラム(キー)からなるデータを、特定のいくつかのカラムについて、階層的にグループ化したい場合があります。JavaとPythonを使って、簡単な例で試してみます。

 本記事で扱う小さなデータ(csvファイル)とソースコード(JavaとNotebook形式Python)はこちらにありますので、よろしければお使い下さい。

■例題:トランザクションデータ(通貨取引)のグループ化
 何をしたいのかを、図1で説明します。図1(a)は、参考資料[1]のcsvデータを若干編集したものです。先頭行は、3つのカラム名(City, Currency, Value)を示しています。2行目以降のトランザクションを集約して、右側の(b)に示すように、取引所(City)でグループ化し、さらに通貨(Currency)毎の取引額(Value)の平均値を求めたい。この処理は、初歩的なプログラミングでも可能ではありますが、恐らく、込み入ったものになるでしょう。ここでは、分かりやすく、効率的なプログラムにしたいのです。


■JavaのStream、groupingByの利用
 図2に示したJavaプログラムは、StreamとCollectionのチュートリアルである参考資料[1]を参考にしています。まず、1〜2行目で上記のcsvデータを読み込み、3行目でトランザクションを3つのカラム対応のデータに分割しますが、データの先頭行は不要なので4行目のfilterで削除します。5行目では、各トランザクションに対するオブジェクトを生成しています。そのクラスの定義は(b)にあります。このオブジェクトのプロパティを利用して、6〜7行目で、Cityについてグループ化し、さらにCurrencyについて纏めてそれらの平均値を得ています。ストリームに対するgroupingByが2重に適用されているところがポイントです。ここで、例えば、「Tranz::getCity」は、トランザクションオブジェクトに対して、一斉にクラスTranzのメソッドを適用する(Cityデータを得る)ことを意味します。8〜11行目は結果の出力表示です。


 1〜7行目までの、2重のグループ化では、if文もforループ文も使われておらず、処理の流れを把握しやすいのが魅力です。実行結果は、図1(b)のようになります。

■ Pythonのpandas、groupbyの利用
 次に同じことを、資料[2]を参考にしてPythonでやってみます。グルーピングの考え方はJavaの場合と同じですが、Pythonでの記述量は、図2(a)のように大幅に少なくできます。実質1行(4〜5行目に渡る)で、右側の(b)の実行結果が得られます!素晴らしいですね。PythonのモジュールPandasを使っており、そのなかのgroupbyが効果的に働いています。そして、Javaの場合に切り捨てた先頭行のカラム名(City, Currency, Value)が、自動的に内部で生成されるオブジェクトに対応しています。


 このように、PythonのPandasは効率的プログラミングに貢献しています。しかしながら、これで全面的にPythonの勝利ということではないでしょう。Javaの場合は、明示的に生成したオブジェクトと一連の処理がstreamとして分かりやすいという捨てがたい魅力があります。また、JavaのStream(とそしてラムダ式)は、マルチコアマシン上での並列実行性能を高めるためにあるとも言われますので、大規模データ処理の場合の性能比較も楽しみになります。

[参考資料]
[1] Raoul-Gabriel Urma, "Java SE8ストリームを使用したデータ処理(パート1 & パート2)", Oracle.com/JavaMagazine, March/April, 2014.
[2] Soner Yıldırım, "3 Python Pandas Tricks for Efficient Data Analysis",
https://towardsdatascience.com/3-python-pandas-tricks-for-efficient-data-analysis-6324d013ef39