PythonでIrisのDataを対象に生成モデル(Generative model)を構築してみた

動機

PRML1.5章(決定理論)において、予測モデルの構築方法は決定木やSVMといった手法で得られる「識別モデル」と、ベイズアプローチで得られる「生成モデル」に分かれると書いてあった。識別モデルでは、入力に説明変数x、出力に目的変数yを取る写像関数({y=f(x)} )しか得られないが、生成モデルでは、目的変数を得る確率({p(y|x)}:事後確率)の他、説明変数自体の生起確率({p(x)})から外れ値検出が可能であるとのこと。
従来この「識別モデル」ばかり使っていた(さらに言えば、識別モデルの出力を試行錯誤して確率を出そうとまでしていた)ので、この「生成モデル」に非常に興味を持った。しかし本には具体的に「生成モデル」を算出した例は記載されていなかったため、勉強がてらお馴染みIrisのデータを用いて「生成モデル」を構築しようと思った次第。

生成モデル(Generative model)の算出方法

  • 生成モデルを構築するためには、学習データを用いて説明変数と目的変数の同時確率を導出する必要がある。
{ \displaystyle p(x, y) }
  • 同時確率を求めるためには、尤度関数を算出し、それを説明変数について積分することで算出する。
{ \displaystyle p(x, y) = \int{p(x|y)dy} }
  • 尤度関数は①データの分布が多変量ガウス分布に従う、②各データは独立、と仮定して、最尤推定から算出する。最尤推定というと難しそうだが、本仮定においては学習データの各目的変数条件下における平均と共分散行列を算出するだけでよい。
{ \displaystyle p(x|y) = \frac{1}{\sqrt{(2\pi)^{m}|\Sigma|}}\exp{\left\{-(x-\mu)^{T}\Sigma^{-1}(x-\mu)\right\}} }
{ \displaystyle \mu = E(x|y) }
{ \displaystyle \Sigma = Cov(x|y) }

Irisデータとは

このページを見られている方にあまり説明の必要はないと考えられるが、簡単に言うと、おしべの長さ等の4種の説明変数があり、各値と説明変数である花の種類(3種)がセットになっているデータ。データ分析手法の精度のチェック等によく用いられる。

f:id:Rosyuku:20160626222957p:plain:w500

生成モデル構築結果

上述した算出方法を用いて全データから生成モデルを構築し、訓練データと同じ150個のデータを無作為に抽出した結果。似た雰囲気が出ていることが分かる。
次回は訓練データ数を変えた場合や、データの外れ値チェック、および予測精度をチェックしようと思う。

f:id:Rosyuku:20160626223007p:plain:w500

スクリプト(参考)

作りがイマイチなので本当に参考。

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import math

#独立同時分布のデータを得る関数
def iid(mu, cov, num, columns, seed=0):
    np.random.seed(seed)
    data = np.random.multivariate_normal(mu, cov, num)
    
    return pd.DataFrame(data = data, columns=columns)

if __name__ == "__main__":
    
    #元データ
    df = pd.read_csv('iris.csv', index_col=0)
    
    #カテゴリ名を取得
    df.Name = df.Name.astype('category')
    categories = list(df.Name.cat.categories)

    #尤度パラメータを取得
    genparam = []
    for i, c in enumerate(categories):
        tdf = df[df.Name==c].copy()
        tmu = np.array(tdf.mean())
        tcov = np.array(tdf.cov())
        tpov = float(len(tdf) / len(df))
        
        genparam.append([c, tmu, tcov, tpov])
        
    genparam = pd.DataFrame(genparam, columns=['category', 'mu', 'cov', 'weight'])

    #無作為に150データを取得
    gen2 = pd.DataFrame(columns=list(df.columns[:-1]))
    for ind in genparam.index:
        genp = genparam.ix[ind]
        temp = iid(genp['mu'], genp['cov'], 50, list(df.columns[:-1]))
        temp['Name'] = genp['category']
        
        gen2 = pd.concat([gen2, temp])
    
    gen2['gen'] = 'Gen'    
    gen2 = gen2[df.columns]

    #プロット
    sns.pairplot(df, hue='Name')
    sns.pairplot(gen2, hue='Name')



パターン認識と機械学習 上

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA