知識ゼロからPythonで体験する機械学習

# このページのURL

https://goo.gl/Hcr2Sz

# はじめに

## まず、機械学習とは何かというお話を

"機械学習(machine learning)"とは、人間が学習を行うのと同様に、コンピュータにデータから学習を行わせるための技術、そして研究分野のことです。最近、"人工知能"がニュースや新聞で話題になり、その中で"深層学習(deep learning)"という技術が中心的な役割を演じていることも報道されています。機械学習は人工知能の一分野であり、深層学習は機械学習の一種です。

つまり、深層学習、機械学習、人工知能には、以下の図のような包含関係があります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/78656897-b59e-1dc2-821a-fb3a37ce5ad1.png" width="500px">

# 機械学習でこんなことができます

この記事では、人工知能の分野で世界標準となっているPythonというプログラミング言語を使って、機械学習を簡単に体験してもらいます。Pythonの機械学習ライブラリscikit-learnのウェブページには、以下のようなチートシートが掲載されています。これを見れば、自分の持っているデータに対して、機械学習で何ができるかがすぐ分かります。

http://scikit-learn.org/stable/tutorial/machine_learning_map/

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/13dfad2d-fd64-424d-aa54-65103afac2e9.png" width="500px">

機械学習でできることは、以下の4つに分類されます。

- 識別(classification) ... データとそのグループ分けの情報から学習し、未知のデータをグループ分けする(例: ネコとイヌの画像を識別する)
- 回帰(regression) ... 問題と答のデータから学習し、問題から答を予測する(例: 株価の予測)
- クラスタリング(clustering) ... 正解のデータなしに、データをグループ分けする(例: 顧客データから顧客をグループ分け)
- 次元縮約(dimension reduction) ... 多くの項目からなるデータを加工し、本質的な少数の項目を得る(例: 顧客データから顧客の行動を特徴づける指標を抽出)

今回はこの中から、「識別」をPythonで体験してみます。

# Pythonのプログラムを動かすもっとも簡単な方法

## repl.itを使いましょう

ここでは、インストール不要ですぐ使える方法として、repl.it という無料のウェブサービスを紹介します[^Anaconda]。このサービスを利用すれば、ウェブブラウザの上でPythonのプログラムを動かすことができます。また、URLからプログラムやデータファイルを共有することができます。

[^Anaconda]: より標準的な方法としては、Anacondaというインストーラで自分のPCにPythonをインストールし（参考: [Anacondaを利用したPythonのインストール(Windows)](http://pythondatascience.plavox.info/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB-windows)）、Jupyter Notebookでプログラムを実行する方法（参考: [Jupyter Notebookを使ってみよう](http://pythondatascience.plavox.info/python%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83/jupyter-notebook%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)）などがあります。

https://repl.it/

上記のURLを開くと、以下のようにプログラミング言語を選択するページが現れます。**ここでは`Python3`と入力し、Enterキーを押します**（`Python3`はPythonのバージョン3を意味します)。

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/a6e65b79-3c31-13cb-a7b0-c9369e8792a8.png" width="500px">

すると、以下のようなページが現れます。エディタ(左側の白い部分)にプログラムを入力し、ページ上の"run▶"ボタンを押せばプログラムが実行され、コンソール（右側の黒い部分）にプログラムの実行結果が表示されます。

## Hello!と表示してみる

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/59ad6e54-bb34-76ff-6430-58a600698894.png" width="500px">

試しに以下のプログラムをエディタに入力し、"run▶"ボタンを押してみましょう。プログラムがうまく動けば、以下のようにコンソールに"Hello!"と表示されます。

```py3:Hello!と表示するプログラム
print("Hello!")
```
```text:実行結果
Hello!
```
URLから実行: https://repl.it/JU2E/0

## プロジェクトモードにする

次に、**ページ左上の<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/542e4c50-a33d-0593-ca57-77becd5ee6c9.png" width="30px">ボタンを押します**。すると、"Welcome to Project Mode!"(プロジェクトモードへようこそ！)というメッセージが出ますので、**"Continue"ボタンを押します**。

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/1685ca4d-e4af-95f3-d316-ca37d7c75c72.png" width="500px">

これでプロジェクトモードになりました。プロジェクトモードでは、複数のファイルを扱うことができて、以下のようにエディタの上についているタブでファイルを切り替えます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/35476fcd-ab70-e500-9f26-13d79a8de6a5.png" width="500px">

# Pythonプログラミングのもっともラフな解説

## 変数とリスト

プログラムの中でデータ（数値や文字列など）を取っておく箱のようなものを「**変数**」といい、変数にデータを入れておくことで、そのデータをプログラムの中でもう一度使うことができます。Pythonでもこの変数を使いますが、C言語やJavaといった他のプログラミング言語とは違い、**変数の種類を表す「型」を指定する必要がありません**。Pythonでは、「ある変数にあるデータを入れる」という意味のプログラムを書くだけでOKです。

例えば、以下のようなプログラムを書きたいとします。

- "a"という名前の変数に1.23という数を入れる
- "b"という名前の変数に"Hello!"という文字列を入れる

この場合、以下のように書けばOKです。ただし、プログラムの後半2行では、変数に入っているデータをコンソールに表示しています。

```py3
a = 1.23
b = 'Hello!'
print(a)
print(b)
```

また、変数に番号を付けえ区別することにより、複数の変数を一つにまとめることもできます。こうした変数のことを「**リスト**」といいます。例えば、1, 2, 3, 4, 5という5つの数値を"list"という名前のリストに入れる場合には、以下のように書きます。ただし、プログラム2行目ではリストの内容をコンソールに表示しています。

```py3
list = [1, 2, 3, 4, 5]
print(list)
```

