機械学習超入門 

# 概要
社内の勉強会用に「機械学習って何？どうやって使うの？」というテーマでまとめたものです。この記事の内容が他の方の役に立てたら嬉しいです。

# 機械学習 ＝ AI？
機械学習は人工知能の一分野で、ディープラーニングは機械学習の一分野です。

<img width="350" alt="Picture1.png" src="https://qiita-image-store.s3.amazonaws.com/0/105335/0323497c-e3d8-4d7e-cd89-bba3810520d6.png">


#### ルールベース
多重If文や探査により多彩なパターンを網羅して、複雑な条件でも適切な出力がされるようにプログラムされているもの

#### 機械学習　
データのパターンや特徴を学習し、それをもとに未知のデータに対して何かしらの予測を出力する

##### ディープラーニング
データの特徴となる要素の取捨選択を自動で行うことができる、機械学習の手法の一つ

##### 強化学習
ある環境において、　エージェントが状況を観測しながら行動することを繰り返し試行し、目的を達成するための最適な意思決定を学習するもの

#### **Point!**
ルールベースだと、例外が発生すると人が手でルールを書き換える必要があり、どんどんデータが増えた時に、対応するのが困難
**→　機械学習では、コンピュータにやらせる！**

※以下、教師あり学習を前提に記載しています。

# 機械学習の種類
教師あり学習については、大きく分けて、回帰と分類がある。
回帰：予測の結果が数値のもの。2018年日本のGDPは？ → 回帰
分類：予測の結果がクラスであるもの。この花は、菖蒲か杜若か？ → 分類

# 機械学習って何をどうするの？

<img width="400" alt="flow.png" src="https://qiita-image-store.s3.amazonaws.com/0/105335/aaae17ca-c44a-2bc3-db56-a75512681500.png">


## 1. 何をするか決める
何をどの程度の精度で判断させたいかを決めます。

## 2. データを集める
予測・判断に必要なデータを集めます。
すでにDBに蓄積されたデータを使ったり、WEBから取得したりします。
集めたデータは「学習用データ」と「テストデータ」に分けます。

### クローリング
URLを元にWEBページのデータをダウンロードする技術です。
pythonのrequestsを使ったクローリング例：

```py:crawling.py
import requests
r = requests.get('https://ja.wikipedia.org/wiki/Python')
r.text
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/89d6125e-60a3-d48c-776d-171359f34fbb.png)

※Wikipediaには[データベース・ダンプ](https://ja.wikipedia.org/wiki/Wikipedia:%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89)があり、こちらを利用したほうが良い旨、コメントにてご教示いただきました。

### スクレイピング
ダウンロードしたWEBページから必要な情報を抽出し加工する技術
pythonのBeautifulSoupを使ったスクレイピング例：

```py:scraping.py
from bs4 import BeautifulSoup
soup = BeautifulSoup(r.content, 'html.parser')
soup.find(class_='mw-redirect').string
```

```py
>>> 'マルチパラダイム'
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/d3d6e9ed-2b72-cada-5d92-fca837406ba1.png)



### APIで取得
各サービスが公開している RESTful APIを使用して取得
[GitHub API](https://developer.github.com/enterprise/2.4/v3/search/)でデータ取得してpandasで加工した例：

```py:get_github_data.py
import requests
import pandas as pd

git_res = requests.get('https://api.github.com/search/repositories?q=language:python+created:2017-07-28&per_page=3')
pd.DataFrame(git_res.json()['items'])[:][['language', 'stargazers_count', 'git_url', 'updated_at', 'created_at']]
```


![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/fd6cf1a3-d31c-98ba-e094-0d943c5f135b.png)

## 3. データを整形する
集めたデータを整形します。どのように整形をするかは、データの種類とそのあとのモデル作成の作業によって、様々です。

### 欠損値の補間
特徴量のなかで歯抜けしているデータを、平均値や０で埋めて、データを補間します。
また、カテゴリーとして記載されている文字をフラグに置き換える（ダミー変数変換）処理なども行います。

<img width="300" alt="ffill.png" src="https://qiita-image-store.s3.amazonaws.com/0/105335/3f289f2a-af36-ba25-0712-13dbac3f179a.png">

### トリミング
画像データから特定のキャラを判別したい場合など、トリミングを行ったりアノテーションデータを作成します。

### 形態素解析
文章などは形態素解析によって分かち書きに変換し、さらにベクトル変換する事で数値として扱えるようにします。

#### janomeの例
インストール

```bash
pip install janome
```
分かち書き

```py:janome_test.py
# -*- coding: utf-8 -*-
from janome.tokenizer import Tokenizer
t = Tokenizer()

document = u'これはテストデータです'
tokens = t.tokenize(document)
for token in tokens:
    print(token.surface)
```

出力

```basy
これ
は
テスト
データ
です
```

## 4. モデルを作って学習
モデルとは、入力データ ( 予測・判断の要因 ) から出力データ ( 予測・判断の結果 ) に変換するためのもの。粗く言うと関数。

### 手順
取得したデータから、予測結果の要因となりそうなデータの構造や相関などを整理・分析して、一定の自由度を与えたモデルを作成する。学習用データでパラメータを決定して予測モデルを作成する。

イメージ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/c5dde529-e9e3-e10c-1261-d177ccb878a8.png)

* 特徴ベクトル ( 特徴量 ) ：予測の要因となる値
* 真偽ラベル ( ターゲット ) ：予測される値
* パラメータ：モデルに自由度を与える値
* 予測モデル：パラメータが確定したモデル
* 予測ラベル：予測モデルを使用した予測結果


### ライブラリ
専門知識や経験が必要な部分ですが、ある程度容易に作成できるライブラリがある。

