线性判别准则和线性分类算法【人工智能】

目录

一、线性判别分析LDA原理

LDA的原理及推导过程

 LDA算法流程

 LDA算法优缺点

 二、线性分类算法(支持向量机SVM)

优缺点

优点:

缺点:

三、LDA算法代码实现 

python编程实现:

 sklearn 库实现

 四、月亮数据集算法可视化

使用线性LDA对月亮数据集聚类

 使用k-means对鸢尾花数据集聚类

 使用SVM对月亮数据集聚类

五 . 总结

六 参考链接


 一、线性判别分析LDA原理

LDA的原理及推导过程

 

 

 第K 类样本的方差:

 各个类别的样本方差之和:

 

 

 

 

 证明:

 

 

 注意: (1)选取特征值时,如果一些特征值明显大于其他的特征值,则取这些取值较大的特征值,因为它们包含更多的数据分布的信息。相反,如果一些特征值接近于0,我们将这些特征值舍去。
(2)由于 W 是一个利用了样本类别得到的投影矩阵,因此它能够降维到的维度d的最大值为 K-1

 LDA算法流程

 

 LDA算法优缺点

优点

    1.在降维过程中可以使用类别的先验知识经验,而像PCA这样的无监督学习则无法使用类别先验知识。

    2.LDA在样本分类信息依赖均值而不是方差的时候,比PCA之类的算法较优。

缺点

    1.LDA不适合对非高斯分布样本进行降维,PCA也有这个问题。

    2.LDA降维最多降到类别数k-1的维数,如果我们降维的维度大于k-1,则不能使用LDA。当然目前有一些LDA的进化版算法可以绕过这个问题。

    3.LDA在样本分类信息依赖方差而不是均值的时候,降维效果不好。

    4.LDA可能过度拟合数据。
 

 二、线性分类算法(支持向量机SVM)

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。


优缺点

优点:

有严格的数学理论支持,可解释性强,不依靠统计方法,从而简化了通常的分类和回归问题;
能找出对任务至关重要的关键样本(即:支持向量);
采用核技巧之后,可以处理非线性分类/回归任务;
最终决策函数只由少数的支持向量所确定,计算的复杂性取决于支持向量的数目,而不是样本空间的维数,这在某种意义上避免了“维数灾难”。

缺点:

  • 训练时间长。当采用 SMO 算法时,由于每次都需要挑选一对参数,因此时间复杂度为 [公式] ,其中 N 为训练样本的数量;
  • 当采用核技巧时,如果需要存储核矩阵,则空间复杂度为 [公式] ;
  • 模型预测时,预测时间与支持向量的个数成正比。当支持向量的数量较大时,预测计算复杂度较高。

三、LDA算法代码实现 

python编程实现:

1.引入相关库:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#计算均值,要求输入数据为numpy的矩阵格式,行表示样本数,列表示特征    
def meanX(data):
    return np.mean(data, axis=0) #axis=0表示按照列来求均值,如果输入list,则axis=1

LDA算法实现:

#计算类内离散度矩阵子项si
def compute_si(xi):
    n = xi.shape[0]
    ui = meanX(xi)
    si = 0
    for i in range(0, n):
        si = si + ( xi[i, :] - ui).T * (xi[i, :] - ui )   
    return si

#计算类间离散度矩阵Sb
def compute_Sb(x1, x2):
    dataX=np.vstack((x1,x2))#合并样本   
    print ("dataX:", dataX)
    #计算均值
    u1=meanX(x1)
    u2=meanX(x2)    
    u=meanX(dataX) #所有样本的均值
    Sb = (u-u1).T * (u-u1) + (u-u2).T * (u-u2)
    return Sb
    
        
