In [1]:
import numpy as np
import matplotlib.pyplot as plt

In [2]:
#Debug
def allShape(list):
    for arr in list:
        print(arr.shape)

#定義常用函數
def sigmoid_cross_entropy(y_hat, y):
    return y_hat - y

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

def sigmoid_prime(x):
    return sigmoid(x) * (1 - sigmoid(x))

def ReLU_square(y_hat, y):
    return 2 * (y_hat - y) * ReLU_prime(y_hat)

def ReLU(x):
    return np.maximum(x,np.zeros(x.shape))

def ReLU_prime(x):
    return (x > 0).astype(float)

In [3]:
#學習速率
learning_rate = 0.01

#選用函數

def loss_prime(y_hat, y):
    return sigmoid_cross_entropy(y_hat, y)

def connect(x):
    return sigmoid(x)

def connect_prime(x):
    return sigmoid_prime(x)
'''
def loss_prime(y_hat, y):
    return ReLU_square(y_hat, y)

def connect(x):
    return ReLU(x)

def connect_prime(x):
    return ReLU_prime(x)
'''


Out[3]:
'\ndef loss_prime(y_hat, y):\n    return ReLU_square(y_hat, y)\n\ndef connect(x):\n    return ReLU(x)\n\ndef connect_prime(x):\n    return ReLU_prime(x)\n'

In [4]:
class Network(object):
    
    def __init__(self, sizes):
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.zeros((1, y)) for y in sizes[1:]]
        self.weights = [np.random.rand(x, y) - 0.5 for x, y in zip(sizes[:-1], sizes[1:])]
    
    def feedforward(self, x):
        (xs, _) = self.feedforwardRecord(x)
        return xs[-1]
    
    def feedforwardRecord(self, x):
        xs = [np.array(x)]
        ss = [np.array(x)]
        
        for b, w in zip(self.biases, self.weights):
            s = np.dot(x, w) + b
            x = connect(s)
            
            xs.append(x)
            ss.append(s)
        return (xs, ss)
    
    def backpropagationWith(self, xs, ss, y):
        
        delta_out = []
        delta_in = loss_prime(xs[-1], y)
        
        dbs = [np.mean(delta_in, axis=0)]
        dws = [np.mean(np.dot(np.transpose(xs[-1]), delta_in), axis=0)]
        
        for idx in range(self.num_layers - 2, 0, -1):
            
            delta_out = np.dot(delta_in, np.transpose(self.weights[idx]))
            delta_in = delta_out * connect_prime(ss[idx])
            db = delta_in
            dw = np.dot(np.transpose(xs[idx - 1]), delta_in)
            
            dbs.insert(0, np.mean(db, axis=0))
            dws.insert(0, np.mean(dw, axis=0))
        
        return (dbs, dws)
    
    def updateWith(self, dbs, dws):
        
        new_b = []
        for b, db in zip(self.biases, dbs):
            new_b.append(b - learning_rate * db)
        
        new_w = []
        for w, dw in zip(self.weights, dws):
            new_w.append(w - learning_rate * dw)
        
        self.biases = new_b
        self.weights = new_w
    
    def showbiasesweights(self):
        allShape(self.biases)
        print(self.biases)
        allShape(self.weights)
        print(self.weights)

In [5]:
myNN = Network([2, 3, 1])

In [6]:
def judgeFunction(x):
    #必須補維度 將來計算 才能正常 或許是 右乘相關
    return np.logical_or(np.sum(x, axis=1) < 0.5, np.sum(x, axis=1) > 1.5).astype(float)[:,np.newaxis]

total_test = 10000000
to_print = 10000
batch = 50
acc = 0

for i in range(total_test):
    x = np.random.rand(batch, 2)
    ys = judgeFunction(x)
    (xs, ss) = myNN.feedforwardRecord(x)
    y_hats = xs[-1]
    
    (dbs, dws) = myNN.backpropagationWith(xs, ss, ys)
    myNN.updateWith(dbs, dws)
    
    acc_batch = 0
    for y_hat, y in zip(y_hats, ys):
        acc_batch += float(y == float(y_hat > 0.5))
    
    acc += acc_batch / batch
    if (i + 1) % to_print == 0:
        score = acc / float(to_print)
        process = int((i + 1) / to_print)
        print('{num:03d}'.format(num = process), ">", '{num:.6f}'.format(num = score))
        acc = 0
        if score > 0.99:
            break


001 > 0.750626
002 > 0.750468
003 > 0.750580
004 > 0.815154
005 > 0.979348
006 > 0.986292
007 > 0.987898
008 > 0.988566
009 > 0.989202
010 > 0.989998
011 > 0.990006

In [7]:
def colorFrom(y):
    if y > 0.5:
        return 'red'
    else:
        return 'blue'
    
plt.figure(figsize=(9, 9))
x0s = np.linspace(0, 1, 20, dtype = np.double)
x1s = np.linspace(0, 1, 20, dtype = np.double)

fig = plt.figure()
ax = fig.add_subplot(1,2,1)
for x0 in x0s:
    for x1 in x1s:
        y = myNN.feedforward(np.array([[x0, x1]]))
        ax.scatter(x0, x1, c = colorFrom(y), s = 30, alpha = 0.5, marker = 's')
        
ax = fig.add_subplot(1,2,2)
for x0 in x0s:
    for x1 in x1s:
        y = judgeFunction(np.array([[x0, x1]]))
        ax.scatter(x0, x1, c = colorFrom(y), s = 30, alpha = 0.5, marker = 's')

plt.show()


<matplotlib.figure.Figure at 0x10edb2438>

In [8]:
myNN.showbiasesweights()


(1, 3)
(1, 1)
[array([[-9.83967774,  0.92209286,  2.65448711]]), array([[-10.05268229]])]
(2, 3)
(3, 1)
[array([[  4.48965809, -10.40212677, -11.40832605],
       [  4.6962896 , -11.06174162, -12.0592315 ]]), array([[ 198.01326206],
       [ 198.27094398],
       [ 198.6004495 ]])]