马上要读研 未来方向是机器学习 最近要加紧学习啦~
先来研究了一下最基本的“决策树” 虽然现在又很多决策树实现的工具 例如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()