デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理を基礎からやり直す。https://qiita.com/yaju

ディープラーニング(深層学習)を理解してみる(識別問題)

はじめに

前々回の「対数logを理解してみる」と前回の「自然対数の底(ネイピア数) e を理解してみる」では、人工知能に使用する基礎的な数学知識が足りなかったのでシリーズとは脱線して書いてみました。 また、このシリーズで書いていきます。

ニューラルネットワークは、回帰問題と分類問題があります。
これまでやってきたリンゴとミカンの値段を予測するというのが回帰問題で、今回やるのは分類問題(識別問題)となります。

以前フレームワークのTensorFlowを使用してやりましたが、今回はフレームワークを使用しないでやってみます。
yaju3d.hatenablog.jp

識別問題とは

入力データから判断して分類させる問題。今回の例では買えるのか買えないのかを判断させる。 識別分類器としてロジスティック回帰を使う。

ロジスティック回帰とは

ロジスティック回帰は、発生確率を予測する手法です。 基本的な考え方は線形回帰分析と同じなのですが、予測結果が 0 から 1 の間を取るように数式やその前提に改良が加えられています。 今回のように購入有無(買える or 買えない)の2値しかとりえない値を従属変数の実績値として用い、説明変数を用いてその発生確率を説明するという構造になっています。

例題

たかしくんは八百屋へ財布を預かってお使いに行きました。
しかし、たかしくんはお金を 数えられません。

気まぐれおやじ曰く、
リンゴ2個+ミカン3個、リンゴ0個+ミカン16個 なら買えるが、リンゴ3個+ミカン1個、 リンゴ2個+ミカン8個は買えないとのこと。

リンゴ1個+ミカン11個は買えますか? → 識別問題 f:id:Yaju3D:20160421011949p:plain

式で表そうとしてみる…
f:id:Yaju3D:20160421012015p:plain f:id:Yaju3D:20160421012037p:plain

シグモイド曲線

f:id:Yaju3D:20160421012100p:plain
※シグモイド曲線とは、入力した値を0から1の間に収めてくれる関数の1つ
 多くの自然界に存在する事柄は、このようなS字曲線を取る。
 生物の神経細胞、細胞の生存率曲線などなど

予測式(モデル)が作れた!
f:id:Yaju3D:20160421012204p:plain

ロジスティック回帰
f:id:Yaju3D:20160421012219p:plain

プログラム

import numpy as np
import pandas as pd

def p_y_given_x(x, w, b):
    # x, w, b から y の予測値 (yhat) を計算
    def sigmoid(a):
        return 1.0 / (1.0 + np.exp(-a))
    return sigmoid(np.dot(x, w) + b)

def grad(x, y, w, b):
    # 現予測値から勾配を計算
    error = y - p_y_given_x(x, w, b)
    w_grad = -np.mean(x.T * error, axis=1)
    b_grad = -np.mean(error)
    return w_grad, b_grad
  
def gd(x, y, w, b, eta=0.1, num=1000):
    for i in range(1, num):
        # 入力をまとめて処理
        w_grad, b_grad = grad(x, y, w, b)
        w -= eta * w_grad
        b -= eta * b_grad
        e = np.mean(np.abs(y - p_y_given_x(x, w, b)))
        yield i, w, b, e

x = np.array([[2., 3.], [0., 16.], [3., 1.], [2., 8.]])
y = np.array([1., 1., 0., 0.])

# w, b の初期値を作成
w = [-10,-10]
b = 200
gen = gd(x, y, w, b)

for i, w, b, e in gen:
  if (i+1) % 100 == 0:
    print(i+1,b,w,e);

実行結果

100 196.2993226598431 [-22.375      -12.28583744] 0.6420233463035018
200 192.7195561228789 [-34.875      -12.06210203] 0.6420233463023709
300 189.1722948623358 [-47.25687076 -11.79079916] 0.48881302062549137
400 186.7724229463934 [-55.05210822 -11.5078109 ] 0.2665264782982885
500 185.57859640809747 [-58.91482296 -11.29546188] 0.02159297746827703
600 185.4754835638496 [-59.25851476 -11.22680836] 0.007859710540613895
700 185.42589243161035 [-59.4240343  -11.19266882] 0.004766951474845803
800 185.39307584996868 [-59.53360836 -11.16986379] 0.003414942999345553
900 185.36853902132037 [-59.61555193 -11.15273521] 0.002658633400582877
1000 185.34894411228476 [-59.68099871 -11.13901984] 0.002175879579138274

TensorFlowで実行した結果とほぼ同じになっています。
f:id:Yaju3D:20160421012400p:plain

予測結果

0.95848435 ≒ 0.96 f:id:Yaju3D:20160424232047p:plain