リスト"list"の1番目のデータは"list[0]"、2番目は"list[1]"、...、5番目は"list[4]"というように、リストに含まれる要素を番号で区別します(番号が0から始まることに注意しましょう)。この書き方を使って、以下のように各要素を別々に表示してみます。

```py3
list = [1, 2, 3, 4, 5]
print(list[0])
print(list[1])
print(list[2])
print(list[3])
print(list[4])
```

では、試しに以下のプログラムを実行してみましょう。

```py3:リストの使い方
# -*- coding: utf-8 -*-

list = [180, 77, 29]  # リスト(身長、体重、年齢)

print(list)    # リストの全ての要素を表示
print(list[0]) # リストの1番目の要素を表示
print(list[1]) # リストの2番目の要素を表示
print(list[2]) # リストの3番目の要素を表示

list[1] = 80   # 2番目の要素(体重)だけ書き換え

print(list)    # リストの全ての要素を表示
```
```test:実行結果
[180, 77, 29]
180
77
29
[180, 80, 29]
```
URLから実行: https://repl.it/JU2x/1

変数には、数や文字列だけではなく、データとデータに対する操作をまとめた「**オブジェクト**」を入れることもできます。オブジェクトを理解するためには、オブジェクト指向プログラミングと呼ばれる考え方を理解する必要があり、ここでは説明しきれないので省略します。Pythonの文法をしっかりと勉強したい方は、ウェブラーニングや書籍を参照して下さい[^2]。

[^2]: プログラミング初心者がPythonの基礎的な文法を学ぶには、paizaラーニングの[Python3入門編](https://paiza.jp/works/python3/primer)が手頃です。

## ライブラリを使おう

Pythonを使う魅力は充実したライブラリにあります。

- NumPy ... ベクトル・行列演算などの数値計算。
- SciPy ... 統計、最適化、積分、信号処理など。
- Matplotlib ... グラフの描画。
- scikit-learn ... 機械学習。

# ニューラルネットワークを使ってみよう

深層学習でも使われている機械学習技術「ニューラルネットワーク」を使ってみます。ニューラル(neural)とは「神経の」という意味で、脳神経系などの神経回路を、形式的に模倣していることを表しています。ニューラルネットワークは、以下のように層状の構造を持ち、入力を受け取る「入力層」、結果を計算する「出力層」、その間にある「隠れ層」からなります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/155441/d1780082-f731-c896-fe49-613da2316127.png" width="500px">

## データセット1: Fisherのアイリスのデータ

ここでは、有名な[アイリスのデータ](http://pythondatascience.plavox.info/scikit-learn/scikit-learn%E3%81%AB%E4%BB%98%E5%B1%9E%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88)を用いて、ニューラルネットワークの識別能力を試してみます。アイリスのデータは、以下のURLからもダウンロードすることができます。

https://wkurebayashi.github.io/material/iris.csv

まず、以下のプログラムで、アイリスのデータをグラフにしてみましょう。

```py3
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np

data = np.loadtxt('iris.csv', delimiter=',')  # データの読み込み
plt.scatter(data[:,0],data[:,1],c=data[:,-1]) # 散布図を描画
plt.savefig('graph.png')                      # 画像の作成
```
URLから実行: https://repl.it/JWhd/0

では、このデータから学習した後で、未知のデータを識別できるか見てみます。

```py3
# -*- coding: utf-8 -*-
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
import numpy as np

# データの読み込み
data = np.loadtxt('iris.csv', delimiter=',')
X = data[:,:-1]
y = data[:,-1]

# データを学習用(train)、テスト用(test)に分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# ニューラルネットワークで学習
model = MLPClassifier(solver="sgd", random_state=0, max_iter=10000, hidden_layer_sizes=[1000,])

# ニューラルネットワークで予測
model.fit(X_train, y_train)

# 分類結果を表示
print ("識別率： ", model.score(X_test, y_test))
```
URLから実行: https://repl.it/JWkI/0

## データセット2: 数字の手書き画像データ

次に、これも有名な[数字の手書き画像データ](http://pythondatascience.plavox.info/scikit-learn/scikit-learn%E3%81%AB%E4%BB%98%E5%B1%9E%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88)を使います。このデータは、以下のURLからもダウンロードすることができます。

https://wkurebayashi.github.io/material/digits.csv

まず、以下のプログラムで、手書き数字のデータを画像として表示してみましょう。

```py3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

# データの読み込み
data = np.loadtxt('digits.csv', delimiter=',')
X = data[:,:-1]
y = data[:,-1]

# データの表示
plt.imshow(X[0,:].reshape(8,8), cmap=plt.cm.gray_r)
plt.savefig('graph.png')
```
URLから実行: https://repl.it/JWi1/2

では、このデータから学習した後で、未知のデータを識別できるか見てみます。

```py3
# -*- coding: utf-8 -*-
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier

# データの読み込み
data = np.loadtxt('digits.csv', delimiter=',')
X = data[:,:-1]
y = data[:,-1]

# データを学習用(train)、テスト用(test)に分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# ニューラルネットワークで学習
model = MLPClassifier(solver="sgd", random_state=0, max_iter=10000, hidden_layer_sizes=[1000,])

# ニューラルネットワークで予測
model.fit(X_train, y_train)

# 分類結果を表示
print ("識別率： ", model.score(X_test, y_test))
```
URLから実行: https://repl.it/JWiB/1

# 最後に課題＆感想をウェブフォームから提出

https://docs.google.com/forms/d/e/1FAIpQLSfLBH-zLRpOEHVuxXl_p5RJDIGWGQgDUm1VXJB87LCZoEA6YQ/viewform

おつかれさまでした。