Last active
January 26, 2018 13:50
-
-
Save darden1/6323b7dec19f40246ef5dd8ad1fecb79 to your computer and use it in GitHub Desktop.
my_multi_class_ logistic_regression1.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| import numpy as np | |
| class MultiClassLogisticRegression(): | |
| def __init__(self): | |
| self.init_state = True # 重みの初期化判定フラグ | |
| self.W = None # 重み | |
| self.b = None # 閾値 | |
| self.loss = np.array([]) # トレーニングデータのLoss | |
| self.val_loss = np.array([]) # テストデータのLoss | |
| self.acc = np.array([]) # トレーニングデータの正答率 | |
| self.val_acc = np.array([]) # テストデータの正答率 | |
| def fit(self, X, Y, batch_size, epochs, mu, validation_data, verbose): | |
| """ | |
| # 学習の実施 | |
| ## 引数の説明 | |
| - X: トレーニングサンプル | |
| - Y: その教師データ | |
| - batch_size: ミニバッチのサイズ | |
| - epochs: エポック数 | |
| - mu: 学習率 | |
| - validation_data: テストデータ。(X_test, y_test)のように。タプル形式で渡す。 | |
| - verbose: 学習ログを出力するかどうか。0で出力しない。それ以外で出力する。 | |
| """ | |
| # サンプル数、特徴量数、クラス数 | |
| n_samples, n_features = X.shape | |
| n_classes = Y.shape[1] | |
| # テストデータ | |
| val_X = validation_data[0] | |
| val_Y = validation_data[1] | |
| # 重み初期化 | |
| if self.init_state: | |
| self.W = np.ones([n_features, n_classes]) | |
| self.b = np.ones([1, n_classes]) | |
| self.init_state = False | |
| # エポックループ | |
| for i_epoch in range(epochs): | |
| # トレーニング&テストデータのLossと正答率を保存 | |
| self.loss = np.append(self.loss, self.closs_entropy(X, Y)) | |
| self.val_loss = np.append(self.val_loss, self.closs_entropy(val_X, val_Y)) | |
| self.acc = np.append(self.acc, self.accuracy_score(Y, self.predict(X))) | |
| self.val_acc = np.append(self.val_acc, self.accuracy_score(val_Y, self.predict(val_X))) | |
| # ミニバッチを回す回数 | |
| n_batch = int(np.floor(n_samples/batch_size)) | |
| # ミニバッチループ | |
| for i_batch in range(n_batch): | |
| # トレーニングデータをバッチサイズ数分切り取る | |
| if i_batch == n_batch-1: # 最後のループ(端数があるので最後は全部選択) | |
| X_batch = X[batch_size*i_batch:, :] | |
| Y_batch = Y[batch_size*i_batch:, :] | |
| else: | |
| X_batch = X[batch_size*i_batch:batch_size*(i_batch+1), :] | |
| Y_batch = Y[batch_size*i_batch:batch_size*(i_batch+1), :] | |
| # Lossの重み勾配 | |
| dW, db = self.grad_loss(X_batch, Y_batch) | |
| # 重みアップデート | |
| self.W -= mu*dW | |
| self.b -= mu*db | |
| # 学習ログ出力 | |
| if verbose!=0: | |
| print("Epoch " + str(i_epoch+1) + "/" + str(epochs) + \ | |
| " loss: " + str(self.loss[-1]) + \ | |
| " acc: " + str(self.acc[-1]) + \ | |
| " val_loss: " + str(self.val_loss[-1]) + \ | |
| " val_acc: " + str(self.val_acc[-1])) | |
| def softmax(self, Z): | |
| """ソフトマックス関数""" | |
| return np.exp(Z)/np.sum(np.exp(Z), axis=1)[:, np.newaxis] | |
| def closs_entropy(self, X, Y): | |
| """交差エントロピー""" | |
| Phi = self.softmax(np.dot(X, self.W) + self.b) | |
| n_samples = X.shape[0] | |
| return -np.sum(Y*np.log(Phi))/n_samples # サンプル数で割って1サンプル当たりの平均値にする | |
| def grad_loss(self, X, Y): | |
| """交差エントロピーの重み勾配""" | |
| Phi = self.softmax(np.dot(X, self.W) + self.b) | |
| n_samples = X.shape[0] | |
| dW = -np.dot(X.T, Y - Phi)/n_samples | |
| db = -np.dot(np.ones([1, n_samples]), Y - Phi)/n_samples | |
| return dW, db | |
| def predict(self, X): | |
| """予測実施関数""" | |
| Phi = self.softmax(np.dot(X, self.W) + self.b) | |
| class_label = np.argmax(Phi, axis=1) | |
| Y_pred = np.zeros([X.shape[0], self.W.shape[1]]) | |
| for i in range(len(Y_pred)): | |
| Y_pred[i, class_label[i]] = 1 | |
| return Y_pred | |
| def accuracy_score(self, Y_true, Y_pred): | |
| """正答率算出関数""" | |
| acc = np.array([np.sum(Y_true[i,:]==Y_pred[i,:])==len(Y_true[i,:]) for i in range(len(Y_true))]) | |
| return np.sum(acc)/len(acc) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment