Chapter 49 Perceptron

x1 <- runif(30,-1,1) 
x2 <- runif(30,-1,1)
#form the input vector x
x <- cbind(x1,x2)

#helper function to calculate distance from hyperplane
calculate_distance = function(x,w,b) {
    sum(x*w) + b
}

#linear classifier
linear_classifier = function(x,w,b) {
    distances =apply(x, 1, calculate_distance, w, b)
    return(ifelse(distances < 0, -1, +1))
}

#function to calculate 2nd norm
second_norm = function(x) {sqrt(sum(x * x))}

#perceptron training algorithm
perceptron = function(x, y, learning_rate=1) {
    
    w = vector(length = ncol(x)) # initialize w
    b = 0 # Initialize b
    k = 0 # count iterations
    
    #constant with value greater than distance of furthest point
    R = max(apply(x, 1, second_norm)) 
    
    incorrect = TRUE # flag to identify classifier
    
    #initialize plot
    plot(x,cex=0.2)
    
    #loop till correct classifier is not found
    while (incorrect ) {
        
        incorrect = FALSE 
        
        #classify with current weights
        yc <- linear_classifier(x,w,b)
        #Loop over each point in the input x
        for (i in 1:nrow(x)) {
            #update weights if point not classified correctly
            if (y[i] != yc[i]) {
                w <- w + learning_rate * y[i]*x[i,]
                b <- b + learning_rate * y[i]*R^2
                k <- k+1
                
                #currect classifier's components
                # update plot after ever 5 iterations
                if(k%%5 == 0){
                    intercept <- - b / w[[2]]
                    slope <- - w[[1]] / w[[2]]
                    #plot the classifier hyper plane
                    abline(intercept,slope,col="red")
                    #wait for user input
                    cat ("Iteration # ",k,"\n")
                    cat ("Press [enter] to continue")
                    line <- readline()
                }
                incorrect = TRUE
            }
        }
    }
    
    s = second_norm(w)
    #scale the classifier with unit vector
    return(list(w=w/s,b=b/s,updates=k))
}

#train the perceptron
p <- perceptron(x,Y)
#classify based on calculated 
y <- linear_classifier(x,p$w,p$b)


plot(x,cex=0.2)

#zoom into points near the separator and color code them
#marking data points as + which have y=1 and – for others
points(subset(x,Y==1),col="black",pch="+",cex=2)
points(subset(x,Y==-1),col="red",pch="-",cex=2)

# compute intercept on y axis of separator
# from w and b
intercept <- - p$b / p$w[[2]]

# compute slope of separator from w
slope <- - p$w[[1]] /p$ w[[2]]

# draw separating boundary
abline(intercept,slope,col="green")