Bridge over troubled Techs.

オープンストリーム CTO 寺田英雄のブログ

仏像の歴史と、システム開発の歴史

(以下の話は、ラジオかなにかで聞きかじった話で、私も歴史学や考古学の専門家ではないので、細部には誤りもあるかと思うので、その点ご注意ください)

 

日本の仏像製作は、仏教伝来した6世紀の飛鳥時代から始まり、鎌倉時代運慶/快慶で有名な慶派が登場したときに、完成度や芸術性などがピークに達したとされている。

写真:東大寺の阿形像(運慶・快慶作)

 

この時代の仏師は、一人で仏像の全身を彫り上げることができる力量をもっており、深い精神性や芸術性を感じさせる仏像を製作することができた。仏師は今で言う芸術家=アーティストに近い存在だったのだ。

 

その後、室町時代以降は、いろいろな理由から仏像製作のレベルは低下していき、徐々に仏師も『職業仏師』化していった。すなわち、仏像製作の分業化が進み、頭部だけ作る仏師やら、胴体だけを作る仏師やらに別れ、仏像の全身を彫り上げることのできる仏師は激減したらしい。その後現代にいたるまで、作品のレベルは鎌倉時代を超えることはできなくなった。

 

・・・この話を聞いて思ったのは、『これってソフト開発・システム開発の歴史に似ているな』ということである。

 

ITという言葉も産業としても存在しなかった初期の時代、コンピュータに取り組んでソフトを作るとなれば、一人で何でもやるのが普通だった。情報も少なかったが、ハードもソフトも何でも知り尽くしてやろう、という情熱のある人ばかりだった。そこに未来と可能性を感じた一部の人が、熱狂的に取組むのがコンピュータ・ソフト開発だったのだ。

 

現在のソフト開発は大規模化・複雑化していて、細かく分業して実施するのが普通になった。初期のころほどの熱気や、全体を深く見通してやろう、という人は相対的に少なくなった。これはコンピュータに限らず、どんな分野でも産業化にともなって必ず起きることで(例:ロック)、しょうがないのだけど、ちょっと寂しさを感じるのも事実。

 

・・・だからどうだというわけではないのですが、仏像の話でふと浮かんだので書き留めてみました。

読書メモ:『考える脳 考えるコンピュータ』

Numenta の HTM理論に興味をもったので読んでみた。結果的には非常に楽しく読めた。

考える脳 考えるコンピューター

考える脳 考えるコンピューター

 
  • 著者ジェフ・ホーキンスさんは超一流のエンジニア&起業家。一旦いくつかのビジネスを成功させてから、脳を模範にした汎用人工知能を開発するため大学に入り直して神経科学を学んでいる。この気合の入り方が凄い。
  • 2005年の出版だと考えると、その後今日に至るAI発展の萌芽になる話がいろいろ含まれているのが興味深い。Deep Learning(という言葉はもちろん使われていないが)の原型である脳の視覚野の話なども概説されている。
  • 彼のアイデアの根幹は、大脳新皮質の柱状構造をモデルにした人工知能。実はこの本全体がこの人工知能モデルの基本設計書みたいな雰囲気がある。執筆当時の最先端の神経科学の知見を援用しつつも、エンジニアらしい割り切りで『仕様』を決めている。現在 Numentaが取り組んでいるHTMもこの延長線上にある。
  • 近年急速に研究が進んだとはいえ、脳の内部構造は超絶に複雑で、まだまだ謎だらけである。しかし彼は『一見複雑に見えても、なんらかのシンプルな基本原理によって駆動されているはず』という信念にもとづき、いくつか仮説を導入しつつも設計をまとめている。
  • よく知られているように、大脳新皮質はいくつかの機能別の領野にわかれているが、実際に観察すると神経細胞の構造はどこも同じに見える。したがって脳の情報処理は、機能別に別のアルゴリズムを使うのではなく、統一された一つのアルゴリズムで動いているというのが彼の主張。
  • いくつかの神経科学の知見をもちいて、大脳新皮質は記憶にもとづく予測器の役割を果たしているとしている。この部分はいま自分が一番問題意識を持っているテーマに繋がるので興味深く読んだ。
  • 脳神経の活動のスパース性についても言及がある。
  • 『意識』がなぜ生じるのかにつても、大胆な?仮説を展開している。私はかなり説得力のある面白い説明だと思った。

 

今後は、NumentaのHTM(NuPIC)の具体的な中身を調べてみよう。

 

