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

In [2]:
import shapely
from shapely.geometry import Polygon
from shapely.geometry import Point
from shapely.geometry import MultiPoint

In [3]:
polygon_coords = [(0.5,0.5),(1,2.5),(2.5,4),(3,3),(2.5,2.5),(3.5,1),(2.5,0),(2,2),(1.5,1),(0.5,0.5)]
polygon = Polygon(polygon_coords)

def get_true_label(point):
    label = 0
    if Point(point).within(polygon):
        label = 1
    return label

In [4]:
def generate_grid_points(count_per_side):
    size_x = 4
    size_y = 4
    xs = np.linspace(0,size_x, count_per_side)
    ys = np.linspace(0,size_y, count_per_side)
    xv, yv = np.meshgrid(xs, ys)
    points = np.array(np.zeros(shape=(3,xv.flatten().shape[0]), dtype=float))
    points[0] = xv.flatten()
    points[1] = yv.flatten()
    return points

def get_grid_points_with_labels(count_per_side, label_func):
    points = generate_grid_points(count_per_side)
    labels = []
    for i in range(len(points[0])):
        point = np.array([points[0][i], points[1][i]])
        label = label_func(point)
        points[2,i] = label
        labels.append(label)

    #points[2] = np.array(labels)
    return points

In [5]:
def step_func(x):
    if x <= 0:
        return 0
    else:
        return 1

def identity(x):
    return x

def perceptron(x, w, b):
    return step_func(x*w + b)

In [83]:
class Neuron:
    def __init__(self, activation_func, input_dims):
        self.act_func = activation_func
        self.in_dims = input_dims
        self.w = np.random.rand(input_dims,)
        self.b = np.random.randn()
    
    def set_to_AND(self):
        self.w = np.ones((self.in_dims,), dtype=np.float)
        self.b = -self.in_dims + 0.5
    
    def set_to_OR(self):
        self.w = np.ones((self.in_dims,), dtype=np.float)
        self.b = 0
        
    def out(self, x):
        x = x.flatten()
        self.w = self.w.flatten()
        return self.act_func(np.dot(x,self.w) + self.b)
    
    def plot(self):
        points = get_grid_points_with_labels(100, self.out)
        plt.scatter(points[0],points[1],c=points[2])
        plt.show()
    
class Layer:
    def __init__(self, no_neurons=None, activation_func=None, input_dims=None):
        self.neurons = []
        if no_neurons is not None and activation_func is not None and input_dims is not None:
            self.neurons = [Neuron(activation_func, input_dims) for i in range(no_neurons)]
        else:
            print("Created an empty layer. Add modules instead of neurons by add_module().")
    
    def add_module(self, network):
        self.neurons.append(network)
    
    def out(self, x):
        return np.array([n.out(x) for n in self.neurons])


class Network:
    def __init__(self):
        self.layers = []
        self.in_dims = 0
    
    def add_layer(self, layer):
        new_layer_in_dim = layer.neurons[0].in_dims
        
        if len(self.layers) > 0 and len(self.layers[-1].neurons) != new_layer_in_dim:
            last_layer_out_dim = len(self.layers[-1].neurons)
            print("Provided layer has neurons with input dim", new_layer_in_dim, 
                  "while last layer has",last_layer_out_dim,"neurons = output dimensions.\n",
                 "Provided layer will not be added!")
        else:
            self.layers.append(layer)
            if len(self.layers) == 1:
                self.in_dims = layer.neurons[0].in_dims
    
    def out(self, x):
        layer_output = x
        for layer in self.layers:
            layer_output = layer.out(layer_output)
        return layer_output
    
    def list_layers(self):
        for layer in self.layers:
            print(len(layer.neurons), "neurons")
    
    def plot(self, plot_neurons=True):
        if plot_neurons:
            for l in range(len(self.layers)):
                for n in range(len(self.layers[l].neurons)):
                    print("Layer",l,"neuron",n,":")
                    neuron = self.layers[l].neurons[n]
                    try:
                        neuron.plot()
                    except Exception:
                        print("Has",neuron.in_dims,"input dimensions. Cannot plot.")
                
        print("Output of the whole network:")        
        points = get_grid_points_with_labels(100, self.out)
        plt.scatter(points[0],points[1],c=points[2])
        plt.show()

