机器学习(二)线性模型

线性模型(一元回归线性模型,多元线性回归模型)

由d个属性描述的示例Xi={x1,x2,.....,xd},其中Xi为X中的第i个个示例,xd表示示例Xi在第d个属性的取值;

线性模型即通过线性函数来进行预测的函数,即 f(X)=w1x1+w2x2+.....+wdxd +b,写成向量形式 f(X)=w^T X+b

(注L这里的w与b通过数据集合学习求解得出)

简单的,对于f(x)=wx+b;(一元线性回归)通过小二乘法寻找一条直线使得所有样本点到此直线的距离之和最小;

1)列出点到预测直线的距离和公式;2)分别对w和b求偏导数使偏导数等于0,并结合以给数据即可求解出w和b;

 对于一般形式(多元线性回归)类似的也可以通过最小二乘法对参数w^T和b进行估计;

把数据集合X表示为一个最后一列为常数1的m*(d+1)的数组A,带入多元线性方程组得到矩阵形式

在这里令Z=(w1,w2,w3......,wm,b),则有线性方程组Y=AZ,由矩阵论的有关概念得最小二乘解的有关概念

由方程A^T A Z=A^T Y求解出来的Z即为最小二乘解;

当(A^T A)为满秩矩阵时,则Z=(A^T A)^-1 (A^T Y);前m个元素为w,最后一个元素为b;

当(A^T A)为不可逆矩阵时,此时可以求出多个Z,一般解决此类问题的方法是采用引入正则化项

广义线性模型:对于单调可微函数g(.),令y=g^-1(w^T X+b),这样得到的模型为广义线性模型,其中g(.)称之为联系函数。

分类问题的求解(logistic回归)

对于分类任务,只需要找到一个单调可微的函数将真实标记y与线性回归模型联系在一起,这里有两种函数可以选择

1)单位阶跃函数(在z=0处间断点,函数不连续)

2)sigmoid函数在一定程度上近似单位阶跃函数,同时单调可微,图像如下所示: (显然优于上述函数)

这样我们就可以构建广义线性回归模型:

对上述 模型两侧做对数运算可得到下述方程:

 若将y视为样本x为正例的可能性,则1-y就为x视为负例的可能性,正负例的比值称之为几率,反映了x为正例的相对可能性

对其取对数则得到对数几率(logit)。这种模型被称为Logistic回归模型。

优点:1)直接对分类可能性进行建模,无需事先假设数据分布,这样避免了假设分布不准确带来的问题。

2)它不是预测出“类别”,而是得到近似概率的预测,有利于解决利用概率作为辅助决策的任务。 

现在我们的任务是如何确定上述模型中的参数w和b,将上述公式中的y视为后验概率P(y=1 | x)则1-y为P(y=0 | x)

我们可得下述方程,很显然:P(y=1 | x)=1-P(y=0 | x);

 对上述方程两侧求指数易得:

于是我们可以通过“极大似然估计法”,来估计w和b,对于给定的数据集,进行对数似然估计:

或者p(y | x,w)=y h(x)+(1-y) (1-h(x)); //这两种形式都可以,因为是二分类问题这里的y只有两种取值0和1;

由上述式子我们可得出最大似然函数(如下图所示)

 对上述似然函数两侧对数化可得:

 最后我们只需求解上述函数的最大值(Max)即可(只需要将上式对w求导,令导函数等于0即可求得对应的w)。

方向导数&梯度

方向导数:在一个多元函数中沿着某一射线方向上的变化率;(我们不仅要知道函数在坐标轴正方向上的变化率(即偏导数),而且还要设法求得函数在其他特定方向上的变化率。)

梯度的定义(可推广至多元)

注:1)梯度是一个向量;2)梯度的方向是最大方向导数的方向;3)梯度的值是最大方向导数的值;

算法过程:

 首先初始化各个参数,即根据实际情况赋予初始值,我一般取θi为1,学习率α为0.01,0.001,0.0001等;

在这里我们采取梯度上升算法

我们想要的w=w+alpha*对w的导数,进行多次循环访问即可逼近最大值;

(这里的alpha为学习率一般取0.01,0.001,0.0001。不应过大,也不能过小。过大可能导致发散线性,过小会导致收敛过慢)

