Skip to content

Instantly share code, notes, and snippets.

@darden1
Last active August 23, 2016 10:25
Show Gist options
  • Save darden1/dc886aa903b2eb98f9be604a21604e73 to your computer and use it in GitHub Desktop.
Save darden1/dc886aa903b2eb98f9be604a21604e73 to your computer and use it in GitHub Desktop.
StudyMachineLearning_LogisticRegression.py
# -*- coding: utf-8 -*-
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
def main():
# ---アヤメデータの取得
df = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", header=None)
y = df.iloc[0:100, 4].values
y = np.where(y == "Iris-setosa", 0, 1)
X = df.iloc[0:100, [0, 2]].values
# ---トレーニングサンプルの標準化
Xstd = np.copy(X)
Xstd[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std()
Xstd[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std()
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオン,バッチ勾配降下法))
clf = LogisticRegression(eta=0.01, numEpoch=20, shuffle=True)
clf.fit(Xstd, y)
plotResult(clf,Xstd,y,"Standardization","On","BGD")
# ---学習実施(学習率:0.2 最大エポック数:20 (特徴量を標準化,シャッフルオン,バッチ勾配降下法))
clf = LogisticRegression(eta=0.2, numEpoch=20, shuffle=True)
clf.fit(Xstd, y)
plotResult(clf,Xstd,y,"Standardization","On","BGD")
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオン,確率的勾配降下法))
clf = LogisticRegression(eta=0.01, numEpoch=20, shuffle=True)
clf.fitSGD(Xstd, y)
plotResult(clf, Xstd, y, "Standardization", "On", "SGD")
# ---学習実施(学習率:0.2 最大エポック数:20 (特徴量を標準化,シャッフルオン,確率的勾配降下法))
clf = LogisticRegression(eta=0.2, numEpoch=20, shuffle=True)
clf.fitSGD(Xstd, y)
plotResult(clf, Xstd, y, "Standardization", "On", "SGD")
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオン,一発解法))
clf = LogisticRegression(eta=0.01, numEpoch=20, shuffle=True)
clf.fitLS(Xstd, y)
plotResult(clf, Xstd, y, "Standardization", "On", "LS")
def plotResult(clf,X,y,trainSampleState,shuffeled,fitAlgorism):
#---プロットのプロパティ
markers = ('s', 'o', 'x', '^', 'v')
colors = ('green', 'yellow','red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
labels = ('setosa', 'versicolor')
fig = plt.figure(figsize=(18, 10))
plt.clf()
ax1 = fig.add_subplot(231)
ax2 = fig.add_subplot(232)
ax3 = fig.add_subplot(233)
ax4 = fig.add_subplot(234)
ax5 = fig.add_subplot(235)
# ---エポック数と重みのプロット
epochTimes = np.array(range(0, clf.numEpoch + 1))
clf.W_ = np.array(clf.W_)
ax1.plot(epochTimes, clf.W_[:, 0].T[0], color="blue", label="w0")
ax1.plot(epochTimes, clf.W_[:, 1].T[0], color="red", label="w2")
ax1.plot(epochTimes, clf.W_[:, 2].T[0], color="green", label="w1")
ax1.legend(loc="upper left")
ax1.set_xlabel('Epochs')
ax1.set_ylabel('Weight')
ax1.set_title("Epochs and weight")
ax1.set_xlim(0, clf.numEpoch)
# ---ax1.set_xticks(range(0,numEpoch+1,1))
ax1.grid()
# ---エポック数と正答率のプロット
epochTimes = range(1, clf.numEpoch + 1)
ax2.plot(epochTimes, np.array(clf.correctAnswerRateEachEpoch_) * 100, color="blue", marker="o",
label="Correct answer rate")
# ---ax2.legend(loc="upper left")
ax2.set_title("Epochs and correct answer rate")
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Correct answer rate[%]')
ax2.set_xlim(0, clf.numEpoch)
ax2.grid()
# ---教師データのクラスラベルが1(バージカラー)であるである確率
numTrainSamples = len(y)
trainSampeleIndex=range(numTrainSamples)
ax3.plot(trainSampeleIndex, clf.probability(X)*100, color="blue", marker="o",label="Probability")
ax3.set_title("TrainSamples and probability(label=1)")
ax3.set_xlabel('TrainSamples')
ax3.set_ylabel('Probability[%]')
ax3.set_xlim(0, numTrainSamples)
ax3.grid()
# ---エポック数とコスト関数のプロット
epochTimes = range(1, clf.numEpoch + 1)
ax4.plot(epochTimes, np.array(clf.J_)[:, 0][:, 0], color="blue", marker="o",
label="Cost function values")
# ---ax3.legend(loc="upper left")
ax4.set_title("Epochs and cost function values")
ax4.set_xlabel('Epochs')
ax4.set_ylabel('Cost function values')
ax4.set_xlim(0, clf.numEpoch)
ax4.grid()
# ---ax3.set_xticks(range(0,numEpoch+1,1))
# ---決定領域のプロット
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
dx = 0.02
X1 = np.arange(x1_min, x1_max, dx)
X2 = np.arange(x2_min, x2_max, dx)
X1, X2 = np.meshgrid(X1, X2)
Z = clf.predict(np.array([X1.ravel(), X2.ravel()]).T)
Z = Z.reshape(X1.shape)
# ---決定領域
ax5.contourf(X1, X2, Z, alpha=0.5, cmap=cmap)
ax5.set_xlim(X1.min(), X1.max())
ax5.set_ylim(X2.min(), X2.max())
# ---アヤメデータ
for idx, cl in enumerate(np.unique(y)):
ax5.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
alpha=1.0, c=cmap(idx),
marker=markers[idx], label=labels[idx])
ax5.set_title("Decision regions")
ax5.set_xlabel("Sepal length [cm]") # がく片の長さ
ax5.set_ylabel("Petal length [cm]") # 花びらの長さ
ax5.legend(loc="upper left")
ax5.grid()
pngFileName=u"ロジスティック回帰学習結果_トレーニングサンプル" +trainSampleState +u"_シャッフル"+shuffeled+u"_Fitアルゴリズム"+fitAlgorism+ u"_学習率"+str(clf.eta)+u"_最大エポック数"+str(clf.numEpoch)+ ".png"
plt.savefig(pngFileName, dpi=300)
class LogisticRegression(object):
def __init__(self, eta=0.01, numEpoch=10, shuffle=True, random_state=None):
self.eta = eta #学習率
self.numEpoch = numEpoch #最大エポック数
self.shuffle = shuffle #トレーニングサンプルをシャッフルする?
if random_state:
np.random.seed(random_state)
self.W_=[] #各エポックごとに重みを保存するリスト
self.J_=[] #各エポックごとにコスト関数を保存するリスト
self.correctAnswerRateEachEpoch_=[] #各エポックごとに正答率を保存するリスト
def __actFunc(self, z):
"""活性化関数(__でプライベート関数)"""
return 1.0 / (1.0 + np.exp(-z))
def __quantizer(self, phi):
"""量子化器(__でプライベート関数)"""
return np.where(np.array(phi) >= 0.5, 1, 0)
def __shuffle(self, X, y):
"""トレーニングサンプルのシャッフル(__でプライベート関数)"""
r = np.random.permutation(len(y))
return X[r], y[r]
def predict(self, X):
"""予測関数"""
X = np.matrix(X)
m, n = X.shape
X = np.c_[np.matrix(np.ones((m, 1))), X]
z=X*self.w_
phi=self.__actFunc(z)
return self.__quantizer(phi)
def probability(self, X):
"""教師データのクラスラベルが1である確率を求める関数"""
X = np.matrix(X)
m, n = X.shape
X = np.c_[np.matrix(np.ones((m, 1))), X]
z=X*self.w_
phi=self.__actFunc(z)
return phi
def fit(self, X, y):
"""バッチ勾配降下法による学習の実施"""
# ---トレーニングサンプルのシャッフル
if self.shuffle:
X, y = self.__shuffle(X, y)
# ---特徴行列
X = np.matrix(X)
m, n = X.shape
# ---しきい値用に一番左側の列に1を追加
X = np.c_[np.matrix(np.ones((m, 1))), X]
# ---教師データベクトル
y = np.matrix(y).T
# ---重みベクトル(初期化)
self.w_ =np.matrix(np.zeros((n+1,1)))
# 重みを学習回数ごとに保存
self.W_.append(self.w_.tolist())
for indexEpoch in range(1,self.numEpoch+1): #エポックループ
correctAnswer=[] #各トレーニングセットに対する教師データと予測値の正誤表をイニシャライズ
# ---特徴行列と重みベクトルの掛け合わせ
z = X * self.w_
# ---活性化関数出力ベクトル
phi =self.__actFunc(z)
# ---コスト関数
J = -y.T * np.log(phi) - (np.ones((m, 1)) - y).T * np.log(np.ones((m, 1)) - phi)
# ---コスト関数の勾配
gradJ = -X.T * (y - phi)
# ---重み更新
dw = - self.eta * gradJ
self.w_ = self.w_ + dw
# 重みをエポックごとに保存
self.W_.append(self.w_.tolist())
# コスト関数をエポックごとに保存
self.J_.append(J.tolist())
#--正答表
correctAnswer = np.where(np.array(y == self.__quantizer(phi)) == True, 1, 0)
#各エポックごとに正誤表から正答率算出し保存
self.correctAnswerRateEachEpoch_.append(float(sum(correctAnswer))/len(correctAnswer))
def fitSGD(self, X, y):
"""確率的勾配降下法による学習の実施"""
# ---トレーニングサンプルのシャッフル
if self.shuffle:
X, y = self.__shuffle(X, y)
# ---特徴行列
X = np.matrix(X)
m, n = X.shape
# ---しきい値用に一番左側の列に1を追加
X = np.c_[np.matrix(np.ones((m, 1))), X]
# ---教師データベクトル
y = np.matrix(y).T
# ---重みベクトル(初期化)
self.w_ = np.matrix(np.zeros((n + 1, 1)))
# 重みを学習回数ごとに保存
self.W_.append(self.w_.tolist())
for indexEpoch in range(1, self.numEpoch + 1): # エポックループ
correctAnswer = [] # 各トレーニングセットに対する教師データと予測値の正誤表をイニシャライズ
for xi, yi in zip(X, y): # トレーニングセットループ
# ---特徴行列と重みベクトルの掛け合わせ
zi = xi * self.w_
# ---活性化関数出力ベクトル
phii = self.__actFunc(zi)
# ---コスト関数の勾配
gradJi = -xi.T * (yi - phii)
# ---重み更新
dwi = - self.eta * gradJi
self.w_ = self.w_ + dwi
# ---特徴行列と重みベクトルの掛け合わせ
z = X * self.w_
# ---活性化関数出力ベクトル
phi =self.__actFunc(z)
# ---コスト関数
J = -y.T * np.log(phi) - (np.ones((m, 1)) - y).T * np.log(np.ones((m, 1)) - phi)
# 重みをエポックごとに保存
self.W_.append(self.w_.tolist())
# コスト関数をエポックごとに保存
self.J_.append(J.tolist())
# --正答表
correctAnswer = np.where(np.array(y == self.__quantizer(phi)) == True, 1, 0)
# 各エポックごとに正誤表から正答率算出し保存
self.correctAnswerRateEachEpoch_.append(float(sum(correctAnswer)) / len(correctAnswer))
def fitLS(self, X, y):
"""一発学習の実施"""
# ---トレーニングサンプルのシャッフル
if self.shuffle:
X, y = self.__shuffle(X, y)
# ---特徴行列
X = np.matrix(X)
m, n = X.shape
# ---しきい値用に一番左側の列に1を追加
X = np.c_[np.matrix(np.ones((m, 1))), X]
# ---教師データベクトル
y = np.matrix(y).T
# ---重みベクトル(初期化)
self.w_ = np.matrix(np.zeros((n + 1, 1)))
# 重みを学習回数ごとに保存
self.W_.append(self.w_.tolist())
for indexEpoch in range(1, self.numEpoch + 1): # エポックループ
correctAnswer = [] # 各トレーニングセットに対する教師データと予測値の正誤表をイニシャライズ
# ---コスト関数を最小にする重みを一発で算出
dy = 1e-10
yHat = np.where(y == 1, 1 - dy, dy) #---log(0)が計算できないのでyをdyだけずらしてやる
self.w_ = np.linalg.inv(X.T*X)*X.T*(np.log(yHat)-np.log(np.ones((m, 1)) - yHat))
# ---特徴行列と重みベクトルの掛け合わせ
z = X * self.w_
# ---活性化関数出力ベクトル
phi = self.__actFunc(z)
# ---コスト関数
J = -y.T * np.log(phi) - (np.ones((m, 1)) - y).T * np.log(np.ones((m, 1)) - phi)
# 重みをエポックごとに保存
self.W_.append(self.w_.tolist())
# コスト関数をエポックごとに保存
self.J_.append(J.tolist())
# --正答表
correctAnswer = np.where(np.array(y == self.__quantizer(phi)) == True, 1, 0)
# 各エポックごとに正誤表から正答率算出し保存
self.correctAnswerRateEachEpoch_.append(float(sum(correctAnswer)) / len(correctAnswer))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment