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

In [2]:
#定義常用函數
def sigmoid(z):
    """The sigmoid function."""
    return 1.0 / (1.0 + np.exp(-z))

def sigmoid_prime(z):
    """Derivative of the sigmoid function."""
    return sigmoid(z) * (1 - sigmoid(z))

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

def allShape(list):
    for arr in list:
        print(arr.shape)

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 = sigmoid(s)
            
            xs.append(x)
            ss.append(s)
        return (xs, ss)
    
    def backpropagationWith(self, xs, ss, y):
        
        delta_out = []
        delta_in = xs[-1] - y #cross entropy loss
        
        dbs = [delta_in]
        dws = [np.dot(np.transpose(xs[-1]), delta_in)]
        
        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 * sigmoid_prime(ss[idx])
            db = delta_in
            dw = np.dot(np.transpose(xs[idx - 1]), delta_in)
            
            dbs.insert(0, db)
            dws.insert(0, dw)
        
        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):
    if x[0, 0] > 0.5 and x[0, 1] < 0.5:
        return 1
    if x[0, 0] < 0.5 and x[0, 1] > 0.5:
        return 1
    return 0
'''
def judgeFunction(x):
    return float( np.sum(x) < 0.5 or np.sum(x) > 1.5)


total_test = 10000000
to_print = 100000
acc = 0

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


001 > 0.75077
002 > 0.75162
003 > 0.75112
004 > 0.74739
005 > 0.74971
006 > 0.75099
007 > 0.74741
008 > 0.74872
009 > 0.74995
010 > 0.7513
011 > 0.75185
012 > 0.75079
013 > 0.7487
014 > 0.74998
015 > 0.75167
016 > 0.74833
017 > 0.74753
018 > 0.91225
019 > 0.99317
020 > 0.99346
021 > 0.99464
022 > 0.99423
023 > 0.99455
024 > 0.99495
025 > 0.99498
026 > 0.99481
027 > 0.99474
028 > 0.99492
029 > 0.99479
030 > 0.9952

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 0x103e61518>

In [8]:
myNN.showbiasesweights()


(1, 3)
(1, 1)
[array([[  5.54519715,  -5.02415814, -16.36584103]]), array([[-17.242119]])]
(2, 3)
(3, 1)
[array([[-12.62830861,  -4.66372777,  10.43033774],
       [-12.81451868,   0.35409882,  10.40502463]]), array([[ 54.93710928],
       [ 54.45194523],
       [ 54.87014418]])]

In [ ]: