学習メソッドの実装(1)

モデルパラメータを,訓練データから学習する fit() メソッドを,単純に多次元配列として,NumPy 配列を利用する方針で実装します. 実は,この実装方針では NumPy の利点は生かせませんが,後の 単純ベイズ:上級編 章で,NumPy のいろいろな利点を順に紹介しながら,この実装を改良してゆきます.

定数の設定

まず,メソッド内で利用する定数を定義します. このメソッドの引数は,訓練データの特徴ベクトル集合 X とクラスラベル集合 y であると 単純ベイズクラスの仕様 で定義しました. 最初に,この引数から特徴数や訓練事例数などの定数を抽出します. X は,行数が訓練事例数に,列数が特徴数に等しい行列に対応した2次元配列です. そこでこの変数の shape 属性のタプルから訓練事例数と特徴数を得ます.

n_samples = X.shape[0]
n_features = X.shape[1]

実装する単純ベイズは,クラスも特徴も全て二値としましたが,このことを定義する定数も定義しておきます.

n_classes = 2
n_fvalues = 2

特徴の事例数とクラスラベルの事例数は一致していなくてはならないので,そうでない場合は ValueError を送出するようにします. yshape 属性を調べてもよいのですが,これは1次元配列なので長さを得る関数 len() 1 を用いて実装してみます.

if n_samples != len(y):
    raise ValueError('Mismatched number of samples.')

以上で,モデルパラメータを学習する準備ができました.

注釈

1

2次元以上の NumPy 配列に len() を適用すると shape 属性の最初の要素を返します.

クラスの分布の学習

単純ベイズ:カテゴリ特徴の場合 の式(4)のクラスの分布のパラメータを求めます. 計算に必要な量は総事例数 \(N\) とクラスラベルが \(y\) である事例数 \(N[y_i=y]\) です. \(N\) はすでに n_samples として計算済みです. \(N[y_i=y]\) は, \(y\in\{0,1\}\) について計算する必要があります. よって,大きさ n_classes の大きさのベクトル nY を作成し,各クラスごとに事例を数え上げます.

nY = np.zeros(n_classes, dtype=int)
for i in range(n_samples):
    nY[y[i]] += 1

モデルパラメータ self.pY_ は式(4)に従って計算します. なお,後で値を書き換えるので np.empty() で初期化したあと,各クラスの確率を計算して格納します 2

self.pY_ = np.empty(n_classes, dtype=float)
for i in range(n_classes):
    self.pY_[i] = nY[i] / n_samples

注釈

2

Python3 では,整数同士の除算の結果も実数ですが,Python2 では切り捨てした整数となります. これを避けるために,Python2 では n_samplesfloat(n_samples) のように実数型に変換しておく必要があります.

特徴の分布の学習

単純ベイズ:カテゴリ特徴の場合 の式(5)の特徴の分布のパラメータを求めます. 計算に必要な量のうち \(N[y_i=y]\) は,すでに式(4)の計算で求めました. もう一つの量 \(N[x_{ij}=x_j, y_i=y]\) は,特徴 \(j=1,\ldots,K\) それぞれについて,特徴の値 \(x_j\in\{0,1\}\) とクラス \(y\in\{0,1\}\) について計算する必要があります. よって,この量を保持する配列は3次元で,その shape 属性は (n_features, n_fvalues, n_classes) とする必要があります. この大きさの 0 行列を確保し,各特徴それぞれについて,各特徴値と各クラスごとに事例を数え上げます.

nXY = np.zeros((n_features, n_fvalues, n_classes), dtype=int)
for i in range(n_samples):
    for j in range(n_features):
        nXY[j, X[i, j], y[i]] += 1

モデルパラメータ self.pXgY_ は式(5)に従って計算します.

self.pXgY_ = np.empty((n_features, n_fvalues, n_classes),
                      dtype=float)
for j in range(n_features):
    for xi in range(n_fvalues):
        for yi in range(n_classes):
            self.pXgY_[j, xi, yi] = nXY[j, xi, yi] / float(nY[yi])

以上で,単純ベイズのモデルパラメータの学習を完了しました.