1、python

本课程的机器学习的算法都是基于python语言实现的,所以你需要有一定的python语言基础。

2、python机器学习的库:scikit-learn

特性: 
1)简单高效的数据挖掘和机器学习分析 
2)对所有用户开放,根据不同需求高度可重用性 
3)基于Numpy, SciPy和matplotlib 
4)开源,商用级别:获得 BSD许可

覆盖问题领域: 
分类(classification),,回归(regression), 聚类(clustering), 
降维(dimensionality reduction),模型选择(model selection), 预处理(preprocessing)

3、使用scikit-learn

方式一:pip, easy_install(两个都是python安装package的工具,感觉pip更好用) 
方式二(推荐): 可使用Anaconda(这是一个科学计算环境 ,包含numpy, scipy,matplotlib等科学计算常用package,当然也包含scikit-learn包) 
anaconda下载地址:www.continuum.io/downloads 
anaconda安装注意问题:匹配的Python解释器版本(2.7 or 3.5), 系统版本(32位or64位)

4、安装Graphviz(数据可视化软件)

下载地址:www.graphviz.org 
安装完成后,将C:\Program Files (x86)\Graphviz2.38\bin(找你的graphviz/bin的路径)加入到系统变量path中


5、决策树算法实现

首先将原始数据录入csv文件中(如下图)

 

5.1、引入sk-learn相关的package

# 1.引入sk-learn相关的包
# DictVectorizer:数据类型转换
from sklearn.feature_extraction import DictVectorizer

# 2.CSV 文件处理读取包
import csv

# 3.数据预处理的包、决策树包、读写字符串的包
from sklearn import preprocessing
from sklearn import tree
from sklearn.externals.six import StringIO

 

5.2、读取csv文件的数据到程序中

# 4.读取csv文件到程序中
# 从文件中读取,并且保存在allData变量中
allData = open('AllData.csv')
# csv 按行读取数据
reader = csv.reader(allData)
# next方法可以打印第一行数据
headers = next(reader)

# 打印第一行数据
print("打印第一行数据:\r\n", headers)

 

结果显示:

5.3、对数据预处理

 

# 5.数据预处理过程
# 建立两个集合,一个装特征,一个装标签
featureList = []  # 这个是创建了一个空的list
labelList = []

# 遍历csv文件中每一行
for row in reader:
    # 将标签加到labelList中
    labelList.append(row[len(row) - 1])  # 拿到最后一列数据,就是标签
    # 接下来这几个步骤是为了让特征值转化为一种字典的形式,这样才可以使用sk中的DictVectorizer
    # sk可以直接将特征的类别值转化为01值
    rowDict = {}  # 这个是创建一个空字典,承载特征字典
    for i in range(1, len(row) - 1):  # 从第一列遍历到最后一列
        # headers是第一行,第一行的第一个age(第0个是id): youth
        rowDict[headers[i]] = row[i]  # next之后是直接从数据那一栏开始取数据
    featureList.append(rowDict)
print("打印特征字典第一条记录:\r\n", featureList[0])

结果显示:

5.4 实例化特征

# 6.实例化特征  01表示  10维向量表示
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()
print("特征工程后,打印每一条记录的特征值:\r\n" + str(dummyX))
# 年龄有youth,middle,senior三个情况
# 收入有高、中、低三种
# 学生:是否 两种
# 信用:好、一般两种
# 拿一个十维向量表示,有表示1,没有表示0,表示给定的14条记录
print('打印特征名称:\r\n', vec.get_feature_names())

# label标签转化,直接用preprocessing中的LabelBinarizer()方法就可以
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
# yes用1表示   no用0表示
print("特征工程后,打印每一条记录的标签值:\r\n" + str(dummyY))
print("labelList名称(表示是否会买电脑):" + str(labelList))

结果显示:

E:\Anaconda\python.exe D:/pywork/decisionTree/sk_forDecisionTree.py
打印第一行数据:
 ['id', 'age', 'income', 'student', 'credit_rating', 'classForBuys']
打印特征字典第一条记录:
 {'age': 'youth', 'income': 'high', 'student': 'no', 'credit_rating': 'fair'}