def LDA(x1, x2):
    #计算类内离散度矩阵Sw
    s1 = compute_si(x1)
    s2 = compute_si(x2)     
    #Sw=(n1*s1+n2*s2)/(n1+n2)
    Sw = s1 + s2
    
    #计算类间离散度矩阵Sb
    #Sb=(n1*(m-m1).T*(m-m1)+n2*(m-m2).T*(m-m2))/(n1+n2)
    Sb = compute_Sb(x1, x2)
    
    #求最大特征值对应的特征向量    
    eig_value, vec = np.linalg.eig(np.mat(Sw).I*Sb)#特征值和特征向量
    index_vec = np.argsort(-eig_value)#对eig_value从大到小排序,返回索引
    eig_index = index_vec[:1] #取出最大的特征值的索引
    w = vec[:, eig_index] #取出最大的特征值对应的特征向量
    return w

构造数据集:

def createDataSet():  
    X1 = np.mat(np.random.random((8, 2)) * 5 + 15)  #类别A
    X2 = np.mat(np.random.random((8, 2)) * 5 + 2)   #类别B
    return X1, X2  

x1, x2 = createDataSet()

print(x1,x2)

 LDA训练:

w = LDA(x1, x2)
print("w:",w)

# 编写一个绘图函数
def plotFig(group):  
    fig = plt.figure()  
    plt.ylim(0, 30)  
    plt.xlim(0, 30)  
    ax = fig.add_subplot(111)  
    ax.scatter(group[0,:].tolist(), group[1,:].tolist())  
    plt.show()  
#绘制图形
plotFig(np.hstack((x1.T, x2.T)))  

 

 实例测试:

test2 = np.mat([2, 8]) 
g = np.dot(w.T, test2.T - 0.5 * (meanX(x1)-meanX(x2)).T)  
print("Output: ", g  )

 sklearn 库实现

#coding=utf-8

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
import numpy as np

def main():
    iris = datasets.load_iris() #典型分类数据模型
    #这里我们数据统一用pandas处理
    data = pd.DataFrame(iris.data, columns=iris.feature_names)
    data['class'] = iris.target
    
    #这里只取两类
#     data = data[data['class']!=2]
    #为了可视化方便,这里取两个属性为例
    X = data[data.columns.drop('class')]
    Y = data['class']
    
    #划分数据集
    X_train, X_test, Y_train, Y_test =train_test_split(X, Y)
    lda = LinearDiscriminantAnalysis(n_components=2)
    lda.fit(X_train, Y_train)
    
    #显示训练结果
    print lda.means_ #中心点
    print lda.score(X_test, Y_test) #score是指分类的正确率
    print lda.scalings_ #score是指分类的正确率

    X_2d = lda.transform(X) #现在已经降到二维X_2d=np.dot(X-lda.xbar_,lda.scalings_)
    #对于二维数据,我们做个可视化
    #区域划分
    lda.fit(X_2d,Y)
    h = 0.02
    x_min, x_max = X_2d[:, 0].min() - 1, X_2d[:, 0].max() + 1
    y_min, y_max = X_2d[:, 1].min() - 1, X_2d[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    Z = lda.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)

    #做出原来的散点图
    class1_x = X_2d[Y==0,0]
    class1_y = X_2d[Y==0,1]
    l1 = plt.scatter(class1_x,class1_y,color='b',label=iris.target_names[0])
    class1_x = X_2d[Y==1,0]
    class1_y = X_2d[Y==1,1]
    l2 = plt.scatter(class1_x,class1_y,color='y',label=iris.target_names[1])
    class1_x = X_2d[Y==2,0]
    class1_y = X_2d[Y==2,1]
    l3 = plt.scatter(class1_x,class1_y,color='r',label=iris.target_names[2])
    
    plt.legend(handles = [l1, l2, l3], loc = 'best')
    
    plt.grid(True)
    plt.show()

if __name__ == '__main__':
    main()

 

 四、月亮数据集算法可视化

使用线性LDA对月亮数据集聚类

