1.机器学习步骤框架
1)把数据集拆分为训练集和测试集
2)用训练集和训练集的特征向量来训练算法
3)用学习来的算法运用在测试集上来评估算法
2.决策树(Decision Tree)
类似于流程图的树结构:其中,每个内部节点表示在一个属性上测试,每个分支代表一个属性输出。而每个树叶节点代表类或者类的分布。树的最顶层是根节点。
这张图就是一个决策树,最开始的根节点是(玩:9次,不玩:5次),然后根据天气情况分为了三个分支:
1)晴天 (其中,玩:2次,不玩:3次) 在晴天的情况下,有根据湿度分了两个分支:
1)湿度<= 70 (玩:2次,不玩:0次)
2)湿度 >70 (玩:0次,不玩:3次)
2)阴天 (玩:4次,不玩:0次) 阴天条件下都是玩的状态,所以就没有分支了
3)雨天 (玩:3次,不玩:2次) 在雨天的情况下,有根据有无风分了两个分支:
1)有风 (玩:0次,不玩:2次)
2)无风 (玩:3次,不玩:0次)
**这时候应该有一个疑问;这个分支的依据是什么?为什么晴天之后是按照湿度分支,而雨天是按照有无风分支???**
3.熵概念的提出(entropy):信息和抽象,如何度量
一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少
例如:在世界杯开始前,一共有32支球队参赛,我们来预测最后的冠军,如果各队获胜几率一样的话,那我们根据二分法,则至少要猜测五次;而如果我们知道了前面的比赛,在决赛阶段来猜测冠军的话,只需要猜测一次。
比特(bit)来衡量信息的多少
计算公式 -(p1 log p1 + p2 log p2 + … + p32 * log p32) p为每支球队夺冠的概率
H(X) = -求和(P(X) * log(P(X)) 概率 x 概率的对数,然后求和
变量的不确定性越大,熵也就越大
3.1 决策树归纳算法(ID3) 就是如何选择根和节点的方法
信息获取量(Information Gain): Gain(A) = Info(D) - Info_A(D)
通过A来作为节点分类获取了多少信息
类似,Gain(income) = 0.029,Gain(student) = 0.151,Gain(credit_rating)=0.048。所以,选择age作为第一个根节点。
接下来重复操作,选择出接下来的节点。
算法
1)树以代表训练样本的单个结点开始(步骤1)。
2)如果样本都在同一个类,则该结点成为树叶,并用该类标号(步骤2和3)。(如都买或者都不买,这样的情况就可以成为树叶了)
3)否则,算法使用称为信息增益的基于熵的度量作为启发信息,选择能够最好的将样本分类的属性(步骤6)。该属性成为该结点的“测试”或者“判定”属性(步骤7)。在算法的该版本中,
4)所有的属性都是分类的,即离散值。连续属性必须离散化。
5)对测试属性的每个已知的值,创建一个分支,并据此划分样本(步骤8-10)。
6)算法使用同样的过程,递归地形成每个话费上的样本判定树。一旦一个属性出现在一个结点上,就不必该结点的任何后代上考虑它(步骤13)。
7)递归划分步骤仅当下列条件之一成立 停止:
8) (a)给定结点的所有样本属性属于同一类(步骤2和3)
9)(b)没有剩余属性可以用来进一步划分样本(步骤4)。在此情况下,使用多数表决(步骤5)。
10)这涉及将给定的节点转换成树叶,并用样本中的多数所在的类标记它。替换地,可以存放结点样本的类分布
11)(c)分支
12)test_attribute = a 没有样本(步骤11)。这种情况下,以sample中的多数类创建一个树叶(步骤12)
Python代码:
"""sklearn 对数据的输入格式有一定的要求,这个DictVectorizer可以将输入的数据转化为整型"""
"""sklearn要求数据必须是整型的数据"""
from sklearn.feature_extraction import DictVectorizer
"""原始数据存在一个csv格式的文件中"""
import csv
from sklearn import preprocessing
"""用到decision tree"""
from sklearn import tree
from sklearn.externals.six import StringIO
#Read in the csv file and put feature in a list of dict and list of class label
"""存放open进来的csv文件"""
allElectronicsData = open(r'D:\.......','rb')
reader = csv.reader(allElectronicsData)#reader可以按行读取内容
headers = reader.next()#读入第一行
print(headers)
featureList = [] #第一个list用来装取feature的信息
labelList = []#第二个list用来装取label的信息
#把原始数据转化为带有字典的list
for row in reader:
labelList.append(row[len(row) - 1]) #对行做循环,每次把每一行的最后一个信息(即label)存入labelList
rowDict = {}
for i in range(1,len(row)-1):#每一行中其他的feature,也要一次读入,逐个遍历
rowDict[headers[i]] = row[i]#字典的key值对应从reader中读取的值,一个字典对应数据中的一行
featureList.append(rowDict)
print(featureList)
#vectorize features
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()#直接转化为整数型的格式
print("labelList: " + str(labelList))
#vectorize class label
lb = preprocessing.LabelBinarizer()#python中直接提供了一个将classlabel转化为数值的模块
dummyY = lb.fit_transform(labelList)
print("dunmmyY: "+ str(dummyY))
#dunmyX,dunnyY都符合了分类器的格式
#using decision tree for classification
clf = tree.DecisionTreeClassifier(criterion='entropy')#首先定义一个分类器 (括号中的属性是分类器的分类标准,选用哪种方式进行分类,这里是信息熵)
clf = clf.fit(dummyX,dummyY)#建模,填入数据(训练)
print("clf: " + str(clf))
#visulize model 把生成的决策树画出来
with open("allElectronicInformationGainRri.dot",'w') as f:
f = tree.export_graphviz(clf,feature_names=vec.get_feature_names(),out_file=f)#把feature_names要返回成原来的样子
#这是预测的部分了
oneRowX = dummyX[0,:]#原始输入数据的第一行
print("oneRowX: " + str(oneRowX))
newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print("newRowX: " + str(newRowX))
predictedY = clf.predict(newRowX)#对新的数据进行预测
print("predictedY: " + str(predictedY))
print("dunmmyX:" + str(dummyX))
print(vec.get_feature_names())