机器学习实战 学习记录(1-3章)

 参考:机器学习实战Peter Harrington

(11条消息) 机器学习实战教程(13篇)_chenyanlong_v的博客-CSDN博客_机器学习实战

一、机器学习:(1)有监督学习:(分类、回归)k-近邻、朴素贝叶斯、支持向量机、决策树 

                         (2)无监督学习:(聚类、密度估计)k-均值、DBSCAN

       →如何选择?(1)预测目标变量的值:选择有监督学习  ①目标变量为离散型 选择分类算法(如是/否 红/黄/黑 1/2/3) ②目标变量为连续型数值 选择回归算法

                             (2)不预测目标变量的值:选择无监督学习  ①只需将数据划为离散的组 选择聚类算法  ②还需估计数据与每个组的相似程度 选择密度估计算法

二、K-近邻算法(KNN):存在一个有标签的训练样本集,输入没有标签的新数据后,将新数据的每个特征与样本集中数据的每个特征进行比较,提取出特征最相似的分类标签。只选择样本数据集中前K个最相似的样本(通常K不大于20)。

优点:精度高、对异常值不敏感、无数据输入假定

缺点:计算复杂度、空间复杂度高

适用数据范围:数值型和标称型

示例1:

# -*- coding: UTF-8 -*-
import numpy as np
import operator


def createDataSet():
    # 四组二维特征
    group = np.array([[1, 101], [5, 89], [108, 5], [115, 8]])
    # 四组特征的标签
    labels = ['爱情片', '爱情片', '动作片', '动作片']
    return group, labels
if __name__ == '__main__':
    #创建数据集
    group, labels = createDataSet()
    #打印数据集
    print(group)
    print(labels)

def classify0(inX, dataSet, labels, k):
    # numpy函数 shape[0]返回dataSet的行数
    dataSetSize = dataSet.shape[0]
    # 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # 二维特征相减后平方
    sqDiffMat = diffMat ** 2
    # sum()所有元素相加,sum(0)列相加,sum(1)行相加
    sqDistances = sqDiffMat.sum(axis=1)
    # 开方,计算出距离
    distances = sqDistances ** 0.5
    # 返回distances中元素从小到大排序后的索引值
    sortedDistIndices = distances.argsort()
    # 定一个记录类别次数的字典
    classCount = {}
    for i in range(k):
        # 取出前k个元素的类别
        voteIlabel = labels[sortedDistIndices[i]]
        # dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
        # 计算类别次数
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # python3中用items()替换python2中的iteritems()
    # key=operator.itemgetter(1)根据字典的值进行排序
    # key=operator.itemgetter(0)根据字典的键进行排序
    # reverse降序排序字典
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    # 返回次数最多的类别,即所要分类的类别
    return sortedClassCount[0][0]


if __name__ == '__main__':
    # 创建数据集
    group, labels = createDataSet()
    # 测试集
    test = [101, 20]
    # kNN分类
    test_class = classify0(test, group, labels, 3)
    # 打印分类结果
    print(test_class)

示例2:

示例3:

三、决策树:找到在划分数据分类时起决定作用的特征(所以需评估每一个特征),完成后原始数据集就被分为几个数据子集。如果某个分支下的数据属于同一类型则不需再进行分割,否则则需重复划分。

优点:计算复杂度不高,对中间值的缺失不敏感,可以处理不相关特征数据

缺点:可能产生过度匹配问题

适用数据类型:数值型和标称型

信息增益 :在划分数据集之前之后信息发生的变化成为信息增益。(用来作为特征选择的标准,获得增益最高的特征就是最好的选择)。

(1)为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值(数学期望),通过下面的公式得到:

当熵中的概率由数据估计(特别是最大似然估计)得到时,所对应的熵称为经验熵。我们定义样本数据表中的数据为训练数据集D,则训练数据集D的经验熵为H(D),|D|表示其样本容量,及样本个数。设有K个类Ck, = 1,2,3,...,K,|Ck|为属于类Ck的样本个数,因此经验熵公式就可以写为 : 

示例1:计算给定数据集的香农熵

# -*- coding: UTF-8 -*-
import numpy as np
from math import log

