Gemを作って気がついたこと

 書捨ての100行ぐらいのスクリプトではなくて、RubyのGemを公開するのは2回目である。前回のGemは変なGemだったので、ある程度ちゃんとしたGemは今回が初めてだと思う。いくつかやっているうちに気がついたことがあるので、忘れないうちに文章にして記録する。

ソフトを世界中に公開できる手段があるというのは気持ちいい

 まずはポジティブなところから。やっぱり gem install で簡単にソフトウェアを流通できる環境といいうのは便利でものすごいことだと思う。アイディアを形にしたら発表して、地球の反対側に住んでいる人にも瞬時に使ってもられる。これって控えめに言っても、大変なことだと思います。

シミュレーションが作りたいのかな

 私は大量のデータから、単純な回答を求めるものよりも、シンプルなルールから複雑な結果を生み出すものが好きらしい。シミュレーションを作る場合、シミュレーションを実行するクラスと、GUIを表示する2つのクラスを作成するのがよいようだ。大量にデータを扱う場合は、drubyやApacheArrowなどを挟んで非同期的にするとスピードが早くなるのかもしれない‥けどわからない。大量のデータを検索するようなものが必要になったら sqliteや ActiveRecord みたいなものを勉強していけばよいのかな。

Gemには命名規則がある

 知っている人には当たり前の話なのだろうけれども、単語の区切りは _(アンダーバー)、既存のGemやクラスの拡張は – (ハイフン)でつなぐ。Gemの命名はディレクトリの構造と一致するようにする。

Vimで複数の文章を開いてコピペするのが苦手

 普段はvimで満足している(基本機能しか使いこなせていないけれど)。Jupyterのように一つの100行ぐらいの書捨てのスクリプトを書けば満足なので初心者向けの機能で十分なのだ。しかし、Gemを作る場合には、クラスごとにファイルを作成するから、AのファイルからBのファイルに飛び回る、コピペするといった操作が必要になる。これが私にはできなかった。geditとかを開いてGUIでっている。しかし、本当は勉強すればVimでもできるはずだ。とりあえず画面のスプリット機能を使いはじめてたけれども、慣れるまでかなり時間がかかりそう。

クラスを作成する場合や、メソッドを作成する場合に、自分のいるスコープの外側に何があるか気にする

 書捨てのスクリプトだと、いつでもトップレベルからスタートするので、自分の外側の世界に何があるか、ということを気にしなくてもよかった。トップレベルからrequireしたり、includeしたり、ネストしたクラスを作る場合でも、基本的には内側へ内側へとモジュールが広がっていくので、外側の世界を気を配る必要はなかった。しかしGemを作る場合や、既存のライブラリを拡張する場合は、このメソッドはどこに生やすべきか、そのメソッドがいる場所から外側にはどんな世界が見えるべきか、ということを考える必要がある。

 メソッドがどの場所に生えているか、どのスコープに存在するか、モジュールとモジュールの内包構造をどうするか、という問題について、オブジェクト指向の強いRubyでも、特殊な記法を採用しているように見える。new とか使わないで人間の視覚に訴えかけるように、モジュールやクラスを定義するという感じで。

 あるモジュールから動的に特定の条件のメソッドだけ引っこ抜いて、よそのクラスに打ち込んだり、特異メソッドを互いにやりとしたり、その時々の状況に応じて、クラスの継承関係がダイナミックに逆転したり、といったことはあんまりやらないみたいだ。

 そう考えると、どのクラスがどのクラスを内包するか、メソッドがどこの場所にあるか、という場所をあとから変更するのは用意ではなく、一旦その骨格が決まってしまうと、あるパッケージ・ライブラリの進化の律速‥などという言葉があるのかわからないけれども‥のようなものになりやすくなっていると思われる。思いつきだが、ランダムにスコープやモジュール構成や、メソッドの範囲が変化するようにしておいて、どのような構成の時に最も落ち着くか、焼きなますようにしてシミュレーションしていくと面白いかもしれない。その場合、ユースケース(評価関数)に応じて局所最適解がいくつもあって、そのために同じような機能でも、ライブラリが複数発生するのだとしたらおもしろいと思う。こんどぜひともやってみたいけれども、本当にそんなことできるかな? そういうシミュレーションはAIによるプログラミングにつながっている気がする。GANのように、APIを使うAIと、設計するAIが、相互作用のなかで学習してライブラリを成長させていく。そんな妄想。

 自然界であ、AとBの2つのモノの相互作用の近くに複雑な構造が現れていくというものが多いから、そう考えると、クラスやモジュールの膜の表面に複雑なメソッドがはえていくのも、相互作用の中で表面が複雑化していく自然現象に似ている気がする。クラスやモジュールの内包関係が一旦規定してされてしまうと、なかなか変化せず、持続的な進歩を行うよりも、まっさらな状態から新しく作り直した方が早いケースが多いところも似ている。

 やや話は変わるけれども、普段の生活でも、この場やスペースがどういう場所で、職権がどの範囲まででとか、そういうことを考えなければならないシーンは多い気がする。モジュールの外側の世界を気にし始めたら、実世界でもそういう自分の外側にあるスコープがやけに気になるようになった。

 うーん、考えていたらずいぶんと遠いところにきてしまった。

やっぱりそれ以前にモジュールとか、特異メソッドとか、モジュールのインスタンス変数とか、クラス変数とかよくわかっていない。もちろんlambdaとprocの違いも

 ここのへんはRuby関連の読み物の中ではしょっちゅう出てくるけれども、未だにさっぱりわからない。悲しい。

トップレベルにメソッドを生やしたい場合は、Kernelモジュールを拡張すればいい

 タイトルの通りだけれども、awesome_print のようにトップレベルにメソッドを生やすタイプのライブラリーってどうやって定義しているのだろうかと思って調べて知った。

Gemは $LOAD_PATH にファイルを追加している

 これは gemspec を見れば気がつくことだけれども、今まで見過ごしていた。思ったより簡単な仕組みなんだなと思った。今はたまたまGemという仕組みが普及しているけれども、パッケージの作成、管理、配布を行う別の方法があってもおかしくないと感じた。

 $LOAD_PATHをRubyドキュメントで調べて、Kernel モジュールの中に特殊変数という名前のグローバル変数があることを知った。この特殊変数たち、大事なんだろうけれども、何となく見た目があまりかわいくない感じがするな。あくまでイメージの話だけど。

GUIを作るのは案外むずかしい

 世の中はプロが作った使いやすいGUIがあふれているため、GUIを作るのは簡単だという気がしてしまう。でも、それは思い違いだと思った。上の話と似ているけれども、あとから、この機能がほしい、あの機能がほしいという感じで少しずつGUIを修正して改変していくと、最終的に出来上がったものが微妙になっていく傾向があるみたいだ。

 GUIを考えるときは、一旦頭の中を博しにして、PCの電源を切って、コードのことは忘れて鉛筆と上で図面を書きながら考えることが必要みたい。

 少なくとも既存のGUIを眺めながらこっちの方がいい、あっちの方がいいと逐次的に修正を繰り返すだけではよいGUIを作るには不十分みたいである。GUIビルダーで仕上がりを観察しながら作れば、コードを手打ちするよりも便利なGUIができる、というわけでもないんだなということがわかった。

 市販のソフトで、GUIとデザインに半分以上のお金を払っているんじゃないかと感じることは多い。そういうものを「ギミック」と軽視する向きもあるけれども、やっぱりプロの仕事というものはすごいものだと思う。そういう無形の価値も評価されて、正当な対価が支払われるといいと思う。

今のところRuby/GTKでGIOのリソースやcomposite classを使う意味は薄いかな

 使ったほうが便利な場面も出てくるのかもしれないけれども、私のシンプルな使い方では compsit class を使うメリットはあんまりない感じがした。Windowsだとglib-compileresourcesとか、個別の環境では動かないこともあるし、とりあえず素人が書くぶんには、クラスを継承して、GObjectとRubyのオブジェクトを一致させようとか考えずに、委譲を中心にやっていった方がいいみたい‥というか難しくてそれしかできない。

Ruby以外の言語のことも勉強した方がいい気がした

 Rubyのこともよくわかっていないし、他の言語を勉強する能力も余力もないけれども、やっぱり世界にはたくさんすごい人がいて、その人たちはRubyではなくて、いろいろな言語でソフトを書いている場合が多いので、そういうものを雰囲気だけでも、やっぱり他の言語もちょこっとだけでも触れてみる方が人生が豊かになるんだろうなと思った。時間は有限だけど。

Gray-Scott というのを作ってみた記録

Qiitaへ投稿しようかとも思ったが、わからないことだらけなので、おとなしくブログにしておこうと思った。

  • 行列計算 : Numo::NArray
  • GUI : Ruby/GTK3

