线性及非线性分类器

模式识别课程实验

在鸢尾花数据集上实现感知器算法和支持向量机算法。

鸢尾花数据集iris包含3类鸢尾花,分别为山鸢尾(Iris-setosa)、杂色鸢尾(Iris-versicolor)和维吉尼亚鸢尾(Iris-virginica),每类各 50 条记录,共 150 条记录,每条记录都包含 4 项特征:花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width)。如下图:

 sklearn中datasets中的鸢尾花数据与上图有不同。

读取iris鸢尾花数据集,绘制散点图展示3类鸢尾花。

def show():
    print('')
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target  #分类标签

    tab=["Sepal.Length 萼片长度","Sepal.Width 萼片宽度","Petal.Length 花瓣长度","Petal.Width 花瓣宽度"]
    for i in range(4):
        for j in range(i+1,4):#两个循环实现在4个维度上选择2个来绘图
            print('绘制', tab[i], '与', tab[j], '数据的图像')
            x0 = X[y == 0, i:i + 1]
            x1 = X[y == 1, i:i + 1]
            x2 = X[y == 2, i:i + 1]
            y0 = X[y == 0, j:j + 1]
            y1 = X[y == 1, j:j + 1]
            y2 = X[y == 2, j:j + 1]

            # 表示绘制图形的画板尺寸为8*5
            plt.figure(figsize=(8, 5))
            # 散点图的x坐标、y坐标、标签
            plt.scatter(x0, y0, label='Iris-setosa 山鸢尾')
            plt.scatter(x1, y1, label='Iris-versicolor 杂色鸢尾')
            plt.scatter(x2, y2, label='Iris-virginica 维吉尼亚鸢尾')
            plt.xlabel(str(tab[i]) + '/cm')
            plt.ylabel(str(tab[j]) + '/cm')
            # 添加标题 '鸢尾花萼片的长度与宽度的散点分布'
            title = '鸢尾花数据的散点分布'
            plt.title(str(title))
            # 显示标签
            plt.legend()
            plt.show()
    print('**图片绘制结束**')

结果展示:

 

像是这样的图片,有6张。 

使用感知器算法区分山鸢尾和维吉尼亚鸢尾

def PLA(max_iter=2000,step=0.1,w=[1,-1],w_0=5,print_data=1):#迭代次数,步长,初始权重,初始偏置,显示模式
    #max_iter 最多迭代max_iter次
    #step 步长
    w=np.mat(w)    #初始权重
    w_0=np.mat(w_0)     #偏置

    #print_data控制输出 0-不输出 1-少输出 2-多输出
    if print_data==0:#p1 p2 控制显示的等级
        p1=p2=False
    elif print_data==1:
        p1=True
        p2=False
    elif print_data==2:
        p1=p2=True


    a=np.bmat('w_0 w')

    #input data
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target  # 目标
    # 舍弃y==1的部分(不要第二个分类)
    XX = X[y != 1,:]
    # 舍弃y==1的部分
    y = y[y != 1]
    tab = y

    for i in [0,2]:
        if i==0:
            xlabel = '花萼长度'
            ylabel = '花萼宽度'
        if i==2:
            xlabel = '花瓣长度'
            ylabel = '花瓣宽度'

        #花萼长度和花萼宽度
        #只要前两项数据(萼片数据)
        X = XX[:, i:i+2]

        #转换
        x = np.mat(X)



        #初始化
        r1=np.mat('1')
        y_n=[]
        for ii in range(len(tab)):
            r2 = x[ii]
            y_i=np.bmat('r1 r2')
            if tab[ii]==2:
                y_i=y_i*-1
            #print('y',ii,'=',y_i)#完成计算
            y_n.append(y_i)#存储

        #更改格式为matrix
        y=np.bmat(y_n[0])
        for ii in range(1,len(y_n)):
            r2=y_n[ii]
            y=np.bmat('y;r2')


        #迭代
        tiaos=0
        for iter_num in range(max_iter):
            if p1:print('第',iter_num+1,'轮:')
            true_num = 1    #统计是否全部分类成功
            for ii in range(len(tab)):
                yy=np.dot(a,y[ii].T)

                if p2:print('y',ii+1,'=',yy)

                if yy>0:
                    if p2:print('分类正确')
                    true_num=true_num*1
                elif yy==0:
                    if p2:print('=0!')
                    true_num=true_num*1
                else:
                    if p2:print('分类错误,更新参数')
                    a=a+step*y[ii]
                    if p2:print('a=',a)
                    true_num=true_num*0
            if true_num==1:     #全部分类成功
                if p1:print('全部分类成功')
                break
        if p1:print('如果没有显示‘全部分类成功’则迭代超过上限')
        #绘图
        x=np.array(x)
        x0=[]
        y0=[]
        x1=[]
        y1=[]
        for ii in range(len(tab)):
            if tab[ii]==0:
                x0.append(x[ii][0])
                y0.append(x[ii][1])
            elif tab[ii]==2:
                x1.append(x[ii][0])
                y1.append(x[ii][1])



        # 表示绘制图形的画板尺寸为8*5
        plt.figure(figsize=(8, 5))
        # 散点图的x坐标、y坐标、标签
        plt.scatter(x0, y0, label='山鸢尾')
        plt.scatter(x1, y1, label='维吉尼亚鸢尾')

        #分类线
        a = np.array(a)
        a=a[0]
        if a[1]!=0 and a[2]!=0:
            max_plot=max(max(x0),max(x1))
            min_plot=min(min(x0),min(x1))
            plot_x1=min_plot
            plot_x2=max_plot
            plot_y1=(-a[0]-a[1]*plot_x1)/a[2]
            #print(plot_y1)
            plot_y2=(-a[0]-a[1]*plot_x2)/a[2]
            #print(plot_y2)
            plt.plot([plot_x1, plot_x2], [plot_y1, plot_y2], color='r')

        plt.xlabel(xlabel)
        plt.ylabel(ylabel)
        # 添加标题
        title = '感知器算法区分山鸢尾和维吉尼亚鸢尾'
        plt.title(str(title))
        # 显示标签
        plt.legend()
        plt.show()

结果展示:

 

注:分类平面受到参数影响,可能与示例图片不同。 

基于花萼长度和花萼宽度两个特征用线性SVM算法区分山鸢尾和维吉尼亚鸢尾

def SVM1():
    print('基于花萼长度和花萼宽度两个特征用线性SVM算法区分山鸢尾和维吉尼亚鸢尾。')
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target#目标

    #舍弃y==0的部分(不要第2个分类),并且只要前两项数据(萼片数据)
    X = X[y != 1, :2]

    #舍弃y==0的部分(不要第2个分类)
    y = y[y != 1]

    n_sample = len(X)
    #print('样本数量:',n_sample)

    #这里先绘制图像
    plt.figure(figsize=(8, 5))

    x0 = X[y == 0, 0]
    y0 = X[y == 0, 1]
    plt.scatter(x0, y0,s=10, label='Iris-setosa 山鸢尾')
    x2 = X[y == 2, 0]
    y2 = X[y == 2, 1]
    plt.scatter(x2, y2,s=10, label='Iris-virginica 维吉尼亚鸢尾')

    #随机数种子
    np.random.seed(0)
    #print(np.random.rand(5))

    #产生一个随机序列(不重复,不遗漏0-【n-1】),由于固定了随机数种子,order每次运行都是一样的
    order = np.random.permutation(n_sample)
    #print(order)

    #按照随机序列进行随机排序
    X = X[order]

    #按照一样的随机序列进行随机排序
    y = y[order].astype(float)

    #0.9的训练(90)
    X_train = X[: int(0.9 * n_sample)]
    y_train = y[: int(0.9 * n_sample)]
    #测试
    X_test = X[int(0.9 * n_sample) :]
    #y_test = y[int(0.9 * n_sample) :]

    clf = svm.SVC(C = 50,kernel="linear", gamma=20)#错误术语的惩罚参数C , kernel核函数类型 , gamma核函数系数

    clf.fit(X_train, y_train)

    # Circle out the test data 圈出测试数据none
    plt.scatter(
        X_test[:, 0], X_test[:, 1], s=30, facecolors="none", zorder=100, edgecolor="k"
    )

    #绘制超平面

    #计算分类面方程,计算划线点
    #wx+b=0 , w=[ , ]
    b=clf.intercept_
    w=clf.coef_
    x_max = X[:, 0].max()
    x_min = X[:, 0].min()
    max_y=(-b-w[0][0]*x_max)/w[0][1]
    min_y=(-b-w[0][0]*x_min)/w[0][1]
    x=[x_min,x_max]
    y=[min_y,max_y]

    plt.plot(x,y,'-r')
    plt.title('线性SVM算法区分山鸢尾和维吉尼亚鸢尾')
    plt.xlabel('花萼长度(sepal length)')
    plt.ylabel('花萼宽度(sepal width)')
    plt.legend()
    plt.show()

结果展示:

注:超平面受到参数影响,可能与示例图片不同。  

 基于所有特征用SVM算法区分三类鸢尾花,分别使用线性核、RBF核和Sigmoid核进行分类。

def SVM():
    print('基于所有特征用SVM算法区分三类鸢尾花,分别使用线性核、RBF核和Sigmoid核进行分类。')
    #导入数据
    from sklearn.datasets import load_iris
    iris = load_iris()
    X = iris.data
    #print(X.shape, X)
    y = iris.target
    #print(y.shape, y)

    for kernel in ['linear','rbf','sigmoid']:
        #svm
        C = 10
        gamma = 100
        Svm=svm.SVC(kernel=kernel,C=C,gamma=gamma)
        #使用全部特征对鸢尾花进行分类
        Svm.fit(X[:,:4],y)
        #训练得分:
        print('\nkernel=',kernel,' C=',C,' gamma=',gamma,':')
        print("training score:", Svm.score(X[:, :4], y))
        #print("predict: ", Svm.predict([[7, 5, 2, 0.5], [7.5, 4, 7, 2]]))

结果展示:

 

 

使用到的库:

import numpy as np
import matplotlib.pyplot as plt
...
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False
#中文支持
...

from sklearn import datasets

from sklearn import svm

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值