机器学习—决策树(案例:判断网店浏览用户是否购买电脑)

什么是决策树/判定树(decision tree)?

判定树是一个类似于流程图的树结构:其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布。
此图给出的是根据天气决定是否去玩的判定树
此图给出的是根据天气决定是否去玩的判定树

决策树是机器学习中分类方法中的一个重要算法

它对小规模数据集的处理非常直观,可靠。一般用于处理离散性数据,而连续型数据(1-100岁)我们需要对该数据进行分段处理例如1-25岁 称为年轻 25-50中年 50+老年 ,但在实际应用中,该分段处理跟超参数的性质差不多,对结果的影响非常大,所以连续型数据的分段处理又是一个新的内容。

构造决策树的基本算法

熵(entropy)概念:

一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少
在这里插入图片描述
变量的不确定性越大,熵也就越大。

信息获取量(Information Gain)概念:

信息获取量(Information Gain):Gain(A) = Info(D) - Infor_A(D)
是不是头很大?往下看实践一波

引入问题:判断网店浏览用户是否购买电脑

对用户数据进行收集,得到一份小规模的样本(决策树适用)
在这里插入图片描述
第一步计算是否购买的熵:
在这里插入图片描述
代入熵的公式一共是有9个yes 5个no 得到上述公式

我们再计算age(年龄的熵)在这里插入图片描述
14个样本中有5个年轻人 4个中年人 还有五个老伯得到上述式子及结果

接下来计算关于关于年龄段的信息量:
在这里插入图片描述
上述为age的信息量
在这里插入图片描述
通过观察我们选取信息量最大的作为根节点
在这里插入图片描述
重复上述取根节点操作得到(ID3决策树)
在这里插入图片描述

算法思路:

树以代表训练样本的单个结点开始(步骤1)。
如果样本都在同一个类,则该结点成为树叶,并用该类标号(步骤2 和3)。
否则,算法使用称为信息增益的基于熵的度量作为启发信息,选择能够最好地将样本分类的属性(步骤6)。该属性成为该结点的“测试”或“判定”属性(步骤7)。在算法的该版本中,
所有的属性都是分类的,即离散值。连续属性必须离散化。
对测试属性的每个已知的值,创建一个分枝,并据此划分样本(步骤8-10)。
算法使用同样的过程,递归地形成每个划分上的样本判定树。一旦一个属性出现在一个结点上,就不必该结点的任何后代上考虑它(步骤13)。
递归划分步骤仅当下列条件之一成立停止:
(a) 给定结点的所有样本属于同一类(步骤2 和3)。
(b) 没有剩余属性可以用来进一步划分样本(步骤4)。在此情况下,使用多数表决(步骤5)。
这涉及将给定的结点转换成树叶,并用样本中的多数所在的类标记它。替换地,可以存放结
点样本的类分布。
© 分枝
test_attribute = a i 没有样本(步骤11)。在这种情况下,以 samples 中的多数类
创建一个树叶(步骤12)

其他算法:(其实就是换一个计算信息量分方式选取一个合适的根)

C4.5: Quinlan
Classification and Regression Trees (CART): (L. Breiman, J. Friedman, R. Olshen,C.Stone)共同点:都是贪心算法,自上而下(Top-down approach)区别:属性选择度量方法不同: C4.5 (gain ratio), CART(gini index), ID3 (Information Gain)

树剪枝叶 (避免overfitting)

先剪枝:按某个函数方法得到一个差不多的树(精细程度)就停止
后剪枝:按某个函数方法得到一个完整的树(所有属性类分)然后进行剪枝叶(取掉那些过于精细的叶子结点)

总结

决策树的优点:

直观,便于理解,小规模数据集有效

决策树的缺点:

处理连续变量不好
类别较多时,错误增加的比较快
可规模性一般(小数据量、少属性)

希望各位大神看完能给个赞,如果有错欢迎指正,给予我一个进步、改正的机会

#该id3直接使用科学库完成,所以不过多解释代码详细逻辑及转换
#control+鼠标指指向看不懂的方法,会有详细的使用帮助
#看不懂的再给我留言,我会进行答复
from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import preprocessing
# from sklearn.externals.six import StringIO
import numpy

# Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open('AllElectronics.csv', 'rt')
reader = csv.reader(allElectronicsData)
headers = next(reader)

print(headers)

featureList = []
labelList = []

for row in reader:
    labelList.append(row[len(row)-1])#row[len(row)-1] 每一行最后一个值
    rowDict = {
    
    }
    for i in range(1, len(row)-1):
        rowDict[headers[i]] = row[i]
    featureList.append(rowDict)

print(featureList)

# Vetorize features
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList) .toarray()

print("dummyX: " + str(dummyX))
print(vec.get_feature_names())

print("labelList: " + str(labelList))

# vectorize class labels
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
print("dummyY: " + str(dummyY))

# Using decision tree for classification
# clf = tree.DecisionTreeClassifier()
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX, dummyY)
print("clf: " + str(clf))


# Visualize model
with open("allElectronicInformationGainOri.dot", 'w') as f:
    f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)

oneRowX = dummyX[0, :]
print("oneRowX: " + str(oneRowX))

newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print("newRowX: " + str(newRowX))
newRowX=numpy.array(newRowX).reshape(1,-1)
predictedY = clf.predict(newRowX)
print("predictedY: " + str(predictedY))



猜你喜欢

转载自blog.csdn.net/LiaoNailin/article/details/108638477