Git: https://github.com/kojix2/Gray-Scott

 f = 0.04, k = 0.06 の場合は上のような模様が表示される。

 まず、Gray-Scottとは一体何なのか、私にはさっぱりわかっていない。難しいのでNumpyのサンプルをNumo::NArrayに書き換えているだけである。中身はちっともわかっていない。

 書店でこの本を見つけて、買ってしまった。まだ読んでいないのだが、とりあえず一番最初に出てくるGray-Scott がすごい。ググるとWebGLを使ってヌルヌル動くデモがヒットするのだが、素晴らしくて度肝を抜かれた。自分でも作りたくなった。本のサンプルはPythonやNumpyで書かれているので、スピードや見た目よりもわかりやすさ重視である。素人がNArrayに逐語訳して勉強した気になるには最適である。

 CPUだと遅いのでこの機会にCumo/NArrayを試してみようかしらん、とも思ったが、Ubuntu18.10には公式のCudaが提供されてない。Cuda/Nvidia-driverをインストールするときは、高確率でブラックスクリーンに遭遇して時間を消耗するのでせっかく調子よく動いている手元のパソコンでは試さないことにしておく。

 今はRuby/GTKの勉強中なので、Ruby/Tkを使えば簡単なのにという気持ちもあったが、Ruby/GTKで作ってみることにした。

 GNOMEの画像を扱うっぽいオブジェクトはたくさんあって、どれがどういう関係なのか、きちんと把握できていない。まずCairoというライブラリがある。これはサーフェイスを作って、サーフェイスに書き込んで、PNGやPDFに保存するという仕組みらしい。次にPixbufというのがある。これは行列のような感じで、スケールを変更したり、bmpやpngで保存したりといった基本的な機能だけ持っているようである。GtkImageというのが、Gtkで画像を表示するウィジェットらしい。このほかにGtkDrawingAreaというものがある。これはCairoと組み合わせて使うらしい。動画の再生のサンプルなどでもDrawingAreaと組み合わせて使っている例がある。今回DrawingAreaを使うか、GtkImageを使うか迷ったが、StackOverflowで、DrawingAreaよりもGtkImageの方が軽いと主張しているサイトを見つけたので、GtkImageにNArrayから作ったデータを入れたPixbufを流し込むようにしてみた。一瞬RedArrowという単語が頭をかすめたがそんな難しいものを使う必要はないであろう。GtkImageはマウスのイベントを補足してくれないので、マウスの位置情報などを取得したい場合は、イベントボックスを親に配置する必要があるようである。本当にこのやり方が良いのかはわからない。そのほかにClutterとか、Gstreamerとかもあるが、これらはもっと難しそうである。

 さて、Ruby/Gtk が Ruby/Tk と比較して特に優れているところは、Gladeを見ながらGUIを作れるところだと思う。Gladeは不安定でクラッシュしやすいが、メインウィンドウに表示されているウィジェットをあれこれクリックしなければかなりクラッシュの頻度を下げられるという知見を得た。

 今回Gladeで気になったのは「シグナルハンドラー」の欄の右隣にある「ユーザーデータ」という項目である。これが何を意味するのかわからないが、シグナルが呼ばれたときに、一緒にウィジェットを渡せるという意味ではないかと推測している。しかしRuby/GTKではそのようには動作しなかった。使い方が間違っているのかもしれない。Glade は Microsot Office のように項目が膨大なので、使いこなせるようになるにはかなり時間がかかりそうだ。

 そのほか気になったのは、GLib::Timeout.add の部分だ。GUIのライブラリはメインループを回しているのでループしたいときに処理を待つ必要が出てくる。Ruby/Tkの場合はスレッドとの相性が非常に悪いことで有名で、drubyサーバーのプロセスや、処理専用のプロセスを別に立てて動かすとうまくいく。しかし、Ruby/Gtkで遊んでいる人はあまりいないみたいなので、どうすればいいのかわからない。GLibを勉強して、なるべくGLibの仕組みに乗っかるのがいいのか、やっぱりdrubyサーバーを立てるのか、Ruby本体をもっと勉強すればなんとかなるのか‥。そもそもGLibやRubyの非同期処理を理解することは可能なのか。少なくとも、GLib::Timeout.add で秒数を指定するだけだと、処理が終わらなかった時に、フリーズするみたいだ。

 NArray の演算は inplaceを使った方が2割ぐらい早いらしいので、今回は積極的にinplaceを使ってみた。inplaceという表記は長くて、現実的ではないので、横着だけどエイリアスをつけて_(アンダーバー)に置き換えることにした。Alifeの元本では、laplacianの計算に、rollというメソッドを使っていたが、NArrayではこれは未実装であったので、その部分は逐語訳した。そのほか濃度を彩度に変換した方が見栄えがいいのでインターネット上に公開されているNumpyのコードをありがたく参考にして、HSV→RGBの処理をNArrayで書いた(書き写した)が、この時にマスキングの不具合をみつけた。きちんと計測したわけではないが、HSV→RGB部分の処理はかなり時間がかかっているようで、改善の余地があると思う。

 できあがったものは、WebGLに比べるとだいぶ速度は遅いものの、だいたい期待通り動作するようだった。Ruby/Tk で作ったソフトよりも見栄えがいいのが嬉しい。

 さて、これで何を考えるか、というと、いろいろと思うところはあるのである。f や k の値をいろいろ変えて遊んでみたけれども、いずれのパラメータのときも、生命現象に非常によく似ていて、めちゃくちゃ興味深いと思った。でも慌ててなにか考える前にしばらくは頭の中にぼんやりとどめておくことにする。


Ruby/Gtk のつらいところなど

 Ruby/Gtk をさわり続けようとしているけれども、やっぱりいろいろな意味でドキュメントが無いのはつらい。

 意外だったのは、GNOME に関する日本語の文章が少ないところ。書きたい初心者いっぱいいると思ったんだけどいない。技術的な文章は、読んでもわからないからよいとして、Macでありがちな思想を語る感じのエモい文章、そういうのも読みたいと思ったけど全然ない。GNOME 思想でググると、リーナスがGNOME3に不満とか、GNOMEの思想は腐っておるとか、そういう末期感あふれるページばかりが上位にヒットする。2018年の地球はUbuntuがUnityやめてGNOMEに戻ってきた世界線なんですけどね。やっぱり Linux のデスクトップ環境を使っている人は少ないのだろうか。

 そもそもGNOMEの思想というものは存在するのだろうか。私はRuby-GNOME2に触れるまで、勝手にGTKは保守本流だと思っていた。FirefoxとかThunderbirdとかのイメージがあるし、キュートで緑なアイツに比べると古くて落ち着いて枯れた感じがする。Qtは開発企業がどんどん変わってスれてしまい、ちょっと幸薄なイメージだ。KDEアプリはGNOMEアプリよりクラッシュしやすい気がする。(まあGlade先生は鬼のようにクラッシュしますけどね)

 けれども、歴史を振り返ってみるとGNOMEは互換性のない変更をかなりやらかしているらしい。Ruby-GNOME2のパッケージもごっそりと大量に入れ替わっている。昔からLinuxデスクトップ使っていた人には常識なのだろう。私は最近までMacやWindowsばかり使っていたし、エンジニアでもなんでもないので全然知らなかった。GNOMEが枯れた感じになったのも最近のことなのだろう。

 GNOMEの創始者のイカザさんという方は、私の中ではMonoDevelopを作っている人のイメージである。調べると会社がすでにMicrosoftの一部になっていたり、途中Mac環境を使用していることを公言したり。そりゃあ創始者がそう言うぐらいならGNOMEは混乱して当然なのだろう。そういう紆余曲折もあって、思想なんかぐっちゃぐちゃで、したがって熱く語る人もいないのかも知れないない。

 さて、日本語のドキュメントが少ないのは仕方がないとして、英語の初心者向けドキュメントも少ないのにはがっかりした。RubyでダメなときはPythonの英語のドキュメントをググると大体解決する。PythonのGTKバインディングは、今はPyGobjectと言うらしい。ところがこれが、GitHubで71しかスターがないのである。少なすぎである。

 もちろんGitHubはGNOMEにとって本家ではなくて、GitLabが本家である。そういう理由もいろいろあるのだろうが、それを考慮しても71はマジで少ない。率直に言って、人気がないのだろう。

 そんなPyGobjectだが、英語の公式ドキュメントも、いまひとつ魅力がないのであった。あまり読みたい気持ちにならない。

 考えてみると、それも当たり前の話で、gobject introspectionを使うということは、APIを設計しない、という意味する。つまり人々が使いやすいようにするという意識を何度も通過してPyGobjectを作るわけではないため、その点については思い入れが薄くなるだろう。だからバインディングの作者は公式のドキュメントを書くモチベーションが低くなるのだろう。また書くべきですらないかもしれない。本家GNOMEリファレンスを見れば常に最新の情報が手に入るわけで、そうするべきかも知れない。

 他のやり方としては、ドキュメントを自動生成するのも悪くない。Rubyの場合はyardでドキュメントがサクサク閲覧できると嬉しいのだが今のところそうはなっていない。yard-gobject-introspection というのが開発中らしい。しかし、仮に自動生成できたとして、生成されたドキュメントに魅力があるかということは別問題である。

 プログラミングの素人には、Cの粒度はいつ見ても細かすぎて難しいと感じる。というか何をみてもだいたい難しい。エンジニアの人は難しいって言ったら負けだろうけど、私はエンジニアじゃないので正直言って、コンピュータの全てがこんがらがっていて難しく感じられる。ああ難しい難しい。

 GUIのライブラリーは、Shoesみたいに簡単なのがいいのかも知れない。でも個人的にはShoesはなんか嫌い。Shoesは最初に触ったときからずーっと嫌いだからもう変わらないと思う。Shoes系は簡単だけど、全然軽くない。やっぱりTkの手軽さ、書き味の柔らかさが過小評価されているんじゃないかなと思う。でもLinuxをメインにしてから、Tkのウィジェットは見た目が汚なすぎて、使う気が起きないけどな。

Crystal言語がはやい

すごい!

素人でも気軽にたのしくRubyで高速計算する方法を探してきた。そしてNArrayをみつけた。しかし、数年ぶりにNArrayを超えるかもしれない逸材を発見してしまった。Crystal言語である。Crystal言語は、マルチプロセスに対応する気もあるらしく、xargsやparalellジェムを日々愛用している私はとても期待している。そんなCrystalのメモ。

開発者

アルゼンチンに住んでいる

コンパイル

速度比較

色々な言語で計算速度を比較してみたを参考にライプニッツ級数の計算で測定した。グラフを見ると、Rubyと全く同じコードにも関わらず、コンパイル時間を含めてもNArrayより早いことがわかる。これはただ事ではない。PCによってはもっと差が出る印象。

Ruby & Crystal

NArray

 realusersys
Ruby61.887s61.812s0.028s
Crystal (コンパイル&実行)7.923s7.900s0.196s
Crystal (最適化コンパイルしたものを実行)6.821s6.812s0.000s
Numo::NArray10.163s9.860s0.256s

ほんの少しさわってイマイチに感じるところ

半日さわった印象としては、型のキャストがわかりにくい。たとえばUInt8をfloat32やfloat32に変換する方法をググってもしばらく見つけられなかった。.to_fでよいらしいが、.as(Float64)とかで統一してくれた方わかりやすい気もする。あと、どうしてもコンパイルに時間がかかる。kemal(sinatra相当)使ったコードをコンパイルするだけで体感数秒以上かかる。GUIライブラリが弱くてキャンバスに図形描写したりするの苦手っぽい。ライブラリ眺めてる pointerof とか出てくる。コンピュータに強い人にとっては長所なんだろうけど。

よいところ

crystal shards コマンドが優秀。Rubyもこうあるべきだと思う。htop眺めてると、files = Dir.glob files.each とかやったときに自動的にマルチスレッドしてくれているっぽい。だいたいRubyと同じ。コミュニティの雰囲気も洗練されていて悪くなさそう。とにかく処理が早い。

追記:さらに1日さわってRubyとの違いを感じたところ

上記は、数値計算のことだけを考えていたので、オブジェクト指向の部分、クラスやメソッドなども少し触ってみたらRubyとかなり違いがあった。まずは型チェックが厳しい。ある程度はコンパイラ?が型を推測してくれるが、必ずしも推測万能ではないので、推測が難しいところは自分で型を指定していく必要がある。特に引数のチェックは厳しい。Arrayとかは最初に型を指定する。こんな制約もあるので何でもかんでもArrayを使うべきではなく、構造体とかタプルとかSliceとか用途に合った型の採用を検討するほうがいいかも。デバックの時にRubyとはかなり頭の切り替えが必要そう。いろんな型を受け取るメソッドはオーバーライドという書き方も使って行く。ゲッター、セッターは、attr_readerの代わりにgetterとか名前が違う。irbがないので、crystal playを使う。(こういうのはRubyにも搭載されているべき。Jupyterに依存するべきではないと思う。)cloneとかequalとかto_jsonとか動かないので、自分でコードを書く必要がある。そして便利なマクロが用意されているので、それを使う。マクロは便利そうだが直感的になんとなく闇を感じる。2つobjectをreternするときはタプルが便利。injectのかわりにreduce、””と”意味が違う、require_relativeない。プライベートメソッドはprivate def hogeと書く。Threadとかも何気に動くっぽいけど、spawn使えとのこと。forkもあるっぽいが試していない。RubyはC言語のライブラリをラッパーになって処理を呼んでるだけの場合も多く、そういうものはCrystalに書き直しても大して早くならない。そのため「Crystalizationで爆速!」が(俺の趣味レベルで)実現できる範囲は思ったより狭いかも。コミュニティ若いので、ちょっとドキュメント書くだけでも歓迎される雰囲気がある。すごい。

使い分け

NArrayの方が可読性がよいので、特にスピードを求める部分だけCrystalで書けばいいと思う。素人なので、難しいことは考えずにパイプでつないだり、普通に実行結果をファイルに保存して、処理をつないでいけばよいと思う。Rubexとかもいいけど、やっぱり簡単な方がいい。

ビットコインと癌とひらめきとネットワーク

ずっと前からぼんやり考えているアイディアと、昨日思いついたアイディア。

 ビットコインの仕組みがよくわかっているわけじゃないけど、癌との何らかの類似性がないかを考えている。組織の定常性が保たれている状態から、ある時から癌が発生していく状態が、ビットコインが負のサイクルに陥って終焉していく状態に似ているのではないかという妄想である。そもそもビットコインが終焉していくのがどういう状態なのか誰もわからないので、そんな類似性が本当にあるのかわからないが。ビットコインが終焉する段階では、マイナーの数も減り、簡単に誤ったブロックを生成することができるようになり、そのようなブロックがあちこちで生み出されるような気がするのである。そのような状況が本当に訪れるのかわからないが、癌と類似するのではないだろうか。この世の中の安定性や定常性は、手段があっても時間内にできないという事を基盤に保たれていることが多く、暗号もその一つだ。そのあたりと癌の類似性がどうなっているのか、なんとなくひっかかるものがある。そこらへんに若い頃は癌が発生せず、年齢を重ねてから癌が発生する秘密が隠されている気がする。とはいっても、生体はビットコインよりもずっと複雑だし、具体的にどのようにアナロジーを考えればいいのか全くわからないけどね。

 もうひとつは昨日思いついたアイディア。ディープラーニングで、特徴次元を落とした多次元空間を探るのは難しい。一つの学習モデルが作られたとしても、それを他の構成のネットワークに流用することは難しい。こういうのを人間はどうやってやっているんだろうか。僕が何かを考えていて、一番楽しいのは、全く別の場所のアイディアを他の場所に投影すると、意外な類似性を示すときだ。例えば、(本当にそんな類似性があるのかわからないが)上の段落で書いたビットコインと癌のように。これは、ある場所で使っている認識の構成を、他の場所に流用することとも考えられるかも知れない。つまり、人間は、特徴空間の構造を識別して、他の特徴空間と比べたり、ある場所で使っているネットワークを他の場所でも使ってみるというようなことが柔軟にできるのかも知れない。

 忘れないように書き留めておく。

Chainerの勉強中

とてもわかりやすい本です。読みながら勉強。

途中でお世話になったサイト 〜Pythonの基礎知識〜

Pythonの知識ゼロなので、適宜ググりながら読み進める。
Python: オブジェクトのメソッド一覧を取得する
Pythonでのファイル操作
クラス継承
Chainer v1からChainer v2への移行
Python入門 – リスト・タプル・辞書
__future__ モジュールについて