In [63]:
net = Network()
net.add_layer(Layer(no_neurons=4, activation_func=step_func, input_dims=2))
net.add_layer(Layer(no_neurons=1, activation_func=step_func, input_dims=4))
net.list_layers()


4 neurons
1 neurons

In [66]:
n1 = net.layers[0].neurons[0]
n1.b = -0.25
n1.w = np.array([-0.5,1])

n2 = net.layers[0].neurons[1]
n2.b = -1.5
n2.w = np.array([4,-1])

n3 = net.layers[0].neurons[2]
n3.b = 2
n3.w = np.array([-2,1])

n4 = net.layers[0].neurons[3]
n4.b = 3
n4.w = np.array([-0.5,-1])

nAND = net.layers[1].neurons[0]
nAND.set_to_AND()
net.plot()


Layer 0 neuron 0 :
Layer 0 neuron 1 :
Layer 0 neuron 2 :
Layer 0 neuron 3 :
Layer 1 neuron 0 :
Has 4 input dimensions. Cannot plot.
Output of the whole network:

In [67]:
net2 = Network()
net2.add_layer(Layer(no_neurons=4, activation_func=step_func, input_dims=2))
net2.add_layer(Layer(no_neurons=1, activation_func=step_func, input_dims=4))
net2.list_layers()


4 neurons
1 neurons

In [68]:
n1 = net2.layers[0].neurons[0]
n1.b = -3
n1.w = np.array([0.5,1])

n2 = net2.layers[0].neurons[1]
n2.b = 1.5
n2.w = np.array([1,-1])

n3 = net2.layers[0].neurons[2]
n3.b = 9
n3.w = np.array([-2,-1])

n4 = net2.layers[0].neurons[3]
n4.b = 0
n4.w = np.array([-1,1])

nAND = net2.layers[1].neurons[0]
nAND.set_to_AND()
net2.plot()


Layer 0 neuron 0 :
Layer 0 neuron 1 :
Layer 0 neuron 2 :
Layer 0 neuron 3 :
Layer 1 neuron 0 :
Has 4 input dimensions. Cannot plot.
Output of the whole network:

In [69]:
net3 = Network()
net3.add_layer(Layer(no_neurons=4, activation_func=step_func, input_dims=2))
net3.add_layer(Layer(no_neurons=1, activation_func=step_func, input_dims=4))
net3.list_layers()


4 neurons
1 neurons

In [70]:
n1 = net3.layers[0].neurons[0]
n1.b = 0
n1.w = np.array([1,-1])

n2 = net3.layers[0].neurons[1]
n2.b = -10
n2.w = np.array([4,1])

n3 = net3.layers[0].neurons[2]
n3.b = 2.5
n3.w = np.array([-1,1])

n4 = net3.layers[0].neurons[3]
n4.b = 6.25
n4.w = np.array([-1.5,-1])

nAND = net3.layers[1].neurons[0]
nAND.set_to_AND()
net3.plot()


Layer 0 neuron 0 :
Layer 0 neuron 1 :
Layer 0 neuron 2 :
Layer 0 neuron 3 :
Layer 1 neuron 0 :
Has 4 input dimensions. Cannot plot.
Output of the whole network:

In [84]:
final_net = Network()
network_layer = Layer()
network_layer.add_module(net)
network_layer.add_module(net2)
network_layer.add_module(net3)

final_net.add_layer(network_layer)
final_net.add_layer(Layer(no_neurons=1, activation_func=step_func, input_dims=3))

nOR = final_net.layers[1].neurons[0]
nOR.set_to_OR()
final_net.plot(plot_neurons=False)


Created an empty layer. Add modules instead of neurons by add_module().
Output of the whole network:

In [ ]:


In [ ]: