2018年05月13日に初出の投稿

Last modified: 2018-05-13

昨今、機械学習を応用したプロジェクトが数多く紹介されている。その一つに、例えばスマートフォンで撮影した花とか葉とか魚とかの名前を自動で検索するアプリケーションがある。Facebook で、アップロードした写真から人物らしき姿を見つけ出して、既に登録されている人物の顔写真と照合し、「これは誰それさんでは?」と知らせる機能も原理は同じだ。

ソフトウェア開発者として簡単にそういう原理を使おうというなら、手順としては次のようになるだろう。まず形式的な観点から必要なのは、既にあるデータの特徴と、入力されたデータの特徴を比較して、類似度を算出するようなアルゴリズム(仮に「AC」とする)をつくることだ。更に、比較したいデータの要素が複数あってベクトルなり行列として表現できるなら、入力データの一部の要素が欠落している場合に不足しているデータを合理的に推定して補充できるアルゴリズム(仮に「AR」)も必要だろう。

これらのアルゴリズムは、全く形式的な処理だけを行う。入力されたものがテキストだろうと画像だろうと、あるいは犬の写真だろうと葉っぱの写真だろうと関係ない。要するに入力されたデータは全てバイナリのビット列として何か特徴のあるパターンをもつと想定すれば区別は必要ないからだ。そして、ビット列のパターンとしてだけ入力を扱うことによって、「特徴とは何か」という哲学に悩む必要もなくなる。全てのビット列を扱うのだから、そこから「どれが特徴に値することなのか」とわざわざ比較対象のデータを抜き出さなくてもいいからだ。例えば、AC がユニコード文字列のテキストデータだけを比較すると仮定すれば、「お」というデータは「\u304a」でしかありえない。「お」が平仮名であるとか、ゴシック体で表示されているとか、日本語の文字であるとか、そんなことはどうでもよいのであって、「\u304a」と同じビット列のパターンをもつかどうか(持つ)、「\u304b」と同じビット列のパターンをもつかどうか(持たない)だけが問題になる。

しかし、入力が比較対象と完全に同じデータか、それとも違うデータかという単純な比較だけなら、AC など小学生でも作れる( "if ( A === B ) then function();" で終わりだ)が、たいていはどちらかのデータの一部が不足していたり、どちらかに余計なデータが多すぎたり、あるいは入力データも比較対象もそれぞれデータが不足していたり余計なデータを持つかもしれない。例えば、1枚の写真から或る人物の顔を特定する場合、その画像に含まれる大半のデータは、比較対象である当人の顔写真の特徴となるデータとは何の関係もない、背景の山のデータだったり、隣に写っている人物のデータだったりする。よって、AR というアルゴリズムを正確に説明しなおすなら、不足している情報を補うだけではなく、比較するにあたって「そもそも何が不足しているか」を推定できなくてはならない。こうした、データを比較するにあたって設計者が作りこんでしまうかもしれない予断や偏見を、可能な限りフィードバックされた結果をもとにして修正する仕組みが必要となる。よって、どう比較するかだけではなく、何が比較に値するかを、推定と結果のフィードバックを再帰的に繰り返しながら AC, AR を(できれば結果として)向上させてゆくプロセスが「学習」である。

ここでは簡単に文字列の比較を扱う。そして、入力データ A と、手持ちのデータベースにある比較対象データ B とを比べて、両者がどのていど「似ているか」を計測することにしよう。入力データ A を、このシステムの利用者が指定した URL だと仮定すると、その URL についてウェブページのソースコードをダウンロードするネットワーク関数を使えば、ソースコードはすぐに手に入る。PHP なら file_get_contents() 関数などでデータの入手先を A とすればよい。あとはタグを取り除いたり、ソースコードのセマンティクスを仮定してヘッダやフッタといった、比較したいコンテンツとは関係ない HTML 要素も取り除いてゆく。この結果を A から得たデータなので [A] としよう。

文字列がどのていど似ているかを計測して序列を作るという形式的な目的だけなら、[A] と比較するべき手持ちのデータベースは、実は必要ない。なぜなら [A] と比較することで、最も似ている文字列データ、つまりは「正解」を仮定する必要がなくなるからだ。このような、「正解」を必要とせずに大量のデータを闇雲に入力していっても所定の目的が果たせる場合に、そこで実行される学習処理を「教師なしの学習(unsupervised learning)」と呼んでいる。他方、所定の目的が何か決まっていて、[A] が特定の B というデータに最も一致するということが要求されるなら、そこでの学習には B という基準を初期条件として与えておかなくてはならない。これを「教師ありの学習」と言う。

教師なしの学習を実行するなら、まず手始めに簡単な AC から始められる。つまり、単純に [A1] と別のデータ [A2] とを文字列として比較するだけだ。一文字目から比較を開始して、何文字目まで一致するかを、比較した結果の序列として扱えばいい。「かわもとたかゆき」と「かわもとひさゆき」は4文字目まで一致するので「スコア4」とすれば、「かわもとたかゆき」と「かわたにたかゆき」は2文字目までしか一致しないので「スコア2」であり、このスコアが大きいほどデータの類似度は高いと判定する。あまりにも単純で馬鹿馬鹿しいが、確率微分方程式や行列を使って Google がやっていることも概念としては同じである。これを PHP で実装するなら、既にレーベンシュタイン関数というものが用意されていて、

$score = levenshtein( A1, A2 );

だけで済む。この関数は、A1 の文字列を一つ一つ置き換えたり入れ替えたり追加したり削除して、何回のステップで A2 に変換できるかという手順の回数で両者の類似度を計測する。もちろん、AC としてレーベンシュタイン関数がパフォーマンスの点で最善かどうかは自明ではない(文字列どうしの単なる一致だけを判定するなら == よりも遅いに決まっている)。しかし、少なくともこのような仕組みを使って、手持ちの膨大なテキスト情報と比較するか、あるいはオンラインのリソースを対象にして比較するかの違いはあるが、学習を勝手に始めさせられる。オンラインのリソースを使うなら、入力した [A1] に対して既存の検索サイトから得た結果(たくさんの URL)を使って、テキストコンテンツを file_get_contents() 関数でダウンロードしてから整形しなおして、自前のデータベースに格納して比較対象として蓄えてゆく。もちろん検索サイトから結果を得た時点で、既に他人が作った AC を利用しているという限界はあるが、自前で Google のロボットと同じことを全世界のドメインに対して闇雲に実行することはきわめて難しい。先のノートで、後続企業も Google に追いつく検索結果の品質に到達できると書いたが、誰でもできるなどと言ってはいない。

  1. もっと新しいノート <<
  2. >> もっと古いノート

冒頭に戻る


※ 以下の SNS 共有ボタンは JavaScript を使っておらず、ボタンを押すまでは SNS サイトと全く通信しません。

Google+ Twitter Facebook