numpy实现决策树

决策树的原理就是找到易于区分类的特征值进行空间划分,得到最终的分类空间。

import numpy as np 
import matplotlib.pyplot as plt 
def mid(node):
    print(node.index,node.value,node.lay_num,node.att)
    if node.flag==0:
        mid(node.left)
        mid(node.right)
def predict(data,node):
    if node.flag==1:
        return node.clas
    if data[node.index]<=node.value:
        return predict(data,node.left)
    else:
        return predict(data,node.right)
class tree:
    def __init__(self,lay_num=0,str="gen"):
        self.flag=0
        self.index=0
        self.value=0
        self.clas=0
        self.lay_num=lay_num
        self.att=str
        self.left=None
        self.right=None
def ginic(data):
    sum=len(data)
    sum1=0
    sum2=0
    for i in range(len(data)):
        if data[i,4]==1:
            sum1+=1
        else:
            sum2+=1
    p1=0
    p2=0
    if sum==0:
        return 0
    if sum1==0:
        p1=0
    else:
        p1=sum1/sum
    if sum2==0:
        p2=0
    else:
        p2=sum2/sum
    return 1-p1**2-p2**2    
def compute(feature,value,data):
    d1=[]
    d2=[]
    for i in range(len(data)):
        if data[i,feature]<=value[feature]:
            d1.append(data[i])
        else:
            d2.append(data[i])
    d1=np.array(d1)
    d2=np.array(d2)
    sum1=len(d1)
    sum2=len(d2)
    sum11=0
    sum12=0
    sum21=0
    sum22=0
    for i in range(sum1):
        if d1[i,4]==1:
            sum11+=1
        else:
            sum12+=1
    for i in range(sum2):
        if d2[i,4]==1:
            sum21+=1
        else:
            sum22+=1
    p1=0
    p2=0
    if sum1==0:
        p1=0
    else:
        p1=sum1/len(data)
    if sum2==0:
        p2=0
    else:
        p2=sum2/len(data)
    gi=p1*ginic(d1)+p2*ginic(d2)    
    return gi,value[feature]
def gini(index,data):
    length=len(data)
    min=1000
    in_value=0
    for i in range(length):
        if data[i,index]!=data[0:length,index].max():
            gi,da=compute(index,data[i],data)
            if min>gi:
                min=gi
                in_value=da
    return min,in_value
def create(data,i,str):
    node=tree(lay_num=i,str=str)
    node.lay_num=i
    k=i
    att=np.zeros((4,2))
    min=2
    flag=0
    for i in range(len(data)-1):
        if data[i,4]!=data[i+1,4]:
            flag=1
    if flag==0:
        node.flag=1
        node.att="leaf"
        node.clas=data[0,4]
        print(node.clas)
        return node
    index=0
    value=0
    for i in range(4):
        att[i,0],att[i,1]=gini(i,data)
        if min>att[i,0]:
            min=att[i,0]
            value=att[i,1]
            index=i
    w1=[]
    w2=[]
    node.index=index
    node.value=value
    for i in range(len(data)):
        if data[i,index]<=value:
            w1.append(data[i])
        else:
            w2.append(data[i])
    w1=np.array(w1)
    w2=np.array(w2)
    node.left=create(w1,k+1,"left")
    node.right=create(w2,k+1,"right")
    return node    
w=20
train=np.random.randint(-300,300,(w,4))
train=train.astype(float)
train_lable=np.zeros((w,1))
test=np.random.randint(-300,300,(w,4))
traint=train.astype(float)
test_lable=np.zeros((w,1))
for i in range(w):
    if 1*train[i,0]+2*train[i,1]+3*train[i,2]+4*train[i,3]-1>0:
        train_lable[i]=1
    else:
        train_lable[i]=-1
    if 1*test[i,0]+2*test[i,1]+3*test[i,2]+4*test[i,3]-1>0:     
        test_lable[i]=1
    else:
        test_lable[i]=-1  
train=np.concatenate((train,train_lable),axis=1)
train=np.array([[1,1,-1,1,1],[2,1,-1,1,1],[3,1,-1,1,1],[4,1,-1,1,1],[5,1,-1,1,1],[-1,-2,-1,1,1],[-1,-3,-1,1,1],[-1,-1,1,1,1],[-1,-1,-1,2,-1],[-1,-1,-1,1,-1]])
test=np.concatenate((test,test_lable),axis=1)
node1=create(train,0,"gen")
acc=0
for i in range(250):
    w=predict(test[i],node1)
    if w==test[i,4]:
        acc+=1
print(acc/250)
print(train)
mid(node1)
posted @ 2021-08-17 16:47  祥瑞哈哈哈  阅读(250)  评论(0)    收藏  举报