Python
機械学習
scikit-learn

数学も英語もPythonもわからないけど機械学習に触れたかった(前編)

概要

数学も英語もPythonもよくわからないし、機械学習とは一生縁がないのではと思っていた最中、突如仕事で必要になって必至に勉強したときのお話(前編)

後編はこちら
数学も英語もPythonもわからないけど機械学習に触れたかった(後編)

当時ブログに起こしたものをQiitaで書き直したのと、何もわからないド素人が頑張ったのでツッコミどころ満載かも。

前提

以下の環境で実装、動作確認済み

$ python --version
Python 3.5.2
$ pip list
ascii (3.6)
numpy (1.14.3)
pandas (0.22.0)
Pillow (5.1.0)
pip (9.0.1)
python-dateutil (2.7.2)
pytz (2018.4)
scikit-learn (0.19.1)
scipy (1.0.1)
setuptools (20.7.0)
six (1.11.0)
urllib3 (1.22)
wheel (0.29.0)

そもそも機械学習ってなんなのさ

機械学習の勉強をしようにも、そもそも機械学習とはなんなのか、コレガワカラナイ。

機械学習(きかいがくしゅう、英: machine learning)とは、人工知能における研究課題の一つで、人間が自然に行っている学習能力と同様の機能をコンピュータで実現しようとする技術・手法のことである。(wikipedia引用)

まぁ人間っぽい学習をコンピュータにもやらせましょうというお話なのかな。とりあえず機械学習の定義とかにあまり拘らずに、一般的に考えられる機械学習を自分でもやってみようという緩い方向で進める。

環境構築

ええい、俺は手っ取り早く機械学習をやりたいんだ。VM入れるとかPythonのインストールとかやってられるか。

Python3とそのパッケージ管理ツールであるpipをすぐに使えそうなDockerコンテナを立ち上げる。僕はvimmerなので直接コンテナ内で作業することに。

$ docker run -it --name python3 vaeum/ubuntu-python3-pip3 bash

pyenv?Anaconda?jupyter?そんなハイセンスなものは今回は使わない。

scikit-learnとは

scikit-learnとは、どうやらPythonにおける事実上標準と言っても過言ではない機械学習のためのライブラリらしい。

機械学習と言えばTensorFlowというイメージがあるけど、TensorFlowはディープラーニングまで幅広くできる分学習コストが高いそうなので、今回はお手軽に機械学習ができるsckit-learnを用いることに。(一応scikit-learnでもディープラーニングまでできる?)

インストールする。

$ pip install scikit-learn

Pandas/Numpy/scipyについて

Pythonで機械学習を行う上で捗るライブラリとのこと。

Pandas
データ解析を支援するためのライブラリ。汎用的なデータ構造の構築や、データ内の演算などをサポートする。

Numpy
科学計算用のライブラリ。特に行列に対する計算は普通にPythonで行うより圧倒的に早い。

scipy
numpy使ってさらに高度な科学技術計算できる奴。多分使わない。

とりあえずこのライブラリも、使うかどうかはともかく、初めに導入しておく。

$ pip install numpy pandas scipy

足し算の機械学習について

機械学習の中でも比較的わかりやすいらしい、sckit-learnの線形回帰アルゴリズムを用いて、足し算を学習させる。

足し算って完全に演算によって求められるもので、機械学習で扱うモノじゃないってことはもちろん理解してるけど、雰囲気を掴むために身近なところから始める。

というか、よくある機械学習入門は初っ端からやれ売上の予測だの、画像の仕分けだの機械学習してる感が凄かったので、最初は小学生でもできる足し算から始めたかった。

流れとしては以下のようになる

  1. 足し算の式と、その答えの組み合わせをいくつか用意する
  2. sckit-learnに式と答えの組み合わせを学習させ、学習モデルを生成
  3. 標準入力から二種類の整数を学習モデルに与え、予測結果を標準出力する

教師あり学習について

前項の「式と答えの組み合わせ」みたいに、正解を教えてあげる学習方法を、教師あり学習と言うらしい。

教師あり学習は、データの組み合わせと、それに対する答えのセットを複数セット学習させることで、データの組み合わせを与えただけでその答えを予測してもらおうという学習モデル。

今回は足し算を学習させるので、データの組み合わせが式で、答えが和と考えれば良い。

というかこの時点で「教師なし学習」なんてものがあることを想像もできてない。

線形回帰について

Wikipediaをそのまま掲載すると以下の通り

ho.png

なるほどなるほど。何を言ってるかよくわからないが、足し算に置き換えれば非常にシンプルになる?

  • 目的変数Yは、足し算における和である。
  • 説明変数X1,X2は、足し算のそれぞれの数値である。
  • この場合、線形回帰直線は、Y = X1 + X2の形になるので、

この式を予測することが線形回帰学習である(あってるか極めて怪しい)

実装

このあたりからPythonの勉強と並行して進めた。PHPとRubyそれなりに使えるし似たようなもんやろ・・・。

モジュールのimport

今回は、Pandasによる学習用データの入力と、scikit-learnの線形回帰モデルを用いるので、以下のimport文を記述する。Numpyは今回出番なし。

from pandas import DataFrame
from sklearn import linear_model

学習データの用意

学習データは、PandasDataFrameの形式で用意する。DataFrameはデータの集合を二次元で表現して、なんか読み書きをスゲェ便利にする奴。

sckit-learnでは、学習データとその答えを別々に渡す必要があるので、それぞれformulas,answersに代入する。

formulas = DataFrame([
    [0, 0],
    [0, 1],
    [0, 2],
    [1, 0],
    [1, 1],
    [1, 2],
    [2, 0],
    [2, 1],
    [2, 2]
])
answers = DataFrame([0, 1, 2, 1, 2, 3, 2, 3, 4])

0+0は0だよ。0+1は1だよ。と、幼稚園児に算数を教えるように優しく手ほどきする。

学習データを学習させる

importしたlinear_modelを用いて、先程用意した学習データを予測する。
LinearRegressionメソッドで学習モデルを取得できるので、それに対してfitメソッドで学習データを割り当て、学習を開始する。

model = linear_model.LinearRegression()
model.fit(formulas, answers)

リニアレグレッションって必殺技感あって良いですね。

学習結果を確認する

学習が完了したmodelに対して、predictメソッドを用いることで、新たなデータに対する答えの予測値を取得することができる。
例えば以下では、10 + 20の予測結果を取得する。

predected_answer = model.predict([[10, 20]])

「10に20足したら何になると思う?」
「うーんとね、さんじゅう!!」

的な(適当)

動作確認

これまでのコードを以下のように整理しつつ、標準入力で受け付けた2つの整数の和を予測して出力できるようにする。

 #
 # 2つの整数の足し算を機械学習し、任意の足し算を回答させる
 #
 from pandas import DataFrame
 from sklearn import linear_model

 # 足し算の例とその答えを用意する
 formulas = DataFrame([
     [0, 0],
     [0, 1],
     [0, 2],
     [1, 0],
     [1, 1],
     [1, 2],
     [2, 0],
     [2, 1],
     [2, 2]
 ])
 answers = DataFrame([0, 1, 2, 1, 2, 3, 2, 3, 4])

 # 式と答えを線形回帰学習させる
 model = linear_model.LinearRegression()
 model.fit(formulas, answers)

 while True:

     # 標準入力から計算式を取得
     print('> ', end='')
     x, y = list(map(lambda x: int(x), input().split(' ')))

     # 学習モデルを用いて回答を取得し、標準出力
     predected_answer = model.predict([[x, y]])
     print("{0} + {1} = {2}".format(x, y, int(predected_answer[0][0])))

実行すると、すぐに学習が完了する。コレに対して標準入力で適当に2数を入力すると、その予測結果が出力される。

# python addition.py
> 1 1
1 + 1 = 2
> 10 20
10 + 20 = 30
> 333 777
333 + 777 = 1110
> 18782 18782
18782 + 18782 = 37564

なんちゅう賢い子じゃ・・・。

後半へ続く

ほんのちょっとずつわかってきたので、次はもう少し実用的な機械学習をしてみる。

数学も英語もPythonもわからないけど機械学習に触れたかった(後編)