NikkeiBP のインタビューに答えました

先日、『ねこもに』に関して、NikkeiBP社のインタビューを受けた。その記事が下記に公開されている。

itpro.nikkeibp.co.jp

 

ディープラーニング ResNet のヒミツ

 先日、当社と共同研究をしている庄野研のゼミに参加させてもらった。その日は論文の輪講の日だった。そこでM2のSさんがレクチャーしてくれた Deep Residual Leaning の話が面白かったので、以下メモとして記してみる。

#なお、このメモはDLについての基本的な仕組みは知っている人を前提に書いている。

 ResNetとは?

 もの凄い勢いで活発に研究されている Deep Learning 系機械学習であるが、昨年 ILSVRC'2015 という学会のコンペで、一般物体認識で最高性能を叩き出した ResNet (Deep Residual Net)という学習・識別器がある。当時 Microsoft Research にいた Kaiming He 氏が開発した、152層!のニューラルネットである。その論文はこちら

 多層ネットワークの勾配消失/発散問題

 昨今のDL研究で分かってきたDLの性質の一つとして、"Wide より Deep"というものがある(追記:さらに最近では、Wideも重要という論文も出てきている)。同じニューロン数で学習するなら、ネットワークの各層の幅(ニューロン数)をワイドにするよりも、階層の深さをよりディープにしたほうが性能があがるという性質である。

#なお、これは経験則に近いものらしく、理論的になぜそうなのかというのは、あまり良く分かってはいないらしい。 

 ならば、『どんどん階層を増やせば良いじゃない』か、と誰でも考えるが、問題はそれほど単純ではない。従来の方式で単純に階層を増やしすぎると勾配消失(vanishing)勾配発散(exploding)という問題が発生してしまって、うまく学習できなくなるのである。なお、この勾配の消失や発散をまとめて degradation と呼ぶらしい。de-gradationというニュアンスであろうか。 

勾配消失が起きる理由

 DLで学習する際には各層ごとに活性化関数を微分して勾配を求める。まず入力層に近い『浅い』層ではその層への入力と出力の差(accuracy)が大きいため、微分操作は有効に働く。しかし、学習が層の『深い』段階へと進むにつれ、(当たり前だが)学習が収束に近づくと入力から出力への変換精度がどんどん上がっていくため、入力と出力の差は極めて小さくなり、勾配を取りにくくなる。層から層への伝播は掛け算の性質をもっているため、この差の減少傾向は指数関数的になる。つまり、層を増やしていくと、あっという間に勾配が消えてなくなってしまうのである。

勾配発散が起きる理由

 DLでは、ある層のニューロンは次の層のニューロンと重みWで積和をとって結合している。この重みが1以上ならば、多層になると『重み✕重み✕重み・・・』が発散する可能性があることがわかる。

Residual Learning(残差学習)

 普通のDLの各階層では、入力信号 x をそのままネットワークに入力して出力 H(x) を計算し学習する。

 ResNetでは、出力から入力を引いた残差(Residual) F(x)=H(x)-x を学習する形にする。なぜそんなことをするのか?・・・前述の勾配消失の説明を思い出してほしい。DLでは深い層にいくほど、入力と出力の差が小さくなる、つまりH(x)はxに極めて近い値になる。しかし H(x) は有限なNNによる非線形写像であり、綺麗にxに近づけることは難しい場合が多い。むしろ、xに極めて近い出力が欲しいのだから、単純にxをそのまま出力し、それと H(x) の差 F(x) をNNで表現して写像すれば良いのではないか、という理屈が成り立ちそうだからである。(これがこの論文で実証したい中心仮説である。)

 これを実装するには、F(x)を直接計算しようとするよりも、下図のようなショートカット接続をネットワークに導入すれば良い。これにより weight layer(NN階層)はF(x)を学習する形になる。

f:id:terada-h:20161213165701p:plain

図1 残差学習の基本ユニット(これを何層も重ねる)

f:id:terada-h:20161213190641p:plain

図2 ResNetの実装例(34層)。左:従来の方式、右:ResNet方式

 ResNetの結果

 論文にある実験結果によれば、ResNetは素晴らしい効果を産んでおり、従来方式だと階層を増やしていくと、むしろ精度(エラー率)が悪化していたが、ResNet だとそのようなことはなく、層を増やせば増やすほどエラー率が低下する傾向となっている。

 たとえば、18層と34層を比較した結果が図3である。従来方式だと34層のほうが18層よりエラーが増えてしまっている。ResNetでは34層の方が良い結果となっている。

f:id:terada-h:20161213191516p:plain

図3 学習エラーの比較。左:従来方式、右:ResNet

さらに多階層もOK

 論文によれば、筆者らはさらに実験を続け、1202層!のResNetでも同様の傾向、つまり、degradation に邪魔されることなく学習が可能で、さらにエラー率が低下することを確認しているそうである(訓練誤差0.1%、テスト誤差7.93%)。

 この手法の登場により、理屈の上では飛躍的にDLの階層を増やせることになった。計算量は膨大になっていくが、計算機にお金を掛けられる人達であれば、どんどん階層を増やして精度を上げられるのである。すでに画像のパターン分類のようなタスクであれば、人間を超える認識精度に達していると言われるDLであるが、さらなる精度向上が何をもたらすのか興味深い所である。

昔ながらのプログラム設計論(スマホアプリ系)

0.いきさつ

先日、社内で新人に説明するために、基本的なプログラムのモジュール設計法について大急ぎでメモにまとめた。もしかしたら他にも誰かの役に立つかもしれない。せっかくなのでブログのネタにしてしまおう、ということでブログに掲載してみることにした。

ここに書いたことは全然目新しくはなくて、昔からある考え方であるが、現在でも有効なものである。非常に基礎的な考え方なので、オブジェクト指向設計でも、構造化設計でも、(場合によっては関数型でも?、)有効な考え方である。プログラム設計を分割統治法で考えようとするとき、この考え方をマスターしておくと、品質の高いプログラムを実装するのがたやすくなるはずである。

意外に、最近はこうしたことをハッキリ説明してくれている文献があまり見当たらない。特に新人が最初に参考にするような書籍やネット記事などでも触れられていることが少ないのだが、何故だろう? 非常に大事なプログラマの『感覚』なのではないかと思うのだが。

 

1. プログラムのモジュール(クラス・メソッド)分割方針について

プログラムを設計していく場合、クラスなりメソッドなり、何かのカタマリ(=ここではモジュールと呼びます)に分割していくわけですが、そこには経験的に上手くいく指針があります。それらを以下に説明します。

1.1. 常に『このモジュール(クラス・メソッド)の責務(Responsibility)は何か?』を明確にして分割する

  • 『責務』という日本語だと分かりにくいですが、Responsibilityという英語だと、プログラマの直感に近いニュアンスです。
  • Responsibilityは、'Response + ablility' という構成の語であり、『(ある要求に)反応・応答する能力を持っている』という意味です。
  • クラスやメソッドを設計するときのプログラマの意識は、Responsibility=『外部からの要求を受けて、決められた仕事を実施して結果を返すユニット』にあります。
  • このとき、そのモジュールの責務=『どの範囲の要求に応答し、どこまで仕事をさせることにするか』を明確に決めておくことが大事です。
  • 責務を曖昧にしていると、どっちつかずで位置づけが分かりにくく、デバッグがしにくかったり、将来の機能拡張や引継ぎのときに混乱を生じる原因になったりします。

1.2. 一つのモジュールには、明確にシンプルに説明できる一つの責務だけを持たせる

  • 一つのクラスや一つのメソッドにたくさんの機能を盛り込むと、ややこしくなってバグの元になります。
  • 例えば、『なにかを計算して、その結果を表示する、エラーならエラー表示を行う』という機能を一つのメソッドに詰め込むのは、原則として良くない設計です。
    • 以下の4つの単機能の下位メソッドを作り、それらをまとめて制御する上位モジュールを作るのが基本です。
      • 計算する
      • 計算結果を判定する
      • 結果を表示する
      • エラーを表示する

1.3. モジュール間の上下関係・主従関係を明確にする

  • 上位(主位)モジュールは:
    • いろいろな下位モジュールを呼び出します。
    • 全体の状況(状態)を把握しています。
    • 状態を持ち、その更新に責任を持ちます。
    • スレッドやタイマーを管理し、システムのさまざまな処理を起動するタイミングを統括します。
    • メモリやDB,リソースの初期化・確保・削除・解放に責任を持ちます。
    • 別名:Activeモジュールといいます。
  • 下位(従位)モジュールは:
    • 上位モジュールから呼び出されたら、単純な一つの責務を実行します。
    • いつ呼び出されるかは知りません。
    • なぜ呼び出されるかも知りません。
    • 上位モジュールの存在は知りません。
    • 他の下位モジュールの存在も知りません。
    • リソースの確保や解放はしません。
    • 『副作用』や『状態を持つ・状態を更新する』のはナシにするのが理想です。副作用があったとしても最小限かつ明確なものにします。
    • 別名:Passiveモジュールと呼びます

