Skip to content

Instantly share code, notes, and snippets.

@darden1
Last active January 26, 2018 13:50
Show Gist options
  • Select an option

  • Save darden1/6323b7dec19f40246ef5dd8ad1fecb79 to your computer and use it in GitHub Desktop.

Select an option

Save darden1/6323b7dec19f40246ef5dd8ad1fecb79 to your computer and use it in GitHub Desktop.
my_multi_class_ logistic_regression1.py
# -*- 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