Pythonでのロジスティック回帰の実装を分かりやすく解説する

スポンサーリンク

このチュートリアルの目的は、ゼロから独自のロジスティック回帰を実装することです。

これは、同じトピックに関する前回のチュートリアルでは、組み込みのメソッドを使用して関数を作成しましたが、それとは異なるものになります。

ロジスティック回帰は、主に2値分類の問題に使用される古典的な手法です。

いくつかの修正により、多クラス分類の問題にも使用できますが、この記事では2値分類を実行します。

スポンサーリンク

ロジスティック回帰をゼロから実装する

ステップバイステップでアルゴリズムを分解し、その内部動作を理解し、最終的に独自のクラスを作成します。

ステップ1:シグモイド関数を理解する

ロジスティック回帰のシグモイド関数は、2つ以上の離散クラスにマッピングできる確率の値を返します。

入力変数の集合が与えられると、我々のゴールは、そのデータ・ポイントをカテゴリ(1または0)に割り当てることです。

シグモイド関数は、入力点がクラスの1つに属する確率を結果を出力すると、以下の様になります。

#Defining a sigmoid function
def sigmoid(z):
    op = 1/(1 + np.exp(-z))
    return op

ステップ2:損失関数

損失関数はパラメータ/重みで構成され、損失関数を最適化すると言うとき、我々は単にパラメータ/重みの最適値を見つけることを意味します。

ロジスティック回帰の損失関数は、以下のように定義される。

#Loss Function
 
def loss(h, y):
    return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()
#Gradient_descent
 
def gradient_descent(X, h, y):
    return np.dot(X.T, (h - y)) / y.shape[0]

ステップ3:勾配降下法

勾配降下法は、損失関数の重みに関する導関数です。

損失関数の導関数を求めた後、これを得る。

#import required modules
import numpy as np
 
class LogisticRegression:
    def __init__(self,x,y):     
        self.intercept = np.ones((x.shape[0], 1)) 
        self.x = np.concatenate((self.intercept, x), axis=1)
        self.weight = np.zeros(self.x.shape[1])
        self.y = y
         
    #Sigmoid method
    def sigmoid(self, x, weight):
        z = np.dot(x, weight)
        return 1 / (1 + np.exp(-z))
     
    #method to calculate the Loss
    def loss(self, h, y):
        return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()
     
    #Method for calculating the gradients
    def gradient_descent(self, X, h, y):
        return np.dot(X.T, (h - y)) / y.shape[0]
 
     
    def fit(self, lr , iterations):
        for i in range(iterations):
            sigma = self.sigmoid(self.x, self.weight)
             
            loss = self.loss(sigma,self.y)
 
            dW = self.gradient_descent(self.x , sigma, self.y)
             
            #Updating the weights
            self.weight -= lr * dW
 
        return print('fitted successfully to data')
     
    #Method to predict the class label.
    def predict(self, x_new , treshold):
        x_new = np.concatenate((self.intercept, x_new), axis=1)
        result = self.sigmoid(x_new, self.weight)
        result = result >= treshold
        y_pred = np.zeros(result.shape[0])
        for i in range(len(y_pred)):
            if result[i] == True:
                y_pred[i] = 1
            else:
                continue
                 
        return y_pred
            
from sklearn.datasets import load_breast_cancer
 
#Loading the data
data = load_breast_cancer()
 
#Preparing the data
x = data.data
y = data.target
 
#creating the class Object
regressor = LogisticRegression(x,y)
 
#
regressor.fit(0.1 , 5000)
 
 
y_pred = regressor.predict(x,0.5)
 
print('accuracy -> {}'.format(sum(y_pred == y) / y.shape[0]))

重みは、導関数(gradient descent)×学習率で更新される。

重みを更新します。

fitted successfully to data
accuracy -> 0.9209138840070299

ここで-αは学習率です。

Putting it all together

上記の手順をまとめるためのクラスを作成してみましょう。

以下は、ロジスティック回帰をゼロから実装するための完全なコードです。

この実装では、Pythonのnumpyモジュールを使用しています。

Loss Function
Loss Function

アルゴリズムを実装するために、学習率と反復回数を入力引数として必要とする fit メソッドを定義しました。

上記のクラスは、入力データと目標値を与えることで初期化することができます

さて、いよいよ実装をテストしてみましょう。

Gradient Of Loss Function
Gradient Of Loss Function

結果は以下の通りです。

Updating Weights
Updating Weights

実装したモデルの精度は92%で、まずまずの結果でした。

このチュートリアルのノートブックは、私のGitHub Repositoryで見ることができます。

まとめ

この記事は、バイナリ分類タスクを実行するために、ゼロからロジスティック回帰モデルを実装することについてのすべてでした。

また、0からコーディングすることで、回帰アルゴリズムの内部動作も明らかにしました。

それでは、また次回お会いしましょう。

タイトルとURLをコピーしました