guildっぽい単語

http://rebuild.fm/158/ を聞いてて、 guild でも別にいいし、この辺の単語は一通り検討されてる気がするけれどなんとなく思いついたものを書いてみる。


Rubyの “guild” についてはどういうものかというのは http://www.atdot.net/~ko1/activities/2016_rubykaigi.pdf に書いてあるが、互いに参照関係にないオブジェクトのグループ分けを行うことで、異なる「ギルド」に所属するスレッド同士は独立して(パラレルに)動作できる、という仕組み。

パラレル・コンカレント系の用語なのでスレッドナントカ、とか系の単語がいいのかも、と思ったけれど、話を聞いた感じではどちらかというと概念的にはオブジェクトの所属関係を意味するものなのか、という印象を受けた。

そうすると集団を意味する単語系のtribe、clan、caravan、群れ系のhorde、troop、bandなど、あるいはregiment(連隊)、battalion(大隊)、company(中隊)などの単語はどうかなぁ。

あとは所属関係を地理的なアナロジーでとらえて、continent、planet、universe、world、galaxyとかみたいな単語とか。

あんまりいい案ではないかな……。まあとりあえずそんなかんじ。

ところでスレッドをたばねる単語としたら日本的には「板」(board)なのではないでしょうか、などと言ってみるテスト。

 

tensorflowの型付け

http://shinh.skr.jp/m/?date=20160912#p01

はいその通りです。というか前者の意味なんだとすると、それはなんというかその、一般的に動的言語は全部ダメという結論になってしまうように思うのですけどどうでしょうか。あと変数名typoはJSなら “use strict” で防げたりする、といったこともあるので、型というよりは処理系や言語仕様の話じゃないかなぁという気も。


で、tensorのサイズの型付けなんですが、理論的には依存型(dependent types)で解決済の話題という気もする。確かリストのサイズを型レベルで覚えておいて、空リストへのheadをコンパイルエラーにする話とかあったよなー……と思って検索したら https://www.schoolofhaskell.com/user/konn/prove-your-haskell-for-great-safety/dependent-types-in-haskell みたいな話はあります。

ただまあ理論的な結果があるといっても、現実の問題に実際に適用してみたらいろいろな細かい問題はおこりうるだろうとは思うんですよね。convolutionみたいな引数はけっこうややこしいだろうし、embedded lookupみたいなので値域とサイズが入れ替わる場合とかもあるし。

あと自然言語処理みたいな応用例だと数万次元とかあるわけですが、サイズをナイーブにチャーチ数でエンコードしたらパフォーマンス的に大丈夫なんだろうか、とか。

まあそれなりにやってみたら面白いのでは、というのが素人考えですが、理論的には大して面白くないかもしれない。

ドラマ『シリコンバレー』シーズン3

HBOのテレビドラマシリーズ Silicon Valley のシーズン3がGoogle Playに来てたので観た。今回も面白かった!

シリコンバレーの大企業Hooliから飛び出したリチャード・ヘンドリクスが創業したスタートアップ、Pied Piperの面々の活躍(?)を描いたコメディシリーズのシーズン3。Hooliとの訴訟を乗り越えたものの最後の最後でいきなりの解任騒ぎとなったシーズン2のラストでしたが、そこからそのままつながったシーズン3も見どころは多く、いろんな小ネタがてんこ盛り。

ネタ的には、主人公のリチャード・ヘンドリクスがタブ派であることを明言し、せっかくできたfacebook社員の彼女とタブ・スペース論争で喧嘩して別れるあたりがおかしいし、冒頭でベンダーのエンジニアがコーディング規約に従ってくれない……という話からの展開はまあ見事。ただ一番面白かったのは Pipey。あれは声を上げて笑ったし本当になんというか、完成度が高い……。

それにしても、ギークネタの使い方もうまいですけど、毎回毎回いろんな小ネタをはさみつつ、各回でもきちんと起承転結がついていながら、思わぬ伏線が回収されて綺麗な結末に着地していく流れが本当に見事だなと。シーズン2の判決シーンも好きなんだけど、シーズン3のラストも謎の感動がありました。


ところでオープニングも毎シーズン微妙に細かく変わっていていろいろ芸コマ(YouTube)。シーズン2で出現したUberのバルーンは脇に出てきたLyftのバルーンとぶつかってるし、ドローンが飛び交ってるし、Yahoo!のところに阿里巴巴があるし、Googleの上にAlphabetの看板が立ってるし。

Screenshot 2016-09-06 at 00.08.53

比較のためにシーズン1の動画を見てたらsgiが崩れてGoogleになったりNetscapeがChromeになったりMyspaceがあったりNapsterのバルーンがしぼんで落ちたり、とにかく芸コマですし、ちゃんと時流を合わせててすごいなぁ。

Screenshot 2016-09-06 at 00.11.44.png

手もちのChromebookにもPlay Storeが来たので

手元のChromebook Pixel2にもGoogle Play Storeが来ていて大半のアンドロイドアプリが利用可能になってました。

喜び勇んでいろいろと入れてみた。

Screenshot 2016-09-01 at 20.27.39

しかしまぁなんだな。思ったよりも「これを入れねば!」というアプリってあんまりないんだよなぁ。Kindleはクラウドリーダーはいろいろしょぼいので良いかも、というのとあとはSkypeぐらい? てかまあSkypeも、もう何年も使っておらず、そっちで繋がってる人々はそんなにいないし。

微妙にウェブ対応がしょぼいやつで、モバイルアプリのほうが良いやつとかもあるんだろうけど、あんまりデスクトップで使うものというのもないものですね。アンドロイドアプリはモバイルコンテキストで使うものが多いしな。

あとはゲームとかなのかなぁ。

とりあえずFirefox(モバイル)を入れて「おーChromeOSでFirefoxがうごいた!」って遊びをしている……

猫を飼う

本当に唐突ですが、猫を飼うことになりました。

IMG_20160818_194922

以下、適当に体験談の羅列です。日本とアメリカの違い的なことを言おうかと思いましたがよく考えてみたら日本のことも知らんしアメリカの一般論はわからないので。

猫の引き受け元

検索してみたり、先達からの教えに従い、Silicon Valley Animal Control Authority (SVACA) という施設に行きました。いわゆアニマルシェルターで、里親から引き取ってしばらく育てながら引き取り手を探したりするような団体のようです。サンタクララにあり、我が家からは激近。

ほかにもサンノゼだとThe Dancing Catという猫カフェ(兼シェルター)があったり、ほかにもペットショップもあるようですが、なにぶん行っていないのでわかりません。

さてこのSVACAという施設も、特に予約などはせず、ある週末いきなり行ったのですが、ふつうにいろいろ見せてくれました。猫はたくさん、ほかにウサギと犬がいくらか、といったあたり。猫は2-6ヶ月の仔猫が多かったですが、年のいった子も多少いました。引っ越しとか飼い主が去らざるを得なかった事例とかなのかな。猫はどれも(もとの飼い主からつけられた)名前がついていました。動物の分布はタイミングにいっても変わるでしょうけど。

で、実際に行ってみて、さらに部屋に入って実際に戯れたりしてみた結果として「この子にしよう」と決まった場合は係の人にその意思を伝えて引き受けるということになります。

猫の引き受けの手続き

ただうちの場合、ほんとうにいきなり手ぶらで行ったもので、そのままでは引き受けることはできませんでした。最低限、猫のキャリーを持ってこないと引き受けても連れて帰ることができないため、手続きをしてくれません。その他、こちらも猫を飼うのは初めてということもあり、必要な用具もよくわかりませんので、アニマルシェルターの人に教えてもらいました(その後、適当に日本語で本も買った)。

行ったのは夕方ということもあり、もろもろ買い揃える時点でその日は終了。残りは翌日以降ということですが平日は引き受けに行くのは難しい……。ともあれ、24時間はホールドできるとのことで、押さえてもらってその日は退散。

そのあいだにいろんな用具を買い揃えつつ、ちょっと忙しくて引受に行けない……となったのですが、やっと金曜に引き受けられる目処が立った、という感じ。

実際の引き受けの手続きはもろもろの書類手続きと注意事項があって、adoption feeというのが$150でした。medical recordもくれました。

13996031_1025917497503624_2490766977086030669_o

引き受け後