* [scikit-learn](http://scikit-learn.org/stable/) :　python用の機械学習系
* [statsmodels](http://www.statsmodels.org/stable/index.html) :　python用の統計学系
* [Spark MLlib](http://mogile.web.fc2.com/spark/spark160/mllib-guide.html) :　ビッグデータの分散処理用の機械学習系ライブラリ提供
* [XGBoost](https://xgboost.readthedocs.io/en/latest/) :　高精度なアンサンブル学習モデルを作成できるライブラリ

scikit-learnを使用した例：
問題に対してよさげな[モデル](http://scikit-learn.org/stable/tutorial/machine_learning_map/)　( 今回は線形回帰 ) を選び、学習データをモデルにフィットさせて、学習済みモデルを作成。

```py:liner_reg_sample.py
import numpy as np
from sklearn import linear_model

# 収集したデータと仮定
x_data = np.arange(-3, 10, 0.1).reshape(-1, 1)
y_data = (1/2) * x_data + np.random.normal(0.0, 0.5, len(x_data)).reshape(-1, 1)

# 学習用データとする
x_train = x_data[70:]
y_train = y_data[70:]

# モデルを学習データにフィットさせる
reg = linear_model.LinearRegression()
reg.fit(x_train, y_train)
```

学習用データとテスト用データを分けるための[train_test_split](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)があります。
(今回は章ごとに読みやすくするために、使用しませんでした。)


### ハイパーパラメータ
モデルによっては、人の手で値を決める必要のあるハイパーパラメータがある。これは学習によって決定しない。 ( 例：DLの層の数、学習回数など )

ハイパーパラメータの決定方法

* グリッドサーチ：ハイパーパラメータの範囲を決め、等間隔に区切って全ての組み合わせを試す方法
* ランダムサーチ：ハイパーパラメータがある分布に従うとし、その中でランダムな組み合わせを試す方法


### その他
機械学習の手法をざっくりまとめた記事を以前、投稿しました。モデル構築のヒントになればと思います。
[Qiita 機械学習の情報を手法を中心にざっくり整理](http://qiita.com/ishizakiiii/items/f6909696c616fd6294ca)



## 5. テストデータで予測
作成したモデルを使用し、テストデータで予測を行います。

scikit-learnを使用した一例 ( 上記コードの続き ) ：

```py:liner_reg_sample.py
# テストデータ
x_test = x_data[:71]
y_test = y_data[:71]

# 予測
pred = reg.predict(x_test)

# 決定係数
print('score:', reg.score(x_test, y_test))
```

```py
>>> score: 0.714080213722
```

## 6. 検証
テストデータでの予測がどのくらいの精度で当たっているかを検証します。
各モデルにあった評価尺度で検証します。
### 評価尺度
##### 分類

* 正解率 ( accuracy ) : 全体のなかの正解した割合
* 適合率 ( precision ) : hogeクラスと予測した中で実際にhogeクラスであった割合
* 再現率 ( recall ) : 実際にhogeクラスであるデータの中で、hogeクラスと予測した割合
* F値 ( f1-score ) : 適合率と再現率の調和平均

scikit-learnにこれらを出力する[accuracy_score](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html)や[classification_report](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html)があります。


##### 回帰

* 平均絶対誤差 ( MAE ) : 予測値と正解値の差の絶対値の平均
* 平均二乗誤差 ( MSE ) : 予測値と正解値の差の2乗の平均
* 平均二乗誤差平方根 ( RMSE ) : 平均二乗誤差の平方根

scikit-learnにこれらを出力する[mean_absolute_error](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_absolute_error.html)や[mean_squared_error](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html)があります。

### 検証手法
* ホールドアウト検証 : データを学習用データとテスト用データにある割合で分割して検証する方法 
イメージ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/63477ec2-c144-a856-4724-d59abd6320e3.png)


* K-分割交差検証 : データをK個に分けて、1個をテスト用データとして、それ以外を学習用データとする。テスト用データの選び方はK通りあるので、全組み合わせで検証して精度の平均で評価する方法。
イメージ ( K=3 )
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105335/6de7433a-d221-10b8-a288-5e38ac8ca965.png)

scikit-learnを使用した一例 ( 上記コードの続き ) ：

```py:liner_reg_sample.py
from sklearn.metrics import mean_squared_error
from math import sqrt

# 相関係数
print('corr:', np.corrcoef(y_test.reshape(1, -1), pred.reshape(1, -1))[0, 1])

# RMSE
print('RMSE:', sqrt(mean_squared_error(y_test, pred)))
```

```py
>>> corr: 0.895912443712
>>> RMSE: 0.6605862235679646
```

可視化できる場合はグラフ化し、視覚的に確認します。

```py:liner_reg_sample.py
plt.scatter(x_test, y_test, color='blue')
plt.plot(x_test, pred, color='red')
plt.show()
```

![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/105335/a0a127a5-b900-935a-742f-60a5f393ec66.png)

### レポーティング
どのようなモデリングをしたか、テストデータは何を使ったか、どの程度の精度が出たのかを記録しておく。
私はpythonで書いているので、Jupyter notebookにてMarkdownで記載してます。


[Qiita : Jupyter Notebookをより便利に使うために、色々まとめ](https://qiita.com/ishizakiiii/items/b98bbf8997f039f40058#html%E8%A8%98%E8%BC%89)

## 7. 戻る
検証にて求める精度が出なかった場合は、何がダメだったのかを整理して、手順 「2. データを集める」 or 「3. データを整形する」 or 「4. モデルを作って学習」 に戻ります。このサイクルをぐるぐる回します。

# キーワード
## 過学習
学習データに過度に適応してしまい、未知のデータに対する予測の精度が低くなってしまう事。

## 特化型AI・汎用型AI
特化型AIとは、ある特定の分野において使用できるAIのこと。
汎用型AIとは、異なる多数の分野において使用できるAIのこと。（鉄腕ア○ムみたいなの）
ほとんどのAIは特化型AIです。


# おわり
勉強会では概要のみだったので、少し情報を追加した形でナレッジ共有できたらと思いQiita投稿しました。誤りがありましたらご指摘いただけたら嬉しいです。