Rubyと違うところなど

・Pythonでは関数はオブジェクト
・Pythonでは空白インデントが意味を持つ
・Pythonではファイルが自動的にモジュールになる

Chainerのバージョン確認

Configオブジェクト

trainモードとtestモード

Variableクラス

numpy.ndarrayまたはcupy.ndarrayを梱包している。
どの関数から生成されたか記憶してあるため、計算グラフを構成できる。

ネットワークのグラフを描写する

誤差逆伝播の対象にするかどうか

Functionクラス

大量にあってどれが大事なのかよくわからない
https://docs.chainer.org/en/stable/reference/functions.html

Linkクラス

全結合のもの

p77 Chainerの主要クラスの関係性が秀逸

Optimizerクラス

Trainerクラス

なんとなく半分ぐらいわかった気になったので、exampleのコードを改変して遊んでみる

最小限MNIST

この資料が大変よい
Chainer: ビギナー向けチュートリアル Vol.1

MNISTでCNNもやってみる

Mnistのデータを3次元で呼ぶ必要がある。RubyとちがってMapできないから面倒だなと思ってforループで変換していたが、
chainer.datasets.get_mnist(ndim=3)
すればよいのだ。

MNISTのはずれ画像を眺めてみる

人間でも間違えそうなものと、人間だったら間違えないものが含まれている。とくに8は間違いすぎていると思う。
全体的に値の少ない文字のほうが間違いにくいという傾向があるように思われて、とても興味深い。










データセットクラス

データセットもクラスであると。(numpy配列, 正解ラベル)タプルの集合みたいになっている。
あらかじめchainerに同封されているサンプルデータもある。
・MNIST dataset
・CIFAR-10 (3, 32, 32) 50000 10000
・CIFAR-100 (3, 32, 32) 50000 10000
・Penn Tree Bank dataset as long word sequences (929589, 73760, 82430)
・Penn Tree Bank word vocabulary (dict 単語=>数字)
・SVHN dataset (3, 32, 32) 73257 26032

オプティマイザ

・AdaDelta
・AdaGrad
・Adam
・MomentumSGD
・NesterovAG
・RMSprop
・RMSpropGraves
・SGD
・SMORMS3

イテレータクラス

以前は自分でfor文書いてたらしい
・SerialIterator
・MultiprocessIterator

アップデータ

・Updater
・StandardUpdater
・ParallelUpdater(parallel GPU Updater)
・MultiprocessParallelUpdater(multiprocess parallel GPU Updater)

目標逆算と予想介入 2つの考え方

これから1ヶ月〜数カ月ぐらいかかるような大きめ仕事が増えていくと思うので、昔の記憶を思い出して書いてみる。

 これから書くことは、私が大学生の時に学祭の準備をしながら考えたことである。だから本当はかなり前の話になる。

 社会に出てからは「何をやるべきか」について自分の頭で考えて決断しなければならないような機会は少なかった。避けてきたと言ってよいかもしれない。世間では、自分の頭で考えることが大事だと言われている。しかし実際には、自分の頭で考えることが望ましいとは限らない。狭い視野で考えた結果が、集団心理に流されるよりも正しいという保証はどこにもない。個人の狭い考えで何か事を起こして、いざ問題が起こったら大変である。そうならないように、組織は大きな力で個人が自分の考えで行動しないように工夫している。それに第一、自分の頭で考えるということは大きな苦行なので、あまり続けていると精神がまいってしまう。こうしてみると果たして考えることが良いことなのかもわからない。…しかし、今日はその話はしない。

 2つの異なる考え方がある。これを「目標逆算」方式と「予想介入」方式と名づけることにする。世の中には仕事のハウツー本がたくさんあるので、それぞれの方式に、それらしい正式名称があるのかも知れない。とはいっても、大学生が考えたことなので、大した内容ではない。

 大きなプロジェクトに取り掛かるとき、人はそれを細かい仕事に細分化する。大きな仕事を、扱いやすい適度なサイズまで小さく切り分けて、紙に書きだしてリストアップする。頭の中だけで、仕事を整理しようとすると、やらなければならない事に抜けが生じるので、紙に書き出すことが大事だと思う。大学祭の準備で、僕が仕事が進まずに困っていると、ある先輩が「困っていることを全部紙に書きだしたか?」と尋ねてきた。紙に書いて、問題を実際に実行可能なサイズまで分割することが、とても大事だというのだ。これが「目標逆算」方式の考え方だと思う。

 大学生はみすぼらしいけど、夢がある。大学祭でも大きな理想を立てる。「これがやりたい」「あれがやりたい」と大きなプロジェクトが立ち上がる。一度目標を立てたら、その目標を達成するために必要な「やらなければならないこと」をノートにリストアップする。まず目標を立てて、逆算して仕事を分割し、最後に実行するので、これを「目標逆算」方式と名付けた。この、目標逆算方式は、確かに最初はうまくいくのだが、やがて目標と現実の乖離が目立ち始め、締め切りが近くなると、「あれも間に合わない」「これも間に合わない」として、否応なしに目標の方を下げていくことになる。少なくとも私の場合はそういうことが多かった。そして、大学生らしく、最後は徹夜の突貫工事が始まるのである。そして、プロジェクトが成功しようがしまいが、終わったあと、ちょっとした心の傷を負うのである。(それもよい思い出である)

 どうして、必ずこうなってしまうのか、うまくいかないのか。悩んでいた時に思い浮かんだのが「予想介入」方式だった。これは、目標逆算とは逆の方法だ。まず、目標は立てない。何をやろうとも考えない。もしも何の対策もせず、地球を放置していたら、この先ものごとがどう回転していくか、人々が何を重い、どう行動するかを、勝手気ままに予想する。その上で、望ましくない未来が生じる兆候をみつけた場合は、それに対してどのような変化を加えればいいか、介入すればいいかを考えるのである。この方法を使うと、「目標逆算」では想像していなかったようなボトルネックに気が付きやすくなる。それに目標逆算方式よりも、人々の気持ち…たとえば怠け心とか…汲んだ予想が行われるので、たとえ成果があがらなくても、「予想した未来よりはマシな結果になったな」と考えて、心の傷も負いにくいことがわかった。この方式を未来の予想に介入するため「予想介入」方式と名付けた。しかし最終的なアウトプットが、先ほどの目標逆算方式よりも高くなるとは限らない。

 以上が、つまらないが大学生のときに考えたことだ。自分の頭で考えて行動している人たちからみると(そういう人が多いとも思わないが)、ごく当たり前で初歩的なことが書いてあると思う。

 私は「予想介入」が苦手だ。だから、もし「目標逆算と予想介入のどちらがより高度な方法なのか?」と言われたら、「たぶん、予想介入の方が高度な方法なのだと思う」と答えるだろう。なぜならば、予想逆算は自分自身に対する予想ふくむ。つまり自己言及的要素があるためメタ度が高く難しいと思われる。また、予想逆算は、自分自身の心の中にあるポリティカル・コレクトネスを一時的にoffにして、自分自身の直感的なセンサーに正直になる必要がある。これも大変難しいことだ。

しかし、世の中には予想介入にばかり特化して、およそ目標逆算はできないといった人々も確かにいるらしく、その人たちはその人たちで、困ったものだろうと思う。

 実は最初は、目標逆算方式のことを「理想追求方式」と名付けようと思っていた。でも予想介入方式が理想を追求していないのかと言ったら、そうじゃないと思う。このあたりは「理想」、ひいては「自尊感情」、「モチベーションの維持」などの問題が絡むので考えるのが難しいところだ。そういうわけで十分に頭の中で整理できないので書けない。きっと誰かがいいことを書いているのだろうが、どうやってググればいいのかもわからないので調べにくい。

人工知能に神を期待すること

タイトルは釣りみたいなもので内容も中2みたいなエントリーだが、4月ごろからフワフワと考えていて、なかなか文章にできないことをアウトプットしてみる。

人工知能脅威論ってネット上でもよく見かける。たとえば

 > 将来は人工知能が全部決めて人間が従うだけ
 > 人工知能が人間に対抗してくる 

などなど。でもディープラーニングによる画像認識のようなちゃちなソフトを人工知能と言うなら、これはおかしな話だと思う。
なぜこんな認識違いが起こるかというと、実は人工知能が脅威だと思っている人と、そう思っていない人ではそもそも人工知能に求めている「機能」が違うんじゃないかっていう話です。

少し話が飛躍するかもしれないが、どんな組織でもいいので、日本型組織を想像してほしい。
働かないトップがいる。実務家がいる。

トップは必ずしも物事の詳細について詳しいわけではない。実務家ほど仕事ばかりやっているわけでもない。全体の方向性を決めたり、たまに口を挟む程度で、実権はあまりない。単なる偉い人だ。
一方で実務家は現場で指揮を取ってあくせく働く。知識も経験も豊富だ。何か決定したら、トップに奏上する。トップはこれを承認する。

実は、トップは余裕がある組織でないと養うことはできない。実務家だけの組織や、実務家がトップを兼任している組織はたくさんある。
それでも、僕は、働かないトップがいる組織の方がパフォーマンスがいいのを何回も見てきた。働かないトップを支えるのは日本型組織の一つの理想形だと思う(多分)。ただし働かないトップを養うためには組織の余裕がかなり必要になる。ある意味贅沢品である。(豊かであるからトップが養えるのか、トップがいるから豊かなのか、というのは難しい問題である。)

ここで、トップの果たしている役割と、実務家の果たしている役割は全く違う。
にもかかわらず、トップは実務家のように知識や実行力が豊富であるべきだとされ、実務家はトップのように品格のある人であるべきだとされる。

トップの果たしている「機能」は明らかに重要だが、その意味・内容は実務家のもたらす「機能」と違って明瞭ではない。トップとは何をしている人なのだろうか。

私は仕事でも、あえてこの「トップ」の持つ役割・機能を意識して振る舞うときがある。つまり自分は何もしなくても、ただ黙って傍らで他者の仕事を眺めているだけで、自分は何らの知識や技能がなくても、何もしないよりはうまく仕事が回転していくことをよくある。本当に何もしていない。ただ横にいて見ているだけなのだ。誠に非科学的な話かもしれないが、この時、私は心理的には上司や同僚や部下の心理的負担に手を差し伸べている。お金に例えると、自分はなにもしていないが精神的に作業に「出資」しているような状態だと思う。私は実際には何も働いていない状況ではあるが、人々は私の精神的な出資率も高いと判断して、私も仕事の完遂を願っていると判断して勝手に行動してくれる。そして、終わったあとなぜかとても感謝される。

一方でこの精神的な出資のことを意図的にまたは無意識のうちに軽視していると、どんなに実務能力があっても、あいつは「未熟」であると影口を叩かれる。

このような状況は誰しも経験するのではないだろうか。

上司がまだ仕事をしている時に、特に用事がなくても居残ってしまう日本人の奇妙な性質もこれで説明ができる。例えシゴトをしていないくても、上司と一緒に居残りしている彼は精神的に出資をしているのだ。そしてこの精神的な出資が、とてもありがたく感じられるのである。(念のために書いておくと、そのような仕事法の総合的な善悪までは私は判断しかねる。)

出資者には当然要件があって、それは「仕事の成功を強く願っている」ということが必要だ。逆に「願う」ことさえできれば実務能力はゼロでも構わない。

では「願う」とは何なのだろうか? 既存の枠組み…たとえば強化学習の延長線上で、それは実現できるのか?

その答えは現状では2通りあると思う。(1)マシーンは願っているふりをすることができる (2)マシーンが願うことは実現できていない。
両方共正解だ。欲望するコンピュータというものがまだ開発できていないので(2)は当然だ(本当かな?)

それより(1)に注目したい。人間は仮想的なマシーンを頭の中に構築することで、願っているふりをするマシーンを作ることができる。え?意味がわからないって?もう少し読み進めてほしい。

組織や国家は、昔から膨大な予算をかけてこれをやってきた。卑弥呼の時代から、人々は祈祷をしてきた。シャーマンとはひょっとすると、願う力の強い人たちである。膨大な僧侶を雇い、彼らは鎮護国家を祈祷…「願って」きた。僧侶は膨大な知識を使って仏教理論を構築していった。

奈良の大仏様をみてみよう。人々はコレが銅の塊に過ぎないことを知っている。しかしそれは同時に宇宙の真理を人々に照らし悟りに導く仏なのである。平安時代の人々は仏教による鎮護国家を目指して、真面目に国家予算を使ってこの大きなオブジェを作った。

このオブジェは実質的には何の機能も持たないが、「願う」機能を持つと想定されるオブジェであり、人々を何もせずに「見て」いるのである。つまり擬似的に「トップ」の機能を実現したマシーンの一種だと言ってよいかもしれない。

あるいは、本当の意味で作られたものは、「毘盧遮那仏」という概念であり、この仏像はそのガワに過ぎないにしても…
「大仏様」は人々の頭に毘盧遮那仏という概念を無理なくインストールするための装置だと考えると面白いと思う。

つまり、この点でも歴史は繰り返しているのだと思う。作ろうと思えば、「トップ」すなわち「神」の機能を持つ「人工知能」は作れる。なぜならば「人工知能」に求められている機能は、「神のような実務能力」ではなく「神」の能力なのである。とすると必ずしも高度な実務能力を実装する必要はないからだ。昔から多くの天才的な「神エンジニア」たちがが国家のために働いてきた。そして現在も…

さて君たちも神を作ってみる気になったかな?
一つアドバイスするなら、神を作りたいなら必ずしも人工知能は要らないということだ。

まあ中2的文章を、これ以上書くと自分でも恥ずかしくて恥ずかしくて大怪我しそうなのでこのへんで。でも書かないと気が済まなかった。

numo-gnuplot playground

今日の落書き red-arrowで遊ぶ

難しそうなので今日まで敬遠していたred-arrowを使ってみた。
公式の通りインストール。手順通りコピペでインストールしているだけなので何もわかっていないけど、そういうアホなユーザーも世の中一定数いるから仕方ないよね。Pythonの方もcondaでPyArrowをインストールした。

難しそうなので公式のexampleを試すだけ

パイソン

ルビー

おお、普通に動くじゃないか…。
/dev/shmというのが何か気になったのでインターネッツでググるとRAMディスクのことらしい(正確には違うらしい)。

ということは…なにこれすごい∑( ゚д゚ )

公式スライド

正直Webサイト製作に関するプロの道具であることを求めなければ、Rubyでデータ解析できる状況は十分に整ってきていると感じる。

機械学習に関してはscikit-learnのようなライブラリの力を借りる必要があり、pycallを呼び出して適宜red-arrowでデータを変換していくような使い方が望ましいのかもしれない。

RubyやPythonといった便利な道具があることを知らない or キャリアをまともにこなしていると学習コストを支払えない制度設計になっているために、プログラムでやった方が早いことも含めてプログラムと縁のない方法で仕事をこなさざるをえない非エンジニアの世界の方が、エンジニアの世界よりも広いのである。。