Suppose the data has two attributes and a label -1 or 1. So, we have a three-column matrix $X$ (two attributes and a column of ones for convenience of working with matrix notation) and a column vector $y$. We can use the following formula to compute the coefficients of linear regression that minimizes the mean squared error: $b=(X^TX)^{-1}X^Ty$.
I generated some random training data for a classification problem and computed $b$ using the above formula. Here is the linear separator based on $b$:
Why does linear regression in three dimensions result in a good linear separator for two dimensions? Does this separator minimize some classification error (and how can this be shown)?
P.S.1.: I tried to search for an answer, but came up with mostly the opposite of what I was looking for. Namely, people say that simple (i.e. non-logistic) regression does not work well for classification. In my example it does. This inconsistency is also something I'd like to understand.
P.S.2.: Here is the code (exported from Jupyter Notebook):
# In[1]:
import numpy as np
import matplotlib.pyplot as plt
import math
# In[2]:
def sign(x):
res = np.sign(x)
return np.where(res == 0, 1, res)
# The returned X is a two-column matrix
# The returned y is a one-column matrix of labels
def data():
X = np.random.rand(200, 2)
X[:,0:1] *= 500
X[:,1:2] *= 200
y = [sign(el) for el in (X @ [0.25, 1] - 150) ]
return X, y
# In[3]:
def extendX(X):
Xext = np.ones((X.shape[0], 3)) # Exercise: do it generically
Xext[:, 0:2] = X
return Xext
# Xext -- X extended by a column of ones
# Computes the column of coefficients b
def regression(Xext, y):
XT = np.transpose(Xext)
return np.linalg.inv(XT @ Xext) @ XT @ y
def nMisclassified(Xext, y, b):
return sum(sign(Xext @ b) != sign(y))
# In[4]:
X, y = data()
colors = [('blue' if el == 1 else 'green') for el in y]
plt.scatter(X[:,0],X[:,1],c=colors)
Xext = extendX(X)
b = regression(Xext, y)
xs = np.arange(500)
ys = (xs * b[0] + b[2]) / -b[1]
plt.plot(xs, ys, color = 'red', linewidth = 4)
plt.show()
print("Misclassified: %d" % (nMisclassified(Xext, y, b)))