Last active
December 22, 2018 13:45
-
-
Save darden1/19427cf418bbf8c1fe8572a4627f7528 to your computer and use it in GitHub Desktop.
StudyMachineLearning_AdalineSGD.py
This file contains 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 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", -1, 1) | |
X = df.iloc[0:100, [0, 2]].values | |
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオフ,バッチ勾配降下法)) | |
Xstd = np.copy(X) | |
Xstd[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std() | |
Xstd[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std() | |
ada = Adaline(eta=0.01, numEpoch=20, shuffle=False) | |
ada.fit(Xstd, y) | |
plotResult(ada,Xstd,y,"Standardization","Off","GD") | |
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオフ,確率的勾配降下法)) | |
Xstd = np.copy(X) | |
Xstd[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std() | |
Xstd[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std() | |
ada = Adaline(eta=0.01, numEpoch=20, shuffle=False) | |
ada.fitSGD(Xstd, y) | |
plotResult(ada, Xstd, y, "Standardization", "Off", "SGD") | |
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオン,確率的勾配降下法)) | |
Xstd = np.copy(X) | |
Xstd[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std() | |
Xstd[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std() | |
ada = Adaline(eta=0.01, numEpoch=20, shuffle=True) | |
ada.fitSGD(Xstd, y) | |
plotResult(ada, Xstd, y, "Standardization", "On", "SGD") | |
# ---学習実施(学習率:0.01 最大エポック数:20 (特徴量を標準化,シャッフルオン,最小二乗法)) | |
Xstd = np.copy(X) | |
Xstd[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std() | |
Xstd[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std() | |
ada = Adaline(eta=0.01, numEpoch=20, shuffle=True) | |
ada.fitLS(Xstd, y) | |
plotResult(ada, Xstd, y, "Standardization", "On", "LS") | |
def plotResult(ada,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=(12, 10)) | |
plt.clf() | |
ax1 = fig.add_subplot(221) | |
ax2 = fig.add_subplot(222) | |
ax3 = fig.add_subplot(223) | |
ax4 = fig.add_subplot(224) | |
# ---エポック数と重みのプロット | |
epochTimes = np.array(range(0, ada.numEpoch + 1)) | |
ada.W_ = np.array(ada.W_) | |
ax1.plot(epochTimes, ada.W_[:, 0].T[0], color="blue", label="w0") | |
ax1.plot(epochTimes, ada.W_[:, 1].T[0], color="red", label="w2") | |
ax1.plot(epochTimes, ada.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, ada.numEpoch) | |
# ---ax1.set_xticks(range(0,numEpoch+1,1)) | |
ax1.grid() | |
# ---エポック数と正答率のプロット | |
epochTimes = range(1, ada.numEpoch + 1) | |
ax2.plot(epochTimes, np.array(ada.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, ada.numEpoch) | |
ax2.grid() | |
plt.xlim(0, ada.numEpoch) | |
# ---エポック数とコスト関数のプロット | |
epochTimes = range(1, ada.numEpoch + 1) | |
ax3.plot(epochTimes, np.array(ada.J_)[:, 0][:, 0], color="blue", marker="o", | |
label="Cost function values") | |
# ---ax3.legend(loc="upper left") | |
ax3.set_title("Epochs and cost function values") | |
ax3.set_xlabel('Epochs') | |
ax3.set_ylabel('Cost function values') | |
ax3.set_xlim(0, ada.numEpoch) | |
ax3.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 = ada.predict(np.array([X1.ravel(), X2.ravel()]).T) | |
Z = Z.reshape(X1.shape) | |
# ---決定領域 | |
ax4.contourf(X1, X2, Z, alpha=0.5, cmap=cmap) | |
ax4.set_xlim(X1.min(), X1.max()) | |
ax4.set_ylim(X2.min(), X2.max()) | |
# ---アヤメデータ | |
for idx, cl in enumerate(np.unique(y)): | |
ax4.scatter(x=X[y == cl, 0], y=X[y == cl, 1], | |
alpha=1.0, c=cmap(idx), | |
marker=markers[idx], label=labels[idx]) | |
ax4.set_title("Decision regions") | |
ax4.set_xlabel("Sepal length [cm]") # がく片の長さ | |
ax4.set_ylabel("Petal length [cm]") # 花びらの長さ | |
ax4.legend(loc="upper left") | |
ax4.grid() | |
pngFileName=u"ADALINE学習結果_トレーニングサンプル" +trainSampleState +u"_シャッフル"+shuffeled+u"_Fitアルゴリズム"+fitAlgorism+ u"_学習率"+str(ada.eta)+u"_最大エポック数"+str(ada.numEpoch)+ ".png" | |
plt.savefig(pngFileName, dpi=300) | |
class Adaline(object): | |
def __init__(self, alpha=1.0, eta=0.01, numEpoch=10, shuffle=True, random_state=None): | |
self.alpha = alpha # 活性化関数の定数 | |
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 self.alpha*z | |
def __quantizer(self, phi): | |
"""量子化器(__でプライベート関数)""" | |
return np.where(np.array(phi) >= 0.0, 1, -1) | |
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 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) | |
# ---教師データと活性化関数出力の残差ベクトル | |
e = y - self.alpha * X * self.w_ | |
# ---コスト関数 | |
J = e.T * e / 2 | |
# ---コスト関数の勾配 | |
gradJ = -self.alpha * X.T * y + self.alpha ** 2 * X.T * X * self.w_ | |
# ---重み更新 | |
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): # トレーニングセットループ | |
# ---コスト関数の勾配 | |
gradJi = -self.alpha * xi.T * yi + self.alpha ** 2 * xi.T * xi * self.w_ | |
# ---重み更新 | |
dwi = - self.eta * gradJi | |
self.w_ = self.w_ + dwi | |
# ---特徴行列と重みベクトルの掛け合わせ | |
z = X * self.w_ | |
# ---活性化関数 | |
phi = self.__actFunc(z) | |
# ---教師データと活性化関数出力の残差ベクトル | |
e = y - self.alpha * X * self.w_ | |
# ---コスト関数 | |
J = e.T * e / 2 | |
# ---コスト関数の勾配 | |
gradJ = -self.alpha * X.T * y + self.alpha ** 2 * X.T * X * self.w_ | |
# # ---重み更新 | |
# 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 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 = [] # 各トレーニングセットに対する教師データと予測値の正誤表をイニシャライズ | |
# ---コスト関数を最小にする重みを一発で算出 | |
self.w_ = np.linalg.inv(X.T*X)*X.T*y /self.alpha | |
# ---特徴行列と重みベクトルの掛け合わせ | |
z = X * self.w_ | |
# ---活性化関数 | |
phi = self.__actFunc(z) | |
# ---教師データと活性化関数出力の残差ベクトル | |
e = y - self.alpha * X * self.w_ | |
# ---コスト関数 | |
J = e.T * e / 2 | |
# 重みをエポックごとに保存 | |
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