f:id:terada-h:20161026182230p:plain

図:上位モジュールは、下位モジュール呼び出す

 

f:id:terada-h:20161026182328p:plain


図:下位モジュールは、上位モジュールを呼び出さない。下位モジュール同士の直接のやりとりは、原則やらない。

 

f:id:terada-h:20161026182416p:plain

図:下位モジュールは単純・単機能な責務にする。上位モジュールは状態を管理し、全体を統括する。

2. オブザーバ(Delegate,Listener)パターンについて

オブザーバパターンでは、プログラムコード上は、下位が上位を呼び出す形になる場合がある。ただし、呼び出し先のオブザーバ(delegate, listener)はプロトコル(Swift)やインターフェイス(Java)として抽象化されており、具体的な特定のクラスを差していないので、上記ような意味で上位クラスを呼び出すのとは異なっている。

3. iOSアプリでの上下関係の例

  • 最上位モジュール:AppDelegate
  • 上位モジュール:各画面の ViewController
    • VC内のメソッドの上下関係
      • 上位メソッド
        • 状態を把握・状態遷移を行う
        • クラスのプロパティを変更しても良い。
        • 例:
          • viewDidLoad()
          • viewWillAppear()
          • viewDidAppear()
          • viewWillDisappear()
          • UIボタンやセンサーのイベントハンドラ
            • ただし、ハンドラに長々と制御コードを書くのは好ましくない。制御を集約した別クラスを作って、それを呼び出す形にする、など。
          • ・・・
        • ユニットテストしにくい
      • 下位メソッド
        • 状態を持たない(状態値を変更しない、参照しない)
        • クラスのプロパティを変更しない。
        • 入力=引数のみに依存し、結果は全て return 値だけに反映する。
        • 例:
          • 自分で定義する各種処理ルーチン
        • ユニットテストがやりやすい

4. どこで深刻なバグが起きやすいか

  • 上記説明における、下位モジュールでは、あまり深刻なバグは生まれません。
  • ほとんどの深刻なバグは上位モジュールの状態管理や条件判定、あるいはスレッドやタイマーの制御、メモリやリソースの管理に起因します。
  • したがって、デバッグしやすくするには以下の原則を守ることが大事です。
    • スレッドやタイマーの制御方針を明確に、一貫したものに。
    • 状態の管理や状態遷移の方法を明確に、一貫したものに。できるだけ一箇所・ワンパターンに集約する。
    • 安易にフラグ制御を増やさない。
    • メモリ・リソースの確保・解放は同一レイヤー(階層)に揃える。

以上

『ねこもに』のアルゴリズムを書き、特許出願してみた

ねこもに』は、当社オープンストリームが開発中の新商品である。来年春の発売を目指している。現在開催中のCEATECにて発表・出展し、概ね好評をいただいているようだ。

 

ねこもには、スマホBluetoothを使ったシステムだ。猫の首輪にBluetooth(BLE)発信機を取り付けて、専用のスマホアプリを使って猫を探したりできる。

 

このシステムの肝となるのが、猫の場所を見つけるアルゴリズムである。よく誤解されるのだが、 このアルゴリズムは、iBeacon のような ON/OFF表現ーー『近くに居る・居ない』ーーで猫を見つけるのではない。二次元マップ空間上で、連続値的に猫の存在確率分布を計算して推定しているのである。その部分はちょっとした工夫をしていて、ざっと調べたところ類似の前例が見つからなかったので、現在特許を出願している

 

今回、このアルゴリズムの数理的な部分は私が考案させてもらった。たまたま、この方面の知識と経験があったからである。もちろん、突然思いついた訳ではなく、ねこもにという商品のコンセプトが先にあって、その解決策を考えていくうちに発想できたものである。

 

『ねこもに』のコンセプトは、当社のねこもにチームが発案し、毎年開催している社内コンペに勝ち抜いたものである。猫への愛情にあふれた、なかなか良いアイデアである。ただ、最初にその構成案を聞いたときには、これはちょっと無理じゃないのかな?と思った。情報処理のモデルを単純に考えると、典型的な不良設定問題になっていたからだ。

 

ご存知の通り、不良設定問題とは、与えられた入力情報だけでは答えが一つに定まらない、というタイプの数学的問題である。

 

BLEは、個体を識別するIDの他は、電波強度=距離しか検知できないデバイスである。つまり、BLE自身は一次元センサーであって、二次元的な位置を計測する機能はない。

 

これでどうやって猫の位置を精度良く推定しようか?・・・離散的なON/OFF表現のメッシュマップでもできるけど、それだと、メッシュの分解能以上の精度を出すのは難しいし、広域をサポートしようとすると、メッシュのデータを保持するメモリ容量も膨大なものになる・・・考えるうちに気がついたのはモーションステレオとの類似性である。

 

モーションステレオは、単眼カメラでステレオ視を実現する画像処理技術である。単眼カメラは二次元センサーであり、ステレオ視は奥行きを含めた三次元情報の復元が目的である。つまりここでも、一つ次元が少ないセンサーから、一つ次元の高い情報を再構成している。その点でねこもにの課題と似ていることに気づいた。(気づいたときはちょっと嬉しかった)

 

モーションステレオでは、カメラを移動させながら複数の画像を撮影して、奥行き推定を行う。同様にねこもにでも、スマホを移動させながら、BLEとの距離複数回計測して推定に使えば良いだろう、これが基本コンセプトになった。

 

もう一つの問題がある。それはBLEの距離値の誤差がけっこう大きいことである。BLEから得られる距離値は、周囲の環境の影響を受けたりして、平気で数メートル〜数十メートルぐらいの誤差がでるときがある。画像のモーションステレオなら、それなりに良いレンズなどを揃え、適切なキャリブレーションを実施すれば、ほとんど入力誤差を考慮する必要がないが、BLEは誤差だらけであり、誤差を考慮しないとまともな答は出ないのは明白であった。

 

センサーから誤差の影響を減らしたいとなれば、誰もが考えるのがフィルター理論の適用であろう。私もまずは古典的なカルマンフィルターを考えたが、5秒後に却下した。カルマンフィルターでは、対象物体の運動を線型な方程式で表現できないといけない。気まぐれな猫の運動を線型な方程式で記述できるわけがないw。そうなると・・・パーティクルフィルターを使うのが常識であろう。

 

というわけで、ねこもにでは、パーティクルフィルターを使うことで、誤差込みの距離センサー値を複数回重ねあわせて、二次元位置を逐次推定するモデルを使うことに落ち着いた。

 

パーティクルフィルターを位置推定に使う特許や論文は沢山あるのだが、ほとんどがGPSや移動台車のデッドレコニングなどへの適用例であり、ねこもにのようなアプローチは意外に見つからなかった。なので特許を出願したわけである。

 

実際のソフトウェア実装の話も書こうと思ったが、かなり長くなったので、また別の機会にしよう。

 

 

オープンストリームは面白い会社になりつつある

縁あって、2012年から(株)オープンストリームで仕事をしている。入社した目的は、この会社を単なる受託型のソフト開発会社から脱却させることである。この目的は当時の佐藤社長(現会長)の思いでもあり、それを手伝いたいと思って入社した。

受託開発からの脱却とは、私の解釈では、社会・市場に対してオリジナリティのある商品を自ら提案・発信してビジネスをしていける会社にすることであり、平たく言えば自社製品や自社サービスを柱にしてビジネスをできるようにすること、つまりはメーカー化のことである。

佐藤社長のあとを引き継いだ吉原社長も、この流れを一層進化・深化させようとしている。私も2014年からはCTOに任命いただき、よりダイレクトにこの方向の仕事ができるようになった。

こうした背景のもとで進めてきたプロジェクトが、自社サービスの『LogStream/RecoBee』、『Edamame』、『ねこもに』、そして電気通信大学との人工知能の共同研究である。わずか200名余りの規模で、しかもいままで受託中心で開発をしてきた会社としては、かなり攻めていると思う。どれもまだ緒についたばかりで、失敗や拙い面も多々あるが、とにかくチャレンジし実行していることは(自分の所属会社なので手前味噌だが)なかなか大したものではなかろうか。

いま困っているのは、まだまだ人手が足りないことである。オープンストリームでは、こうした活動に共感し、直接的・間接的に支援してくれる優秀な人材を絶賛募集中である。とりわけ、自分で発想して自律的に動ける人にとっては、とても面白い可能性を秘めた会社である。興味のある方は是非連絡いただきたい。