特征工程后,打印每一条记录的特征值:
[[0. 0. 1. 0. 1. 1. 0. 0. 1. 0.]
 [0. 0. 1. 1. 0. 1. 0. 0. 1. 0.]
 [1. 0. 0. 0. 1. 1. 0. 0. 1. 0.]
 [0. 1. 0. 0. 1. 0. 0. 1. 1. 0.]
 [0. 1. 0. 0. 1. 0. 1. 0. 0. 1.]
 [0. 1. 0. 1. 0. 0. 1. 0. 0. 1.]
 [1. 0. 0. 1. 0. 0. 1. 0. 0. 1.]
 [0. 0. 1. 0. 1. 0. 0. 1. 1. 0.]
 [0. 0. 1. 0. 1. 0. 1. 0. 0. 1.]
 [0. 1. 0. 0. 1. 0. 0. 1. 0. 1.]
 [0. 0. 1. 1. 0. 0. 0. 1. 0. 1.]
 [1. 0. 0. 1. 0. 0. 0. 1. 1. 0.]
 [1. 0. 0. 0. 1. 1. 0. 0. 0. 1.]
 [0. 1. 0. 1. 0. 0. 0. 1. 1. 0.]]
打印特征名称:
 ['age=middle', 'age=senior', 'age=youth', 'credit_rating=excellent', 'credit_rating=fair', 'income=high', 'income=low', 'income=medium', 'student=no', 'student=yes']
特征工程后,打印每一条记录的标签值:
[[0]
 [0]
 [1]
 [1]
 [1]
 [0]
 [1]
 [0]
 [1]
 [1]
 [1]
 [1]
 [1]
 [0]]
labelList名称(表示是否会买电脑):['no', 'no', 'yes', 'yes', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'yes', 'yes', 'no']


 

5.5、决策树分类的核心代码

 


'''
这个地方是重点呀,决策树要来了
其实我们之前做的特征工程也很重要呀
'''
# 7.决策树的建立
# criterion是选择决策树节点的标准,我们按照信息增益标准(ID3算法)criterion='entropy'
# 这个标准默认是基尼指数(CART算法用的这个)criterion='gini'
# skLearn只提供了这两个方法
# 通常就使用基尼系数、数据维度很大,噪音很大时使用基尼系数
# 维度低,数据比较清晰的时候,信息熵和基尼系数没区别
# 当决策树的拟合程度不够的时候,使用信息熵
# 这里我们都进行了尝试
clf = tree.DecisionTreeClassifier(criterion='gini')
clf = clf.fit(dummyX, dummyY)
print("clf:" + str(clf))

结果显示:

E:\Anaconda\python.exe D:/pywork/decisionTree/sk_forDecisionTree.py
打印第一行数据:
 ['id', 'age', 'income', 'student', 'credit_rating', 'classForBuys']
打印特征字典第一条记录:
 {'age': 'youth', 'income': 'high', 'student': 'no', 'credit_rating': 'fair'}
特征工程后,打印每一条记录的特征值:
[[0. 0. 1. 0. 1. 1. 0. 0. 1. 0.]
 [0. 0. 1. 1. 0. 1. 0. 0. 1. 0.]
 [1. 0. 0. 0. 1. 1. 0. 0. 1. 0.]
 [0. 1. 0. 0. 1. 0. 0. 1. 1. 0.]
 [0. 1. 0. 0. 1. 0. 1. 0. 0. 1.]
 [0. 1. 0. 1. 0. 0. 1. 0. 0. 1.]
 [1. 0. 0. 1. 0. 0. 1. 0. 0. 1.]
 [0. 0. 1. 0. 1. 0. 0. 1. 1. 0.]
 [0. 0. 1. 0. 1. 0. 1. 0. 0. 1.]
 [0. 1. 0. 0. 1. 0. 0. 1. 0. 1.]
 [0. 0. 1. 1. 0. 0. 0. 1. 0. 1.]
 [1. 0. 0. 1. 0. 0. 0. 1. 1. 0.]
 [1. 0. 0. 0. 1. 1. 0. 0. 0. 1.]
 [0. 1. 0. 1. 0. 0. 0. 1. 1. 0.]]
