决策树代码实现

马上要读研 未来方向是机器学习 最近要加紧学习啦~

先来研究了一下最基本的“决策树”  虽然现在又很多决策树实现的工具 例如scikit-learn 不过还是想先自己码一码代码 才能理解相关的内容

先来点基础知识篇

信息论相关知识:http://blog.csdn.net/dark_scope/article/details/8459576

决策树算法知识:http://blog.csdn.net/dark_scope/article/details/13168827 我的代码基本上和这个链接里面的一样 要感谢这位大神 不过他的代码有几个小错我改过来了~

多的不说 上代码(不过还没有实现控制决策树的层数,会更新的):  

#-*- coding:utf-8-*-
from __future__ import division
import numpy as np
import scipy as sp
import pylab as py

def pGini(y):
    ty=y.reshape(-1,).tolist() #将原来的y变为一个list
    label=set(ty)  #y中所有的类
    sum=0
    num_case=y.shape[0]
    for i in label:
	sum+=(np.count_nonzero(y==i)/num_case)**2
    return 1-sum

class DTC: #决策树类
    def __init__(self,x,y,property=None):
            #x 是训练样本 是M*N的数组 M是样本数 N是特征数
            #y是每个样本对应的类别
            #property 是一个二进制 长度为N的向量 代表第i个特征是离散的(0)还是连续的(1)
	if x.shape[0]==y.shape[0]:      
	    self.x=np.array(x)
            self.y=np.array(y)
            self.feature_dict={}
	    self.labels,self.y=np.unique(y,return_inverse=True)  #labels是所有不重复的类,y是原来y中每个值对应在labels中的位置 参加:http://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html
	    self.DT=list()
	    if property==None:
		self.property=np.zeros((self.x.shape[1],1))   #默认全为离散的feature
	    else:
		self.property=property
	   
	    for i in range(self.x.shape[1]):
		self.feature_dict[i]=np.unique(x[:,i])   #每个feature都有哪些取值
	else:
	    print 'x,y不一样长!'
    
    def Gini(self,x,y,k,k_v):
	if self.property[k]==0:
	    c1=(x[x[:,k]==k_v]).shape[0]
	    c2=(x[x[:,k]!=k_v]).shape[0]
	    D=y.shape[0]
	    return c1*pGini(y[x[:,k]==k_v])/D+c2*pGini(y[x[:,k]!=k_v])/D
	else:
	    c1=(x[x[:,k]>=k_v]).shape[0]
	    c2=(x[x[:,k]<k_v]).shape[0]
            D=y.shape[0]
	    return c1*pGini(y[x[:,k]>=k_v])/D+c2*pGini(y[x[:,k]<k_v])/D

    def makeTree(self,x,y):
	min=10000
	f_index,f_value=0,0
	if np.unique(y).size<=1:   #如果只有一个类 那就返回是这个类
	    return (y[0])   #返回的是类的序号
	for i in range(self.x.shape[1]):
	    for j in self.feature_dict[i]:
		p=self.Gini(x,y,i,j)
		if p<min:
		    min=p
		    f_index,f_value=i,j

	if min==1:
	    return (y[0])    #如果所有feature都没办法有效地分类 则任意定一个类
        left=[]
	right=[]
	if self.property[f_index]==0:
	    left=self.makeTree(x[x[:,f_index]==f_value],y[x[:,f_index]==f_value])
	    right=self.makeTree(x[x[:,f_index]!=f_value],y[x[:,f_index]!=f_value])
	else:
	    left=self.makeTree(x[x[:,f_index]>=f_value],y[x[:,f_index]>=f_value])  #左大右小
	    right=self.makeTree(x[x[:,f_index]<f_value],y[x[:,f_index]<f_value])
	return [(f_index,f_value),left,right]

    def train(self):
	self.DT=self.makeTree(self.x,self.y)
	print self.DT

    def pred(self,x):
	x=np.array(x)
        result=np.zeros((x.shape[0],1))
        for i in range(x.shape[0]):
	    tp=self.DT
	    while type(tp) is list:  #当仍未到达叶子节点时
		a,b=tp[0]  #第一个分切点
		if self.property[a]==0:
		    if x[i][a]==b:
			tp=tp[1]
		    else:
			tp=tp[2]
		else:
		    if x[i][a]>=b:
			tp=tp[1]
		    else:
			tp=tp[2]
	    result[i]=self.labels[tp]  #获得类
	return result


def test():
	x=np.array([[0,0,0,0,8],[0,0,0,1,3.5],[0,1,0,1,3.5],[0,1,1,0,3.5],[0,0,0,0,3.5],[1,0,0,0,3.5],[1,0,0,1,3.5],[1,1,1,1,2],[1,0,1,2,3.5],[1,0,1,2,3.5]])
        y=np.array([[1],[0],[1],[1],[0],[0],[0],[1],[1],[1]])
        prop=np.zeros((5,1))	
        prop[4]=1 
        a=DTC(x,y,prop)
        a.train()
        print a.pred([[0,0,0,0,3.0],[2,1,0,1,2]])

test()


你可能感兴趣的:(机器学习)