L03: Perceptrons
Implementation of the classic Perceptron by Frank Rosenblatt for binary classification (here: 0/1 class labels) in PyTorch
Imports
import numpy as np
import [Link] as plt
import torch
%matplotlib inline
Preparing a toy dataset
##########################
### DATASET
##########################
data = [Link]('perceptron_toydata.txt', delimiter='\t')
X, y = data[:, :2], data[:, 2]
y = [Link]([Link])
print('Class label counts:', [Link](y))
print('[Link]:', [Link])
print('[Link]:', [Link])
# Shuffling & train/test split
shuffle_idx = [Link]([Link][0])
shuffle_rng = [Link](123)
shuffle_rng.shuffle(shuffle_idx)
X, y = X[shuffle_idx], y[shuffle_idx]
X_train, X_test = X[shuffle_idx[:70]], X[shuffle_idx[70:]]
y_train, y_test = y[shuffle_idx[:70]], y[shuffle_idx[70:]]
# Normalize (mean zero, unit variance)
mu, sigma = X_train.mean(axis=0), X_train.std(axis=0)
X_train = (X_train - mu) / sigma
X_test = (X_test - mu) / sigma
Class label counts: [50 50]
[Link]: (100, 2)
[Link]: (100,)
[Link](X_train[y_train==0, 0], X_train[y_train==0, 1], label='class 0', marker='o')
[Link](X_train[y_train==1, 0], X_train[y_train==1, 1], label='class 1', marker='s')
[Link]('Training set')
[Link]('feature 1')
[Link]('feature 2')
[Link]([-3, 3])
[Link]([-3, 3])
[Link]()
[Link]()
[Link](X_test[y_test==0, 0], X_test[y_test==0, 1], label='class 0', marker='o')
[Link](X_test[y_test==1, 0], X_test[y_test==1, 1], label='class 1', marker='s')
[Link]('Test set')
[Link]('feature 1')
[Link]('feature 2')
[Link]([-3, 3])
[Link]([-3, 3])
[Link]()
[Link]()
Defining the Perceptron model
device = [Link]("cuda:0" if [Link].is_available() else "cpu")
class Perceptron():
def __init__(self, num_features):
self.num_features = num_features
[Link] = [Link](num_features, 1,
dtype=torch.float32, device=device)
[Link] = [Link](1, dtype=torch.float32, device=device)
# placeholder vectors so they don't
# need to be recreated each time
[Link] = [Link](1)
[Link] = [Link](1)
def forward(self, x):
linear = [Link](x, [Link]) + [Link]
predictions = [Link](linear > 0., [Link], [Link])
return predictions
def backward(self, x, y):
predictions = [Link](x)
errors = y - predictions
return errors
def train(self, x, y, epochs):
for e in range(epochs):
for i in range([Link][0]):
# use view because backward expects a matrix (i.e., 2D tensor)
errors = [Link](x[i].reshape(1, self.num_features), y[i]).reshape(-1)
[Link] += (errors * x[i]).reshape(self.num_features, 1)
[Link] += errors
def evaluate(self, x, y):
predictions = [Link](x).reshape(-1)
accuracy = [Link](predictions == y).float() / [Link][0]
return accuracy
Training the Perceptron
ppn = Perceptron(num_features=2)
X_train_tensor = [Link](X_train, dtype=torch.float32, device=device)
y_train_tensor = [Link](y_train, dtype=torch.float32, device=device)
[Link](X_train_tensor, y_train_tensor, epochs=5)
print('Model parameters:')
print(' Weights: %s' % [Link])
print(' Bias: %s' % [Link])
Model parameters:
Weights: tensor([[1.2734],
[1.3464]])
Bias: tensor([-1.])
Evaluating the model
X_test_tensor = [Link](X_test, dtype=torch.float32, device=device)
y_test_tensor = [Link](y_test, dtype=torch.float32, device=device)
test_acc = [Link](X_test_tensor, y_test_tensor)
print('Test set accuracy: %.2f%%' % (test_acc*100))
Test set accuracy: 93.33%
##########################
### 2D Decision Boundary
##########################
w, b = [Link], [Link]
x0_min = -2
x1_min = ( (-(w[0] * x0_min) - b[0])
/ w[1] )
x0_max = 2
x1_max = ( (-(w[0] * x0_max) - b[0])
/ w[1] )
fig, ax = [Link](1, 2, sharex=True, figsize=(7, 3))
ax[0].plot([x0_min, x0_max], [x1_min, x1_max])
ax[1].plot([x0_min, x0_max], [x1_min, x1_max])
ax[0].scatter(X_train[y_train==0, 0], X_train[y_train==0, 1], label='class 0', marker='o')
ax[0].scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], label='class 1', marker='s')
ax[1].scatter(X_test[y_test==0, 0], X_test[y_test==0, 1], label='class 0', marker='o')
ax[1].scatter(X_test[y_test==1, 0], X_test[y_test==1, 1], label='class 1', marker='s')
ax[1].legend(loc='upper left')
[Link]()
Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/[Link]