代码部分:(只是实现了对应数据的分裂,复用程度不高,仅仅限于理解此模型与实现此模型,大佬勿喷!

import  numpy as np
import matplotlib.pyplot as plt
def getData():#获取数据集合
    dataMatrix=[]
    file=open('testSet.txt')
    for line in file.readlines():
        linelist=line.strip().split()
        dataMatrix.append([float(linelist[0]),float(linelist[1]),int(linelist[2])])
    return  dataMatrix

def Logic(Z):
    return 1.0/(1+np.exp(-Z))#sigmoid函数

def Draw(x):
    Data=[]
    for i in x:
        Data.append([i[0],i[1],1])
    DataSet =np.mat(Data)#获取X数据结合
    List1=[]
    List2=[]
    Label=[]
    plt.xlabel('x')
    plt.ylabel('y')#绘制坐标轴
    X=[]
    for i in x:
        if(i[2]==0):
            List1.append([i[0],i[1]])
        else:
            List2.append([i[0],i[1]])#将各个点区分
        X.append([i[0],i[1],1])
        Label.append(i[2])
    Y = np.mat(Label).transpose()
    Xi=np.mat(X)
    X1=[]
    X2=[]#正概率点
    Y1=[]
    Y2=[]#负概率点
    for i in List1:
        X1.append(i[0])
        Y1.append(i[1])#将点依次添加
    for i in List2:
        X2.append(i[0])
        Y2.append(i[1])#将点依次添加

    alpha=0.001#学习率
    stepnum=500
    weight=np.ones((1,DataSet.shape[1])).transpose()#创建一个m*1的矩阵
    for i in range(stepnum):
        h=Y-Logic(Xi*weight)
        weight=weight+alpha*DataSet.transpose()*h#梯度上升
    #print(weight)
    xi = np.linspace(-4,4)#绘制x的区间
    yi=[]#绘制直线的y坐标
    weight=weight.tolist()#将数组转化为列表
    for i in xi:
        data=(weight[0][0]*i+weight[2][0])/weight[1][0]
        yi.append(-1*data)
        print(yi)
    plt.plot(X1,Y1,".b")
    plt.plot(X2,Y2,".r")#绘制图像
    plt.plot(xi,yi)#绘制预测直线
    plt.show()

if __name__== '__main__':
     Matrix=getData()
     Draw(Matrix)

实现效果:(总体上基本实现了分类的划分)

 线性判别分析(LDA)

模型思想:将样例点投影到一条直线上去,使得同类样例的点尽可能的接近,异类的样例投影点尽可能的远离;

在给定数据集D={xi,yi}上yi属于【0,1】,令Xi,μi,∑i 分别表示i属于【0,1】类的示例集合,均值向量,协方差矩阵。若

将数据投影到直线w上,则两类样本的中心在直线上的投影分别为(w^T)μ0,(w^T)μ1;若将所有样本点都投影到这一

条直线上,则两类样本的协方差分别为(w^T)∑0 (w)和(w^T)∑1 (w),由于直线属于一维空间则上述所有式子均为

实数。想要使得同类样本点尽可能的接近,可以让(w^T)∑0 (w)和(w^T)∑1 (w)尽可能的小(即:同类样例投影点

的协方差),而想要使得异类样例的投影点尽可能的远离,可以让类中心的距离尽可能的大,即

||(w^T)μ0-(w^T)μ1||

尽可能的大。如果要同时考虑两者,则可以得到最大化的目标函数:

定义类内散度矩阵Sw:

定义类间散度矩阵Sb: 

通过上述两种散度矩阵我们可以重写最大化的目标函数J(w) 得出:

这就是LDA欲最大化的目标,即Sb和Sw的“广义瑞利商” 。现在我们只需确定w即可,通过确定参数w和两样本中心点,我们

即可以得到类边界的大致范围。注意到上式均为关于w的二次项,因此上式的解与w无关,只与其方向有关。为了不失去一

般性,令(w^T)Sw(w)=1,通过拉格朗日乘子法易得在约束条件下有下式成立:

注意到在二分类问题中(Sb) 方向恒为μ0-μ1的方向,不妨令:

与将此式与上式联立求解即可得到:

代码部分(仅仅限于实现,了解此模型)

import  numpy as np
import matplotlib.pyplot as plt
def getData():#获取数据集合
    dataMatrix=[]
    file=open('testSet.txt')
    for line in file.readlines():
        linelist=line.strip().split()
        dataMatrix.append([float(linelist[0]),float(linelist[1]),int(linelist[2])])
    return  dataMatrix

def LDA(Matrix):
    data=np.mat(Matrix)
    Sw=[]
    P=[]#正样例
    N=[]#负样例
    for i in Matrix:
        if i[2]==0:
            N.append([i[0],i[1]])
        else:
            P.append([i[0],i[1]])
    #添加正负样例
    u0=[]
    u1=[]
    x=y=0
    for i in N:
        x=x+i[0]
        y=y+i[1]
    u0.append(x//len(P))
    u0.append(y//len(P))
    print(u0)
    x=y=0
    for i in P:
        x=x+i[0]
        y=y+i[1]
    u1.append(x//len(P))
    u1.append(y//len(P))
    xi=(u1[0]+u0[0])/2
    yi=(u1[1]+u0[1])/2
    u1=np.mat(u1)
    u0 = np.mat(u0)
    print(u1)#将正负样例区分并求出均值向量
    A=np.zeros((data.shape[1]-1,data.shape[1]-1))
    B=np.zeros((data.shape[1]-1,data.shape[1]-1))
    for i in P:
        a=np.mat(i)
        u=np.mat(a-u1)
        A=A+u.transpose()*u
    print(A)
    for i in N:
        a = np.mat(i)
        u=np.mat(a-u0)
        B=B+u.transpose()*u
    print(B)
    Sw=(A+B).I#求矩阵的逆矩阵
    k=(Sw*(u0-u1).transpose()).tolist()
    a=(-1)*k[1][0]//k[0][0]
    X=[]
    Y=[]
    for i in P:
        X.append((i[0]))
        Y.append((i[1]))
    plt.plot(X, Y, '.r')
    X=[]
    Y=[]
    for i in N:
        X.append((i[0]))
        Y.append((i[1]))
    plt.plot(X,Y,'.b')
    b=yi-a*xi
    point=np.linspace(-4,4)
    F = []
    for i in point:
        F.append(a*i+b)
    plt.plot(point,F)
    plt.show()


if __name__== '__main__':
     Matrix=getData()
     LDA(Matrix)

运行结果:

实验数据:

-0.017612	14.053064	0
-1.395634	4.662541	1
-0.752157	6.538620	0
-1.322371	7.152853	0
0.423363	11.054677	0
0.406704	7.067335	1
0.667394	12.741452	0
-2.460150	6.866805	1
0.569411	9.548755	0
-0.026632	10.427743	0
0.850433	6.920334	1
1.347183	13.175500	0
1.176813	3.167020	1
-1.781871	9.097953	0
-0.566606	5.749003	1
0.931635	1.589505	1
-0.024205	6.151823	1
-0.036453	2.690988	1
-0.196949	0.444165	1
1.014459	5.754399	1
1.985298	3.230619	1
-1.693453	-0.557540	1
-0.576525	11.778922	0
-0.346811	-1.678730	1
-2.124484	2.672471	1
1.217916	9.597015	0
-0.733928	9.098687	0
-3.642001	-1.618087	1
0.315985	3.523953	1
1.416614	9.619232	0
-0.386323	3.989286	1
0.556921	8.294984	1
1.224863	11.587360	0
-1.347803	-2.406051	1
1.196604	4.951851	1
0.275221	9.543647	0
0.470575	9.332488	0
-1.889567	9.542662	0
-1.527893	12.150579	0
-1.185247	11.309318	0
-0.445678	3.297303	1
1.042222	6.105155	1
-0.618787	10.320986	0
1.152083	0.548467	1
0.828534	2.676045	1
-1.237728	10.549033	0
-0.683565	-2.166125	1
0.229456	5.921938	1
-0.959885	11.555336	0
0.492911	10.993324	0
0.184992	8.721488	0
-0.355715	10.325976	0
-0.397822	8.058397	0
0.824839	13.730343	0
1.507278	5.027866	1
0.099671	6.835839	1
-0.344008	10.717485	0
1.785928	7.718645	1
-0.918801	11.560217	0
-0.364009	4.747300	1
-0.841722	4.119083	1
0.490426	1.960539	1
-0.007194	9.075792	0
0.356107	12.447863	0
0.342578	12.281162	0
-0.810823	-1.466018	1
2.530777	6.476801	1
1.296683	11.607559	0
0.475487	12.040035	0
-0.783277	11.009725	0
0.074798	11.023650	0
-1.337472	0.468339	1
-0.102781	13.763651	0
-0.147324	2.874846	1
0.518389	9.887035	0
1.015399	7.571882	0
-1.658086	-0.027255	1
1.319944	2.171228	1
2.056216	5.019981	1
-0.851633	4.375691	1
-1.510047	6.061992	0
-1.076637	-3.181888	1
1.821096	10.283990	0
3.010150	8.401766	1
-1.099458	1.688274	1
-0.834872	-1.733869	1
-0.846637	3.849075	1
1.400102	12.628781	0
1.752842	5.468166	1
0.078557	0.059736	1
0.089392	-0.715300	1
1.825662	12.693808	0
0.197445	9.744638	0
0.126117	0.922311	1
-0.679797	1.220530	1
0.677983	2.556666	1
0.761349	10.693862	0
-2.168791	0.143632	1
1.388610	9.341997	0
0.317029	14.739025	0
发布了79 篇原创文章 · 获赞 81 · 访问量 5737

猜你喜欢

转载自blog.csdn.net/weixin_44638960/article/details/102588141