irisデータの俯瞰

概要

irisデータは3つのアヤメの種類(setosa, versicolor, varginica)の150個体について、萼(sepal)と花弁(petal)の長さと幅の組み合わせ4つの特徴量のデータを提供する。これらについて一般的なグラフによる可視化によって俯瞰してみる。

特徴量の分布

クラス分けしない場合

まずアヤメの150個体における4つの特徴量について、3つの種類を区別せずにその分布を見てみる。

この結果を見る限り特に際立った特徴は見いだせない。敢えて言うなら、萼の長さは若干ばらつきが大きく、萼の幅は割合”きれいな”分布。花弁については、長さ・幅とも値の小さいところで独立した分布が見られる。

このデータが異なる種類のものが混在したものだと知っていれば、花弁の独立した分布は特定の種類のものかもしれないと推測できるくらい。

クラス分けした場合

次に4つの特徴量について、3つの種類ごとに分けて表示してみる。

こうすると少し特徴が見えてくる。

花弁の独立した分布はsetosa(ヒオウギアヤメ)のものであることがわかり、額の長さの分布がばらついているのは、複数の種類の特徴量が少しずつずれて重なっているからだということもわかる。

この分布だけだと、花弁の長さ2.5cm、花弁の幅が0.7~0.8cmあたりから小さいと、アヤメの種類はsetosaと特定できそうだが、versicolorとvirginicaは重なっていて、花弁の幅が1.75cmあたりで分けると少し誤判定はあるが概ね分けられそうである。

2つの特徴量同士の関係

比較例

例として、萼の長さと萼の幅、萼の長さと花弁の幅、それぞれの間の関係をプロットしてみる。

萼の長さと花弁の長さの関係を見ると、setosaは明らかに独立したグループだが、versicolorとverginicaは混ざり合っていて分離できそうにない。先ほどのヒストグラムでは、萼の長さ、萼の幅それぞれだけではversicolorとvirginicaは区分できなかった。2次元でプロットするとそれらがうまく区分する可能性もあるが、この場合はうまくいかないようである。

一方、萼の長さと花弁の長さの関係を比べると、versicolorとversinicaも何とか区分できそうである。よくみると、この3つの区分は萼の長さと関係なく、花弁の幅のみで概ね区分できそうである。これも先ほどの花弁の幅のヒストグラムの結果と符合する。

scatter_matrixによる確認

上記のような特徴量の組み合わせは、特徴量がn個の場合にはnC2通りとなる。irisデータの場合、特徴量は4つだから6個の特徴量ペアがあり得る。pandasscatter_matrixを利用すると、このような特徴量のペアについて網羅的に確認できる。

ただしscatter_matrixでは、対角要素のヒストグラムを特徴量ごとに分けることはできないようだ。

pairplotによる確認

seabornpairplotを使うと、対角要素に各特徴量ごとの頻度分布/密度分布を表示することができる。pairplotの場合、ターゲットの品種を文字列で与えるとそれに従った色分けをしてくれて、対角要素の密度分布も品種ごとに分けてくれる。

ペアプロットの結果から、3つの種類は複数の散布図で比較的きれいにグループとなっていることがわかる。

3つの特徴量の関係

最後に、4つの特徴量のうち3つを取り出して3次元の散布図で表示してみる。2次元の散布図ではversicolorとvirginicaで若干の重なりがあるが、3次元化するときれいに分かれるかもしれない。

3次元空間で見ても若干の重なりはあるが、2つの特徴量だけの時に比べて、よりグループ分離の精度が高まることは期待できそうだ。

考えてみれば、アヤメの品種区分のように特徴量が少ない場合のクラス分類問題は、1次元の頻度分布、2次元・3次元の頻度分布のように次元を増やして確認ができれば、区分は比較的容易なように思われる。一方で人の間隔では3次元を認識するのがやっとなので、特徴量の数が増えた時には太刀打ちできない。

畢竟、機械学習・AIとは人間が認識制御困難な多数の特徴量=多次元における判別や相関を如何に実行するかというところなのでは、と思われる。

 

matplotlib.pyplot.scatter – 散布図

概要

scatterはx座標とy座標のペアを与えて散布図を描く。

scatter(x, y, color/c=color, s=n, marker=marker, edgecolors=color)
xyは散布図の点の座標で、数値の場合は1点、配列の場合は複数の点を描く。color(またはc)とedgecolormatplotlibcolor指定markermatplotlibmarkers指定sはマーカーのサイズ。

基本形

複数系列

複数系列の場合は、系列ごとにscatterを実行する。

Irisデータセット

概要

Irisデータセットはアヤメの種類と特徴量に関するデータセットで、3種類のアヤメの花弁と萼(がく)に関する特徴量について多数のデータを提供する。

ここではPythonのscikit-learnにあるirisデータの使い方をまとめる。

データの取得とデータ構造

Pythonで扱う場合、scikit-learndatasetsモジュールにあるload_iris()でデータを取得できる。データはBunchクラスのオブジェクトととのことだが、通常の扱い方は辞書と同じようだ。

データの構造は辞書型で、150個体のアヤメに関する特徴量の配列と各個体の種類、種類名などが格納されている。

データのキーは以下のようになっている。

データの内容

'data'~特徴量データセット

150個体のアヤメに関する、4つの特徴量をレコードとしたデータセット。各個体の4つの特徴量の配列を要素とした2次元配列。列のインデックス(0, 1, 2, 3)が四つの特徴量に対応している。

'target'~アヤメの種類に対応したコード

3種類のアヤメに対応した0~2のコードの配列。150個体のアヤメに対応した1次元配列。

'target_names'~アヤメの種類名

アヤメの3つの種類の種類名。stosaは「ヒオウギアヤメ」といって少し大人締めの色形だが、versicolorとvirginicaは素人にはその違いがよく分からない。

種類名とコードの関係は以下の通り。

setosa 0
versicolor 1
virginica 2

'feature_names'~特徴名

データの格納順はDESCRの後。アヤメの種類のクラス分けに使う特徴。

sepal(萼)とpetal(花弁)の長さと幅、計4つの特徴の名称が、単位cmを含む文字列で格納されている。

  • ‘sepal length (cm)’ 萼の長さ
  • ‘sepal width (cm)’ 萼の幅
  • ‘petal length (cm)’ 花弁の長さ
  • ‘petal width (cm)’ 花弁の幅

特徴名とコードの関係は以下の通り。

sepal length (cm) 0
sepal width (cm) 1
petal length (cm) 2
petal width (cm) 3

'filename'~ファイル名

これも格納順はDESCRの後で、CSVファイルの位置が示されている。1行目にはデータ数、特徴量数、特徴量名称が並んでおり、その後に150行のアヤメの個体に対する4列の特徴量と1列の種類データが格納されている。このファイルにはfeature_namesDESCRに当たるデータは格納されていない。

'DESCR'~データセットの説明

データセットの説明。print(iris_dataset['DESCR'])のようにprint文で整形表示される。

  • レコード数は150個(3つのクラスで50個ずつ)
  • 属性は、4つの数値属性とクラス(種類)
    →predictiveの意味とclassが単数形なのがわからない

データの利用

データの取得方法

