# This file demonstrates linear discriminant function # theory. # No data is involved, just the densities. # Only two densities, common covariance matrix # # Authors: # H.A. Chipman, 2003 # R.W. Oldford, 2004 # # # The following sets up the grid of points on which the densities will # be evaluated. x1.grid <- rep(seq(-5,18,l=48),48) x2.grid <- rep(seq(-5,18,l=48),rep(48,48)) x.grid <- cbind(x1.grid,x2.grid) # Here are the grid points plot(x.grid) # Note that the aspect ratio (vertical:horizontal ratio) and the scaling (one # unit up for every two across") means that angles in the original scale will # not display correctly in the picture. # For example, the lines # y = x and y = -x are orthogonal to one another in the plane # but do not appear so in the plot. # Add the lines to show this. abline(coef=c(0,1)) # intercept 0, slope 1 ... coef = c(intercept, slope) abline(coef=c(0,-1)) # intercept 0, slope -1 # You will need to resize the window so that the aspect ratio # has the visual scalling match on both axes. Try it. # just a handy function to capture the pathname for the files we will load. web441 <- function(x) {paste('http://www.undergrad.math.uwaterloo.ca/~stat441/R-code/', x, sep='') } # get code for creating densities # (in class we just loaded this file since the machine wasn't connected to the internet). source(web441('dmvnorm.R')) # First plot two multivariate normals as contour plots of the # density # Here are the parameter values; notice the common covariance matrix. mu0 <- c(3,3) mu1 <- c(6,8) Sigma <- cbind(c(1,2),c(2,20)) # Create the class 0 density den0 <- dmvnorm(x.grid,mu0,Sigma) # Plot its contours (6 of them) contour(unique(x1.grid),unique(x2.grid),matrix(den0,48,48),nlevels=6,col='red') # identify the mean as 0 points(mu0[1],mu0[2], pch="0") # Repeat for the class 1 density den1 <- dmvnorm(x.grid,mu1,Sigma) # The following ensures that the drawing occurs as if the existing plot # were `new'. Otherwise the existing plot would be wiped clean before # adding the rest. par(new=T) contour(unique(x1.grid),unique(x2.grid),matrix(den1,48,48),nlevels=6,col='blue') points(mu1[1],mu1[2], pch="1") # The line segment from mu0 to mu1 lines(rbind(mu0,mu1)) # Halfway point half <- (mu0 + mu1) /2 points(half[1],half[2],pch=19,col='black', cex=2) # We can plot the discriminating function by just calculating the # ratio of normal densities ... or log ratio # We explicitly request a contour at height=0, # via the "levels=c(0)" option, which specifies a vector of contour levels par(new=T) contour(unique(x1.grid),unique(x2.grid),levels=c(0), labels=c(""), matrix(log(den0)-log(den1),40,48),nlevels=1,lwd=4,col='black') # # Show the density assuming an equal mixture # # overlayed the others par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(0.5 * (den0 + den1),40,48),nlevels=8,lwd=2, col='brown') # Or on its own with only the discriminant function overlaid. # contour(unique(x1.grid),unique(x2.grid), matrix(0.5 * (den0 + den1),40,48),nlevels=8,lwd=1, col='blue') par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(log(den0)-log(den1),40,48),nlevels=1,lwd=3,col='black') # What if the data are more likely to come from the class 0 # than from the class 1? # # If they are twice as likely from class 0 than class 1 # then this could be described as a different mixture. # say overlaid as par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(((2/3) * den0 + (1/3)* den1),40,48),nlevels=10,lwd=1, col='brown') # Or on its own with only the discriminant function overlaid. # contour(unique(x1.grid),unique(x2.grid), matrix(((2/3) * den0 + (1/3)* den1),40,48),nlevels=10,lwd=1, col='brown') par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(log(den0)-log(den1),40,48),nlevels=1,lwd=3,col='black') # # This can be accommodated by making use of these probabilities # as in par(new=T) contour(unique(x1.grid),unique(x2.grid),levels=c(0), matrix(log(den0)-log(den1)+log(2),40,48),nlevels=1,lwd=2,col='green') # # Similarly, had class 0 been half as likely to occur as class 1 # contour(unique(x1.grid),unique(x2.grid), matrix(((1/3) * den0 + (2/3)* den1),40,48),nlevels=10,lwd=1, col='brown') par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(log(den0)-log(den1),40,48),nlevels=1,lwd=3,col='black') # # This can be accommodated by making use of these probabilities # as in par(new=T)q() contour(unique(x1.grid),unique(x2.grid),levels=c(0), matrix(log(den0)-log(den1)+log(1/2),40,48),nlevels=1,lwd=2,col='green') # If they are 10 times more likely from class 0 than class 1 # then this could be described as a different mixture. # say overlaid as par(new=T) contour(unique(x1.grid),unique(x2.grid), matrix(((10/11) * den0 + (1/11)* den1),40,48),nlevels=30,lwd=1, col='brown') # note that you can also modify the prior probabilities, which has the # has the effect of shifting the line one way or the other. We add to # the log of the ratio the log of the ratio of prior probs. For # example, if class 0 is twice as likely as class 1, we do: par(new=T) contour(unique(x1.grid),unique(x2.grid),levels=c(0), matrix(log(den0)-log(den1)+log(2),40,48),nlevels=1,lwd=2,col='green') # Or, if class 0 is half as likely as class 1, we do: par(new=T) contour(unique(x1.grid),unique(x2.grid),levels=c(0), matrix(log(den0)-log(den1)+log(1/2),40,48),nlevels=1,lwd=2,col='orange') # Or, if class 0 is 10 times as likely as class 1, we do: par(new=T) contour(unique(x1.grid),unique(x2.grid),levels=c(0), matrix(log(den0)-log(den1)+log(10),40,48),nlevels=1,lwd=2,col='blue')