Xiaowuhu/101 (#168)

* Update Level0_TwoLayerNet.py

* up
This commit is contained in:
xiaowuhu
2019-03-29 13:57:42 +08:00
committed by Annbless
parent 8cd0dbf28d
commit 2cc7a82cfa
17 changed files with 438 additions and 321 deletions
@@ -3,6 +3,10 @@ Copyright © Microsoft Corporation. All rights reserved.
在这一章,我们将简要介绍一下激活函数,因为在下一章中将要使用激活函数构造神经网络。
- [挤压(饱和)型激活函数](06.1-挤压型激活函数.md)
- [半线性(非饱和)激活函数](06.2-半线性激活函数.md)
# 激活函数
看神经网络中的一个神经元,为了简化,假设该神经元接受三个输入,分别为$x_1, x_2, x_3$,那么$z=\sum\limits_{i}w_ix_i+b_i$,
@@ -25,12 +29,6 @@ Copyright © Microsoft Corporation. All rights reserved.
用到神经网络中的概念,用‘1’来代表一个神经元被激活,‘0’代表一个神经元未被激活。
这个函数有什么不好的地方呢?主要的一点就是,他的梯度(导数)恒为零(个别点除外)。
这个函数有什么不好的地方呢?主要的一点就是,他的梯度(导数)恒为零(个别点除外)。反向传播公式中,梯度传递用到了链式法则,如果在这样一个连乘的式子其中有一项是零,这样的梯度就会恒为零,是没有办法进行反向传播的。
想想我们说过的反向传播公式?梯度传递用到了链式法则,如果在这样一个连乘的式子其中有一项是零,结果会怎么样呢?这样的梯度就会恒为零,这个样子的函数是没有办法进行反向传播的。于是,数学家们发明了如下激活函数。
- [挤压型激活函数](06.1-挤压型激活函数.md)
- [半线性激活函数](06.2-半线性激活函数.md)
@@ -3,7 +3,7 @@ Copyright © Microsoft Corporation. All rights reserved.
# 挤压型激活函数 Squashing Function
挤压型激活函数中,用的最多的是Sigmoid函数,Sigmoid意为S型。
又可以叫饱和型激活函数。挤压型激活函数中,用的最多的是Sigmoid函数,Sigmoid意为S型。
## 对数几率函数 Logistic Function
@@ -1,12 +1,19 @@
Copyright © Microsoft Corporation. All rights reserved.
适用于[License](https://github.com/Microsoft/ai-edu/blob/master/LICENSE.md)版权许可
# 半线性激活函数
又可以叫非饱和型激活函数。
## ReLU函数
Rectified Linear Unit,修正线性单元,线性整流函数,斜坡函数。
公式:
$$a(z) = max(0,z) = \begin{cases} z & z \geq 0 \\ 0 & z < 0 \end{cases}$$
$$a(z) = max(0,z) = \begin{Bmatrix}
z & (z \geq 0) \\
0 & (z < 0)
\end{Bmatrix}$$
导数:
@@ -1,22 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
import numpy as np
class CSigmoid(object):
def forward(self, z):
a = 1.0 / (1.0 + np.exp(-z))
return a
def backward(self, z, a, delta):
da = np.multiply(a, 1-a)
dz = np.multiply(delta, da)
return da, dz
class CSoftmax(object):
def forward(self, Z):
shift_z = Z - np.max(Z, axis=0)
exp_z = np.exp(shift_z)
A = exp_z / np.sum(exp_z, axis=0)
return A
@@ -0,0 +1,128 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
import numpy as np
import struct
import matplotlib.pyplot as plt
'''
train_image_file = 'train-images-01'
train_label_file = 'train-labels-01'
test_image_file = 'test-images-01'
test_label_file = 'test-labels-01'
'''
train_image_file = 'train-images-10'
train_label_file = 'train-labels-10'
test_image_file = 'test-images-10'
test_label_file = 'test-labels-10'
# output array: 768 x num_images
def ReadImageFile(image_file_name):
f = open(image_file_name, "rb")
a = f.read(4)
b = f.read(4)
num_images = int.from_bytes(b, byteorder='big')
c = f.read(4)
num_rows = int.from_bytes(c, byteorder='big')
d = f.read(4)
num_cols = int.from_bytes(d, byteorder='big')
image_size = num_rows * num_cols # 784
fmt = '>' + str(image_size) + 'B'
image_data = np.empty((image_size, num_images)) # 784 x M
for i in range(num_images):
bin_data = f.read(image_size)
unpacked_data = struct.unpack(fmt, bin_data)
array_data = np.array(unpacked_data)
array_data2 = array_data.reshape((image_size, 1))
image_data[:,i] = array_data
f.close()
return image_data
def ReadLabelFile(lable_file_name, num_output):
f = open(lable_file_name, "rb")
f.read(4)
a = f.read(4)
num_labels = int.from_bytes(a, byteorder='big')
fmt = '>B'
label_data = np.zeros((num_output, num_labels)) # 10 x M
for i in range(num_labels):
bin_data = f.read(1)
unpacked_data = struct.unpack(fmt, bin_data)[0]
label_data[unpacked_data,i] = 1
f.close()
return label_data
def NormalizeData(X):
X_NEW = np.zeros(X.shape)
x_max = np.max(X)
x_min = np.min(X)
X_NEW = (X - x_min)/(x_max-x_min)
return X_NEW
def Sigmoid(x):
s=1/(1+np.exp(-x))
return s
def Softmax(Z):
shift_z = Z - np.max(Z)
exp_z = np.exp(shift_z)
s = np.sum(exp_z, axis=0)
A = exp_z / s
return A
# cross entropy: -Y*lnA
def CalculateLoss(dict_Param, X, Y, count, forward):
A2, dict_Cache = forward(X, dict_Param)
p = Y * np.log(A2)
Loss = -np.sum(p) / count
return Loss
def Test(num_output, dict_Param, num_input, forward):
raw_data = ReadImageFile(test_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(test_label_file, num_output)
num_images = X.shape[1]
correct = 0
for image_idx in range(num_images):
x = X[:,image_idx].reshape(num_input, 1)
y = Y[:,image_idx].reshape(num_output, 1)
A2, dict_Cache = forward(x, dict_Param)
if np.argmax(A2) == np.argmax(y):
correct += 1
return correct, num_images
def Train(X, Y, learning_rate, max_epoch, num_images, num_input, num_output, dict_param, forward, backward, update):
loss_history = list()
print("Training...")
for iteration in range(max_epoch):
for item in range(num_images):
x = X[:,item].reshape(num_input,1)
y = Y[:,item].reshape(num_output,1)
A2, dict_Cache = forward(x, dict_param)
dict_Grads = backward(dict_param, dict_Cache, x, y)
dict_param = update(dict_param, dict_Grads, learning_rate)
if item % 1000 == 0:
Loss = CalculateLoss(dict_param, X, Y, num_images, forward)
print(item, Loss)
loss_history = np.append(loss_history, Loss)
print(iteration)
print("Testing...")
correct, count = Test(num_output, dict_param, num_input, forward)
print(str.format("rate={0} / {1} = {2}", correct, count, correct/count))
plt.plot(loss_history, "r")
plt.xlabel("Iteration(x1000)")
plt.ylabel("Loss")
plt.show()
def LoadData(num_output):
raw_data = ReadImageFile(train_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(train_label_file, num_output)
return X, Y
@@ -5,6 +5,8 @@ import numpy as np
import struct
import matplotlib.pyplot as plt
from Level0_Base import *
'''
train_image_file = 'train-images-01'
train_label_file = 'train-labels-01'
@@ -17,77 +19,7 @@ test_image_file = 'test-images-10'
test_label_file = 'test-labels-10'
# output array: 768 x num_images
def ReadImageFile(image_file_name):
f = open(image_file_name, "rb")
a = f.read(4)
b = f.read(4)
num_images = int.from_bytes(b, byteorder='big')
c = f.read(4)
num_rows = int.from_bytes(c, byteorder='big')
d = f.read(4)
num_cols = int.from_bytes(d, byteorder='big')
image_size = num_rows * num_cols # 784
fmt = '>' + str(image_size) + 'B'
image_data = np.empty((image_size, num_images)) # 784 x M
for i in range(num_images):
bin_data = f.read(image_size)
unpacked_data = struct.unpack(fmt, bin_data)
array_data = np.array(unpacked_data)
array_data2 = array_data.reshape((image_size, 1))
image_data[:,i] = array_data
f.close()
return image_data
def ReadLabelFile(lable_file_name, num_output):
f = open(lable_file_name, "rb")
f.read(4)
a = f.read(4)
num_labels = int.from_bytes(a, byteorder='big')
fmt = '>B'
label_data = np.zeros((num_output, num_labels)) # 10 x M
for i in range(num_labels):
bin_data = f.read(1)
unpacked_data = struct.unpack(fmt, bin_data)[0]
label_data[unpacked_data,i] = 1
f.close()
return label_data
def NormalizeByRow(X):
X_NEW = np.zeros(X.shape)
# get number of features
n = X.shape[0]
for i in range(n):
x_row = X[i,:]
x_max = np.max(x_row)
x_min = np.min(x_row)
if x_max != x_min:
x_new = (x_row - x_min)/(x_max-x_min)
X_NEW[i,:] = x_new
return X_NEW
def NormalizeData(X):
X_NEW = np.zeros(X.shape)
x_max = np.max(X)
x_min = np.min(X)
X_NEW = (X - x_min)/(x_max-x_min)
return X_NEW
def Sigmoid(x):
s=1/(1+np.exp(-x))
return s
def Softmax(Z):
shift_z = Z - np.max(Z)
exp_z = np.exp(shift_z)
#s = np.sum(exp_z)
s = np.sum(exp_z, axis=0)
A = exp_z / s
return A
def ForwardCalculation(X, dict_Param):
def Forward(X, dict_Param):
W1 = dict_Param["W1"]
B1 = dict_Param["B1"]
W2 = dict_Param["W2"]
@@ -95,7 +27,6 @@ def ForwardCalculation(X, dict_Param):
Z1 = np.dot(W1,X)+B1
A1 = Sigmoid(Z1)
#A1 = np.tanh(Z1)
Z2=np.dot(W2,A1)+B2
A2=Softmax(Z2)
@@ -106,7 +37,7 @@ def ForwardCalculation(X, dict_Param):
"A2": A2}
return A2, dict_Cache
def BackPropagation(dict_Param,cache,X,Y):
def Backward(dict_Param,cache,X,Y):
W1=dict_Param["W1"]
W2=dict_Param["W2"]
A1 = cache["A1"]
@@ -119,7 +50,6 @@ def BackPropagation(dict_Param,cache,X,Y):
dLoss_A1 = np.dot(W2.T, dZ2)
dA1_Z1 = A1 * (1 - A1) # sigmoid
#dA1_Z1 = 1-np.power(A1,2) # tanh
dZ1 = dLoss_A1 * dA1_Z1
dW1 = np.dot(dZ1, X.T)
@@ -128,7 +58,7 @@ def BackPropagation(dict_Param,cache,X,Y):
dict_Grads = {"dW1": dW1, "dB1": dB1, "dW2": dW2, "dB2": dB2}
return dict_Grads
def UpdateParam(dict_Param, dict_Grads, learning_rate):
def Update(dict_Param, dict_Grads, learning_rate):
W1 = dict_Param["W1"]
B1 = dict_Param["B1"]
W2 = dict_Param["W2"]
@@ -147,12 +77,6 @@ def UpdateParam(dict_Param, dict_Grads, learning_rate):
dict_Param = {"W1": W1, "B1": B1, "W2": W2, "B2": B2}
return dict_Param
# cross entropy: -Y*lnA
def CalculateLoss(dict_Param, X, Y, count):
A2, dict_Cache = ForwardCalculation(X, dict_Param)
p = Y * np.log(A2)
Loss = -np.sum(p) / count
return Loss
def InitialParameters(num_input, num_hidden, num_output, flag):
if flag == 0:
@@ -173,61 +97,16 @@ def InitialParameters(num_input, num_hidden, num_output, flag):
dict_Param = {"W1": W1, "B1": B1, "W2": W2, "B2": B2}
return dict_Param
def Test(num_output, dict_Param, num_input):
raw_data = ReadImageFile(test_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(test_label_file, num_output)
num_images = X.shape[1]
correct = 0
for image_idx in range(num_images):
x = X[:,image_idx].reshape(num_input, 1)
y = Y[:,image_idx].reshape(num_output, 1)
A2, dict_Cache = ForwardCalculation(x, dict_Param)
if np.argmax(A2) == np.argmax(y):
correct += 1
return correct, num_images
if __name__ == '__main__':
print("Loading...")
learning_rate = 0.1
num_hidden = 32
num_output = 10
learning_rate = 0.05
n_hidden = 32
n_output = 10
X,Y = LoadData(n_output)
n_images = X.shape[1]
n_input = X.shape[0]
m_epoch = 1
dict_Param = InitialParameters(n_input, n_hidden, n_output, 2)
Train(X, Y, learning_rate, m_epoch, n_images, n_input, n_output, dict_Param, Forward, Backward, Update)
raw_data = ReadImageFile(train_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(train_label_file, num_output)
num_images = X.shape[1]
num_input = X.shape[0]
max_iteration = 1
dict_Param = InitialParameters(num_input, num_hidden, num_output, 2)
w = dict_Param["W1"]
print(np.var(w))
loss_history = list()
print("Training...")
for iteration in range(max_iteration):
for item in range(num_images):
x = X[:,item].reshape(num_input,1)
y = Y[:,item].reshape(num_output,1)
A2, dict_Cache = ForwardCalculation(x, dict_Param)
dict_Grads = BackPropagation(dict_Param, dict_Cache, x, y)
dict_Param = UpdateParam(dict_Param, dict_Grads, learning_rate)
if item % 1000 == 0:
Loss = CalculateLoss(dict_Param, X, Y, num_images)
print(item, Loss)
loss_history = np.append(loss_history, Loss)
print(iteration)
print("Testing...")
correct, count = Test(num_output, dict_Param, num_input)
print(str.format("rate={0} / {1} = {2}", correct, count, correct/count))
plt.plot(loss_history, "r")
plt.title("Xavier Initilization")
plt.xlabel("Iteration(x1000)")
plt.ylabel("Loss")
plt.show()
@@ -5,93 +5,14 @@ import numpy as np
import struct
import matplotlib.pyplot as plt
'''
train_image_file = 'train-images-01'
train_label_file = 'train-labels-01'
test_image_file = 'test-images-01'
test_label_file = 'test-labels-01'
'''
train_image_file = 'train-images-10'
train_label_file = 'train-labels-10'
test_image_file = 'test-images-10'
test_label_file = 'test-labels-10'
from Level0_TwoLayerNet import *
# output array: 768 x num_images
def ReadImageFile(image_file_name):
f = open(image_file_name, "rb")
a = f.read(4)
b = f.read(4)
num_images = int.from_bytes(b, byteorder='big')
c = f.read(4)
num_rows = int.from_bytes(c, byteorder='big')
d = f.read(4)
num_cols = int.from_bytes(d, byteorder='big')
image_size = num_rows * num_cols # 784
fmt = '>' + str(image_size) + 'B'
image_data = np.empty((image_size, num_images)) # 784 x M
for i in range(num_images):
bin_data = f.read(image_size)
unpacked_data = struct.unpack(fmt, bin_data)
array_data = np.array(unpacked_data)
array_data2 = array_data.reshape((image_size, 1))
image_data[:,i] = array_data
f.close()
return image_data
def ReadLabelFile(lable_file_name, num_output):
f = open(lable_file_name, "rb")
f.read(4)
a = f.read(4)
num_labels = int.from_bytes(a, byteorder='big')
fmt = '>B'
label_data = np.zeros((num_output, num_labels)) # 10 x M
for i in range(num_labels):
bin_data = f.read(1)
unpacked_data = struct.unpack(fmt, bin_data)[0]
label_data[unpacked_data,i] = 1
f.close()
return label_data
def NormalizeByRow(X):
X_NEW = np.zeros(X.shape)
# get number of features
n = X.shape[0]
for i in range(n):
x_row = X[i,:]
x_max = np.max(x_row)
x_min = np.min(x_row)
if x_max != x_min:
x_new = (x_row - x_min)/(x_max-x_min)
X_NEW[i,:] = x_new
return X_NEW
def NormalizeData(X):
X_NEW = np.zeros(X.shape)
x_max = np.max(X)
x_min = np.min(X)
X_NEW = (X - x_min)/(x_max-x_min)
return X_NEW
def Sigmoid(z):
a=1/(1+np.exp(-z))
return a
def Tanh(z):
a = 2.0 / (1.0 + np.exp(-2*z)) - 1.0
return a
def Softmax(Z):
shift_z = Z - np.max(Z)
exp_z = np.exp(shift_z)
s = np.sum(exp_z, axis=0)
A = exp_z / s
return A
def ForwardCalculation(X, dict_Param):
def forward(X, dict_Param):
W1 = dict_Param["W1"]
B1 = dict_Param["B1"]
W2 = dict_Param["W2"]
@@ -111,7 +32,7 @@ def ForwardCalculation(X, dict_Param):
dict_Cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2, "Z3": Z3, "A3": A3}
return A3, dict_Cache
def BackPropagation(dict_Param,cache,X,Y):
def backward(dict_Param,cache,X,Y):
W1=dict_Param["W1"]
W2=dict_Param["W2"]
W3=dict_Param["W3"]
@@ -139,7 +60,7 @@ def BackPropagation(dict_Param,cache,X,Y):
dict_Grads = {"dW1": dW1, "dB1": dB1, "dW2": dW2, "dB2": dB2, "dW3": dW3, "dB3": dB3}
return dict_Grads
def UpdateParam(dict_Param, dict_Grads, learning_rate):
def update(dict_Param, dict_Grads, learning_rate):
W1 = dict_Param["W1"]
B1 = dict_Param["B1"]
W2 = dict_Param["W2"]
@@ -164,12 +85,6 @@ def UpdateParam(dict_Param, dict_Grads, learning_rate):
dict_Param = {"W1": W1, "B1": B1, "W2": W2, "B2": B2, "W3": W3, "B3": B3}
return dict_Param
# cross entropy: -Y*lnA
def CalculateLoss(dict_Param, X, Y, count):
A3, dict_Cache = ForwardCalculation(X, dict_Param)
p = Y * np.log(A3)
Loss = -np.sum(p) / count
return Loss
def InitialParameters(num_input, num_hidden1, num_hidden2, num_output, flag):
if flag == 0:
@@ -199,67 +114,17 @@ def InitialParameters(num_input, num_hidden1, num_hidden2, num_output, flag):
dict_Param = {"W1": W1, "B1": B1, "W2": W2, "B2": B2, "W3": W3, "B3": B3}
return dict_Param
def Test(num_output, dict_Param, num_input):
raw_data = ReadImageFile(test_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(test_label_file, num_output)
num_images = X.shape[1]
correct = 0
for image_idx in range(num_images):
x = X[:,image_idx].reshape(num_input, 1)
y = Y[:,image_idx].reshape(num_output, 1)
A2, dict_Cache = ForwardCalculation(x, dict_Param)
if np.argmax(A2) == np.argmax(y):
correct += 1
return correct, num_images
if __name__ == '__main__':
print("Loading...")
learning_rate = 0.05
num_hidden1 = 64
num_hidden2 = 16
num_output = 10
n_hidden1 = 64
n_hidden2 = 16
n_output = 10
X,Y = LoadData(n_output)
n_images = X.shape[1]
n_input = X.shape[0]
m_epoch = 1
dict_Param = InitialParameters(n_input, n_hidden1, n_hidden2, n_output, 2)
Train(X, Y, learning_rate, m_epoch, n_images, n_input, n_output, dict_Param, forward, backward, update)
raw_data = ReadImageFile(train_image_file)
X = NormalizeData(raw_data)
Y = ReadLabelFile(train_label_file, num_output)
num_images = X.shape[1]
num_input = X.shape[0]
max_iteration = 10
dict_Param = InitialParameters(num_input, num_hidden1, num_hidden2, num_output, 2)
loss_history = list()
eps = 1e-1
print("Training...")
for iteration in range(max_iteration):
for item in range(num_images):
x = X[:,item].reshape(num_input,1)
y = Y[:,item].reshape(num_output,1)
A3, dict_Cache = ForwardCalculation(x, dict_Param)
dict_Grads = BackPropagation(dict_Param, dict_Cache, x, y)
dict_Param = UpdateParam(dict_Param, dict_Grads, learning_rate)
if item % 1000 == 0:
Loss = CalculateLoss(dict_Param, X, Y, num_images)
print(item, Loss)
loss_history = np.append(loss_history, Loss)
if Loss < eps:
break
#end if
#end if
#end for
if Loss < eps:
break
print(iteration)
print("Testing...")
correct, count = Test(num_output, dict_Param, num_input)
print(str.format("rate={0} / {1} = {2}", correct, count, correct/count))
plt.plot(loss_history, "r")
plt.title("Xavier Initilization")
plt.xlabel("Iteration(x1000)")
plt.ylabel("Loss")
plt.show()
@@ -0,0 +1,68 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
import numpy as np
class CActivator(object):
# z = 本层的wx+b计算值矩阵
def forward(self, z):
pass
# z = 本层的wx+b计算值矩阵
# a = 本层的激活函数输出值矩阵
# delta = 上(后)层反传回来的梯度值矩阵
def backward(self, z, a, delta):
pass
# 直传函数,相当于无激活
class Identity(CActivator):
def forward(self, z):
return z
def backward(self, z, a, delta):
return delta, a
class Sigmoid(CActivator):
def forward(self, z):
a = 1.0 / (1.0 + np.exp(-Z))
return a
def backward(self, z, a, delta):
da = np.multiply(a, 1-a)
dz = np.multiply(delta, da)
return dz, da
class Tanh(CActivator):
def forward(self, z):
a = 2.0 / (1.0 + np.exp(-2*z)) - 1.0
return a
def backward(self, z, a, delta):
da = 1 - np.multiply(a, a)
dz = np.multiply(delta, da)
return dz, da
class Relu(CActivator):
def forward(self, z):
a = np.maximum(z, 0)
return a
# 注意relu函数判断是否大于1的根据是正向的wx+b=z的值,而不是a值
def backward(self, z, a, delta):
da = np.zeros(z.shape)
da[z>0] = 1
dz = da * delta
return dz, mem
class Softmax(CActivator):
def forward(self, z):
shift_z = z - np.max(z, axis=0)
exp_z = np.exp(shift_z)
a = exp_z / np.sum(exp_z, axis=0)
return a
@@ -0,0 +1,57 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
import numpy as np
from Layer import *
from Activators import *
class FcLayer(CLayer):
def __init__(self, input_size, output_size, activator):
self.input_size = input_size
self.output_size = output_size
self.weights = init_array((output_size, input_size), "norm")
self.bias = np.zeros((output_size, 1))
self.activator = activator
#self.x = np.zeros() # input from lower layer
#self.z = np.zeros() # weights multiply for current layer
#self.a = np.zeros() # outpu to upper layer
def forward(self, input):
self.input_shape = input.shape
if input.ndim == 3: # come from pooling layer
self.x = input.reshape(input.size, 1)
else:
self.x = input
self.z = np.dot(self.weights, self.x) + self.bias
self.a = self.activator.forward(self.z)
return self.a
# 把激活函数算做是当前层,上一层的误差传入后,先经过激活函数的导数,而得到本层的针对z值的误差
def backward(self, delta_in, flag):
if flag == LayerIndexFlags.LastLayer or flag == LayerIndexFlags.SingleLayer:
dZ = delta_in
else:
#dZ = delta_in * self.activator.backward(self.a)
dZ = self.activator.backward(self.a, delta_in)
delta_out = np.dot(self.weights.T, dZ)
self.dW = np.dot(dZ, self.x.T)
self.dB = np.sum(dZ, axis=1, keepdims=True)
if len(self.input_shape) > 2:
return delta_out.reshape(self.input_shape)
else:
return delta_out
def update(self, learning_rate):
self.weights = self.weights - learning_rate * self.dW
self.bias = self.bias - learning_rate * self.dB
def save_parameters(self, name):
np.save(name+"_w", self.weights)
np.save(name+"_b", self.bias)
def load_parameters(self, name):
self.weights = np.load(name+"_w.npy")
self.bias = np.load(name+"_b.npy")
@@ -0,0 +1,24 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
from enum import Enum
class LayerTypes(Enum):
FC = 0 # full connection
CONV = 1 # convalution
POOL = 2 # pooling
class CLayer(object):
def __init__(self, layer_type):
self.layer_type = layer_type
def update(self, lr):
return
class LayerIndexFlags(Enum):
SingleLayer = 0
FirstLayer = 1
LastLayer = -1
MiddleLayer = 2
@@ -0,0 +1,100 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
import numpy as np
from enum import Enum
from Layer import *
from FCLayer import *
class CNet(object):
def __init__(self, optimizer_type, loss_function):
self.optimizer_type = optimizer_type
self.loss_function = loss_function
self.layer_list = []
self.layer_name = []
self.output = np.zeros((1,1))
self.layer_count = 0
def add_layer(self, layer, name=""):
self.layer_list.append(layer)
self.layer_name.append(name)
self.layer_count += 1
def forward(self, input_array):
input = input_array
for i in range(self.layer_count):
layer = self.layer_list[i]
output = layer.forward(input)
input = output
self.output = output
return self.output
def backward(self, X, Y):
delta_in = self.output - Y
for i in range(self.layer_count-1,-1,-1):
layer = self.layer_list[i]
flag = self.get_layer_index(i)
delta_out = layer.backward(delta_in, flag)
# move back to previous layer
delta_in = delta_out
def update(self, learning_rate):
for i in range(self.layer_count-1,-1,-1):
layer = self.layer_list[i]
layer.update(learning_rate)
def get_layer_index(self, idx):
if self.layer_count == 1:
return LayerIndexFlags.SingleLayer
else:
if idx == self.layer_count - 1:
return LayerIndexFlags.LastLayer
elif idx == 0:
return LayerIndexFlags.FirstLayer
else:
return LayerIndexFlags.MiddleLayer
def train(self, X, Y, max_iteration, learning_rate):
if X.ndim == 2:
num_feature = X.shape[0]
num_example = X.shape[1]
elif X.ndim == 4:
num_example = X.shape[0]
num_feature = X.shape[1] * X.shape[2] * X.shape[3]
num_output = Y.shape[0]
# num_example = 2000
for i in range(max_iteration):
print(i)
for j in range(num_example):
if j%10==0:
print(i, ":", j)
if X.ndim == 2:
x = X[:,j].reshape(num_feature, 1)
elif X.ndim == 4:
x = X[j] # x.ndim == 3
y = Y[:,j].reshape(num_output, 1)
self.forward(x)
self.backward(x, y)
self.update(learning_rate)
def inference(self, X):
self.forward(X)
return self.output
def save_parameters(self):
for i in range(self.layer_count):
layer = self.layer_list[i]
name = self.layer_name[i]
layer.save_parameters(name)
def load_parameters(self):
for i in range(self.layer_count):
layer = self.layer_list[i]
name = self.layer_name[i]
layer.load_parameters(name)
@@ -21,17 +21,30 @@
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="Activations.py" />
<Compile Include="DataReader.py" />
<Compile Include="GDOptimizer.py" />
<Compile Include="Level0_Base.py" />
<Compile Include="Level2\Activators.py" />
<Compile Include="Level2\DataReader.py" />
<Compile Include="Level2\FCLayer.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Level2\GDOptimizer.py" />
<Compile Include="Level1_ThreeLayerNet.py" />
<Compile Include="Level0_TwoLayerNet.py" />
<Compile Include="LossFunction.py" />
<Compile Include="Level2\Layer.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Level2\LossFunction.py" />
<Compile Include="Level2\Net.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="MnistData.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Parameters.py" />
<Compile Include="WeightsBias.py" />
<Compile Include="Level2\Parameters.py" />
<Compile Include="Level2\WeightsBias.py" />
</ItemGroup>
<ItemGroup>
<Folder Include="Level2\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in