AI始めたい企画の人向け機械学習って何という話

猫も杓子も AI と叫ぶ世の中になりました。
企画や新規事業を考えたいエンジニアから「こういうのって機械学習でできるの？」みたいな質問をちらほら聞くようになってきています。
この記事ではそのような人がほんの少しでも機械学習のことを知って、これはできるできないの肌感を少しでも持ってもらえればいいなと思って書いています。

この記事はわかりやすさを優先するためふわふわ書いています。いろいろ厳密じゃない説明があります。また、この記事を読んで「できそう」と思ったことができないことはたくさんありますし、逆も然りです。


# 機械学習って
機械学習では **Model** にたくさんのデータを与えて学習させます。
Model は人間で言えば脳みそみたいなものです。何かを学習してくれます。

Model にデータを沢山学習させる事によって、うまく行けばその裏側にある法則のようなものを Model が獲得してくれ、結果これまで見たことがないデータに対してもそれっぽい出力を出してくれるようになります。（汎化といいます）

Model が具体的にどんなことを行うのかは機械学習の種類によって変わります。次の節で説明してい行きます。

# 機械学習の種類
機械学習には大きく分けて下の図のように3つの種類があります。
ここではざっとそれぞれの特徴を説明します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/0d6e59e3-7a40-c8c0-383c-18973ae8166e.png)


## 教師あり学習
教師あり学習は「教師データ（正解データ）」がある学習です。一番ベーシックな機械学習です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/f660ba99-b05b-7307-3bea-209824f12164.png)

教師あり学習は以下のようなステップで学習を行います。

1. 猫の画像（**入力データ**）を Model に渡します
2. Model はそれを「犬」と誤って予測しました（**予測**）
    - 予測は出力とか推論とか呼ばれたりもします
3. 正解（**教師データ**）は「猫」なので、予測が「猫」が出やすいように Model を調整（**学習**）します

たくさんのデータで学習が十分に進むと、見たことのない画像を渡しても Model はそれを「犬」だとか「猫」だとか正しい予測ができるようになります。

よって、集めないと行けないデータは、**入力データ**と**教師データ**のペアです。
この入力-教師ペアを大量に集める必要があります。

## 教師なし学習
教師あり学習のように入力データと教師データのペアを用意するのではなく、入力データのみからよしなにそれらを分類したり圧縮したりする学習方法です。
<img src=https://qiita-image-store.s3.amazonaws.com/0/61079/fc104244-27ac-293f-9e65-07a426ca7f60.gif width=320>
_出展: [wikipedia](https://en.wikipedia.org/wiki/K-means_clustering)_

教師なし学習にはいろいろな種類があります。

- 入力データをなんとなく似たもの同士でいくつかの種類に分ける
- 入力データを似たものが似たベクトルになるように変換（圧縮）する

などなど。
ちなみに上の動画はたくさんの点の分布を決められた数に分類する k-means というアルゴリズムです。

教師なし学習では入力データのみから学習を行うため、企画的意図に沿った学習を行わさせることが難しかったり、種類も多様なのでこの記事では説明しません。


## 強化学習
強化学習はアメとムチです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/dd6f162c-f0c3-9f91-9963-db1460bea4cd.png)

Model は**環境**から**状態**をもらって**アクション**を行ない、その結果**報酬**を環境からもらいます。 Model はたくさん報酬を貰えるよう学習していきます。
良いことをしたら褒めて、悪いことをしたら叱るわけですね。

上の画像は Flappy Bird というゲームで、鳥を土管の間をくぐり抜けて飛ばすゲームです。ボタンを押すと鳥が上に飛んで、押さないと下に落ちます。

1. Model は状態（ゲームの画像）を与えられて、次飛ぶか飛ばないかを決めます
2. 環境は Model の決定に従って状態を更新（ゲームが進む）します
3. 環境は次の状態と、報酬を Model に渡します（1にもどる）

このようにして得られる報酬の合計を最大化するように Model は学習していきます。
報酬は、例えば土管にぶつかったら-5点（=叱る）、土管をくぐり抜けたら1点（=褒める）、などが環境から与えられます。

強化学習は、ゲームとロボットの世界で特によく用いられますが、それ以外では今のところそこまで頻繁に使われているわけでは無いように見えます。
正解の行動はわからないけど、どういう状態になればよいかはわかっているようなタスクに対して使われることが多いです。（ゲームだとゴールしたとか、点をとったとかで報酬をつけやすい。）


# 教師あり学習
分野に寄りますが一番よく使われるのは「教師あり学習」です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/f660ba99-b05b-7307-3bea-209824f12164.png)

おさらいすると、

- 入力データと教師データのペアをたくさん集める
- Model は入力からの出力の予測が教師データに近づくよう学習する
- Model に未知の入力を入れてもそれっぽい出力を出すようになる

ここではその中でも、近年流行りの DeepLearning を使ったものを前提として説明していきます。

## 識別問題と生成問題
教師あり学習で解決したい問題は、出力（もしくは教師データ）の種類でおおざっぱにいくつかに分けられます。

- **識別問題**： 出力が「種類」や「Yes/No」など数えられるもの
    - 画像を「猫」「犬」・・・に識別する
    - 文章が「ポジティブな内容」か「ネガティブな内容」か識別する
    - etc.
- **生成問題**： 出力が入力に使われるようなデータ
    - 文章から画像を生成する
    - 質問文から応答文を生成する
    - etc.
- **その他**
    - 画像から、対象の物体が映っている領域を出す
    - etc.

一般に生成問題は識別問題に比べて学習を行うのが格段に難しいことが多いです。



## 具体的な例
実際にはどんな例があるのか見てみましょう。

### 画像の分類
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/add4eb02-015f-c826-c680-bea8046a3f85.png)
画像に映っているのが何なのかを識別します。

- データ
    - 入力データ：画像
    - 教師データ：映っているものの種類
- 種類
    - 識別問題

### 物体検出
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/0827a88a-6cac-c235-f620-040165722230.png)
画像に映っているものを、映っている領域と合わせて出力します

- データ
    - 入力データ：画像
    - 教師データ：映っているものの領域と種類
- 種類
    - その他

### お問い合わせカテゴリ分類
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/37fa79b2-d367-4b3d-cfbf-73788abc6766.png)

- データ
    - 入力データ：問い合わせ内容の文字列
    - 教師データ：カテゴリ
- 種類
    - 識別問題

問い合わせ分類などは、自社で行っている場合すでに人手で分類したものがあるのでデータを集めやすい分野ですね。
一方で、人のカテゴリ分類に本当に一意性があるのかなどは気をつけないとはまります。
[カスタマーサポートAIの失敗と教訓](https://medium.com/mixi-developers/challenge-of-cs-ai-15c65ef7066a)

### 会話 bot
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61079/9918e344-273b-018b-da98-ac6f89097ab3.png)

- データ
    - 入力：ユーザーAの発話
    - 教師データ：ユーザーBの発話
- 種類
    - 生成問題

任意の文章が出力になるのでこれは文章生成の問題になります。
原理的には学習できるのですが、実際これで十分なクオリティ（日本語としてのクオリティ、応答としてのクオリティ）を担保するのはとても難しいです。
[DeepLearning における会話モデル： Seq2Seq から VHRED まで](https://qiita.com/halhorn/items/646d323ac457715866d4)
[作って理解する Transformer / Attention](https://qiita.com/halhorn/items/c91497522be27bde17ce)

また、上記は雑談対話を想定したものですが、記憶やその他の知識を使って会話をする、会話から情報を抽出する、などとなってくるとまた作るべきモデルの性質が大きく変わってきます。

## どのくらいデータを集めるの？？
### テキストの場合
DeepLearning を用いたテキスト分類系だと、私の肌感ではどれだけ少なくても**数十万文**（+それぞれ対応する教師データ）が必要で、**百万単位**くらいになってくるとそれなりに動く印象があります。
1万くらいだと DeepLearning のモデルは学習データの答えをほぼ丸暗記してしまい、学習データに無いデータに対して汎化しない印象があります。（丸暗記してしまって、その裏にある法則のようなものを見つけようとしない）

生成系だとこれが更に増えます。識別系の10倍以上は必要な印象です。
これは、生成系になると入力と出力（教師データ）の組み合わせの数も爆発的に大きくなり、またタスクによってはその裏にある法則が更に複雑になるためです。

### 画像の場合
画像系の学習は私はやったことがないのでわかりません。。
識者の方がコメントで書いてくれないかな（チラッ

なんとなくの肌感としてテキスト系より少ない数で学習できていそうな印象はあります。


### 少ないデータで学習するには？？
少ないデータでうまく学習する方法として「**転移学習**」という方法があります。
これは大量のデータで教師なし学習であったり別のタスクの教師あり学習を行ったモデルをベースにすると、少ないデータでも別の学習をうまくできる場合があるという手法です。

例えて言うなら、マラソンを20年間やってた人ならサッカーも（普通の人よりは）少ない練習でそれなりに強くなるよねみたいな感じです。

#### 画像
画像の世界では、 Google 等の強い企業たちが、大量のデータで物体識別を学習させたモデルを公開しており、それを転移学習させることが非常に多く行われます。

#### テキスト
テキストの世界では、識別に関しては BERT と呼ばれる教師なし的な学習を wikipedia など大量の文章で学習させたものをベースにすると、様々なタスクで性能が上がることが発表されています。
ただ BERT に関しては公式が出している日本語モデルがしょぼかったりするので自分でモデルを wikipedia などのデータから学習させる必要があるかもしれません。（私の職場でもやってますが年末年始のそれなりの期間、高い GPU を回し続けて作ったのでお金はそこそこかかりました。）


## データを集めるときに気をつける点
機械学習の肝はデータです。データをどのように集め、どのように整形するか。

私が大事だと思っているのは、モデル（ニューラルネット）の気持ちになって考えることです。
あなたは人工的に作られたモデルです。世の中のことは何も知りません。常識もなにもありません。
画像のタスクなら、実はその画像は元々3次元世界だったことなんか知りませんし、文章のタスクなら日本語の文法も意味もしりません。
その状態で、与えられた文字列なり画像なりをひたすら見てお勉強をしていきます。果たしてそれで、見たことのない入力に対して正しく返答を返すことができるか？？と考えてみましょう。

以下では、学習がうまくいかない/実運用時に使い物にならない、といった事になりうる陥りがちな罠をいくつか紹介します。

### 入力の情報が足りてない
例えばある文章が質問かどうかを判定する問題を考えましょう。（入力に「？」はつかないとします）

`ご飯食べに行く`

この文章、質問だと思いますか？肯定文だと思いますか？
これだけでは一意に決まりませんね。
でも人間はある発話が質問かどうか大概わかります。なぜか？
たとえば

- 音声的な特徴から判断している（質問は語尾が上がる）
    - 音声の情報も入力に加えることで識別が可能になるかもしれません
- 文脈（それまでの発話）から判断してる
    - 以下のように、直近の何発話か入れてみると、これは質問だなとわかります。
        - A: お腹へったなー
        - B: ご飯食べに行く

### 答えが一意に定まらない
とてもよくあります。
人間ですら人によって、もしくは一人の人間の中でもでも答えが一意に定まらないものです。

例えばある発話からこのユーザーが次また来るかどうか判定するタスクをしてみましょう。

`またこんどぜひお声がけさせてください`

この人、また来るって意味だと思いますか。言葉どおりなのか社交辞令なのか。多分100人の人間にラベルをつけさせたらわりとバラけると思います。

この例は極端ですが、実際計算的に求まるような問題でも無い限り、非常に多くのタスクでこれは起こります。感情の推定とか、問い合わせ分類とか。
想定しているいくつかの代表的なデータでは「一意にさだまるじゃろ」と思っていても、実際に集めたデータを除いてみると、「えっこれどちらだっていうの難しいな・・・」となるというケースが多いのです。

大事なのはエンジニアも企画もとにかく生のデータをしっかり見るということです。

### 集めたデータと実環境でのデータに差異があるもの
学習に使ったデータと実環境で流れてくるデータの質がずれているとモデルはうまく動きません。
よくあるパターンは

- **ジャンルが違う**
    - テキストチャットで集めたデータで音声対話ロボット用のモデルを学習
        - テキストでの会話のしかたと音声での会話の仕方は違うからうまくいかないかも
- **人工的に作らせた入力**
    - 会話データを集めたくて、人を集めて会話をしてもらう
        - 「やって」と言われてやる会話と、実環境の自然な会話は質が違った
- **一部の偏ったデータだけで学習してしまう**
    - 会社の人を集めてデータを作らせた
        - ITリテラシーが高い人ばかりだったので、ITリテラシーが低い人が実環境で使うと壊れる
- **質が刻々と変わっていくデータ**
    - 工場で画像から不良品判定をする学習をさせた
        - 工場の証明が古くなって暗くなったり、モノの配置が変わってデータの質が変わってしまった

### データ作った人が雑/ぶれてる
ラベル付（教師データ作成）をする人が一貫したルールのもとにラベル付けをしておらず学習がうまくいかないというのもよくあります。

例えば物体検出の問題で、「人」が映っているときにその部分である「耳」や「腕」は教師データに含めるのか？何％くらい映ってたら映ってるとみなすのか？
など、データには無限に曖昧性があります。可能な限りルールを明確に定めてラベル付けをして貰う必要があります。

# さあ AI はじめるぞ
（おまけです）
機械学習系の事業で重要なのは次の3つだと私は思っています。

- エンジニア
- 高価な GPU を借りる/買うお金
- 大量のデータ

まず最初に優秀なエンジニアを頑張って捕まえてください。

- どんな学習を行えばよいのかのアーキテクチャを選択できること（モデルやデータの設計）
- そのモデルをうまく学習できること（ハイパーパラメータのチューニングなどは職人技）
- 複雑なモデルをコーディングできること
- プロダクションで動かせるような機械学習インフラを作れること

これらは似ている部分もありますがそれぞれ別の技術です。
そしてこれらのどれかの技術でも持っている人は今引っ張りだこなのでなかなか捕まえられません。
機械学習をする環境（お金、時間、覚悟）が本当にあるのか、そして企画などのメンバーが少しでも機械学習の世界に理解があるのかが重要かもしれません。

エンジニアを捕まえたらその人と相談しつつどのような GPU 環境を作るか、どのようなデータを集めるのか検討していくことになると思います。
ちなみに AWS の p3.8xlarge という GPU サーバーは1台で年間1200万円くらいかかります。（お値段削減する方法はいろいろありますが）

# おわりに
この記事を読んで

- 機械学習の分類（教師あり、教師なし、強化学習 / 識別、生成）
- どんなデータを集めないといけないか

の肌感を掴んでいただければ幸いです。
ここで書かれていることをすべて正しく満たしたとしても、それはまだスタート地点に立ったに過ぎません。
DeepLearning の難しさは使うモデルの選択、膨大な学習テクニックを使いこなすこと、そしてそれらの背景にある数学的知識の理解にあります。
データと GPU が有っても、学習がうまくいくとは限りません。試行錯誤の中でできることを見つけていく長い時間が必要になります。