``````

In [1]:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import shapely
from shapely.geometry import Polygon
from shapely.geometry import Point
from shapely.geometry import MultiPoint

``````
``````

In [71]:

from math import ceil, floor, sin, cos, sqrt
from enum import Enum
class Dataset(Enum):
AND_GRID = 0 #Basic AND function
BASIC_GRID = 1 #Basic grid 4x4 with 8xO and 8xX
BOOL_FUNC = 2 #Boolean function of 5 variables
POLYGON = 3 #Polygon shape dividing 2D grid to 2 classes
MULTI_CLASS = 4 #Function dividing 2D grid to 8 classes

``````
``````

In [107]:

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_top_left_corner(point):
#Returns top left coords of a square the point belongs to
top_left = []
top_left.append(floor(point[0]))
top_left.append(ceil(point[1]))

def get_multi_class_label(point):
top_left_corner = get_top_left_corner(point)
x = top_left_corner[0]
y = top_left_corner[1]
label = x
if y == 1 or y == 3:
label = x + 4
return label

def get_true_label(point, dataset, center_dataset=True):
if center_dataset:
point[0] += 2
point[1] += 2

label = 0
if dataset == Dataset.POLYGON:
if Point(point).within(polygon):
label = 1
elif dataset == Dataset.AND_GRID:
if point[0] >= 2 and point[1] >= 2:
label = 1

elif dataset == Dataset.BASIC_GRID:
l = get_multi_class_label(point)
if l in [0,1,3,5]:
label = 1

else:
print("Not implemented.")

if label == 0:
label = -1

return label*1.0

def step_func(x):
if x <= 0:
return -1.0
else:
return 1.0

``````
``````

In [73]:

def generate_grid_points(count_per_side):
size_x = 4
size_y = 4
start_x = -2
start_y = -2
xs = np.linspace(start_x,start_x+size_x, count_per_side)
ys = np.linspace(start_y,start_y+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)

return points

def get_dataset_grid_points_with_labels(count_per_side, dataset):
points = generate_grid_points(count_per_side)
labels = []
for i in range(len(points[0])):
point = [points[0][i], points[1][i]]
label = get_true_label(point, dataset)
points[2,i] = label
labels.append(label)

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

def plot_dataset(dataset):
if dataset in [Dataset.POLYGON, Dataset.MULTI_CLASS, Dataset.BASIC_GRID, Dataset.AND_GRID]:
points = get_dataset_grid_points_with_labels(100, dataset)
plt.scatter(points[0],points[1],c=points[2])
plt.show()
else:
print("Not implemented yet.")

``````
``````

In [114]:

class Perceptron:
def __init__(self, learn_rate):
self.input_dims = 2
#self.w = (-1)*np.random.rand(self.input_dims,)
self.w = np.zeros((self.input_dims,), dtype=float)
self.b = 0
self.learn_rate = learn_rate

def out(self, x):
x = x.flatten()
return step_func(np.dot(x,self.w) + self.b)

def update_w(self, xs, ys, batch_size):
assert len(xs) == len(ys)
print("Before training: ")
self.plot()
print("Started training with",len(xs),"examples and batch size =",batch_size)

dw = np.zeros((self.input_dims,), dtype=float)
i = 0

for x,y in zip(xs,ys):
if i == batch_size:
i = 0
self.w += dw
dw = np.zeros((self.input_dims,), dtype=float)

dw += self.learn_rate*(y - self.out(x))*x
i+=1

self.w += dw
print("After training: ")
self.plot()

def plot(self):
print("W =", self.w)
print("b =", self.b)
points = get_grid_points_with_labels(100, self.out)
plt.scatter(points[0],points[1],c=points[2])
plt.show()

``````
``````

In [119]:

def get_train_data(dataset, number_of_points, plot_data=True):
print("Getting training data for dataset", dataset,":")
if plot_data:
plot_dataset(dataset)
points = get_dataset_grid_points_with_labels(floor(sqrt(number_of_points*1.0)), dataset)
points = points.T
np.random.seed(0)
np.random.shuffle(points)
xs = points[:,0:2]
ys = points[:,2]
return xs, ys

``````
``````

In [126]:

xs, ys = get_train_data(Dataset.AND_GRID, 10000)
p = Perceptron(learn_rate=0.1)
p.update_w(xs=xs, ys=ys, batch_size=100)

``````
``````

Getting training data for dataset Dataset.AND_GRID :

Before training:
W = [ 0.  0.]
b = 0

Started training with 10000 examples and batch size = 100
After training:
W = [ 0.72727273  4.50909091]
b = 0

``````
``````

In [117]:

plot_dataset(Dataset.BASIC_GRID)

``````
``````

``````
``````

In [125]:

xs, ys = get_train_data(Dataset.BASIC_GRID, 10000, plot_data=False)
p = Perceptron(learn_rate=0.1)
p.update_w(xs=xs, ys=ys, batch_size=100)

``````
``````

Getting training data for dataset Dataset.BASIC_GRID :
Before training:
W = [ 0.  0.]
b = 0

Started training with 10000 examples and batch size = 100
After training:
W = [-4.81212121  1.82222222]
b = 0

``````
``````

In [129]:

xs, ys = get_train_data(Dataset.POLYGON, 10000, plot_data=True)
p = Perceptron(learn_rate=0.1)
p.update_w(xs=xs, ys=ys, batch_size=1)

``````
``````

Getting training data for dataset Dataset.POLYGON :

Before training:
W = [ 0.  0.]
b = 0

Started training with 10000 examples and batch size = 1
After training:
W = [ 0.0040404  -0.39191919]
b = 0

``````
``````

In [ ]:

``````