1 线性回归
1.1 基本形式
给定由d个属性描述的样本,其中
是X在第i个属性上的取值,线性模型是一个通过属性的线性组合来进行预测的函数一般形式如下:
一般用向量形式写成如下:
其中。w和b学得之后,模型得以确定。
1.2 线性回归
给定数据集,其中
。线性回归试图学得一个线性模型尽可能准确的预测实值输出标记。
试图学得,使得
。
如何确定w和b, 关键在于衡量和
之间的差别。在这里我们使用均方误差。因此我们可以使用均方误差最小化来求得w和b,即:
(1)
求解w和b使得上式最小化的过程称为线性回归模型的最小二乘”参数估计“我们可将分别对w和b求导,得到
(2)
(3)
令上式为0可以求得w和b的解。
我们把w和b吸纳进向量形式,把数据集D表示成一个m*(d+1)大小的矩阵X,每一行代表一个样本,该行前d个元素对应d个属性值,最后一个元素恒置为1,即
再把标记写成向量形式,类似与(1)式有
,对
求导得到
(4)
令该式为0可得到的解,由于涉及到逆矩阵,下面做一个简单讨论:
当为满秩矩阵或者正定矩阵时,令上式为0可以得到
最终得到线性模型为
然而现实生活中,往往不是满秩,X的列数多于行数,此时可以解出多个w的值,解决方法是引入正则化。如L2正则化。
1.3 广义线性模型
1.4 对数几率回归
1.5 线性判别分析
线性判别分析(Linear Discriminant Analysis)的思想:给定训练集,设法将样列投影到一条直线上,使得同类样本投影点尽可能进,异类样本投影点尽可能远。在对新样本进行分类时,将其投影到同样的这条直线上,根据投影点来判断新样本的类别。
给定数据集令
分别表示第
类示例的集合,均值向量,协方差矩阵。若将数据投影到直线
上,则两类样本的中心在直线上的投影分别为
和
;若将所有样本点都投影到直线上,则两类样本的协方差跟别为
和
,由于直线时一维空间,因此前边的表达式均为实数。
要使同类样例的投影点尽可能接近,可以使同类样本投影点的协方差尽可能小,即尽可能小。要使异类样例投影点尽可能远,可以使类中心之间的差距尽可能大,即
尽可能大,同时考虑二者,则可以达到最大化的目标
定义”类内散度矩阵“以及”类间散度矩阵
,则J可以重写为
如何确定w?上式分子分母为关于w的二次项,因此上式的解和w的长度无关(若w是解,对于任意常数C,Cw也是解),不失一般性令则上式等价于
由拉格朗日乘子法,上式等价于
其中是拉格朗日乘子,
因为
形状为(2,1)其转置为(1,2),w的形状是(2*1),故后两个的乘积是标量,所以
的方向恒为
,不妨令
,将该式带入上式,得到
.
在实践中常常通过奇异值分解来求Sw的逆。
代码如下:
#完整数据
X = df[:,1:3]
y = df[:,3]
#去掉14行的数据
X = np.delete(X, 14, 0)
y = np.delete(y, 14, 0)
# 获取均值向量
u = []
for i in range(2):
u.append(np.mean(X[y==i],axis=0))
#计算类内散度矩阵
m,n = np.shape(X)
Sw = np.zeros((n,n))
for i in range(m):
x_temp = X[i].reshape(n,1)
if y[i] == 0:
u_temp = u[0].reshape(n,1)
if y[i] == 1:
u_temp = u[1].reshape(n,1)
Sw += np.dot((x_temp - u_temp),(x_temp - u_temp).T)
#利用奇异值分解求Sw的逆
Sw = np.mat(Sw)
U, sigma, V = np.linalg.svd(Sw)
Sw_inv = V.T * np.linalg.inv(np.diag(sigma)) * U.T
#计算w
w = np.dot(Sw_inv,(u[0]-u[1]).reshape(n,1))
print(w)
#画出LDA
f1 = plt.figure(1)
plt.xlim(-0.2, 1)
plt.ylim(-0.5, 0.7)
p0_x0 = -X[:,0].max()
p0_x1 = ( w[1,0] / w[0,0] ) * p0_x0
p1_x0 = X[:,0].max()
p1_x1 = ( w[1,0] / w[0,0] ) * p1_x0
print((w[1,0] / w[0,0]))
plt.title("watermelon")
plt.xlabel("density")
plt.ylabel("sugar_ratio")
plt.scatter(X[y == 0,0], X[y == 0,1],marker = 'o', color = 'k', s=10, label = 'bad')
plt.scatter(X[y == 1,0], X[y == 1,1],marker = 'o', color = 'g', s=10, label = 'good')
plt.legend(loc = 'upper right')
plt.plot([p0_x0, p1_x0], [p0_x1, p1_x1])
#求投影点
def GetProjectivePoint_2D(point, line):
a = point[0]
b = point[1]
k = line[0]
t = line[1]
if k == 0: return [a, t]
elif k == np.inf: return [0, b]
x = (a+k*b-k*t) / (k*k+1)
y = k*x + t
return [x, y]
m,n = np.shape(X)
for i in range(m):
x_p = GetProjectivePoint_2D( [X[i,0], X[i,1]], [w[1,0] / w[0,0] , 0] )
if y[i] == 0:
plt.plot(x_p[0], x_p[1], 'ko', markersize = 5)
if y[i] == 1:
plt.plot(x_p[0], x_p[1], 'go', markersize = 5)
plt.plot([ x_p[0], X[i,0]], [x_p[1], X[i,1] ], 'c--', linewidth = 0.3)
plt.show()