わたしはアパート住まいなので、管理会社に確認をしないといけません。事前に確認を取ったところでは猫は問題なし、ただしdeposit(敷金みたいなものですかね)が追加で$300、また家賃が毎月$50上がるということでした。なので引受後にまた受付に行って、猫の名前と特徴(色とか)を記した書類に改めてサインしてdepositを払って完了、ということになります。

またこの子はマイクロチップは埋め込む処置が行われていたので、その登録も行いました。避妊手術は処置済のようです(英語で検索すると生後8週間程度以降からは避妊手術は安全とされているようです)。

なお猫は室内飼いが原則になっています。これは書類にも明記されているし、またアニマルシェルターから引き受ける際の書類にも明記されていました。現実問題として車に轢かれるなどの危険性が大きいので、猫は部屋から出さないほうがいいのだろうと思います。そもそも野良猫や半ノラみたいな猫は見かけない気がしますし。

というわけで、猫を飼う話でした(案外書くことないなぁ)。

IMG_20160817_200113

Suicide Squad

IMG_20160806_190730

ううーん、微妙!

あんまり期待せずに見に行くと面白いかもしれませんが、傑作とかではないなぁ。なんというか、話が薄いというか話がないというか……キャラを出しすぎてメインのプロットが崩壊している気がする。序盤から手際よく主要キャラクターを紹介していく流れはずいぶん飛ばしているなーとは思ったんですがしかし……。

その分キャラはまぁ魅力的。ハーレイ・クインは事前の評判どおりの良さでしたが、ウィル・スミスのデッドショットが個人的にはけっこう良かった。他の人たちと違ってデッドショットさんは職業的な暗殺者なので、性格破綻者ぞろいのチームの中で比較的まともな性格な感じで割りを食っているかんじなんですよね。

でもやっぱりキャラが多すぎると思うんだよな……。この人もまあこの人でいいけど、出てこなくても話は成立しましたよね?というキャラはいる。けっこういる。テレビシリーズなら人が多くても話数で掘り下げられるけれど、2時間の映画でこの人数で話も掘り下げて敵側の話も描いて……というのはどうしても無理がある。その歪みはそのまま放置されていてしわ寄せされている箇所がおおいという印象。キャラを減らしてメインのストーリーラインにうまく絡めるのが映画としての常道ではあるはず。が、そこをあえてこの方向性にふったわけだ、という捉え方はある。

が、それはそれとしてこういうキャラいいよね?という楽しみ方の映画なのだとすれば、面白くて魅力的なキャラたちが出てくるので、ありなのかもなと。でもそれはちょっと私が求めていたものとは違うかなぁ。

あとジョーカーさんもう少し活躍シーンあるのかと思ってましたね……。

機械学習の環境をGCPで構築する

前回前々回の続き。

今回、tensorflowの趣味プロジェクトにはGCP (Google Cloud Platform) を全面的に使った。手元の環境はChromeOSなので、ローカルには実行環境を持っていない。開発環境になる。

といっても大したことは何もしていない。

学習用に独自のGCEインスタンスを作成する。編集や実験はIPython / Jupyterを使うことになるので、Anacondaをインストールしてこれを使う。tensorflowだけpip installでインストールする。GCEインスタンスにはブラウザから直接端末にログインできる機能があるので、ボタン一発でつなげてたいへん便利だ(ブラウザのポップアップウィンドウなので、Ctrl-wするとウィンドウが消えそうになるなどの問題がじゃっかんありますが)。

jupyterは起動コマンドで 0.0.0.0 を指定しておいて、どこからでもアクセスできるようにしておく。アクセスは手元のブラウザから(ただmatplotlibについては %matplotlib inline が必要)。これもちろん、IPアドレスが判明すると誰でも私の作業環境にアクセスできてしまうのだけど、IPアドレスがephemeralなので、使っていない間にインスタンスをシャットダウンしておくとIPアドレスは毎日変化するので、基本的に私以外の人間がピンポイントで攻撃できるような事態は、かなり起こらないと思われる。

が、ある日の作業中に身に覚えのないアクセスログが出てきたので、たぶん以前にほかの人が私用で作ったIPアドレスとかぶったりしたのだろう、そういう事故は発生する可能性はあるので、その日にパスワードだけは設定することにした。

この辺、真面目に使うのであればインスタンスごとにホスト名を与えて、Let’s Encryptで証明書を与えてhttpsコネクション、といったあたりぐらいまでやるのがスジであろう。あるいは自分のIPアドレスを調べてその都度jupyterの起動コマンドでアクセス元を制限するとか。が、私用だしひとまず適当でよかろうというバランス感覚でこうなっているので、あまりお勧めではない、ということは一応言っておく。

さてそんなわけでIPythonでtensorflowを使ってすべての作業を行うが、長いタスクになってくると、計算処理をやったまま寝るとか出勤するとかいうことになる。今回の実行環境では端末アクセスしてそこでjupyterを立ち上げていたので、端末とのコネクションが切れるとjupyter自体が終了してタスクが終了してしまうようだった。このへん、いろいろ混同していたのもあり、長いジョブを投入するときはIPythonの.ipnbファイル形式から.pyに変換し、その.pyを起動しておくこととした。Python2をいまだに使っているので、non-asciiが出てくると発狂する問題があったりするが……。

より多くの計算リソースが必要になったら、そのときだけ新しいインスタンスを立ち上げてそこで使う(そちらはanaconda/IPythonは導入していないので、.py変換はここでも意味がある)。データの受け渡しは、gsutilが標準でインストールされているのでGoogle Storageに適当なbucketを作ってシェアしておく。

C++やMakefileについては、端末アクセスでvimを入れて書いていたが、Emacs入れたほうが楽だっただろうか、という気もしている。他のエディタを使いたい人はどうするのかなぁ。X11で仮想デスクトップを立ててChrome remote desktopを使えば良さそうだけど、私にはそこまでするモチベーションが湧かなかった。

Emscriptenで生成したjsファイル(や手書きのHTML/JSファイル)の動作確認には何らかのHTTPサーバが必要になるが、楽にセットアップできる環境を考えた結果、WEBrickが一番楽そうだと思ったので、rubyをインストールして数行のファイルサーバを書き、必要に応じて立ち上げたりする、といった手法を採用した。これがRubyに標準添付なのだから楽なものだと思う(書いてて今思い出したけどPythonにもSimpleHTTPServerがあってそのまま使えたような気がする。まあラクなもんですな)。

まあそれぐらいかな。適当にやっているだけで、あまり効率重視しているわけでもない、比較的単純な手法です。

なお、他のありえた構成についていちおう書いておくと、Google Cloud Datalabはインストールされているtensorflowのバージョンが比較的低く、あまりヘビーな計算はおそらく無理(distributed tensorflow以前のバージョンなのでバックエンドを追加もできなさそう)ということで断念、Google Cloud MLはまだ万人が使えるものではなく私用では使えそうもない、といった次第。あとほんとうは、新しいGCEインスタンスを立ち上げるよりはGKEでtensorflow計算クラスタを作ってフロントエンドは維持しつつバックエンドに計算ジョブを投げるほうが柔軟だったのかも、と思いつつ、そこまでは手が回らなかった次第。

全体的にどれぐらいお金がかかったか、というと、全体で$300ていどのコストだったようである(16CPUインスタンスの稼働時間が効いているっぽい)。上げっぱなしでうっかり寝たりとかムダも多く、あまり切り詰めていない値段なので、もう少し安くできたはず。だが、しばらく多数CPUで遊んでいたということを考えればまあ良いのでは、という気がする。普通に高い機器を手元に購入して使ったらもっと高いですし。

tensorflowの学習結果をブラウザから使う

さて前回の続き。

tensorflowで学習が進んだのはわかった、さてある程度うまくいったあたりで、この学習結果で友達たちに見せて遊べるようにするには何があればいいか、ということを考えていた。どうしたらいいだろうか。

まず、tensorflowにはsaverというものがあり、学習結果などをファイルに書き出せ、そこから復帰もできる。これは便利で良いのだけれど、あとで利用するためだけにtensorflowをインストールしたサーバがどこかに必要になるけど、そんなものをメンテしたくない。もっとお気軽にいきたい。

tensorflowの学習結果マトリックスはevalするとnumpyのndarrayに変換できる。numpyにはnpyファイル形式というものがあり、ndarrayはこの形式で保存できる。まずはこれを保存するようにした。少なくともこうしておけばnumpyの入ったPython環境で利用ができるだろう。

