Last active
August 16, 2018 09:47
-
-
Save knbknb/1d17caecd9b800d5148a30d537013668 to your computer and use it in GitHub Desktop.
Rosenblatt's perceptron - this R code is from 2013, based on a forum post by a chinese user. Online course "learning from data", instructor Prof Yaser Abu-Mostafa # http://work.caltech.edu/telecourse.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://gist.github.com/knbknb/1d17caecd9b800d5148a30d537013668 | |
# Thu Aug 16 11:24:05 2018 ------------------------------ | |
# Rosenblatt's perceptron | |
# this is from 2013, based on a forum post by a chinese user (don't remember his name) | |
# "learning from data" course, Prof Yaser Abu-Mostafa | |
# http://work.caltech.edu/telecourse.html | |
# create a xy-plot and an animated gif visualizing the training process | |
data(iris) | |
# simplify dataset 2 features, 2 classes | |
dd <- iris[iris$Species != "versicolor", -(3:4)] | |
# this point (in lower left of plot) breaks linear separation (at least w/o intercept). | |
# leave it in and the algorithm needs 275 steps to find a decision boundary, | |
# comment it out and it needs only 18. | |
# dd <- dd[-42, ] | |
dm <- data.matrix(dd[, 1:2]) | |
dm <- cbind(dm, 1) # to add intercept to the separating plane | |
# binary classification, vector of class attribute is numeric | |
# setosa 1 | |
# virginica -1 | |
dc <- rep(1, nrow(dm)) | |
dc[dd$Species == "virginica"] <- -1 | |
trainPerceptron <- function(dm, dc) { | |
result <- list() | |
oldW <- c() | |
w <- rep(0, ncol(dm)) | |
while (!identical(w, oldW)) { | |
oldW <- w | |
for (i in 1:nrow(dm)) { | |
# # the perceptron learning rule | |
pred <- sign(dm[i,] %*% w) | |
w = w + (dc[i] - pred) * dm[i, ] | |
} | |
# cat(w, "\n") | |
result <- c(result, list(w)) | |
} | |
result | |
} | |
plotPerceptronSteps <- function(pcResult, dm, dc, steps) { | |
for (s in steps) { | |
w <- pcResult[[s]] | |
plot(dm[,1:2], main=paste("step", s), col=ifelse(dc > 0, 1, 2), | |
sub=paste(c("weights: ", w), collapse=' ')) | |
abline(-w[3] / w[2], -w[1] / w[2]) | |
} | |
} | |
pc <- trainPerceptron(dm, dc) | |
# how many iterations, how many frames in the animated GIF | |
nsteps <- length(pc) | |
# test: plot a single png | |
# plotPerceptronSteps(pc, dm, dc, nsteps) | |
# png("perceptron-biased--iris-2D-2class.png", width=600, height=600) | |
# par(mfrow=c(3,3)) | |
steps <- seq(1,nsteps, by=1) | |
# Requires Imagemagick | |
animation::saveGIF( | |
{ | |
plotPerceptronSteps(pc, dm, dc, steps) | |
}, | |
movie.name = sprintf("perceptron-%s-steps--without-point42.gif", max(steps)), | |
interval = .1, # 10 ms frame delay | |
loop=1, | |
outdir = getwd() | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment