How to implement Perceptron in Python? - python

I am trying to follow the book by Daume
http://ciml.info/dl/v0_99/ciml-v0_99-ch04.pdf (page 43).
To fit a model for vanilla perceptron in python using numpy and without
using sciki-learn library.
The algorithm is given in the book
How can we implement this model in practice?
So far I have learned how to read the data and labels:
def read_data(infile):
data = np.loadtxt(infile)
X = data[:,:-1]
Y = data[:,-1]
return X, Y
The help will be appreciated!!

One way I figured out is this:
(Better ideas are always welcome!!)
#!python
# -*- coding: utf-8 -*-#
"""
Perceptron Algorithm.
#author: Bhishan Poudel
#date: Oct 31, 2017
"""
# Imports
import numpy as np
import matplotlib.pyplot as plt
from numpy.linalg import norm
import os, shutil
np.random.seed(100)
def read_data(infile):
data = np.loadtxt(infile)
X = data[:,:-1]
Y = data[:,-1]
return X, Y
def plot_boundary(X,Y,w,epoch):
try:
plt.style.use('seaborn-darkgrid')
# plt.style.use('ggplot')
#plt.style.available
except:
pass
# Get data for two classes
idxN = np.where(np.array(Y)==-1)
idxP = np.where(np.array(Y)==1)
XN = X[idxN]
XP = X[idxP]
# plot two classes
plt.scatter(XN[:,0],XN[:,1],c='b', marker='_', label="Negative class")
plt.scatter(XP[:,0],XP[:,1],c='r', marker='+', label="Positive class")
# plt.plot(XN[:,0],XN[:,1],'b_', markersize=8, label="Negative class")
# plt.plot(XP[:,0],XP[:,1],'r+', markersize=8, label="Positive class")
plt.title("Perceptron Algorithm iteration: {}".format(epoch))
# plot decision boundary orthogonal to w
# w is w2,w1, w0 last term is bias.
if len(w) == 3:
a = -w[0] / w[1]
b = -w[0] / w[2]
xx = [ 0, a]
yy = [b, 0]
plt.plot(xx,yy,'--g',label='Decision Boundary')
if len(w) == 2:
x2=[ w[0], w[1], -w[1], w[0]]
x3=[ w[0], w[1], w[1], -w[0]]
x2x3 =np.array([x2,x3])
XX,YY,U,V = list(zip(*x2x3))
ax = plt.gca()
ax.quiver(XX,YY,U,V,scale=1, color='g')
# Add labels
plt.xlabel('X')
plt.ylabel('Y')
# limits
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
plt.xlim(x_min,x_max)
plt.ylim(y_min,y_max)
# lines from origin
plt.axhline(y=0, color='k', linestyle='--',alpha=0.2)
plt.axvline(x=0, color='k', linestyle='--',alpha=0.2)
plt.grid(True)
plt.legend(loc=1)
plt.show()
# Always clost the plot
plt.close()
def predict(X,w):
return np.sign(np.dot(X, w))
def plot_contour(X,Y,w,mesh_stepsize):
try:
plt.style.use('seaborn-darkgrid')
# plt.style.use('ggplot')
#plt.style.available
except:
pass
# Get data for two classes
idxN = np.where(np.array(Y)==-1)
idxP = np.where(np.array(Y)==1)
XN = X[idxN]
XP = X[idxP]
# plot two classes with + and - sign
fig, ax = plt.subplots()
ax.set_title('Perceptron Algorithm')
plt.xlabel("X")
plt.ylabel("Y")
plt.plot(XN[:,0],XN[:,1],'b_', markersize=8, label="Negative class")
plt.plot(XP[:,0],XP[:,1],'y+', markersize=8, label="Positive class")
plt.legend()
# create a mesh for contour plot
# We first make a meshgrid (rectangle full of pts) from xmin to xmax and ymin to ymax.
# We then predict the label for each grid point and color it.
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
# Get 2D array for grid axes xx and yy (shape = 700, 1000)
# xx has 700 rows.
# xx[0] has 1000 values.
xx, yy = np.meshgrid(np.arange(x_min, x_max, mesh_stepsize),
np.arange(y_min, y_max, mesh_stepsize))
# Get 1d array for x and y axes
xxr = xx.ravel() # shape (700000,)
yyr = yy.ravel() # shape (700000,)
# ones vector
# ones = np.ones(xxr.shape[0]) # shape (700000,)
ones = np.ones(len(xxr)) # shape (700000,)
# Predict the score
Xvals = np.c_[ones, xxr, yyr]
scores = predict(Xvals, w)
# Plot contour plot
scores = scores.reshape(xx.shape)
ax.contourf(xx, yy, scores, cmap=plt.cm.Paired)
# print("xx.shape = {}".format(xx.shape)) # (700, 1000)
# print("scores.shape = {}".format(scores.shape)) # (700, 1000)
# print("scores[0].shape = {}".format(scores[0].shape)) # (1000,)
# show the plot
plt.savefig("Perceptron.png")
plt.show()
plt.close()
def perceptron_sgd(X, Y,epochs):
"""
X: data matrix without bias.
Y: target
"""
# add bias to X's first column
ones = np.ones(X.shape[0]).reshape(X.shape[0],1)
X1 = np.append(ones, X, axis=1)
w = np.zeros(X1.shape[1])
final_iter = epochs
for epoch in range(epochs):
print("\n")
print("epoch: {} {}".format(epoch, '-'*30))
misclassified = 0
for i, x in enumerate(X1):
y = Y[i]
h = np.dot(x, w)*y
if h <= 0:
w = w + x*y
misclassified += 1
print('misclassified? yes w: {} '.format(w,i))
else:
print('misclassified? no w: {}'.format(w))
pass
if misclassified == 0:
final_iter = epoch
break
return w, final_iter
def gen_lin_separable_data(data, data_tr, data_ts,data_size):
mean1 = np.array([0, 2])
mean2 = np.array([2, 0])
cov = np.array([[0.8, 0.6], [0.6, 0.8]])
X1 = np.random.multivariate_normal(mean1, cov, size=int(data_size/2))
y1 = np.ones(len(X1))
X2 = np.random.multivariate_normal(mean2, cov, size=int(data_size/2))
y2 = np.ones(len(X2)) * -1
with open(data,'w') as fo, \
open(data_tr,'w') as fo1, \
open(data_ts,'w') as fo2:
for i in range( len(X1)):
line = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X1[i][0], X1[i][1], y1[i])
line2 = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X2[i][0], X2[i][1], y2[i])
fo.write(line)
fo.write(line2)
for i in range( len(X1) - 20):
line = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X1[i][0], X1[i][1], y1[i])
line2 = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X2[i][0], X2[i][1], y2[i])
fo1.write(line)
fo1.write(line2)
for i in range((len(X1) - 20), len(X1) ):
line = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X1[i][0], X1[i][1], y1[i])
line2 = '{:5.2f} {:5.2f} {:5.0f} \n'.format(X2[i][0], X2[i][1], y2[i])
fo2.write(line)
fo2.write(line2)
def main():
"""Run main function."""
# generate linearly separable data
data = 'data.txt'
data_tr = 'data_train.txt'
data_ts = 'data_test.txt'
data_size = 200
gen_lin_separable_data(data, data_tr, data_ts,data_size)
# read data
epochs = 20
X_train, Y_train = read_data(data_tr)
X_test, Y_test = read_data(data_ts)
# fit perceptron
w, final_iter = perceptron_sgd(X_train,Y_train,epochs)
print('w = ', w)
plot_boundary(X_test,Y_test,w,final_iter)
# contour plot
mesh_stepsize = 0.01
plot_contour(X_test,Y_test,w,mesh_stepsize)
if __name__ == "__main__":
main()
The decision boundary looks like this:

There is an implementation of perceptron in my recent repo: NP_ML. The example result is:

Related

Problem with a perceptron. ValueError: operands could not be broadcast together with shapes (20,2) (20,)

I have a Perceptron code (Raschka). We got an exercise to rebuilt the code. I've tried to generate 2 gaussian distributions with the linear separability (that is the task). Instead of basic irises. I've read some threads here with the same error but unfortunately it doesn't seem like the same thing.
Here I have my perceptron model.
class Perceptron(object):
def __init__(self, eta = 0.0001, n_iter = 20, random_state = 1):
self.eta = eta
self.n_iter = n_iter
self.random_state = random_state
def fit(self, X, y):
rgen = np.random.RandomState(self.random_state)
self.w_ = rgen.normal(loc = 0.0, scale = 0.1, size = 1 + X.shape[2])
self.errors_ = []
for _ in range(self.n_iter):
errors = 0
for xi, target in zip(X, y):
update = self.eta * (target - self.predict(xi))
self.w_[1:] += update * xi
self.w_[0] += update
errors += int(update != 0.0 )
self.errors_.append(errors)
return self
def net_input(self, X):
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
return np.where(self.net_input(X) != 0.0 , 1, -1)
However here I bump into the problem like matrices incompatibility:
I guess this is because of my wrong generated distributions:
import numpy as np
import matplotlib.pyplot as plt
# creating 2 gaussian distributions if x axis and y axis
x1 = 1 + 1 * np.random.randn(20,2)
x2 = 5.5 + 1 * np.random.randn(20,2)
y = np.array([x1, x2]) # target values
y = np.where(y == x1, -1, 1) # giving a class label
y.resize(40,2)
X = np.array([x1, x2]) # parameters
X.resize(40,2)
plt.scatter(x1[:, 0], x1[:, 1], color = 'blue', label = 'класс 1', marker = 'x')
plt.scatter(x2[:, 0], x2[:, 1], color = 'red', label = 'класс 2', marker = 'o')
plt.xlabel('распределение по оси x')
plt.ylabel('распределение по оси y')
plt.legend(loc = 'upper left')
plt.show()
I've played with transposing matrices in different ways but it has no sense. I've also checked my X and y shapes. It is the same: (2, 20, 2) and (2, 20, 2). Both matrices mutually multiply. Dtypes are int32 (y), float64 (X).

Reconstructing polynomials from scipy.interpolate.RectBivariateSpline

I have fitted a 2-D cubic spline using scipy.interpolate.RectBivariateSpline. I would like to access/reconstruct the underlying polynomials within each rectangular cell. How can I do this? My code so far is written below.
I have been able to get the knot points and the coefficients with get_knots() and get_coeffs() so it should be possible to build the polynomials, but I do not know the form of the polynomials that the coefficients correspond to. I tried looking at the SciPy source code but I could not locate the underlying dfitpack.regrid_smth function.
A code demonstrating the fitting:
import numpy as np
from scipy.interpolate import RectBivariateSpline
# Evaluate a demonstration function Z(x, y) = sin(sin(x * y)) on a mesh
# of points.
x0 = -1.0
x1 = 1.0
n_x = 11
x = np.linspace(x0, x1, num = n_x)
y0 = -2.0
y1 = 2.0
n_y = 21
y = np.linspace(y0, y1, num = n_y)
X, Y = np.meshgrid(x, y, indexing = 'ij')
Z = np.sin(np.sin(X * Y))
# Fit the sampled function using SciPy's RectBivariateSpline.
order_spline = 3
smoothing = 0.0
spline_fit_func = RectBivariateSpline(x, y, Z,
kx = order_spline, ky = order_spline, s = smoothing)
And to plot it:
import matplotlib.pyplot as plt
# Make axes.
fig, ax_arr = plt.subplots(1, 2, sharex = True, sharey = True, figsize = (12.0, 8.0))
# Plot the input function.
ax = ax_arr[0]
ax.set_aspect(1.0)
d_x = x[1] - x[0]
x_edges = np.zeros(n_x + 1)
x_edges[:-1] = x - (d_x / 2.0)
x_edges[-1] = x[-1] + (d_x / 2.0)
d_y = y[1] - y[0]
y_edges = np.zeros(n_y + 1)
y_edges[:-1] = y - (d_y / 2.0)
y_edges[-1] = y[-1] + (d_y / 2.0)
ax.pcolormesh(x_edges, y_edges, Z.T)
ax.set_title('Input function')
# Plot the fitted function.
ax = ax_arr[1]
ax.set_aspect(1.0)
n_x_span = n_x * 10
x_span_edges = np.linspace(x0, x1, num = n_x_span)
x_span_centres = (x_span_edges[1:] + x_span_edges[:-1]) / 2.0
#
n_y_span = n_y * 10
y_span_edges = np.linspace(y0, y1, num = n_y_span)
y_span_centres = (y_span_edges[1:] + y_span_edges[:-1]) / 2.0
Z_fit = spline_fit_func(x_span_centres, y_span_centres)
ax.pcolormesh(x_span_edges, y_span_edges, Z_fit.T)
x_knot, y_knot = spline_fit_func.get_knots()
X_knot, Y_knot = np.meshgrid(x_knot, y_knot)
# Plot the knots.
ax.scatter(X_knot, Y_knot, s = 1, c = 'r')
ax.set_title('Fitted function and knots')
plt.show()

Phase portrait of Verhulst equation

I was trying to an example of the book -"Dynamical Systems with Applications using Python" and I was asked to plot the phase portrait of Verhulst equation, then I came across this post: How to plot a phase portrait of Verhulst equation with SciPy (or SymPy) and Matplotlib?
I'm getting the same plot as the user on the previous post. Whenever, I try to use the accepted solution I get a "division by zero" error. Why doesn't the accepted solution in How to plot a phase portrait of Verhulst equation with SciPy (or SymPy) and Matplotlib? works?
Thank you very much for you help!
Edit:
Using the code from the previous post and the correction given by #Lutz Lehmann
beta, delta, gamma = 1, 2, 1
b,d,c = 1,2,1
C1 = gamma*c-delta*d
C2 = gamma*b-beta*d
C3 = beta*c-delta*b
def verhulst(X, t=0):
return np.array([beta*X[0] - delta*X[0]**2 -gamma*X[0]*X[1],
b*X[1] - d*X[1]**2 -c*X[0]*X[1]])
X_O = np.array([0., 0.])
X_R = np.array([C2/C1, C3/C1])
X_P = np.array([0, b/d])
X_Q = np.array([beta/delta, 0])
def jacobian(X, t=0):
return np.array([[beta-delta*2*X[0]-gamma*X[1], -gamma*x[0]],
[b-d*2*X[1]-c*X[0], -c*X[1]]])
values = np.linspace(0.3, 0.9, 5)
vcolors = plt.cm.autumn_r(np.linspace(0.3, 1., len(values)))
f2 = plt.figure(figsize=(4,4))
for v, col in zip(values, vcolors):
X0 = v * X_R
X = odeint(verhulst, X0, t)
plt.plot(X[:,0], X[:,1], color=col, label='X0=(%.f, %.f)' % ( X0[0], X0[1]) )
ymax = plt.ylim(ymin=0)[1]
xmax = plt.xlim(xmin=0)[1]
nb_points = 20
x = np.linspace(0, xmax, nb_points)
y = np.linspace(0, ymax, nb_points)
X1, Y1 = np.meshgrid(x, y)
DX1, DY1 = verhulst([X1, Y1]) # compute growth rate on the gridt
M = (np.hypot(DX1, DY1)) # Norm of the growth rate
M[M == 0] = 1. # Avoid zero division errors
DX1 /= M # Normalize each arrows
DY1 /= M
plt.quiver(X1, Y1, DX1, DY1, M, cmap=plt.cm.jet)
plt.xlabel('Number of Species 1')
plt.ylabel('Number of Species 2')
plt.legend()
plt.grid()
We have:
That is still different from:
What am I missing?
With the help of #Lutz Lehmann I could rewrite the code to get want I needed.
The solutions is something like this:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 4), dpi= 80, facecolor='whitesmoke', edgecolor='k')
beta, delta, gamma = 1, 2, 1
b,d,c = 1,2,1
t = np.linspace(0, 10, 100)
C1 = gamma*c-delta*d
C2 = gamma*b-beta*d
C3 = beta*c-delta*b
def verhulst(X, t=0):
return np.array([beta*X[0] - delta*X[0]**2 -gamma*X[0]*X[1],
b*X[1] - d*X[1]**2 -c*X[0]*X[1]])
X_O = np.array([0., 0.])
X_R = np.array([C2/C1, C3/C1])
X_P = np.array([0, b/d])
X_Q = np.array([beta/delta, 0])
def jacobian(X, t=0):
return np.array([[beta-delta*2*X[0]-gamma*X[1], -gamma*x[0]],
[b-d*2*X[1]-c*X[0], -c*X[1]]])
values = np.linspace(0.05, 0.15, 5)
vcolors = plt.cm.autumn_r(np.linspace(0.3, 1., len(values)))
for v, col in zip(values, vcolors):
X0 = [v,0.2-v]
X = odeint(verhulst, X0, t)
plt.plot(X[:,0], X[:,1], color=col, label='X0=(%.f, %.f)' % ( X0[0], X0[1]) )
for v, col in zip(values, vcolors):
X0 = [6 * v, 6 *(0.2-v)]
X = odeint(verhulst, X0, t)
plt.plot(X[:,0], X[:,1], color=col, label='X0=(%.f, %.f)' % ( X0[0], X0[1]) )
ymax = plt.ylim(ymin=0)[1]
xmax = plt.xlim(xmin=0)[1]
nb_points = 20
x = np.linspace(0, xmax, nb_points)
y = np.linspace(0, ymax, nb_points)
X1, Y1 = np.meshgrid(x, y)
DX1, DY1 = verhulst([X1, Y1]) # compute growth rate on the gridt
M = (np.hypot(DX1, DY1)) # Norm of the growth rate
M[M == 0] = 1. # Avoid zero division errors
DX1 /= M # Normalize each arrows
DY1 /= M
plt.quiver(X1, Y1, DX1, DY1, M, cmap=plt.cm.jet)
plt.xlabel('Number of Species 1')
plt.ylabel('Number of Species 2')
plt.grid()
We get what we were looking for:
Finally, I would like to thank again #Lutz Lehnmann for the help. I wouldn't have solved without it him.
Edit 1:
I forgot $t = np.linspace(0, 10, 100)$ and if you change figsize = (8,8), we get a nicer shape in the plot. (Thank you #Trenton McKinney for the remarks)

How to count points inside a contour obtained from svm.SVC?

I generated a data-set from a bivariate gaussian to simulate a signal and a background. Then I tried to separate the two components using svm.SVC with kernel 'rbf'. Now I'd like to count how many background points lay inside the acceptance region, how many signal points lay outside the region etc. in order to study the efficiency of the separation method.
I have to say that I got parts of this code from an online example because it is the first time for me doing such type of analysis; so I'm not sure I really understand how the contour line is created, consequently I'm not able to handle it and to analyse its position respect to the points.
Thanks
mu_vec1 = np.array([0,0])
cov_mat1 = np.array([[0.3**2,0.5*0.3*0.3],[0.5*0.3*0.3,0.3**2]])
x1_samples = np.random.multivariate_normal(mu_vec1, cov_mat1, 1000)
#mu_vec1 = mu_vec1.reshape(1,2).T
mu_vec2 = np.array([2,1])
cov_mat2 = np.array([[1,0.4],[0.4,1]])
x2_samples = np.random.multivariate_normal(mu_vec2, cov_mat2, 1000)
#mu_vec2 = mu_vec2.reshape(1,2).T
X = np.concatenate((x1_samples,x2_samples), axis = 0)
Y = np.array([0]*1000 + [1]*1000)
plt.scatter(x1_samples[:,0],x1_samples[:,1], label='Signal')
plt.scatter(x2_samples[:,0],x2_samples[:,1],label='Background')
C = 1.0 # SVM regularization parameter
clf = svm.SVC(kernel = 'rbf', C=C, probability = True )
clf.fit(X, Y)
h = .02 # step size in the mesh
# create a mesh to plot in
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
print(clf.score(X,Y))
# Plot the decision boundary. For that, we will assign a color to each
# point in the mesh [x_min, m_max]x[y_min, y_max].
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
# Put the result into a color plot
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, cmap=plt.cm.Paired)
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
I actually solve it using the method 'predict' this way:
false_pos=0
true_pos=0
true_neg=0
false_neg=0
pred_sig = clf.predict(np.c_[x1_samples[:,0], x1_samples[:,1]])
for i in range(0,len(pred_sig)):
if pred_sig[i] == 1:
false_neg=false_neg + 1
if pred_sig[i] == 0:
true_pos=true_pos + 1
pred_back = clf.predict(np.c_[x2_samples[:,0], x2_samples[:,1]])
for i in range(0,len(pred_back)):
if pred_back[i] == 1:
true_neg=true_neg + 1
if pred_back[i] == 0:
false_pos=false_pos + 1
print(true_pos+false_pos+true_neg+false_neg)
purezza = true_pos/(true_pos+false_pos)
rig_fondo = true_neg/(true_neg+false_neg)

Perceptron Algorithm plotting with matplotlib

In an ML course, I m taking, I have 100 entries of data, and I'm using it in a Perceptron Algorithm.
What I want is to show a plot like this one.
As you can see above we have the data represented by point in red and blue and the different calculated lines that minimize the error. This is the output that I want.. Here is my Data and my code.
data.csv
0.78051,-0.063669,1
0.28774,0.29139,1
0.40714,0.17878,1
0.2923,0.4217,1
0.50922,0.35256,1
0.27785,0.10802,1
0.27527,0.33223,1
0.43999,0.31245,1
0.33557,0.42984,1
0.23448,0.24986,1
0.0084492,0.13658,1
0.12419,0.33595,1
0.25644,0.42624,1
0.4591,0.40426,1
0.44547,0.45117,1
0.42218,0.20118,1
0.49563,0.21445,1
0.30848,0.24306,1
0.39707,0.44438,1
0.32945,0.39217,1
0.40739,0.40271,1
0.3106,0.50702,1
0.49638,0.45384,1
0.10073,0.32053,1
0.69907,0.37307,1
0.29767,0.69648,1
0.15099,0.57341,1
0.16427,0.27759,1
0.33259,0.055964,1
0.53741,0.28637,1
0.19503,0.36879,1
0.40278,0.035148,1
0.21296,0.55169,1
0.48447,0.56991,1
0.25476,0.34596,1
0.21726,0.28641,1
0.67078,0.46538,1
0.3815,0.4622,1
0.53838,0.32774,1
0.4849,0.26071,1
0.37095,0.38809,1
0.54527,0.63911,1
0.32149,0.12007,1
0.42216,0.61666,1
0.10194,0.060408,1
0.15254,0.2168,1
0.45558,0.43769,1
0.28488,0.52142,1
0.27633,0.21264,1
0.39748,0.31902,1
0.5533,1,0
0.44274,0.59205,0
0.85176,0.6612,0
0.60436,0.86605,0
0.68243,0.48301,0
1,0.76815,0
0.72989,0.8107,0
0.67377,0.77975,0
0.78761,0.58177,0
0.71442,0.7668,0
0.49379,0.54226,0
0.78974,0.74233,0
0.67905,0.60921,0
0.6642,0.72519,0
0.79396,0.56789,0
0.70758,0.76022,0
0.59421,0.61857,0
0.49364,0.56224,0
0.77707,0.35025,0
0.79785,0.76921,0
0.70876,0.96764,0
0.69176,0.60865,0
0.66408,0.92075,0
0.65973,0.66666,0
0.64574,0.56845,0
0.89639,0.7085,0
0.85476,0.63167,0
0.62091,0.80424,0
0.79057,0.56108,0
0.58935,0.71582,0
0.56846,0.7406,0
0.65912,0.71548,0
0.70938,0.74041,0
0.59154,0.62927,0
0.45829,0.4641,0
0.79982,0.74847,0
0.60974,0.54757,0
0.68127,0.86985,0
0.76694,0.64736,0
0.69048,0.83058,0
0.68122,0.96541,0
0.73229,0.64245,0
0.76145,0.60138,0
0.58985,0.86955,0
0.73145,0.74516,0
0.77029,0.7014,0
0.73156,0.71782,0
0.44556,0.57991,0
0.85275,0.85987,0
0.51912,0.62359,0
And now this is my code. The first part
import numpy as np
import pandas as pd
# Setting the random seed, feel free to change it and see different solutions.
np.random.seed(42)
import matplotlib.pyplot as plt
def stepFunction(t):
return 1 if t >= 0 else 0
def prediction(X, W, b):
return stepFunction((np.matmul(X, W) + b)[0])
# TODO: Fill in the code below to implement the perceptron trick.
# INPUTS
# data X, the labels y,
# the weights W (as an array), and the bias b,
# The function weights and bias W, b, according to the perceptron algorithm,
# and return W and b.
def perceptronStep(X, y, W, b, learn_rate=0.01):
for i in range(len(X)):
y_hat = prediction(X[i], W, b)
if y[i] - y_hat == 1:
W[0] += X[i][0] * learn_rate
W[1] += X[i][1] * learn_rate
b += learn_rate
elif y[i] - y_hat == -1:
W[0] -= X[i][0] * learn_rate
W[1] -= X[i][1] * learn_rate
b -= learn_rate
return W, b
# This function runs the perceptron algorithm repeatedly on the dataset,
# and returns a few of the boundary lines obtained in the iterations,
# for plotting purposes.
# Feel free to play with the learning rate and the num_epochs,
# and see your results plotted below.
def trainPerceptronAlgorithm(X, y, learn_rate=0.01, num_epochs=25):
x_min, x_max = min(X.T[0]), max(X.T[0])
y_min, y_max = min(X.T[1]), max(X.T[1])
W = np.array(np.random.rand(2, 1))
b = np.random.rand(1)[0] + x_max
# These are the solution lines that get plotted below.
boundary_lines = []
for i in range(num_epochs):
# In each epoch, we apply the perceptron step.
W, b = perceptronStep(X, y, W, b, learn_rate)
# Here I have a doubt . Why if y = W0*x1 + W1*x2 + b
# So we can get x2 =y/W1 -(W0*x1)/W1 -b/W1 + y/W1)
# If we remove y/W1 we just get intercept and slope
# But why we are not using the last term y/W1
boundary_lines.append((-W[0] / W[1], -b / W[1]))
return boundary_lines
# Get data and plot the points
data = pd.read_csv('data.csv', header = None)
X = data.iloc[:, :2].values
y = data.iloc[:, -1].values
x1 = X[:, 0]
x2 = X[:, 1]
color = ['red' if value == 1 else 'blue' for value in y]
plt.scatter(x1, x2, marker='o', color=color)
plt.xlabel('X1 input feature')
plt.ylabel('X2 input feature')
plt.title('Perceptron regression for X1, X2')
plt.show()
When you run this code you correctly get
So now I want to plot the line in the same plot the lines that represent the best function for each iteration.For that, I commented the last line above plt.show() and did
# So now lets plot the lines that represent the best function for each iteration
boundary_lines = trainPerceptronAlgorithm(X, y)
x_lin = np.linspace(0, 1, 100)
for line in boundary_lines:
Θo, Θ1 = line
Θ1 = Θ1[0]
Θo = Θo[0]
# TODO: The equation of the error function is
# y = W0*x1 + W1*x2 + b
# So we can get x2 =y/W1 -(W0*x1)/W1 -b/W1 + y/W1)
# If we remove y/W1 we just get intercept and slope
# boundary_lines.append((-W[0] / W[1], -b / W[1])
# plt.axes([-0.5, -0.5, 1.5, 1.5])
plt.plot(x_lin, (Θ1 * x_lin / Θo))
plt.draw()
plt.pause(5)
input("Press enter to continue")
plt.close()
But that does not get me the expected result.
Why doesn't this get the expected result?
The mistake is in plt.plot(x_lin, (Θ1 * x_lin / Θo)) where instead of Θ1 * x_lin / Θo you should have Θo * x_lin + Θ1.
fig, ax = plt.subplots(1, 1, figsize=(8,5))
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.scatter(x1, x2, marker='o', color=color)
for i, line in enumerate(boundary_lines):
Θo, Θ1 = line
if i == len(boundary_lines) - 1:
c, ls, lw = 'k', '-', 2
else:
c, ls, lw = 'g', '--', 1.5
ax.plot(x_lin, Θo * x_lin + Θ1, c=c, ls=ls, lw=lw)
plt.show()
Result:

Categories