irisデータセットから各データを取り出すのに、以下の2つの方法がある。

  • 辞書のキーを使って呼び出す(例:iris_dataset['DESCR']
  • キーの文字列をプロパティーに指定する(例:iris_dataset.DESCR

全レコードの特徴量データの取得

'data'から、150の個体に関する4つの特徴量が150行4列の2次元配列で得られる。4つの特徴量は’feature_names’の4つの特徴名に対応している。

特定の特徴量のデータのみ取得

特定の特徴量に関する全個体のデータを取り出すときにはX[:, n]の形で指定する。

特定のクラスのデータのみ抽出

特定のクラス(この場合は種類)のレコードのみを抽出する方法。ndarrayの条件による要素抽出を使う。

 

 

2次元で配置されたAxesを一括で扱う

subplots()add_subplot()で複数の行数・列数のAxesを生成すると、Axesオブジェクトの2次元の配列となる。

この結果に対して一律に処理をしたい場合(たとえば軸の値や凡例を設定したい、アスペクトを揃えたいなどの場合)、いちいち二重ループを回すのが面倒。

これを1次元配列に変換して一括で扱う方法

変換方法の1つは、以下のように1次元配列で取り出してしまう方法

あるいは、以下のように2次元配列を1次元に変換する方法(当初、reshape(1, -1)[0]のようなことをしていたが、reshape(-1)とすればよいことがわかった)。

こうすると1次元配列axs_1dで2次元のaxsの全要素に対してアクセス可能になる。

このほかにflatten()、ravel()を使う方法もある。flatten()はコピーを返すが、Axesオブジェクトへの参照先は変わらないので同じ効果。

各グラフにカウンターの値を適用するときはenumerate、他のリストなどと同時に変えていくときはzipを使う。

 

matplotlib.pyplot.hist – ヒストグラム

概要

matplotlib.pyplot.histは、配列データのヒストグラムを描画する。主なパラメータのみ示す。

hist(X, bins, range, density, cumulative, histtype, rwidth, color, stacked)
Xはヒストグラムのデータで一つのグラフに一つの1次元配列。その他のパラメーターは以下で説明。

ヒストグラムの形式

度数分布

1次元の配列でデータを渡すと、その度数分布が描かれる。

ただしデフォルトでは各ビンのエッジが区別できないため、これを描くためにはedghecolorの指定が必要。edgecolorの代わりにecで指定してもよい。

頻度分布

density=Trueを指定すると、頻度分布になる。各ビンの総和が1となるように調整され、形状は度数分布と同じ。

累積分布図

cumulative=Trueを指定すると、累積度数分布、累積頻度分布を描く。

ビン数

binsでヒストグラムの柱(ビン)の数等を指定する。デフォルトはbins=10

bins=n
ビンの数を数値で指定する。
bins=sequence
ビンの境界値をリスト等で指定する。

ビン(bin)は英語で、店の商品や工場の部品などを入れておく大きなケース、ストッカーのことをいい、British Englishではごみ箱を指す。日本語の瓶(びん)の呼び名とは関係ないらしい。

レンジ

rangeでヒストグラムのビンを分割する範囲を指定する。そのレンジの上下限値の間でbinsで指定されたビンに分割される。

色・エッジの指定

colorでビンの色、edgecolor/ecでエッジの色、linewidthでエッジの幅を指定する。

ビンの幅

rwidthでビンの幅を指定する。デフォルトはrwidth=1で各ビンが密着。

ヒストグラムのタイプ

histtype='type'でヒストグラムのタイプを指定する。

bar
一般的なヒストグラムの形状。
barstacked
複数のヒストグラムの場合に、同じビンの値を積み上げていく。
step
ビンの間の境界を描かない。
stepfilled
ビンの間の境界を描かず、中を塗りつぶす。

以下の例では、'bar''step''stepfilled'について例示。

複数のヒストグラム

単純な重ね合わせ

複数のヒストグラムを重ね合わせるには、同じターゲットに対して各データについてhistを実行する。

単に重ね合わせると、初めの方のヒストグラムが後の方で塗りつぶされてしまうので、それらを見えるようにするにはalphaで透明度を指定する。

ただし単に重ね合わせただけの場合、各ヒストグラムのビンの境界が必ずしも一致しない。

ヒストグラムとplotの重ね合わせ

こちらを参照。

ビン境界の整合

複数のヒストグラムのビンの境界を一致させるには以下の方法がある。

  • 各グラフに対して同じrangebins=nを指定する
  • 各グラフに対して同じbins=sequenceを指定する

並べる・積み上げる

複数のデータを配列とした場合(複数の1次元のデータを並べて2次元配列として与えた場合)、デフォルトでは各ビンが横に並べられる。

また、stacked=Trueあるいはhisttype='barstacked'を指定した場合、同じ階級のビンが積み上げられる。

戻り値

n
各ビンの値(度数または頻度)
bins
各ビンの境界値
patches
ヒストグラム描画に使われたpatcheオブジェクトのリスト

単一のヒストグラムの場合

以下の例では、nの結果として10個のビンの度数が得られている。

複数のヒストグラムの配列の場合

複数のデータを配列で与えた場合の戻り値。nが3つのデータごとの配列になっている。

 

二項分布

概要

ある試行において起こり得る事象が2通りしかない場合、このような試行をベルヌーイ試行(Bernoulli trial)という。たとえばコインを投げた時に表が出るか裏が出るか、くじ引きを引いたときに当たりが出るかはずれが出るか、など。

ベルヌーイ試行の2つの事象を確率変数X = 1, 0で表し、X = 1となる確率がpであるとする。

(1)    \begin{alignat*}{1} P(X=1) &= p \\ P(X=0) &= 1-p \end{alignat*}

このようなベルヌーイ試行をn回繰り返したとき、X=1が生じる回数の確率分布が二項分布(Binomial distribution)で、B(n, p)のように表示される。二項分布の例には以下のようなものがある。

  • コインの表/裏が出る確率が等しく1/2のとき、このコインを10回投げた時に表がでる回数の分布
  • 打率3割の打者が4回打席に立って2安打以上打つ確率

確率分布

n回のベルヌーイ試行のうち、X=1k回起こるケースは、{}_n \mathrm{C}_k通りなので、二項分布の確率は以下のように表せる。

(2)    \begin{equation*} P(X=k ; p) = {}_n \mathrm{C}_k p^k (1-p)^{n-k} \end{equation*}

全事象

k=0~nの確率の和が全事象の確率であり、二項定理から、

(3)    \begin{equation*} \sum_{k=0}^n {}_n \mathrm{C}_k p^k (1-p)^{n-k} = (p + 1 - p)^n = 1 \end{equation*}

平均と分散

二項分布B(n, p)の平均と分散は、以下のようになる。

(4)    \begin{alignat*}{1} E(X) &= np \\ V(X) &= np(1-p) \end{alignat*}

この導出において興味深いテクニックが使われる

二項分布の形

n=20, p=0.3の二項分布のグラフをPythonで描くと以下のようになる。

正規分布近似

二項分布B(n, p)は、np, np(1-p)が十分大きいとき(具体的には5より大きいとき)、平均np、分散np(1-p)の正規分布で近似できる(ド・モアブル-ラプラスの定理)。

(5)    \begin{equation*} X \sim B(n, p) \rightarrow \frac{X - np}{\sqrt{np(1-p)}} \sim N=(0, 1) \end{equation*}

これは、二項分布の1回の試行において成功する場合をXi = 1、失敗する場合をXi = 0として、成功回数\sum X_iの平均と分散がnp, np(1 − p)であることからわかる。

以下は、n, pの3つずつの組み合わせに対する、二項分布と正規分布の一致具合を比べたもの。表示範囲は、正規分布とみなしたときの-3\sigma \sim 3\sigmaに対応する範囲で設定している。

母集団確率の最尤推定

二項分布の母集団確率の最尤推定量p=k/nである。

実用例

適用例

二項確率が与えられたときの、発生回数や個体数の予測。

  • 当たりの確率がpの掛けの、掛け回数nと当たりの回数k
  • 故障率pの部品について、n個の部品のうちの故障数k
  • 罹患率pの病気について、n人のうちの罹患者数k
  • 支持率pの政党に対して、n人のうちの支持者数k

分析例

上記と逆に、nサンプルから事象がk回発生したときの確率を推定。

 

尤度・最尤推定

コインの例

最尤推定法(maximum likelihood estimation)は確率分布f_Dのパラメーター\thetaを、その母集団から得られたサンプルから推定する方法。

たとえば、表の出る確率が必ずしも1/2でないコインを50回投げた時、表が15回出たとすると、このコインの表が出る確率はいくらか、といった問題。20~30回くらいの間だと普通のコインで表/裏の確率は1/2かなと思うが、50回投げて表が15回しかでないとちょっと疑いたくなる。

ここで、表が出る確率をpとして、n回の試行中表がk回出る確率は以下の通り。

(1)    \begin{equation*} P(k:n\,|\,p) = \binom{n}{k} p^k (1-p)^{n-k} \end{equation*}

先の問題の結果について、母集団の確率をいくつか仮定して計算してみると

(2)    \begin{equation*} \begin{align} p &= 1/2 \quad \rightarrow \quad P(15:50\,|\,0.5) \approx 0.002 \\ p &= 1/3 \quad \rightarrow \quad P(15:50\,|\,0.3) \approx 0.107 \\ p &= 1/4 \quad \rightarrow \quad P(15:50\,|\,0.1) \approx 0.089 \end{align} \end{equation*}

得られたサンプルの下では、少なくともぼ表が出る確率を1/2や1/4と考えるよりは、1/3と考えた方がこのサンプルのパターンが発生する確率が高い。

そこで、サンプルのパターンに対して母集団の確率を変化させてみると、以下のようになる。

グラフ上は、母集団確率が15/50=0.3のときにサンプルパターンの発生確率が最も高くなっている。

解析的に確率が最大となる母集団確率を求めるために、式(1)をpで微分してゼロとなる点を求める。

(3)    \begin{gather*} \frac{d P(k:n\,|\,p)}{dp} = \binom{n}{k}\left(kp^{k-1} (1-p)^{n-k} - p^k (n-k)(1-p)^{n-k-1} \right) = 0 \\ p^{k-1} (1-p)^{n-k-1} \left( k (1-p) - (n-k) p \right) = 0 \\ p^{k-1} (1-p)^{n-k-1} \left( k - np \right) = 0 \end{gather*}

上式の解はp = 0, 1, k/nとなるが、p=0, 1の場合は式(1)がゼロとなることから、確率が最大となるのはp=k/nであることがわかる。

尤度関数と最尤法

母集団の確率分布をf、母集団のパラメータを\theta、得られたサンプルセットをx_1, \ldots, x_nとすると、パラメーターが\thetaである確率は

(4)    \begin{equation*} Pr(x_1, \ldots, x_n \,|\, \theta) = f(x_1, \ldots, x_n \,|\, \theta) \end{equation*}

このとき、パラメーター\thetaに関する尤度関数は以下のように定義される。

(5)    \begin{equation*} L(\theta) = f(x_1, \ldots, x_n \,|\, \theta) \end{equation*}

通常、尤度関数が最大となるパラメーターを求めるためには対数尤度関数が用いられる。

(6)    \begin{equation*} \frac{d}{d \theta} \ln L(\theta) = 0 \end{equation*}

サンプルの質と尤度

先のコインの問題で、試行数が10回の場合と100回の場合を比べてみる。それぞれについて、表の確率が0.3、0.5、0.7に対応する回数は試行回数が10回の場合は3回、5回、7回、試行回数100回に対しては30回、50回、70回である。それぞれの表の階数に対して、母集団確率の尤度関数を描くと以下のようになる。

 

試行回数が100回の場合には分布が尖っており、最尤推定されたパラメーターの確度が高いが、10回の場合には分布がなだらかで、最尤推定された値以外のパラメーターの確率も高くなっている。

最尤推定の場合、サンプルの規模が推定値の信頼度に関わってくる。