• 西瓜书3.4 解题报告(python 多分类学习 十折交叉法)


    偷懒找了UCI上最小的一个数据集,数据大约是集装箱起重机的转动速度、角度,判断其力量大小(我不懂起重机啊啊啊)

    虽然不懂但并不妨碍写代码分类,显然标记就是力量,分为0.3、0.5、0.7三种。具体的模型学习还是使用对率回归,那么数据集如下。

    x=np.array([[1,2,6,7,10,8,3,1,6,7,8,9,9,2,6],[-5,5,-2,2,-2,2,-2,2,-5,5,-5,5,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]])
    y=np.array([0.3,0.3,0.3,0.3,0.3,0.3,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.7,0.7])

    因为是多分类问题所以我们要建立多个分类器,这次使用OvR的方法,建立三个分类器也就是要计算出三组参数的值:

    b=np.array([[0],[0],[1]])
    b1=np.array([[0],[0],[1]])
    b2=np.array([[0],[0],[1]])
    b3=np.array([[0],[0],[1]])

    b是用于计算的时候暂存参数。既然是十折交叉法,那我们每次就取两个样本作为测试集,为了方便计算,每次的训练集我们赋值到另外两个矩阵上,先在全局初始化它们:

    x1=np.zeros(shape=(3,13))
    y1=np.arange(0,13)

    注意这里的y1不能用zeros初始化,否则编译器认为这个y1的shape是(0,13),会报错,非常要命(躺)。

    求参数的主体函数基本不用动,稍微改下参数名以防重复即可:

    def fd():
         b11 = 0
         for i in range(13):
              k=np.exp(np.dot(b.T,np.array([x1[:,i]]).T))
              b11=b11-np.array([x1[:,i]])*( y1[i]-(k/(1+k)))
         return b11
    
    def sd():
         b22 = 0
         for i in range(13):
              k = np.exp(np.dot(b.T,np.array([x1[:,i]]).T))
              b22=b22+np.dot(np.array([x1[:,i]]).T,np.array([x1[:,i]])) * (k/(1+k)) * (1-(k/(1+k)))
         return b22
    
    
    def form():
        mae=0
        ima=0
        b = np.array([[0], [0], [1]])
        while(1):
             ima=0
             for i in range(13):
                  k=np.dot(b.T,np.array([x1[:,i]]).T)
                  ima=ima+(-y1[i]*k+np.log(1+np.exp(k)))
             if(np.abs(ima-mae)<=0.0001):
                  break
             mae=ima
             b11=fd()
             b22=sd()
             b=b-np.dot(linalg.inv(b22),b11.T)
        return b

    然后每次OvR我们要对y1进行重新赋值,将值按要求修改为1和0:

    def sety(tru):
         for k in range(13):
              if (y1[k] == tru):
                   y1[k] = 1
              else:
                   y1[k] = 0
         return

    tru就是该分类器应当分类为真值的y的原值。

    而后为了判断每个分类器的正确率,需要另写一个函数,这里写的这个函数只判断对于单个样本(在全集中的序列号为i)的正误,显然的,

    只要应当判断其为1的分类器出错就可以直接确定其出错,虽然这种操作还是有一定风险的(如果其他分类器也判断该例为正该怎么算),

    但偷懒就这么写了。

    def judg(i):
         s0=0.0
         if (y[i] == 0.3):
              z = np.exp(np.dot(b1.T, np.array([x[:, i]]).T))
         elif (y[i] == 0.5):
              z = np.exp(np.dot(b2.T, np.array([x[:, i]]).T))
         else:
              z = np.exp(np.dot(b3.T, np.array([x[:, i]]).T))
         if (z > 0):
              z=1
         else:
              z=0
         return z

    然后就是每次抽取训练集的函数,也就是从x、y中删掉指定两列之后赋值给x1、y1的函数:

    def delex(i,j):
         k=0
         for f in range(15):
              if(f!=i and f!=j):
                   x1[:,k]=x[:,f]
                   k=k+1
         return
    
    def deley(i,j):
         k = 0
         for f in range(y.size):
              if (f != i and f != j):
                    y1[k] = y[f]
                    k = k + 1
         return

    主函数如下:

    s=0.0
    for i in range(15):
         for j in range(i+1,15):
              s0=0.0
              delex(i,j)
              deley(i,j)
              sety(0.3)
              b1=form()
              deley(i,j)
              sety(0.5)
              b2=form()
              deley(i,j)
              sety(0.7)
              b3=form()
              s=s+(judg(i)+judg(j))/2
              print('',i,'个与第',j,'个作为测试集时的正确率暂时总和为',s)
    s=s/105
    print('正确率为:',s)

    运行结果:

    第 0 个与第 1 个作为测试集时的正确率暂时总和为 1.0...(略)
    第 13 个与第 14 个作为测试集时的正确率暂时总和为 105.0
    正确率为: 1.0

     留一法同理,修改一下参数数量和一些数字就行,编译器作怪的话可以加一些跳出条件。

    补充另一个数据集的读取文件然后进行计算的代码,虽然没有error但是跑了一顿午饭也没跑出什么结果,卡无限循环了,改了个条件终于跑出结果,姑且摆在这里看看。

    import numpy as np
    from numpy import linalg
    import math
    import scipy
    
    
    x=np.ones(shape=(14,178))
    y=np.arange(0,178)
    x1=np.ones(shape=(14,176))
    y1=np.arange(0,176)
    b=np.array([[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1]])
    b1=np.array([[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1]])
    b2=np.array([[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1]])
    b3=np.array([[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1]])
    
    
    def readdata():
        k=0
        file=open('C:\Users\33298\Desktop\data\2\winedata.txt','r')
        for line in file.readlines():
            clas,alcohol,malic,ash,alcalin,magne,t_phenols,flava,nonfla,proantho,color,hue,od,proli=line.split(',')
            #print(clas,alcohol,malic,ash,alcalin,magne,t_phenols,flava,nonfla,proantho,color,hue,od,proli)
            x[:,k]=np.array([alcohol,malic,ash,alcalin,magne,t_phenols,flava,nonfla,proantho,color,hue,od,proli,1]).T
            y[k]=clas
            k=k+1
        return
    
    
    def fd():
        b11 = 0
        for i in range(176):
            k = np.exp(np.dot(b.T, np.array([x1[:, i]]).T))
            b11 = b11 - np.array([x1[:, i]]) * (y1[i] - (k / (1 + k)))
        return b11
    
    
    def sd():
        b22 = 0
        for i in range(176):
            k = np.exp(np.dot(b.T, np.array([x1[:, i]]).T))
            b22 = b22 + np.dot(np.array([x1[:, i]]).T, np.array([x1[:, i]])) * (k / (1 + k)) * (1 - (k / (1 + k)))
        return b22
    
    
    def form():
        mae = 0
        ima = 0
        b=np.array([[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1]]) 
    num=10
    while (num): ima = 0 for i in range(176): k = np.dot(b.T, np.array([x1[:, i]]).T) if(k>1): ima=ima+np.log(1+np.exp(-k)) else: ima = ima + (-y1[i] * k + np.log(1 + np.exp(k))) if (np.abs(ima - mae) <= 0.000001): break mae = ima b11 = fd() b22 = sd() b = b - np.dot(linalg.inv(b22), b11.T)
    num-=1
    return b def sety(tru): for k in range(13): if (y1[k] == tru): y1[k] = 1 else: y1[k] = 0 return def judg(i): s0 = 0.0 if (y[i] == 1): z = np.exp(np.dot(b1.T, np.array([x[:, i]]).T)) elif (y[i] == 2): z = np.exp(np.dot(b2.T, np.array([x[:, i]]).T)) else: z = np.exp(np.dot(b3.T, np.array([x[:, i]]).T)) if (z > 0): z = 1 else: z = 0 return z def delex(i, j): k = 0 for f in range(178): if (f != i and f != j): x1[:, k] = x[:, f] k = k + 1 return def deley(i, j): k = 0 for f in range(y.size): if (f != i and f != j): y1[k] = y[f] k = k + 1 return readdata() s = 0.0 for i in range(178): for j in range(i + 1, 178): s0 = 0.0 delex(i, j) deley(i, j) sety(1) b1 = form() deley(i, j) sety(2) b2 = form() deley(i, j) sety(3) b3 = form() s = s + (judg(i) + judg(j)) / 2 print('', i, '个与第', j, '个作为测试集时的正确率暂时总和为', s) s = s / 15753 print('正确率为:', s)
  • 相关阅读:
    git 常用命令
    目录
    算法--双栈排序
    算法--栈的翻转练习题
    算法--双栈队列
    算法--可查询最值的栈练习题
    Spark算子--union、intersection、subtract
    Spark算子--take、top、takeOrdered
    Spark算子--countByKey
    Spark算子--SortBy
  • 原文地址:https://www.cnblogs.com/forever3329/p/13885401.html
Copyright © 2020-2023  润新知