分类树的应用--电信数据

决策树

决策树是一种有监督学习算法,既可以用于回归问题,也可以用于分类问题。它既适用于分类变量,也适用于连续输入变量和输出变量。在这里插入图片描述
分为:回归树,分类树
生成树状模型方法:Bagging,Random Forests,Boosting
Bagging策略来源于bootstrap aggregation:

  1. 从样本集(假设样本集N个数据点)中重采样选出Nb个样本(有放回的采样,样本数据点个数仍然不变为N);
  2. 对N个样本建立分类器(ID3\C4.5\CART\SVM\LOGISTIC),重复以上两步B次,获得B个分类器;
  3. 根据这B个分类器的投票结果,进行平均,得到最终的函数模型。
    在这里插入图片描述
    随机森林在bagging的基础上更进一步:
  4. 样本的随机:从样本集中用Bootstrap随机选取n个样本。
  5. 特征的随机:从所有属性中随机选取K个属性,选择最佳分割属性作为节点建立CART决策树(也可以是其他类型的分类器,比如SVM、Logistics)
  6. 重复以上两步m次,即建立了m棵CART决策树
  7. 这m个CART形成随机森林,通过投票表决结果,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数)
    在这里插入图片描述
    Boosting于bagging相似,不一样的地方在于这些树不是相互分开独立的,而是连续增长的:每一棵树都是从之前的树生长出来的。Boosting不涉及随机采样,每一棵树都是从之前的树中修改的。
    在这里插入图片描述
    决策树的优点和缺点其有点是便于理解,它贴近于人类做决策的过程,于人类思考方式相似。但是它的准确率不高,数据中小小的扰动就可以使得整个决策树的分类变化。因此对于方差小的数据,使用上述的三种模型方法,可以提高它的准确性。
    来源:https://www.datacamp.com/community/tutorials/decision-trees-R

分类树

决策树的构建概括为3个步骤:特征选择、决策树的生成和决策树的修剪

特征的选择

信息增益:在划分数据集之前之后信息发生的变化成为信息增益,获得信息增益最高的特征就是最好的选择。
香农熵的计算方式:
l ( x i ) = − l o g 2 p ( x i ) l(x_i) = -log_2p(x_i) l(xi)=log2p(xi)
H = − Σ p ( x i ) l o g 2 p ( x i ) H =-\Sigma p(x_i)log_2p(x_i) H=Σp(xi)log2p(xi)
信息增益的计算方式:
H ( Y ∣ X ) = Σ p i H ( Y ∣ X = x i ) H(Y|X) = \Sigma p_iH(Y|X =x_i) H(YX)=ΣpiH(YX=xi)

ID3 算法通过递归的方式建立决策树。建立时,从根节点开始,对节点计算每个独立特征的信息增益,选择信息增益最大的特征作为节点特征。接下来,对该特征施加判断条件,建立子节点。然后针对子节点再此使用信息增益进行判断,直到所有特征的信息增益很小或者没有特征时结束,这样就逐步建立一颗完整的决策树。

C4.5 算法使用了信息增益比来选择特征,这被看成是 ID3 算法的一种改进。

这两个算法从信息增益和信息增益比开始,对整个训练集进行的分类,拟合出来的模型针对该训练集的确是非常完美的。但是,这种完美就使得整体模型的复杂度较高,而对其他数据集的预测能力就降低了,也就是我们常说的过拟合而使得模型的泛化能力变弱。
优化方案:
<1>剪枝处理
前置剪枝,后置剪枝
<2>交叉验证
生成K种决策树(利用不同的剪枝规则),选取性能最好的
<3>随机森林

CART 算法在生成树的过程中,分类树采用了基尼指数(Gini Index)最小化原则,回归树选择了平方损失函数最小化原则。基尼指数在运算过程中的速度会更快一些。

2.数据预处理

pandas读取数据:

from math import log
import pandas as pd
def traindata():
    dataall = pd.read_csv(open('D:/second diploma/Bigdata/Train/processeddata.csv'))
    data = dataall.drop(['X1_total_fee', 'X2_total_fee', 'X3_total_fee', 'X4_total_fee','service1_caller_time', 'service2_caller_time', 'gender','user_id'],axis=1)
    "axis=0代表往跨行(down),而axis=1代表跨列(across),作为方法动作的副词,删除CPA分析后不重要的属性"
#lables = ['service_type', 'is_mix_service', 'online_time', 'month_traffic',
#          'many_over_bill', 'contract_type', 'contract_time', 'is_promise_low_consume', 
#          'net_service', 'pay_times', 'pay_num', 'last_month_traffic', 'local_trafffic_month', 
#          'local_caller_time', 'age', 'complaint_level','former_complaint_fee', 'ave_total_fee']
    lables = data.head(0)
    return data,lables

Python中的():代表tuple元祖数据类型,元祖是一种不可变序列。
Python中的[]:代表list列表数据类型,列表是一种可变序列。
Python中的{}:代表dict字典数据类型,字典是Python中唯一内建的映射类型。字典中的值没有特殊的顺序,但都是存储在一个特定的键(key)下。键可以是数字、字符串甚至是元祖。

变量的类型,根据给出的赋值语句决定(变量的值来决定)
原文:https://www.cnblogs.com/fydeblog/p/7159775.html

3.决策树实现

"香农熵计算"
from math import log
import operator
import numpy as np
import matplotlib.pyplot as plt
def calshannonent(dataset):   #计算信息熵
    numentries=len(dataset)
    labelcounts={}
    for featvec in dataset:               #对dataSet的每一个元素进行处理  
        currentlabel=featvec[-1]        #//将dataSet的每一个元素的最后一个元素选择出来        
        if currentlabel not in labelcounts.keys():  
            labelcounts[currentlabel]=0  #//若没有该键,则使用字典的自动添加进行添加值为0的项,取0是因为下一行代码              
        labelcounts[currentlabel] +=1    #对currentlabel计数,每有一个key:currentlabel,就在对应的key的值上加一
    shannonent=0
    for key in labelcounts:
        prob=float(labelcounts[key])/numentries
        shannonent -=prob*log(prob,2)
    return shannonent

使用R进行处理

利用ID3算法使用了rpart包:

library("rpart")
alldata<-read.csv("alldata.csv",header = TRUE,sep = ",")
myFormula <- label.train~service_type+is_mix_service+online_time+month_traffic+many_over_bill+contract_type+is_promise_low_consume+pay_num+last_month_traffic+local_trafffic_month+local_caller_time+service2_caller_time+age+former_complaint_num+ave_total_fee
tree <- rpart(myFormula,data = alldata,method = "class",parms = list(split="information"),xval=10,control = list(minsplit=20,minbucket=150,cp=0.01))
##minbucket--叶节点所含样本最小数,这里指大于等于20,那么该节点会继续分划下去,否则停止 
##minsplit--每个节点所含样本最小数
##cp--复杂度参数,对每一步拆分,模型的拟合优度必须提高的程度
##预测并计算准确率
library(ggplot2)
library(caret)
library(e1071)
pred.tree <- predict(tree, newdata = test.data, type = "class")
confusionMatrix(pred.tree, test.data$label.test)
library(rattle)
asRules(tree)

##画图
library(cluster)
library(maptree)
draw.tree(tree,cex=0.6,nodeinfo=TRUE,col=gray(0:8 / 8))
plotcp(tree)
printcp(tree)

若想用CART算法来研究,则需要用split="gini"来计算

随机森林

在随机森林算法的函数randomForest()中有两个非常重要的参数,而这两个参数又将影响模型的准确性,它们分别是mtry和ntree。一般对mtry的选择是逐一尝试,直到找到比较理想的值,ntree的选择可通过图形大致判断模型内误差稳定时的值,表示生成决策树的数目(不应设置太小,默认为 500);mtry表示选择的分裂属性的个数;proximity表示是否生成邻近矩阵

library(randomForest)
library(ggplot2)
library(caret)
library(e1071)
library(cluster)
library(maptree)
##randomForest(formula, data=NULL, ..., subset, na.action=na.fail)
set.seed(111)
sub.train <- sample(1:nrow(train.data),200000)#取样
rtree3 <-randomForest(as.factor(train.data$label.train)~., data = train.data, subset = sub.train, mtry=5, ntree =100, importance=TRUE)
print(rtree) #虚线为类别的分类错误率,实线为总体的错误率
ratef<-mean(rtree$err.rate)
ratef
#预测
pred.rtree <- predict(rtree2, newdata = test.data, type = "class")
confusionMatrix(pred.rtree, test.data$label.test,mode='everything')
#调参--mtry
n<-length(names(allfeature_scale))
rate=1     #设置模型误判率向量初始值
for(i in 1:(n-1)){
  set.seed(1234)
  rf_train<-randomForest(as.factor(alldata_balanced$label.train)~.,data=alldata_balanced,mtry=i,ntree=100)
  rate[i]<-mean(rf_train$err.rate)   #计算基于OOB数据的模型误判率均值
  print(rf_train)    
}
rate     #展示所有模型误判率的均值

err.rate: vector error rates of the prediction on the input data, the i-th element being the (OOB) error rate for all trees up to the i-th. 输入数据的预测的矢量误差率,第i个元素是直到第i个的所有树的(OOB)误差率
袋外错误率(oob error) 计算方式如下:

  1. 对每个样本计算它作为oob样本的树对它的分类情况
  2. 以简单多数投票作为该样本的分类结果
  3. 最后用误分个数占样本总数的比率作为随机森林的oob误分率

importance: 表示输出分裂属性的重要性, 第一列是特定于类的度量,计算精确度降低的平均值。 第二列是所有类别的准确度降低的平均。 最后一列是基尼指数减少的平均。

margin: Compute or plot the margin of predictions from a randomForest classifier. 计算并绘制分类器的预测边际。数据点的边际被定义为正确类别的投票比例减去其他类别的最大投票比例。 因此,在多数票时,正边际意味着正确的分类,反之亦然。

confusionMatrix:

predictreference
positivenegative
positive真阳性(TP)假阳性(FP)
negative假阴性(FN)真阴性(TN)
阳性标本(P)阴性标本(N)

准确率=Accuracy = (TP+TN)/(P+N)
错误率=Error Rate = 1 – Accuracy = (FP+FN)/(P+N)
召回率=True Positive Rate = Recall = Sensitivity = TP/P
特异性=True Negative Rate = Specificity = TN/N
阳性预测正确率=Positive Predictive Value = Precision = TP/(TP+FP)
阴性预测正确率=Negative Predictive Value = TN/(TN+FN)
平均准确率=Balanced Accuracy = (Sensitivity+Specificity)/2
TP和TN越高越好就好
F 1 = ( 1 + β 2 ) ∗ p r e c i s i o n ∗ r e c a l l / ( ( β 2 ∗ p r e c i s i o n ) + r e c a l l ) F1 = (1 +\beta^2) ∗ precision ∗ recall/((\beta^2 ∗ precision) + recall) F1=(1+β2)precisionrecall/((β2precision)+recall)
β = 1 \beta = 1 β=1
Prevalence = (TP+FN)/(P+N)
Detection Prevalence =(TP+FP)/(P+N)
Detection Rate = TP/(P+N)

head(treesize(iris_rf,terminal = TRUE)) 
# treesize:计算随机森林中每棵树的节点个数

getTree(rtree2, k=1, labelVar=TRUE))
importance(rtree3)
varImpPlot(rtree3)#变量重要性曲线
margins.rf <- randomForest:::margin(rtree2,train.data)
plot(margins.rf)

library(devtools)
devtools::install_github("ramnathv/rCharts")
library(rCharts)
rPlot(x='bin(x,1)',y='freq',data=train.data,type='bar')

参考:https://zhuanlan.zhihu.com/p/24416833

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值