Beginning AI

統計学・経済学・機械学習を用いて、ほんの少し。世界をもっと良くしてみたい。

機械学習のためのPython入門 クラスとメソッド編

機械学習にどのようなPythonの知識が必要かは、Python機械学習プログラミングの監訳者福島 真太朗(ふくしま しんたろう)さんが以下のように述べられています。

Pythonの文法については、リスト、タプル、ディクショナリなどの基本的なデータ構造、forループ、print関数、zip関数、enumerate関数、関数やクラスの作成方法などが理解できていれば十分です。

thinkit.co.jp

そこで今回はPythonで書かれた機械学習のコードを読めるように、リスト、タプル、ディクショナリなどの基本的なデータ構造、forループ、print関数、zip関数、enumerate関数、関数やクラスの作成方法について学んでいきます。 従ってこの記事は、Pythonを一度もやったことがなく、機械学習のためにPythonを学びたいという人向けです。

今回読み解くPythonコードについて

今回は題材として、パーセプトロンアルゴリズムを使用します。 このコードを完全に理解するためには、機械学習の知識とNumpyの知識が必要になります。 しかし、今回の目的はPythonの基本を学ぶことであるため、それらの解説は省きます。

import numpy as np

class Perceptron(object):
    def __init__(self, eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []

        for _ in range(self.n_iter):
            errors = 0
            for xi, target in zip(X, y):
                update = self.eta * (target - self.predict(xi))
                self.w_[1:] += update * xi
                self.w_[0] += update
                errors += int(update != 0.0)
            self.errors_.append(errors)
        return self

    def net_input(self, X):
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def predict(self, X):
        return np.where(self.net_input(X) >= 0.0, 1, -1)

github.com

importについて

import numpy as np 

import文を使用することで、モジュールやパッケージを呼び出すことができるようになります。 モジュールは複数のファイルをまとめたもののことで、パッケージは複数のモジュールをまとめたものになります。

パッケージやモジュールをimportすることで、他人が作成した機能やコードなどを自分のコードに取り入れることができます。 Pythonの代表的なパッケージとして、ウェブアプリケーションフレームワークFlask数値計算効率化のNumpyがあります。

また、import文に続けて、as ◯◯とすることで、◯◯という名前で、そのパッケージや名前で呼び出せるようになります。

この場合npnumpyを呼び出すことができます。

Numpyについて

Numpyは数値計算ライブラリです。詳しくは説明しませんが、気になる方は以下の記事などを参照してください。

python/numpy - 機械学習の「朱鷺の杜Wiki」

インデント

importの下には、クラスやメソッドが続いていますが、その前にPythonのインデント構造について学ぶ必要があります。 Pythonは入れ子構造についてインデント(空白)で表現します。そのため、endなどを使用しないのが特徴です。

Ruby

class Hoge
  def fuga
  end

  def foo
  end
end

Python

class Hoge
  def fuga

  def foo

class(クラス)について

クラスを定義することで、データやメソッドをまとめることできます。

以下の場合、Perceptronというクラスが、__init__fitというメソッドやself.eta,self.w_というデータをまとめているのがわかるかと思います。

class Perceptron(object):
    def __init__(self, eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []

なぜクラスが必要なのか

なぜクラスが必要なのかという観点は多々あるかと思います。今回は、機械学習とりわけパーセプトロンを実行する観点から述べます。 パーセプトロン機械学習アルゴリズムのひとつのため、多数のデータセットから実行されることが求められます。 その際に毎回同じパーセプトロンアルゴリズムの記述をするのは大変です。

f:id:lasershow151:20161011231131p:plain

そのためクラスを使用して、同じパーセプトロンクラスを使い回す必要があります。

f:id:lasershow151:20161011231207p:plain

method(メソッド)について

メソッドは、ある処理をまとめたものです。 またメソッドは、defを使用することで定義できます。

先ほどのパーセプトロンアルゴリズムには、__init__fitnet_inputpredictというメソッドがありました。 それぞれ以下の処理を担っています。

fit 重みを更新する
net_input ベクトルの計算を行う
predict クラスラベルを予測する

__init__メソッドは特殊なメソッドになります。__init__メソッドはPerceptronClassが呼び出された時に自動的に一番初めに実行されます。

パーセプトロン)クラスとメソッドの使用法について

クラスとメソッドについて知ることができたので、その使い方について説明します。

クラスを呼び出す際は、以下のようにします。

Class名()

従って、パーセプトロンクラスを呼び出す時は、

Perceptron()

とします。

クラスにあるメソッドを呼び出す際は、まずそのクラスのインスタンスを呼び出します。 ※インスタンスメソッドを呼び出すことを想定しています。クラスメソッドはこの限りではありません。

ppn = Perceptron()

ppnというPerceptronクラスのインスタンスを作成しました。 インスタンスを作成することができたら、後はメソッドを呼び出すだけです。 実際にfitメソッドを呼び出してみます。

ppn.fit

このようにインスタンス名.メソッド名とすることでインスタンスが属しているクラスのメソッドを呼び出すことができます。

引数について

先ほど、クラスとメソッドの呼び出し方について説明しました。 しかし実際には、パーセプトロンクラスとそのメソッドは、データをもとにパーセプトロンアルゴリズムを実行するものなので、呼び出す際にデータを渡してあげる必要があります。

例えば、先ほどのパーセプトロンクラスのインスタンスを生成した場面に戻ります。 パーセプトロンクラスには、__init__メソッドがあり、クラスを呼び出すと自動的に呼び出されるため、__init__メソッドが求めるデータを引数として渡す必要があります。

    def __init__(self, eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter

みると__init__メソッドは、eta(学習率)とn_iter(トレーニング回数)を求めています。

従って、パーセプトロンクラスのインスタンスを生成する際には、etan_iterを引数として渡してあげる必要があります。

ppn = Perceptron(eta=0.05, n_iter=100)

同様にメソッドもどのような引数を求められているかを把握する必要があります。

    def fit(self, X, y):
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []

fitメソッドは引数にXyを求めています。従って、fitメソッドを呼び出す際は以下になります。

ppn.fit(X,y)

※Xとyには具体的な値が入ります。

ここまででクラスとメソッドとその使い方について知ることができました。 次回からはクラスとメソッド中に記載されているリスト、タプル、ディクショナリなどの基本的なデータ構造、forループ、print関数、zip関数、enumerate関数について説明します!