打印特征名称:
 ['age=middle', 'age=senior', 'age=youth', 'credit_rating=excellent', 'credit_rating=fair', 'income=high', 'income=low', 'income=medium', 'student=no', 'student=yes']
特征工程后,打印每一条记录的标签值:
[[0]
 [0]
 [1]
 [1]
 [1]
 [0]
 [1]
 [0]
 [1]
 [1]
 [1]
 [1]
 [1]
 [0]]
labelList名称(表示是否会买电脑):['no', 'no', 'yes', 'yes', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'yes', 'yes', 'no']
clf:DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best')

5.6、生成dot文件(让决策树更加直观)

# 8.我们生成一下dot文件,看起来更加直观了
with open("myDotByCART.dot", 'w') as f:
    f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)

dot文件: 

因为我们ID3和CART算法都进行了尝试,所以我们获得了两个dot文件(区别就是在5.5创建决策树的时候criterion='entropy' 还是criterion='gini')

# criterion是选择决策树节点的标准,我们按照信息增益标准(ID3算法)criterion='entropy'
# 这个标准默认是基尼指数(CART算法用的这个)criterion='gini'

使用信息增益标准(ID3算法)criterion='entropy'获得的dot文件:

使用基尼指数(CART算法用的这个)criterion='gini',获得的dot文件

 

5.7、将dot文件用graphviz转换为pdf文件

在命令行下,cd到你的dot文件的路径下,输入 
dot -Tpdf filename.dot -o output.pdf     (filename以dot文件名为准) 
可以看见同路径下生成了pdf文件

如图: 

5.8、测试代码

 

# 9.测试代码,取第1个实例数据,修改之后创建一个新数据
oneRowX = dummyX[0, :]
print("oldRowX:"+str(oneRowX))
oldRowX = oneRowX  # 旧的样本数据
newRowX = oneRowX  # 新的样本数据
newRowX[0] = 1  # 修改age=middle为  1
newRowX[2] = 0  # 修改age=youth 为  0
print("newRowX:"+str(newRowX))  # 新的特征

oldRowX = oldRowX.reshape(1, -1)
newRowX = newRowX.reshape(1, -1)

predictedY_old = clf.predict(oldRowX)
predictedY_new = clf.predict(newRowX)

print("旧的样本预测标签为:"+str(predictedY_old))
print("新的样本预测标签为:"+str(predictedY_new))

结果展示

我本来是想换了一个属性之后,新样本会和旧样本产生不一样的分类结果,但是仔细看了一下数据,并没有什么特征起到决定性作用。所以就没在想这件事情,随便换了一个age特征属性。

5.9、源程序

# 1.引入sk-learn相关的包
# DictVectorizer:数据类型转换
from sklearn.feature_extraction import DictVectorizer

# 2.CSV 文件处理读取包
import csv

# 3.数据预处理的包、决策树包、读写字符串的包
from sklearn import preprocessing
from sklearn import tree
from sklearn.externals.six import StringIO

# 4.读取csv文件到程序中
# 从文件中读取,并且保存在allData变量中
allData = open('AllData.csv')
# csv 按行读取数据
reader = csv.reader(allData)
# next方法可以打印第一行数据
headers = next(reader)

# 打印第一行数据
print("打印第一行数据:\r\n", headers)

# print("测试:", next(reader))
# 5.数据预处理过程
# 建立两个集合,一个装特征,一个装标签
featureList = []  # 这个是创建了一个空的list
labelList = []

# 遍历csv文件中每一行
for row in reader:
    # 将标签加到labelList中
    labelList.append(row[len(row) - 1])  # 拿到最后一列数据,就是标签
    # 接下来这几个步骤是为了让特征值转化为一种字典的形式,这样才可以使用sk中的DictVectorizer
    # sk可以直接将特征的类别值转化为01值
    rowDict = {}  # 这个是创建一个空字典,承载特征字典
    for i in range(1, len(row) - 1):  # 从第一列遍历到最后一列
        # headers是第一行,第一行的第一个age(第0个是id): youth
        rowDict[headers[i]] = row[i]  # next之后是直接从数据那一栏开始取数据
    featureList.append(rowDict)
print("打印特征字典第一条记录:\r\n", featureList[0])

# 6.实例化特征  01表示  10维向量表示
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()
print("特征工程后,打印每一条记录的特征值:\r\n" + str(dummyX))
# 年龄有youth,middle,senior三个情况
# 收入有高、中、低三种
# 学生:是否 两种
# 信用:好、一般两种
# 拿一个十维向量表示,有表示1,没有表示0,表示给定的14条记录
print('打印特征名称:\r\n', vec.get_feature_names())

# label标签转化,直接用preprocessing中的LabelBinarizer()方法就可以
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
# yes用1表示   no用0表示
print("特征工程后,打印每一条记录的标签值:\r\n" + str(dummyY))
print("labelList名称(表示是否会买电脑):" + str(labelList))

'''
这个地方是重点呀,决策树要来了
其实我们之前做的特征工程也很重要呀
'''
# 7.决策树的建立
# criterion是选择决策树节点的标准,我们按照信息增益标准(ID3算法)criterion='entropy'
# 这个标准默认是基尼指数(CART算法用的这个)criterion='gini'
# skLearn只提供了这两个方法
# 通常就使用基尼系数、数据维度很大,噪音很大时使用基尼系数
# 维度低,数据比较清晰的时候,信息熵和基尼系数没区别
# 当决策树的拟合程度不够的时候,使用信息熵
# 两个都试试,不好就换另外一个
clf = tree.DecisionTreeClassifier(criterion='gini')
clf = clf.fit(dummyX, dummyY)
print("clf:" + str(clf))

# 8.我们生成一下dot文件,看起来更加直观了
with open("myDotByCART.dot", 'w') as f:
    f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)


# 9.测试代码,取第1个实例数据,修改之后创建一个新数据
oneRowX = dummyX[0, :]
print("oldRowX:"+str(oneRowX))
oldRowX = oneRowX  # 旧的样本数据
newRowX = oneRowX  # 新的样本数据
newRowX[0] = 1  # 修改age=middle为  1
newRowX[2] = 0  # 修改age=youth 为  0
print("newRowX:"+str(newRowX))  # 新的特征

oldRowX = oldRowX.reshape(1, -1)
newRowX = newRowX.reshape(1, -1)

predictedY_old = clf.predict(oldRowX)
predictedY_new = clf.predict(newRowX)

print("旧的样本预测标签为:"+str(predictedY_old))
print("新的样本预测标签为:"+str(predictedY_new))

因为决策树是我们的训练集训练出来的,那么我们使用训练集上的数据去做预测,预测结果会和它本身标记一样吗?

'''
解决我心中的疑问,为啥我训练集上的数据标签是no 但是经过训练之后,用决策树测试是yes呢?
我们用前三个样本做实验
第一个样本:标签是no   0
第二个样本:标签是no   0
第三个样本:标签是yes  1

'''
# [0, :]表示在二维数组中取0号索引的所有元素
oneRowX = dummyX[0, :]  # 第一个样本特征
print("oldRowX:"+str(oneRowX))
oneRowX = oneRowX.reshape(1, -1)
predictedY_one = clf.predict(oneRowX)
print("第一个样本预测标签为:"+str(predictedY_one))


twoRowX = dummyX[1, :]  # 第二个样本特征
print("twoRowX:"+str(twoRowX))
twoRowX = twoRowX.reshape(1, -1)
predictedY_two = clf.predict(twoRowX)
print("第二个样本预测标签为:"+str(predictedY_two))

threeRowX = dummyX[2, :]  # 第三个样本特征
print("threeRowX:"+str(threeRowX))
threeRowX = threeRowX.reshape(1, -1)
predictedY_three = clf.predict(threeRowX)
print("第三个样本预测标签为:"+str(predictedY_three))




结果显示:(拿训练集做测试是有可能预测值不等于标签值的)

 

5.10、sk-learn的决策树文档

地址:scikit-learn.org/stable/modules/tree.html

 

撒花✿✿ヽ(°▽°)ノ✿........................

 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