def createDataSet():
    dataSet=[[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
    labels=['no surfacing','flippers']
    return dataSet,labels

def calcShannonEnt(dataSet):
    numEntries=len(dataSet)#返回数据集长度
    labelsCounts={}#保存每个标签出现次数的词典
    for featVec in dataSet:#对每组特征向量进行统计
        currentLabel=featVec[-1]#提取标签信息
        if currentLabel not in labelsCounts.keys():#如果标签次数没有放入统计次数的字典,添加进去
            labelsCounts[currentLabel]=0
        labelsCounts[currentLabel]+=1
    shannonEnt=0.0#经验熵(香农熵)
    for key in labelsCounts:#计算香农熵
        prob =float(labelsCounts[key])/numEntries#选择该标签的概率
        shannonEnt-= prob* log (prob,2)#利用公式计算
    return shannonEnt

if __name__ =='__main__' :
    dataSet,features=createDataSet()
    print(dataSet)
    print(calcShannonEnt(dataSet))

 (2)条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性,随机变量X给定的条件下随机变量Y的条件熵H(Y|X),定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

当条件熵中的概率由数据估计(特别是极大似然估计)得到时,所对应的条件熵称为条件经验熵。

设特征A有n个不同的取值{a1,a2,···,an},根据特征A的取值将D划分为n个子集{D1,D2,···,Dn},|Di|为Di的样本个数。记子集Di中属于Ck的样本的集合为Dik,即Dik = Di ∩ Ck,|Dik|为Dik的样本个数。于是经验条件熵的公式可以些为:

信息增益是相对于特征而言的。所以,特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即:

一般地,熵H(D)与条件熵H(D|A)之差称为互信息。决策树学习中的信息增益等价于训练数据集中类与特征的互信息。 

示例2:划分数据集(我们将每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集最优。

# -*- coding: UTF-8 -*-
import numpy as np
from math import log

def createDataSet():
    dataSet=[[0,0,0,0,'no'],[0,0,0,1,'no'],[0,1,0,1,'yes'],[0,1,1,0,'yes'],
             [0,0,0,0,'no'],[1,0,0,0,'no'],[1,0,0,1,'no'],[1,1,1,1,'yes'],
             [1,0,1,2,'yes'],[1,0,1,2,'yes'],[2,0,1,2,'yes'],[2,0,1,1,'yes'],
             [2,1,0,1,'yes'],[2,1,0,2,'yes'],[2,0,0,0,'no']]
    labels=['no surfacing','flippers']
    return dataSet,labels

def calcShannonEnt(dataSet):
    numEntries=len(dataSet)#返回数据集长度
    labelsCounts={}#保存每个标签出现次数的词典
    for featVec in dataSet:#对每组特征向量进行统计
        currentLabel=featVec[-1]#提取标签信息
        if currentLabel not in labelsCounts.keys():#如果标签次数没有放入统计次数的字典,添加进去
            labelsCounts[currentLabel]=0
        labelsCounts[currentLabel]+=1
    shannonEnt=0.0#经验熵(香农熵)
    for key in labelsCounts:#计算香农熵
        prob =float(labelsCounts[key])/numEntries#选择该标签的概率
        shannonEnt-= prob* log (prob,2)#利用公式计算
    return shannonEnt

#划分数据集
def splitDataSet(dataSet,axis,value):#三个参数:待划分的数据集、划分数据集的特征、需要返回的特征的值
    retDataSet=[]#创建返回的数据集列表
    for featVec in dataSet:#遍历数据集,按照某个特征划分数据集,将所有符合要求的元素抽出来
        if featVec[axis]==value:
            reduceFeatVec=featVec[:axis]#去掉特征
            reduceFeatVec.extend(featVec[axis+1:])#将符合条件的添加到返回的数据集
            retDataSet.append(reduceFeatVec)#append是将列表直接作为下一个元素加入,extend是将列表中的元素分别并入
    return retDataSet

def chooseBestFeatureToSplit(dataSet):
    numFeatures=len(dataSet[0])-1#特征数量
    baseEntroy=calcShannonEnt(dataSet)#计算数据集的香农熵
    bestInfoGain=0.0#信息增益
    bestFeature= -1#最佳特征索引值
    for i in range(numFeatures):
        featList=[example[i] for example in dataSet]
        uniqueVals=set(featList)#创建set集合,元素不可重复
        newEntropy=0.0#条件经验熵
        for value in uniqueVals:#计算信息增益
            subDataSet=splitDataSet(dataSet,i,value)#划分后的子集
            prob=len(subDataSet)/float(len(dataSet))#计算子集的概率
            newEntropy+=prob*calcShannonEnt(subDataSet)#计算条件经验熵
        infoGain=baseEntroy-newEntropy#计算信息增益
        print("第%d个特征的增益为%.3f"%(i,infoGain))
        if (infoGain>bestInfoGain):#找到最大的信息增益
            bestInfoGain=infoGain
            bestFeature=i
    return bestFeature

if __name__ =='__main__' :
    dataSet,features=createDataSet()
    print("最优特征索引值:"+str(chooseBestFeatureToSplit(dataSet)))

ID3算法 :从根结点开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,建立子节点,再对子结点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止。最后得到一个决策树。

示例3:递归构建决策树

# -*- coding: UTF-8 -*-
import numpy as np
from math import log
import operator

def createDataSet():
    dataSet=[[0,0,0,0,'no'],[0,0,0,1,'no'],[0,1,0,1,'yes'],[0,1,1,0,'yes'],
             [0,0,0,0,'no'],[1,0,0,0,'no'],[1,0,0,1,'no'],[1,1,1,1,'yes'],
             [1,0,1,2,'yes'],[1,0,1,2,'yes'],[2,0,1,2,'yes'],[2,0,1,1,'yes'],
             [2,1,0,1,'yes'],[2,1,0,2,'yes'],[2,0,0,0,'no']]
    labels=['年龄','工作','房子','信贷情况']
    return dataSet,labels

def calcShannonEnt(dataSet):
    numEntries=len(dataSet)#返回数据集长度
    labelsCounts={}#保存每个标签出现次数的词典
    for featVec in dataSet:#对每组特征向量进行统计
        currentLabel=featVec[-1]#提取标签信息
        if currentLabel not in labelsCounts.keys():#如果标签次数没有放入统计次数的字典,添加进去
            labelsCounts[currentLabel]=0
        labelsCounts[currentLabel]+=1
    shannonEnt=0.0#经验熵(香农熵)
    for key in labelsCounts:#计算香农熵
        prob =float(labelsCounts[key])/numEntries#选择该标签的概率
        shannonEnt-= prob* log (prob,2)#利用公式计算
    return shannonEnt

#划分数据集
def splitDataSet(dataSet,axis,value):#三个参数:待划分的数据集、划分数据集的特征、需要返回的特征的值
    retDataSet=[]#创建返回的数据集列表
    for featVec in dataSet:#遍历数据集,按照某个特征划分数据集,将所有符合要求的元素抽出来
        if featVec[axis]==value:
            reduceFeatVec=featVec[:axis]#去掉特征
            reduceFeatVec.extend(featVec[axis+1:])#将符合条件的添加到返回的数据集
            retDataSet.append(reduceFeatVec)#append是将列表直接作为下一个元素加入,extend是将列表中的元素分别并入
    return retDataSet

def chooseBestFeatureToSplit(dataSet):
    numFeatures=len(dataSet[0])-1#特征数量
    baseEntropy=calcShannonEnt(dataSet)#计算数据集的香农熵
    bestInfoGain=0.0#信息增益
    bestFeature= -1#最佳特征索引值
    for i in range(numFeatures):
        featList=[example[i] for example in dataSet]
        uniqueVals=set(featList)#创建set集合,元素不可重复
        newEntropy=0.0#条件经验熵
        for value in uniqueVals:#计算信息增益
            subDataSet=splitDataSet(dataSet,i,value)#划分后的子集
            prob=len(subDataSet)/float(len(dataSet))#计算子集的概率
            newEntropy+=prob*calcShannonEnt(subDataSet)#计算条件经验熵
        infoGain=baseEntropy-newEntropy#计算信息增益
        print("第%d个特征的增益为%.3f"%(i,infoGain))
        if (infoGain>bestInfoGain):#找到最大的信息增益
            bestInfoGain=infoGain
            bestFeature=i
    return bestFeature

def majorityCnt(classList):
    classCount={}
    for vote in classList:#统计classCount中每个元素出现的次数
        if vote not in classCount.keys():classCount[vote]=0
        classCount[vote]+=1
    sortedClassCount=sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]#返回classCount出现次数最多的元素

#创建决策树
def createTree(dataSet,labels,featLabels):
    classList=[example[-1] for example in dataSet]#取分类标签
    if classList.count(classList[0])==len(classList):#如果类别完全相同,则停止划分
        return classList[0]
    if len(dataSet[0])==1 or len(labels)==0:#遍历完所有特征返回出现次数最多的类标签
        return majorityCnt(classList)
    bestFeat=chooseBestFeatureToSplit(dataSet)#选择最优特征
    bestFeatLabel=labels[bestFeat]#最优特征的标签
    featLabels.append(bestFeatLabel)
    myTree={bestFeatLabel: {}}#根据最优特征的标签生成树
    del(labels[bestFeat])#删除已经使用的特征标签
    featValues=[example[bestFeat]for example in dataSet]#得到训练集中最优特征的所有属性值
    uniqueVals=set(featValues)#去掉重复的使用值
    for value in uniqueVals:#遍历特征,创建决策树
        subLabels=labels[:]#复制类标签,并将其存在新列表变量subLabels中(保证每次调用函数时不改变原始列表的内容
        myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels,featLabels)
    return myTree

if __name__ =='__main__' :
    dataSet,labels=createDataSet()
    featLabels=[]
    myTree = createTree(dataSet, labels, featLabels)
    print(myTree)

(3)使用matplotlib绘制决策树 未解决

决策树的分类

决策树的存储

示例4 隐形眼镜

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值