ちょっと調べてみたらAppEngineからでもnumpyは使えそうなので(https://cloud.google.com/appengine/docs/python/tools/using-libraries-python-27)、まあ最悪それを使えばメンテコストはそれなりに低いものができるとは思う。あんまり面白くはないけれど。

もう一つ別な方法がある。ブラウザ内の処理環境に移植するという方法だ。


ブラウザ内というのはつまりはJavaScriptなのだけど、さすがにマトリックスの計算などをJavaScriptで書きたくない。性能も出ないだろう。そこでEmscriptenを使った。

EmscriptenはC/C++などのコンパイラツールチェインで、LLVMビットコードをasm.jsにコンパイルできる。asm.jsというのは……JSのサブセットで高速化などの最適化がしやすいもの。さらにwebassembly (wasm)にもコンパイルできるようだったが、そもそもwasmが手元のChromeではまだフラグなしでは使えないので今回は見送った。

さてEmscripten。Emscriptenにはem++というC++コンパイラがあり、バックエンドのclang++と連携してLLVMビットコードの生成やasm.jsの生成を行ってくれる。ようするに普通のc++/g++/clang++のところを置き換えてやれば.jsができるようだ。さらにはconfigureなどとうまく連携するためのものもあるようだが、今回は自分がいちから書くだけなので、適当にMakefileを書き、CXXを切り替えればコンパイルできるというやっつけ仕事にした。それにしても、イチからC++のコードを書くのも、白紙の状態からMakefile書くのも、けっこう久しぶりだな……。

行列計算については、C++ではEigenというライブラリが定番のようなのでこれを使った。tensorflowも裏ではEigenを使っているようだ。実装内容は……たんにtensorflowのBasicLSTMCellの実装を見ながら素直に移植した、とまあそれだけで、ここにはそれほどの苦労はない。

苦労はどちらかというとnpyファイルの扱いのほうがあった。npyファイル形式は公開されているが、C++のパーザなんてものはない。というか、検索したらcnpyというライブラリがあったのだけど、今回の自分の用途には向いていなかったようなので、利用しなかった。けっきょくやっつけパーザを自分で書いてEigenのマトリックスにした。

とりあえず一通りのものが動いたところで、手元の環境でネイティブバイナリを動かして、これが動くか確認する必要がある……これはまあ動いた。

とするとEmscriptenでコンパイルされた.jsも同じく動作するはずだ。はずだが……そのためにはnpyファイルをどうにかして生成したJSのコードに渡さないといけない。元はどうあれコンパイルされたJSファイルはふつうのJSと同じ実行環境でしかない。ただファイルを開けばいいというものではない。

外部ファイルはどうやってEmscriptenのC++に読ませたらいいか。これにはいくつか方法があるが、一番手軽なのはコンパイル時にデータファイルを指定する方式だ。

em++に –preload-file というコマンドラインフラグを渡すと、コンパイラはファイルをまとめたパッケージを作り、また生成されたJSファイルではメイン処理が動く前にまずこのパッケージデータを読み込む処理が走る(参考: http://kripken.github.io/emscripten-site/docs/porting/files/packaging_files.html#packaging-files)。そしてC++側でファイルを読み込むコードによってこのパッケージデータ上のデータが読めるようになる。これに必要なnpyをパッケージしておけば、C++側では単にファイルを読めばいいだけになってかなりお手軽だ。

が、試してみた感じではメモリ消費の問題があるようだった。マトリックスはさほど巨大なものではないはずなのだが、そうはいっても全部合わせればそれなりの規模ではあるし、こうしたコードにすることでファイルシステムのエミュレーションも必要になる。試しにやってみたらメモリ消費が急増してまったく動かなかったので、この方向性は諦めた。

ほかにもいろいろあったのだが、けっきょくお手軽なのは

  • JS側で必要なデータをfetchし、
  • その結果のArrayBufferをC++に渡す

ということのようだ。embindを使うとArrayBufferはC++のstd::stringとして入ってくるので、そこから先はnpyパーザを使えば完成、という次第。

ただしこれも、たかが数十MBのデータでもデフォルトでは大きすぎるということで呼び出しに失敗してしまう。これを何とかするにはリンク時に -s TOTAL_MEMORY= でそれなりの大きさのバッファを作る(今回は256MBとした)ことで解決した。これはまああまり賢くはないアプローチである気はする(たとえば、ほんとうはもう少し巨大なデータでも試した結果があったのだけど、そっちはこの方式だと破綻してしまったので試していない)。常識的に考えれば、fetchのストリーミングAPIでちょっとずつC++にデータを渡してやれば良いのだろうけれど。


にしてもEmscripten / asm.js、思ってたよりずっと高速に動作していてけっこうすごい。動作も当然なんの問題もない。いまどき、ブラウザのなかで行列計算したくなったらEmscriptenで一発なのだなあ。

良い時代になりましたね。web assemblyも楽しみになってきました。

ディープラーニングで英語を読ませる

概要

tensorflowの練習に、英単語(アルファベット文字列)を入れると、その読みとなるカタカナを出力するという機械学習課題をやってみて、まぁいちおう動いているなという程度のものができた。

学習結果をブラウザ内で実行できるよう移植して http://www.jmuk.org/en-ja/ に置いといた。

本文

tensorflowを勉強したのはいいのだけど、なんらかの練習課題をやってみたい、なにかいい課題はないだろうか、と思っていた。個人が趣味でやってみる課題では学習データの準備をどうするかが気になるところだけど、それも簡単にそろうやつがいい。データの手動のタグ付けをしない課題がいい。

などと考えているうちに「英単語を読ませてカタカナにする」という課題を思いついた。たとえば “google” という入力文字列から “グーグル” という文字列を出力させたい。そういう問題になる。

これを学習するには学習データとして大量の「英単語とカタカナ語のペア」が必要になるわけだけど、これにはウィキペディアのデータを使う。ウィキペディアのページはサイドバーに他言語版ウィキペディアの同項目のページへのリンクがありますよね。このデータを取ってくることで、同じ事物に対する英単語と日本語の対を取ってこれる。ウィキメディア財団のサイトはどれも定期的にデータをダンプして誰でも取得できるようになっているので、この関係性が格納されたwikidataのデータダンプをある日ダウンロードして項目の対を作った。

もちろんここには漢字の単語やかなり関係性の薄い単語も含まれているので、日本語はカタカナや中黒などのみを含むものとか、末尾のカッコはdisambiguationだから消すとか、まあいろんな適当なヒューリスティックスを入れて学習データを作る。ちなみに当初は項目同士のペアで学習させていたのだけど、なかなかうまく行かなかったので、このデータをもとに単語同士のペアをつくって学習させた。この辺もけっこういろいろ試行錯誤があるのだけど、つまんないと思うので略す。

さて、学習データはできた、ではどう学習させるか。

この課題というのは文字列を受け取って文字列を出力するというものなのだが、文字列の長さは学習ペアごとにけっこうばらばらなので(また文字数も一対一対応ではないので)、ふつうのフィードフォワードニューラルネットワークではうまく解くことができない。リカレントニューラルネットワークを使って解く、seq2seqというモデルを使う。というか、「英語の読みの推定」というのはseq2seqとしては非常に典型的な(であるがゆえに練習課題としてはけっこういい)タスクだと思う。

リカレントニューラルネットワーク(RNN)というのは、前回の出力結果(の一部)を次回の入力に加えるというタイプのニューラルネットワークの総称で、これによって内部状態のようなものが保持でき、時系列データとか、順番に入力がくるようなもの(文字列とか単語列とか)の処理によいとされている。

seq2seqでは典型的にはこのRNNセルをふたつ用意する。まず入力文字列(今回の場合は英語文字列)をいっぽうのRNNに入力していって状態遷移をさせ、遷移結果の状態をふたつ目のRNNに渡す。ふたつ目のRNNにはまず「ここから学習開始」を意味する特殊なシンボル(GO)を入れ、その出力結果を最初の文字とみなす。それ以降はひとつ前の出力結果の文字を入力とし、次の文字を出力していく。文字列の最後にはEOS (end of sentence) という特殊なシンボルが出力されると仮定して、そうなったら完了。

図としてはこんなかんじ。

ここでのABCというのがもとの入力列で、WXYZというのが出力列。この図ではRNNセルは単独だが、ABC側と<go>WXYZ側でセルを分けるのが良いとされている。

さて、実はtensorflowにはRNNやseq2seqのモデルが標準で提供されていてチュートリアルまである(この図もそこへのリンク)。というかさらにいうとtranslate.pyというコマンドがあって、これを使えば特に何もしなくても学習できちゃうかも(さすがにそれはないなと思ったので使わなかったけど)。ともあれこのチュートリアルとリンクされている論文は素直に良いと思うので、詳しくはそのへんを読めばよろしいことでしょう。

自分でいろいろ組んでみて試してみたものの、結果的にはたいしたことない構成に落ち着いたので、この程度なら既存のコードをそのまま動かすんでもいいんじゃないの、という気がするけれど、まあ自分で書いたからこそ、多層化させたりいろいろパラメータをいじったりいろいろ試してみたりというのが目的の練習課題なので、と自分に言い聞かせているところ。

ところでtensorflowにおけるRNNセルやseq2seqの実装というのはなかなか面白い構成になっている。

たとえばRNNセルを表現したクラス RNNCell やその実装である LSTMCell のようなクラスの実装を見ても、実際のマトリックスのデータ(tf.Variableなど)はインスタンス変数としては保持しない。状態数などの基本的なパラメータだけを持っている。そして実際にグラフ構造を作るときに変数の名前で名寄せしてデータを取り出すようになっている。

つまりRNNセルクラスのインスタンスたちは「どういう計算をする」という構造だけを定義していて、具体的に誰と計算をするかは必要なときに決めるわけだ。tensorflowは変数スコープというものを定義することができ、スコープを一致させれば同じマトリックスに対して計算ができるし、変えれば構造は同じだけど違う対象と計算をするようになる。同じような構成を何段も組むときにループを使ってうまく書ける、などのことが綺麗にかけたりするのだろうと思う。あとインスタンスの作成がgraphのスコープと無関係にできるってのもあるのかな。なんにしても変数スコープってそう使うんだなっていう感じはある。

distributed tensorflowがこの変数スコープとうまく適合しているとよく出来ているなあとさらに感心するところな気もするが、あんまりそうなっていない気がする。この辺はまだそこまで煮詰まっていないのかな。


話がずれた。

さて、学習結果をいろいろ遊んでみると、やっぱり相当変な部分がのこっている。日本人の名前がうまく読めない、とかはもうしょうがないとおもうんだけど、ごく普通の名前、たとえばJamesが読めないってのはどうなんだろうな。学習データの偏りじゃないかなと思っているけれども、救えたほうがよいよなーと思ったりもする。が、そういうのをなんとかするために試行錯誤するのも楽しいけれど時間かかるのでとりあえずもういいやこれで、と思うことにした。あきた、とも言う。

それでもなんというか、当初なかなかうまくいかないなーと思っていたものがあるときいきなりそこそこ読めるようになった時はけっこうびっくりしたし、なんというか、すごいなあと素直に思ったものだし、やっぱりそこそこ読めている結果になっていて面白い。なので、自分としてはまあいちおうこんなもんか、ってところまで行けたかなと思ってる次第。まあほんと大したことないんですが……。

記事も長くなったので、ブラウザ環境への移植の話はまた明日にでも。

 

 

アン・レッキー『叛逆航路』と翻訳の話

アン・レッキー『叛逆航路』を読んで唸ってしまった。

どうしてこうなったのかなあ、というか、きっともうちょっとこうじゃないんじゃないかなあ、というモヤモヤがうかんで晴れない。

どういうことか?

『叛逆航路』はいまから考えられないほどの未来が舞台だ。人類圏を席巻するラドチという銀河帝国のようなものがあり、皇帝アナーンダ・ミアナーイは単独の存在ではなくて、複数の個体が(どういう理屈でか)意識を共有して統治している。主人公は戦艦「トーレンの正義」、およびその制御下にある属躰(アンシラリー)という、一種のサイボーグのような存在になっている。各戦艦は人間を改造して制御下においたアンシラリーをいくつも保有していて、意識が共有されている。アンシラリーの視点からすると戦艦もアンシラリーの身体もどっちも自分、といった風になっている。

が、この設定を踏まえて、この小説の最大の特徴は登場キャラクターの人称代名詞にある。

ラドチの言語において人称に性がない、という設定があり、すべての人称は「彼女」(原文ではshe)、個別の一般名詞も女性のものが使われる(「娘」とか)。またアンシラリーである主人公は人間の性別を外見からあまり的確に判断できるわけではないので「彼女は男性だろうか、女性だろうか」と悩んだりする。また一部の舞台の現地語は性別があるので、正しい人称を使えるかどうかで主人公は思い悩む。

この設定、いかにも「フェミニズム方面の何かなのかなあ」という雰囲気を感じさせるものがあるし、実際そうでないとも言い切れないだろうけれども、ただ、それだけともいいがたいものがある。ラドチの超越者たちは複数の身体をもっていて、どういう理屈でか単独の人格に統合され存在している。独特の固有名詞の語感なども込みで、人称をどう表現するか、というのははるか未来の異質な存在になりはてた人類社会を描くためのツールとして使われているのだと思う。

そしてこの点が、ほんとうに翻訳って難しいな、と思うのだ。


日本語の人称に性別がない……とは言わないが、あまり人称の性別を気にしないほうだと思う。「その人」「そいつ」といった表現で中立的な表現もカジュアルにかける。そんなわけで、「彼」「彼女」といった人称代名詞は、あえて性別の情報を付与したいときに使う特殊なものなんじゃないか。すくなくとも英語のshe/heのカジュアルさとはぜんぜん違う。

おそらく原文を英語で読んでいる場合には、序盤で「はてこの小説、sheしか出てこないぞ」と思っているうちに、どうやらラドチの言語では人称がないのをすべてsheとしているという小説なのだ、といった気づきを得ることになるんじゃないか。それと比べると、この「彼女」の頻度はいかにもうるさすぎる。

いっぽう、日本語の小説で男性女性の使い分けでは、セリフってのがけっこう大きい。語尾や役割語を適当に扱うことで話者の性別などがあきらかになる。英語にはそういうものはあまりなく、単語レベルでは同じ文言になっていて、男性と女性でちがう台詞になったりすることは少ない。日本語の翻訳家たちは、小説を読みながら話者を意識して適当に役割語をわりふったりするものだ。

そういうわけで、英語の小説で、セリフに使われる単語などから性別があきらかになるようなことはない。が、そのように役割語を持たせない表現を日本語で実施すると、いかにも生硬かつ無味乾燥で読みづらい会話になってしまう。かといって適当に性別をわりふって役割語を当てはめるわけにもいかない。正直、どのキャラやどの身体が男性でどのキャラが女性なのか(そもそも複数の身体を持つ場合にどうなっているのか)、といったことは最後までよーわからんというのがこの本であり、その宙ぶらりんであるということが小説としてのキモでもあるわけで、そんなことをして読みやすくなってしまっても意味がないわけだ。


ここで言いたいのは訳がいいとかわるいとかではない。そのことははっきり言っておきたい。むしろ原文の面白い試みを的確に尊重してたくみに訳した本と言える。

でも結果として、日本語の小説としてはちょっと珍しいレベルのすごい文体の小説になっちゃっているんじゃないか。原文は英語の小説として異常ということはないんじゃないかという気がする(気になったので2巻を英語で買ってみてちょっと読み始めてみたが、今のところこの推測は反駁されていない)。違和感がないというわけではないが、小さなひっかかりを覚える程度のさじ加減なのでは。

しかし、英語で語る上でたくみに構成されたものが日本語になって同じように効果を発揮するわけでもない、という、それはもちろんしごく当たり前のことであるわけですが、その当たり前の難しさが、不可避的に表面化しているのがこの本なのではないか。

やっぱり日本語の小説としてはちょっとなんというか、変さが際立ちすぎてしまっていている、ということがあるのではないだろうか? 「彼女が連発されているのは原文で人称代名詞が基本的にすべてsheになっていることがあって……」みたいな前置きが必要なのではないか? たぶんそんなに難解な本というわけでもないのに。

繰り返すけど、訳が良いとか悪いとかいうレベルの話ではなく、この本を英語から日本語に訳すということである意味避け得ないポイントであって……

小説の翻訳って、ほんと難しいよな。

そんなことを思わさせられました。

が、不必要に難解になってしまったという意味で、あんまりおすすめの本ではないと思った。