年末のご挨拶と近況、あるいは機械学習のはじめ方

あ、退職エントリとかではないです。雑多な駄文をお許しください。

2018年を振り返る

3月にカリフォルニア州パロアルトのラボに異動になって早くも3/4年が経ちました。 自分としてはまだ1年経ってないのかという感じです。もっと長く居るような気もするが、来たばかりのような感じもある。 生活には完全に慣れました。結局の所、生きていくだけなら "You need a bag?" に "No" だけ言えれば何とかなります。

家族のこと、子供のこと

家族が適応に苦しんでいます。特に子供は、8月からTKという公立小学校の下部組織に通っていますが、予想を遥かに超えて心を閉ざしたままです。 娘はとてもシャイで、思ったことが口にできません。非常に端的に言うと、生きる力が強くありません。象徴的なできごとが幾つかありました。

ある日、先生が陪審員の義務で代わりの先生が来た日、普段とは違う教室に預けられた。 お昼になってみんなは弁当を取りに行ったが娘は「誰も教えてくれなかったから」部屋に残り、そのまま食事も摂らずに途方に暮れて過ごした。

またある日はバッグにフォークが入ってなかった。実際には底の方に入っていて気付かなかった。 娘は「手で食べるのはお姉さんじゃないから」そのまま諦めてお弁当を食べなかった。

自分だけ食事をとっていけないはずがない。隣の部屋に歩いていけばよいのだ。 フォークがなければ手で食べればよいのだ。どのみちおにぎりとタコさんウインナーとかしか入っていない。 食器がなければ "fork!" と言えばいい。"Help me!" でもいい。言葉なぞ重要ではないのだ。毎日毎晩教えた。それでもできない。

それでも娘の不安と孤独と理不尽を思うと怒る気にはなれません。こんな目に遭わせてすまなかったねと抱き合って泣くしかできません。 向いてない、向いてなかったんだ。この地には勝者しかいない。敗者は去ったのだ。我々は路傍の石にすぎない。

どうすべきか結論は出ておりませんが、会社が親身に相談に乗ってくれているのでもうちょっと色々考えてみようと思います。ありがたいことです。

仕事

僕のこの地でのミッションは、会社に新たな収益源の萌芽をもたらすことです。 サービスの詳細をまだ公開できないのが心苦しいのですが、前期はプロトタイプとして小さなウェブサービスをひと月ぐらいでひとりで開発しました。方法論だけ以下のエントリにまとめてあります。

fushiroyama.hatenablog.com

会社はこれを非常に高く評価してくれて、ボーナスをいっぱいくれました。本当に良い会社です。ありがたいことです。

その後一瞬モチベーションを失いかけたのですが、後述する機械学習のプロジェクトが始まってまたモリモリとやる気が戻ってきました。 いまは死ぬ前の山のフドウのような清らかな笑顔で仕事場に向かっております。

機械学習

実はこのエントリで一番書きたかったのがこれです。これも以前別エントリで書きましたが、僕はこの言い方は好きではないのだが、まあいわゆる文系出身でして、数学はIAIIBまでしかやっていません。それも大部分は忘却の彼方に置いてきました。その状態からとりあえず機械学習のプロジェクトを始めるまでの準備をここに残そうと思います。

以下、自分が現状認識している機械学習について持論を述べておりますが、これは大いに誤っている可能性がありますから、容赦なくご指摘ください。来春までのプロジェクトの糧にしたいです。

fushiroyama.hatenablog.com

まず、機械学習の目的なのですが、これが個人的にとても重要だと思っています。我々のプロジェクトの場合、機械学習を利用する目的は「よりユーザのコンテキストを理解した提案をするため」です。

昨今世間で言われる "AI" の大部分は、機械学習の「学習済みモデル」を指していると認識しております。 これは関数のようなもので、ある入力に対して直ちに結果を出力します。プログラミングアルゴリズムとの違いは、これが単純なif-elseによる分岐ではなく、膨大なデータを使った学習の結果できあがったある種のブラックボックスであるという点です。 この関数の出力が、人間が目で見て頭で考えて行うそれよりも高精度であることが機械学習を使う究極の目的のひとつです。

機械学習が得意なことは限られています。すなわち、

  1. 連続的な変化から次の結果を予測する。これが「回帰 (Regression)」
  2. いくつかある候補の中から、入力したものがどれに類するか判定する。これが「分類 (Classification)」
  3. 雑多なデータの集まりから(時には人間にもわからない)性質の類似を見つけ出し、自律的にまとまりをくくりだす。これが「クラスタリング (Clustering)」

これらが考えられます。

1と2は実際のデータと正解データを与えながら学習させ、最終的には未知なるデータを渡した時に正解を予測してもらうという使い方をします。これは教師あり学習と呼ばれます。 対して3は、人間にも正解が分からないがデータを繰り返し与えることで特徴の似通っている部分をもとに群を形成してもらい、未知なるあるデータがどの群に類するかを出力してもらって同じ群の商品をユーザにオススメするなどの使い方をします。これは教師なし学習と呼ばれます。

僕の会社は世界最大規模のニュースメディアカンパニーであり、最大の強みは膨大な量のニュース記事そのものです。 したがって僕らがやりたいことは、ユーザが読みたいであろう記事をいかにユーザにシームレスに提供するかというところに帰着します。 必然的に、3の応用系が僕のミッションとなりそうです。

機械学習の数学

ここからが本題なんですが、僕は機械学習のプロジェクトを始める前に理論寄りの勉強をしました。 これには理由がありまして、自分の頭で考えて試行錯誤するための自力が欲しかったからです。

もしやりたいことが「カリフォルニアに棲む全野鳥の詳細な画像認識」のようにハッキリと決まっており、そのための教師データ(野鳥の画像)もある場合は、理論などすっ飛ばしてとにかく機械学習のライブラリなりフレームワークなりの使い方のみ覚えた方が求める結果に早くたどり着けると思います。

で、理論を学ぶ場合はどうしても高校程度の数学を避けて通ることができません。 ただそれほど極端に恐れる必要はなく、ざっくりと「行列の内積」と「微分」がわかれば良さそうです。 ここでは自分が基礎知識を身につけるために使った教材を紹介したいです。

ゼロから作るDeep Learning

この本はマジで素晴らしいです。Deep Learning機械学習の手法のひとつで、敢えて誤解を恐れずに言うならば、教師データから最適な重みパラメータ(後述)を自動獲得することを目指した学習手法です。

この本の特徴は、特定の機械学習のライブラリやフレームワークの使い方の解説に主眼を置いておらず、NumPyという行列の計算を便利に行うためのライブラリとPyplotというグラフ描画用ライブラリを用いる以外はもっぱら愚直に機械学習で利用する関数を理論に基づいて実装していくというスタイルをとっていることです。

はじめはパーセプトロンという、複数の信号を受け取ってひとつの信号を出力する回路を実装します。 信号(たとえば電流を想像してください)は、重みと呼ばれる信号を増幅/減退させるための係数を掛けて、それが閾値を超えると1、それ以外は0を出力するというような極めてシンプルなものです。 これを使って、プログラマなら誰でも理解できるANDゲートやORゲート(論理回路)を実装します。 次に、シンプルな論理回路を組み合わせてXORゲートのような非線形回路を実装し、ニューラルネットにつなげます。

それからニューラルネットワークという、パーセプトロンの発展形を実装していきます。ニューラルネットワークでは信号の出力部分を司る関数(活性化関数といいます)にシグモイド関数などのなめらかな変化を表現する関数を用い、単純な01の信号から連続的な実数の変化を出力できるようになります。 ディープラーニングとはこのニューラルネットワークを多層に重ねて学習をさせることで精度を上げる手法です。

ここで必要となる数学の知識は、たかだか指数関数の値の変化だとかその総和であるとか総和に対する割合であるとか、いずれも四則演算であって何ら恐れる必要がありません。行列の内積も、結局の所データをベクトルとして表現して各ニューロンを通る際に次元を合わせなければならないという程度に過ぎず、かしこまって高校の教科書を取り出さなくても次のウェブサイトを参照するぐらいで十分です。

atarimae.biz

この本ではその後も、新しく出てくる知識はとくに外部情報に頼ることなく解説を読みながら進められる程度の難易度でずっと進んで行きます。 損失関数という、ニューラルネットワークが手掛かりにしながら適切なパラメータを探るための関数を自分で実装しながら二乗和誤差を使った最小二乗法(最近話題になりましたね)などを学びます。

さて、この辺りで微分が出てきます。 機械学習では学習の際に最適なパラメータを探索していくんですが、このときに各データがどういう風に変化していくかをその瞬間の変化量を元に求めます。 これこそが微分であり、それ以上でもそれ以下でもありません。

僕はどれだけ思い出しても高校時代にまともに微分をやった記憶がなく、正直イチからの勉強になりましたが、これについてもこの本の解説がとても丁寧なので特に難なく読み進められると思います。たとえば、次は本書で紹介される数値微分Pythonでの実装例ですが、

def numerical_diff(f, x):
    h = 1e-4  # 0.0001
    return (f(x + h) - f(x - h)) / 2 * h

これって、第一引数に関数を、第二引数に何か変数を取ってすごーーーーーく小さい値を加えつつ実行したときの差分を、その小さな値で割った(つまりその小さい値の範囲内での変化量。ただの比)だけですよね。プログラマだからこそ、教科書にある lim -> 0 みたいなのより分かりやすいと思うんです。

指数関数の微分公式とかも突然当たり前の知識として出てくるんですが、これも次のリンク等を見ておけば十分です。

atarimae.biz

あとは、勾配法、微分を効率的に行う誤差伝播法、畳み込みニューラルネットワークと発展していきます。 この本では主にMNISTという手描き数字のデータセットを使った画像認識を扱っていますが、続刊では自然言語処理も扱っているようです。 とにかく、最初に読む一冊として強くおすすめします。

ゼロから作るDeep Learning ? ―自然言語処理編

ゼロから作るDeep Learning ? ―自然言語処理編

「超」入門 微分積分

先述のとおり、個人的には「ゼロから作るDeep Learning」を手を動かしながら読んでいけば、機械学習をやるための数学を別途やる必要はそれほどないように思っていますが、夜に補完的に読んでいる本を紹介します。

「超」入門 微分積分 (ブルーバックス)

「超」入門 微分積分 (ブルーバックス)

これは中々面白い本で、微分積分を小中学校で学ぶような図形の面積の求め方といったイメージしやすいアプローチで解説してくれる本です。

特徴的なのは、まずは積分から解説している点です。筆者の主張によると、積分法の方がずっと古代から成立したものであり、それが身近なものの面積や体積の近似を簡単に求めるための実用的な用途であり、図形から視覚的に理解しやすいだろうという考えのようです。 実際に三角形や長方形を使って半球やトーラス体などの面積や体積を求めますが、小中学校の知識から極限に関する洞察などをわかりやすく与えてくれます。

後半では期待する微分の解説ですが、これも可能な範囲で極力二次元三次元図形を使った視覚的にイメージしやすい方法で変化量を解説してあり、微分の各種公式がどうしてそういう形なのかも暗記ではなく理解から導出できるような作りになっています。 これを読む前と後で機械学習の勉強に対する貢献があったか否かはちょっと判断がむずかしいですが、増減表とかは僕は知らなかったので今後高校数学をやる上ではとても良かったです。それに、何よりの貢献はやはり微分に対する恐怖が減ったことかな。

やさしく学ぶ 機械学習を理解するための数学のきほん

それから、これは紹介するかちょっと迷ったんですが一応読んだので紹介しておきます。 機械学習で使われる用語や理論を分かりやすく解説してあるという点で、前出の「ゼロから作るDeep Learning」に小さい重みを、「超入門 微分積分」に大きい重みを掛けてシグモイド関数に通したような本ですが、女の子二人の会話形式で進んでいく体裁が好みの分かれるところです。ハマる人にはハマると思うので書店で見かけたら試し読みしてみてください。

今後

このエントリで書いた内容はあくまで機械学習プロジェクトの準備体操であって、恐らく現実世界の課題を解決するために想像を超える艱難辛苦が待ち受けていることは想像に難くありません。年明けからは外部の協力会社さんにエキスパートアドバイザーとして入ってもらいながら、いまやってるプロジェクトの最適なレコメンデーションエンジンを実装予定です。

重ね重ね、会社にはこのAIの時代に自分に1Qを投資して機械学習のプロジェクトをやらせてもらえることを感謝します。 よい結果を出すことが会社への最大の恩返しだと思うので、気合を入れて頑張ろうと思います。

それでは少し早いですが、よいお年を。白山、タイキック。