#基于线性LDA算法对月亮数据集进行分类
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from mpl_toolkits.mplot3d import Axes3D
def LDA(X, y):
    X1 = np.array([X[i] for i in range(len(X)) if y[i] == 0])
    X2 = np.array([X[i] for i in range(len(X)) if y[i] == 1])
    len1 = len(X1)
    len2 = len(X2)
    mju1 = np.mean(X1, axis=0)#求中心点
    mju2 = np.mean(X2, axis=0)
    cov1 = np.dot((X1 - mju1).T, (X1 - mju1))
    cov2 = np.dot((X2 - mju2).T, (X2 - mju2))
    Sw = cov1 + cov2
    w = np.dot(np.mat(Sw).I,(mju1 - mju2).reshape((len(mju1),1)))# 计算w
    X1_new = func(X1, w)
    X2_new = func(X2, w)
    y1_new = [1 for i in range(len1)]
    y2_new = [2 for i in range(len2)]
    return X1_new, X2_new, y1_new, y2_new
def func(x, w):
    return np.dot((x), w)
if '__main__' == __name__:
    X, y = make_moons(n_samples=100, noise=0.15, random_state=42)
    X1_new, X2_new, y1_new, y2_new = LDA(X, y)
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
    plt.show()

 使用k-means对鸢尾花数据集聚类

# -*- coding:utf-8 -*-
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
 
# 导入月亮型数据(证明kmean不能很好对其进行聚类)
X,y = make_moons(n_samples=200,random_state=0,noise=0.05)
print(X.shape)
print(y.shape)
plt.scatter(X[:,0],X[:,1])
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
y_pred = kmeans.predict(X)
cluster_center = kmeans.cluster_centers_
plt.scatter(X[:,0],X[:,1],c=y_pred)
plt.scatter(cluster_center[:,0],cluster_center[:,1],marker='^',linewidth=4)
plt.show()


 使用SVM对月亮数据集聚类

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_moons

# 导入数据集
X,y = make_moons(n_samples=200,random_state=0,noise=0.05)

h = .02  # 网格中的步长

# 创建支持向量机实例,并拟合出数据
C = 1.0  # SVM正则化参数
svc = svm.SVC(kernel='linear', C=C).fit(X, y) # 线性核
rbf_svc = svm.SVC(kernel='rbf', gamma=0.7, C=C).fit(X, y) # 径向基核
poly_svc = svm.SVC(kernel='poly', degree=3, C=C).fit(X, y) # 多项式核
lin_svc = svm.LinearSVC(C=C).fit(X, y) #线性核

# 创建网格,以绘制图像
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))

# 图的标题
titles = ['SVC with linear kernel',
          'LinearSVC (linear kernel)',
          'SVC with RBF kernel',
          'SVC with polynomial (degree 3) kernel']


for i, clf in enumerate((svc, lin_svc, rbf_svc, poly_svc)):
    # 绘出决策边界,不同的区域分配不同的颜色
    plt.subplot(2, 2, i + 1) # 创建一个2行2列的图,并以第i个图为当前图
    plt.subplots_adjust(wspace=0.4, hspace=0.4) # 设置子图间隔

    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) #将xx和yy中的元素组成一对对坐标,作为支持向量机的输入,返回一个array
    
    # 把分类结果绘制出来
    Z = Z.reshape(xx.shape) #(220, 280)
    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8) #使用等高线的函数将不同的区域绘制出来

    # 将训练数据以离散点的形式绘制出来
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    plt.xlim(xx.min(), xx.max())
    plt.ylim(yy.min(), yy.max())
    plt.xticks(())
    plt.yticks(())
    plt.title(titles[i])

plt.show()

五 . 总结

本次实验了解了LDA算法和SVM算法的原理优缺点,以及两类算法的代码实现过程。.LDA在样本分类信息依赖均值而不是方差的时候,比PCA之类的算法较优。SVM算法最终决策函数只由少数的支持向量所确定,计算的复杂性取决于支持向量的数目,而不是样本空间的维数,这在某种意义上避免了“维数灾难”。

六 参考链接

线性判别准则与线性分类编程实践

线性判别分析(LDA)基本原理及实现

 

线性判别分析LDA原理及推导过程(非常详细)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>