版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第一章机器学习基本概念
全套可编辑PPT课件第1章机器学习基本概念.pptx第2章决策树.pptx第3章k近邻算法.pptx第4章支持向量机(SVM).pptx第5章线性模型.pptx第6章贝叶斯分类器.pptx第7章数据降维.pptx第8章聚类算法.pptx第9章人工神经网络.pptx第10章随机森林.pptx第11章机器学习在生物信息中的应用.pptx引言机器学习作为当前解决人工智能问题的主要技术,在该体系中处于核心地位。它作为一门多领域交叉学科,涉及了统计学、概率论、逼近论、算法复杂度理论等多门学科。该学科实际上是研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,并重新组织已有的知识结构使之不断改善自身的性能。当下主要应用领域有机器视觉、语音识别、数据挖掘等。这些应用在我们的日常生活中随处可见,如:微信上的语音输入,支付宝的扫脸付款,停车场入口的车牌识别等等。机器视觉和模式识别都是与机器学习关联比较密切的领域。其中机器视觉是通过硬件和程序的结合来实现人的视觉功能,包括图像理解,三维空间信息获取,运动感知等问题。而模式识别则是对声音、图像及其它类别对象的识别问题,机器学习成为了解决这类问题的工具。另外,机器学习在数据的挖掘和分析中也得到应用,如:信息检索,用户行为分析等。在本书中,我们将从监督学习,非监督学习及半监督学习来对机器学习进行讲解。从案例代码着手,帮助大家了解机器学习的各种算法。目录算法分类1.1模型评价指标1.2模型选择1.3CONTENTS算法分类1.1算法分类1.1.1监督信号机器学习的算法可以分为有监督学习和无监督学习,其区别就是是否带有标签值。假如我们要识别a-i的字母图像,我们需要将每张图片的式样和它所述的字母类别相关联起来,那么这个类别就是标签值。在有监督学习中,样本数据是带有标签值的,它从训练样本中学习得到一个模型,然后通过该模型来测试新的样本所属的类别。样本的值可归为输入值与标签值,其公式如下:
X作为输入值,是外部采集的数据。Y作为输出值,是自定义的标签值。标签值可以是整数,实数或向量。有监督学习通过给与一定量的训练样本,来推导出映射函数:
该函数需要很好的表达训练样本的信息,让函数的输出值y和样本的标签值尽可能的一致。训练样本数是有限的,而实际情况却是无限的,因此,在训练时只能选取一部分的样本,找到误差最小的表达函数,用来减少识别的错误率。算法分类我们所见到的人脸识别,语音识别,手写文字识别等都属于有监督学习,此类学习都是需要提前采集样本,对样本进行标记,并生成相关模型,再通过模型对未标记的新样本进行类型的预测。无监督学习则是对没有标签的样本进行分析,发现样本集的分布规律。无监督学习的典型代表是聚类,数据降维等,它们处理的样本都不带有标签。另外还有一种是有监督学习与无监督学习的结合,即半监督学习。对于有些实际问题,标注训练样本的成本高,无监督学习准确率又太低。因此利用少量有标签样本和大量无标签样本进行学习能够解决这样的问题。在半监督学习中,无标签样本的数量远大于有标签样本数量。1.1.2分类与回归在有监督学习中,如果样本标签是整数,即预测函数是一个向量到整数的映射,这称为分类问题。当类型数为2时,称为二分类问题,标签类别一般设置为+1和-1,分别对应正样本和负样本。对于分类问题,如果预测函数是线性函数则称为线性模型,它是n维空间的线性划分。线性函数是超平面,在二维平面中是直线,三维空间中是平面。二分类问题的线性预测函数为:
算法分类其中w是权重向量,b是偏置项。通过sigmoid函数映射到(0,1)上,并划分一个阈值,大于阈值的分为一类,小于等于分为另一类,可以用来处理二分类问题。更进一步:对于N分类问题,则是先得到N组w值不同的wx+b,然后归一化,比如用softmax函数,最后变成N个类上的概率,可以处理多分类问题。当决策函数是非线性函数时称为非线性模型,其分类边界是n维空间中的曲面。在生活中我们见到的情况大多数都属于非线性的,所以要求预测函数具有非线性建模的能力。在有监督学习中,如果标签值是连续实数,则称为回归问题,此时预测函数是向量到实数的映射:
与分类问题一样,预测函数可以是线性函数也可以是线性函数或非线性函数。线性函数称为线性回归。对于有监督学习,机器学习算法在训练时的任务是给定训练样本集,选择预测函数的类型称为假设空间,然后确认函数的参数值,如线性模型中的w和b。对于参数的确定,通常所用的方法为构造一个损失函数,它表示预测函数的输出结果和样本标签中标记的值之间的误差。对所有训练样本的误差求平均值,这个值是参数θ的函数:算法分类
其中L(x_i;θ)为单个样本的损失函数,l为训练样本数。训练的目的是最小化损失函数,求解损失函数的极小值可以确定θ的值,从而确定预测函数。1.1.3判别模型与生成模型按照求解的方法,可以将分类算法分为判别模型和生成模型两种。给定特征向量与标签值,生成模型对联合概率p(x,y)建模,判别模型对条件概率p(y|x)进行建模。不使用概率模型的分类器也被归为判别模型,它将直接得到预测函数而不关心样本的概率分布,其函数式如下所示:
算法分类这3种模型也分别被称为生成学习,条件学习和判别学习。除此以外,对于生成模型和判别模型还有另一种定义形式。生成模型对条件概率p(x|y)建模,判别模型对条件概率p(y|x)建模。前者依据标签值y来生成随机样本数据x,后者则根据样本特征向量x的值判断其标签值y。常见的生成模型有贝叶斯分类器、高斯混合模型、隐马尔科夫模型、生成对抗网络等。典型的判别模型有决策树、kNN算法、人工神经网络、支持向量机、logistic回归等。1.1.4强化学习强化学习是一类特殊的机器学习算法,它根据输入数据确定要执行的动作,输入数据是环境参数。和有监督学习算法类似,也要有训练过程。在训练中,对正确的动作进行奖励,错误的动作进行惩罚,训练完成后即可得到预测模型来进行测试。模型评价指标1.2模型评价指标在对各种机器学习算法和模型的好坏进行比较的时候,需要定义一个指标来衡量模型精度。有监督学习分为训练和预测两个阶段,一般用与训练样本集不同的另一个样本集统计算法的精度。更复杂的则是再引入一个验证集,用于确定模型的某些人工设定的超参数,优化模型。下表1-1展示了两种常见问题的评价指标。类型评价指标指标定义分类问题准确率测试样本集中被正确分类的样本数与测试样本总数的比值回归问题回归误差预测函数输出值与样本标签值之间的均方误差表1-1分类与回归问题评价指标1.3模型选择模型选择1.3.1过拟合与欠拟合有监督学习训练的目标是使训练集上的误差最小化。由于训练样本集和测试样本集是不同的,因此要考虑如下问题。(1)算法在训练集上的表现。如果在训练集上表现不好,一般来说在实际运用上精确度就很难保证。(2)在训练集上学习得到的模型能否有效的运用在测试集上。其衡量标准是泛化能力。泛化能力是指模型从训练集推广到测试集的能力。设计者们希望模型在训练集和测试集上都有较高的准确率。针对这两个问题定义了过拟合和欠拟合的概念。过拟合过学习欠拟合欠学习模型选择过拟合也称为过学习,他的直观表现是在训练集上表现很好,但是在测试集上表现却不好,因此其推广泛化性能差。过拟合产生的根本原因是训练数据包含抽样误差,在训练时,模型将抽样误差也进行了拟合。抽样误差是指抽样得到的样本集和整体数据之间的偏差。其引发的原因如下:(1)模型本身过于复杂,拟合了训练样本集中的噪声。因此需要选用相对简单的模型。(2)训练样本太少或者缺乏代表性。因此需要增加样本数量,或者增加样本的多样性。(3)训练样本噪声干扰,导致模型将这些噪声拟合,此时需要将噪声进行剔除或者修改模型,使其对噪声的敏感度降低。欠拟合也称为欠学习,其表现是训练得到的模型在训练集上表现差,没有学习到数据的规律。其引发的原因是模型过于简单或者特征数太少无法正确确立映射关系。模型选择1.3.2偏差-方差分解模型的误差通常可以分解成样本真实噪声、偏差与方差。样本真实噪音是任何学习算法在该学习目标上的期望误差的下界,这个噪声是任何学习算法都无法避免的。偏差度量了某种学习算法的平均估计结果所能逼近学习目标的程度,即刻画了学习算法本身的拟合能力。方差度量了在面对同样规模的不同训练集时,学习算法的估计结果发生变动的程度,即刻画了数据扰动所造成的影响。在模型的实际制定中,如果过于简单,一般会有较大的偏差和较小的方差;如果过于复杂,则会有较大的方差和较小的偏差。这两个值是一对互相矛盾的值,所以我们需要在偏差和方差之间做出一个折中的选择。举一个简单的例子,如果我们投掷飞镖,当飞镖在空中时,受到重力的影响将进行曲线运动。如果不考虑空气的阻力,这条曲线是一个抛物线;如果考虑空气阻力,那这条曲线将更加复杂。我们用抛物线的模型对飞镖的轨迹进行预测,在确定飞镖的速度,投掷位置与标靶直接按的距离后,可以通过修改投掷的角度来让飞镖命中靶心。当我们使用抛物线函数时就产生了偏差,因为理论上飞镖的落点不会在把靶心,而是在靶心靠下的位置,此时我们将修改模型。无论选用哪种模型,受到投掷力度,风速等外部条件的影响,即使理论上落点在靶心,但实际结果依然会有偏差,这就是方差。ThankYou
谢谢观看!第二章决策树
目录基本流程与划分2.1训练算法2.2决策树算法案例2.3CONTENTS决策树是一种基于规则的方法,它用一组嵌套的规则进行预测。在树的每个决策节点处,根据判断的结果进入下一个分支,反复直行此类操作最终到达叶子节点,得到预测结果。这些规则是通过训练得到的,而不是人工制定的。基本流程与划分2.1基本流程与划分下面我们来对一个简单的案例进行说明:假设孩子们想要出去打羽毛球,尽管愿望非常的强烈,但是天气的变化对于打羽毛球确是有很大的影响。当天的天气将是是否能够打羽毛球的先决条件。表2-1中记录了两周内的天气情况与是否去打羽毛球的记录,其中包含了4项天气指标与最终结果。在下一次决定去放风筝前,可以利用下表2-1数据构建出一颗决策树,如图2-1所示,来帮助我们判断当天的天气是否适合打羽毛球。表2-1天气数据表日期天气温度湿度风力是否打球1晴热高弱否2晴热高强否3阴热高弱是4雨中等高弱是5雨冷正常弱是6雨冷正常强否7阴冷正常强是8晴中等高弱否9晴冷正常弱是10雨中等正常弱是11晴中等正常强是12阴中等高强是13阴热正常弱是14雨中等高强否基本流程与划分图2-1天气树状图图2-1中所示就是一个决策树。一棵决策树由节点,和有向边构成。节点又可以分为两类:内部节点和叶节点。基本流程与划分决策树节点有向边内部节点叶节点一个决策树有节点和有向边构成,其中节点分为内部节点和叶子节点。当节点为内部节点时,根据样本对应的特征值移动到当前这个节点的子节点。若当前为内部节点,则返回叶节点所表示的分类标记,分类过程结束。根据所示决策树及当天天气,判断孩子是否能够打球:1、先看天气,今天是晴天;再看湿度,今天湿度高;不去打球。2、先看天气,今天是雨天;再看风力,今天风不大;去打球。3、先看天气,今天是阴天;直接去打球。通过这个例子,我们可以发现,决策树决策的过程就像是执行一个包含一系列if-else语句的算法,该算法并非手写,而是根据训练样本自动生成的。训练算法2.2训练算法决策树中关键的问题是如何用训练样本建立决策树。不论是分类还是回归问题,决策树都需要对训练样本尽可能的进行正确的预测。简单的来说,就是从根节点开始构造,递归的用训练样本建立起决策树,这样的树能将训练集正确的进行分类,或者对训练集的回归误差最小化。在实现此方法前需要我们解决以下问题。特征向量有多个分量,每个决策节点上应该选择哪个分量做判定?这个判定会将训练样本集一分为二,然后用这两个子集构造左右子树。通过特征将树进行左右分支,判断的规则尤为重要。对数值型变量要寻找一个分裂阈值进行判断,小于该阈值进入左子树,否则进入右子树。对于类别型变量则需要为它确定一个子集划分,将特征的取值集合划分成两个不相交的子集,使得整个集能够分到左子树集或右子树集中。对于分类问题,当节点的样本都属于同一类型时将停止分类,但这样可能会导致树的节点过多、深度过大,产生过拟合问题。另一种方法是当节点中的样本数小于一个阈值时停止分裂。接下来就需要对每个叶节点赋予类别标签或者回归值,也就是说,对到达叶子节点时样本将会被赋子一个实数值。训练算法由于特征有数值型变量和类别型变量两种情况,决策树有分类树和回归树两种类型,组合起来一共有4种情况。在此我们将只对数值型变量进行介绍。2.2.1递归分裂决策树训练算法是一个递归的过程。首先创建根节点,然后递归地建立左子树和右子树。如果练样本集为A,训练算法的整体流程如下。(1)用样本集A建立根节点,找到一个判定规则,将样本集分裂成A1和A2两部分,同时为根节点设置判定规则。(2)用样本集A1递归建立左子树。(3)用样本集A2递归建立右子树。(4)如果不能再进行分裂,则把节点标记为叶子节点,同时为它赋值。训练算法其实现代码如下所示:defmajorityCnt(classList):classCount={}forvalueinclassList:ifvaluenotinclassCount:classCount[value]=0classCount[value]+=1classCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)returnclassCount[0][0]在确定这个递归流程之后,接下来要解决的核心问题是怎样对训练样本集进行分裂。训练算法2.2.2寻找最佳分裂训练时需要找到一个分裂规则把训练样本集分裂成两个子集,因此,要确定分裂的评价标准,根据它寻找最佳分裂。对于分类问题,要保证分裂之后左右子树的样本尽可能纯,即它们的样本尽可能属于不相交的某一类或者几类。为此需要定义不纯度的指标:当样本都属于某一类时不纯度为0:当样本均匀地属于所有类时不纯度最大。满足这个条件的有熵不纯度、Gini不纯度,以及误分类不纯度等,下面分别进行介绍。不纯度指标用样本集中每类样本出现的概率值构造。因此,首先要计算每个类出现的概率,这通过训练样本集中每类样本数除以样本总数得到
其中,N_i是第i类样本数;N为总样本数。根据这个概率值可以定义各种不纯度指标。样本集D的熵不纯度定义为:
训练算法熵是信息论中的一个重要概念,用来度量一组数据包含的信息量大小。当样本只属于某一类时熵最小,当样本均匀地分布于所有类中时熵最大。因此,如果能找到一个分裂让熵最小,这就是我们想要的最佳分裂。样本集的Gini不纯度定义为:
当样本属于某一类时Gini不纯度的值最小,此时最小值为0;当样本均匀地分布于每一类时Gini不纯度的值最大。这源自于如下数学结论,在下面的约束条件下
训练算法对于如下目标函数:
所有变量相等时它有极小值,只有一个变量为其他变量为0时该函数有极大值,这对应于Gini不纯度的极小值,即所有样本都来自同一类时Gini不纯度的值最小,样本均匀地属于每一类时Gini不纯度的值最大。将类概率的计算公式代入Gini不纯度的定义,可以得到简化的计算公式:
样本集的误分类不纯度定义为:
训练算法之所以这样定义是因为人们会把样本判定为频率最大的那一类,因此,其他样本都会被错分,故错误分类率为上面的值。和上面的两个指标一样,当样本只属于某一类时误分类不纯度有最小值0,样本均匀地属于每一类时该值最大。上面定义的是样本集的不纯度,我们需要评价的是分裂的好坏,因此,需要根据样本集的不纯度构造出分裂的不纯度。分裂规则将节点的训练样本集分裂成左右两个子集,分裂的目标是把数据分成两部分之后这两个子集都尽可能纯。因此,我们计算左右子集的不纯度之和作为分裂的不纯度,显然求和需要加上权重,以反映左右两边的训练样本数。由此得到分裂的不纯度计算公式为
训练算法
训练算法这个值可以看作Gini纯度,它的值越大,样本越纯。寻找最佳分裂时需要计算用每个阈值对样本集进行分裂后的这个值,寻找该值最大时对应的分裂,它就是最佳分裂。如果是数值型特征,对于每个特征将1个训练样本按照该特征的值从小到大排序,假设排序后的值为:
图2-2为数值型变量找最佳分裂阈值训练算法
把均值的定义带入上式,得到:
训练算法根据样本集的回归误差,我们同样可以构造出分裂的回归误差。分裂的目标是最大程度地减小回归误差,因此,把分裂的误差指标定义为分裂之前的回归误差减去分裂之后左右子树的回归误差:
训练算法将误差的计算公式代入上式,可以得到
训练算法由于N和
是常数,要让上式最大化等价于让下式最大化:
训练算法2.2.3叶子节点值的设定如果不能继续分裂,则将该节点设置为叶子节点。对于分类树,将叶子节点的值设置成本节点的训练样本集中出现概率最大的那个类;对于回归树,则设置为本节点训缘样本标签值的均值。2.2.4属性缺失在某些情况下样本特征向量中一些分量没有值,这称为属性缺失。例如,晚上我们无法观察到物体的颜色值,颜色属性就缺失了。在决策树的训练过程中,寻找最佳分裂时如果某一个属性上有些样本有属性缺失,可以把这些缺失该属性的样本剔除掉,然后照常训练,这是最简单的做法。此外,还可以使用替代分裂规则。对于每个决策树节点除了计算出一个最佳分裂规则作为主分裂规则,还会生成一个或者多个替代分裂规则作为备选。在预测时如果主分裂规则对应的特征出现缺失,则使用替代分裂规则进行判定。需要注意的是,替代分裂对于分类问题和回归问题是做相同的处理。训练算法现在的关键问题是怎样生成替代分裂规则。主分裂和替代分裂对所有样本的分裂结果有4种情况,分别为LL,LR,RL,RR.LL表示被主分裂、替代分裂都分到了左子树的样本数;LR表示被主分裂分到了左子树,被替代分裂分到了右子树的样本数;RL表示被主分裂分到了右子树,被替代分裂分到了左子树的样本数;RR表示被主分裂和替代分裂都分到了右子树的样本数。LL+RR是被替代分裂正确分类的样本数,LR+RL.是被替代分裂错分的样本数。由于可以将左右子树反过来,因此,给定一个特征分量,在寻找替代分裂的分裂阈值时要让LL+RR或者LR+RL最大化,最后取它们的最大值:max(LL+RR,LR+RL)该值对应的分裂阈值为替代分裂的分裂阈值。对于除最佳分裂所用特征之外的其他所有特征,都找出该特征的最佳分裂和上面的值。最后取该值最大的那个特征和分裂阈值作为替代分裂规则。训练算法2.2.5剪枝算法如果决策树的结构过于复杂,可能会导致过拟合问题。此时需要对树进行剪枝,消掉某些节点让它变得更简单。剪枝的关键问题是确定剪掉哪些树节点以及剪掉它们之后如何进行节点合并。决策树的剪枝算法可以分为两类,分别称为预剪枝和后剪枝。前者在树的训练过程中通过停止分裂对树的规模进行限制;后者先构造出一棵完整的树,然后通过某种规则消除掉部分节点,用叶子节点替代。预剪枝可以通过限定树的高度、节点的训练样本数、分裂所带来的纯度提升的最小值来来实现,具体做法在前面已经讲述,在源代码分析中会介绍实现细节。后剪枝的典型实现有降低错误剪枝、悲观错误剪枝、代价-复杂度剪枝等方案。分类与回归树采用的是代价-复杂度剪枝算法,下面重点介绍它的原理。代价是指剪枝后导致的错误率的变化值,复杂度是指决策树的规模。训练出一棵决策树之后,剪枝算法首先计算该决策树每个非叶子节点的a值,它是代价与复杂度的比值。该值定义为:
训练算法
训练算法子树的错误率为树的所有叶子节点错误率之和。计算出⍺值之后,剪掉该值最小的节点得到剪枝后的树,然后重复这种操作直到剩下根节点,由此得到一个决策树序列:
第一步
第二步第二步根据真实误差值从上面的树序列中挑选出一棵树作为剪枝后的结果。这可以通过交叉验证实现,用交叉验证的测试集对上一步得到的树序列的每一棵树进行测试,得到这些树的错误率,然后根据错误率选择最佳的树作为剪枝后的结果。2.3决策树算法案例决策树算法案例案例1鸟类与非鸟类判定本案例将根据2个特征将动物分成两类:鸟类和非鸟类。其中一个特征是是否有翅膀,另一个特征是是否能在空中飞行。决策树算法案例案例流程1.收集数据:可以使用任何方法2.准备数据:由于树构造算法只适用于标称型数据,因此数值型数据必须离散化分析数据:理论上来说,可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期3.训练算法:构造树的数据结构4.测试算法:使用决策树执行分类5.使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义决策树算法案例样本编号是否能飞行是否有翅膀是否是鸟类1是是是2是是是3是否否4否是否5否是否1.收集数据决策树算法案例样本编号是否能飞行是否有翅膀是否是鸟类111Y211Y310N401N501N2.准备数据样本数据转换决策树算法案例利用createDataSet()函数将数据输入:
defcreateDataSet():
#dataSet前两列是特征,最后一列对应的是每条数据对应的分类标签
dataSet=[[1,1,'y'],
[1,1,'y'],
[1,0,'n'],
[0,1,'n'],
[0,1,'n']]
labels=['canfly','wing']
returndataSet,labels决策树算法案例3.分析数据为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面的公式得到:
defcalcShannonEnt(dataSet):
#-----------计算香农熵--------------------------
#求list的长度,表示计算参与训练的数据量
numEntries=len(dataSet)
#计算分类标签label出现的次数
labelCounts={}
#thethenumberofuniqueelementsandtheiroccurance
forfeatVecindataSet:#将当前实例的标签存储,即每一行数据的最后一个数据代表的是标签
currentLabel=featVec[-1]决策树算法案例#为所有可能的分类创建字典,如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。
ifcurrentLabelnotinlabelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1
#对于label标签的占比,求出label标签的香农熵
shannonEnt=0.0
forkeyinlabelCounts:
#使用所有类标签的发生频率计算类别出现的概率。
prob=float(labelCounts[key])/numEntries
#logbase2
#计算香农熵,以2为底求对数
shannonEnt-=prob*log(prob,2)
returnshannonEnt决策树算法案例4.划分数据集defsplitDataSet(dataSet,index,value):
#-----------切分数据集------------------------------------
retDataSet=[]
forfeatVecindataSet:
#index列为value的数据集【该数据集需要排除index列】
#判断index列的值是否为value
iffeatVec[index]==value:
#chopoutindexusedforsplitting
#[:index]表示前index行,即若index为2,就是取featVec的前index行
reducedFeatVec=featVec[:index]
reducedFeatVec.extend(featVec[index+1:])
#[index+1:]表示从跳过index的index+1行,取接下来的数据
#收集结果值index列为value的行【该行需要排除index列】
retDataSet.append(reducedFeatVec)
returnretDataSet决策树算法案例5.选择切分数据集的最佳特征defchooseBestFeatureToSplit(dataSet):
#-----------选择最优特征------------------------------------
#求第一行有多少列的Feature,最后一列是label列嘛
numFeatures=len(dataSet[0])-1
#label的信息熵
baseEntropy=calcShannonEnt(dataSet)
#最优的信息增益值,和最优的Featurn编号
bestInfoGain,bestFeature=0.0,-1
#iterateoverallthefeatures
foriinrange(numFeatures):
#createalistofalltheexamplesofthisfeature
#获取每一个实例的第i+1个feature,组成list集合
featList=[example[i]forexampleindataSet]
#getasetofuniquevalues
#获取剔重后的集合,使用set对list数据进行去重
uniqueVals=set(featList)决策树算法案例
#创建一个临时的信息熵
newEntropy=0.0
#遍历某一列的value集合,计算该列的信息熵
#遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。
forvalueinuniqueVals:
subDataSet=splitDataSet(dataSet,i,value)
prob=len(subDataSet)/float(len(dataSet))
newEntropy+=prob*calcShannonEnt(subDataSet)
#gain[信息增益]:划分数据集前后的信息变化,获取信息熵最大的值
#信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。
infoGain=baseEntropy-newEntropy
print('infoGain=',infoGain,'bestFeature=',i,baseEntropy,newEntropy)
if(infoGain>bestInfoGain):
bestInfoGain=infoGain
bestFeature=i
returnbestFeature决策树算法案例6.创造树defcreateTree(dataSet,labels):
classList=[example[-1]forexampleindataSet]
#如果数据集的最后一列的第一个值出现的次数=整个集合的数量,也就说只有一个类别,就只直接返回结果就行
#第一个停止条件:所有的类标签完全相同,则直接返回该类标签。
#count()函数是统计括号中的值在list中出现的次数
ifclassList.count(classList[0])==len(classList):
returnclassList[0]
#如果数据集只有1列,那么最初出现label次数最多的一类,作为结果
#第二个停止条件:使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。
iflen(dataSet[0])==1:
returnmajorityCnt(classList)
#选择最优的列,得到最优列对应的label含义
bestFeat=chooseBestFeatureToSplit(dataSet)#获取label的名称
bestFeatLabel=labels[bestFeat]决策树算法案例#初始化myTree
myTree={bestFeatLabel:{}}#注:labels列表是可变对象,在PYTHON函数中作为参数时传址引用,能够被全局修改
#所以这行代码导致函数外的同名变量被删除了元素,造成例句无法执行,提示'nosurfacing'isnotinlist
del(labels[bestFeat])
#取出最优列,然后它的branch做分类
featValues=[example[bestFeat]forexampleindataSet]
uniqueVals=set(featValues)
forvalueinuniqueVals:
#求出剩余的标签label
subLabels=labels[:]
#遍历当前选择特征包含的所有属性值,在每个数据集划分上递归调用函数createTree()
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
returnmyTree决策树算法案例7.使用决策树进行分类defclassify(inputTree,featLabels,testVec):
#获取tree的根节点对于的key值
firstStr=list(inputTree.keys())[0]
#通过key得到根节点对应的value
secondDict=inputTree[firstStr]
#判断根节点名称获取根节点在label中的先后顺序,这样就知道输入的testVec怎么开始对照树来做分类
featIndex=featLabels.index(firstStr)
#测试数据,找到根节点对应的label位置,也就知道从输入的数据的第几位来开始分类
key=testVec[featIndex]
valueOfFeat=secondDict[key]
print('+++',firstStr,'xxx',secondDict,'---',key,'>>>',valueOfFeat)
#判断分枝是否结束:判断valueOfFeat是否是dict类型
ifisinstance(valueOfFeat,dict):
classLabel=classify(valueOfFeat,featLabels,testVec)
else:
classLabel=valueOfFeat
returnclassLabel决策树算法案例8.执行函数defbirdTest():
myDat,labels=createDataSet()
importcopy
myTree=createTree(myDat,copy.deepcopy(labels))
print(myTree)
print(classify(myTree,labels,[1,1]))
dtPlot.createPlot(myTree)
if__name__=="__main__":
birdTest()
通过上述步骤,已经完成了决策树的分类。但是为了能够更加直观的看到决策树,我们需要添加一段代码来将该树画出,并显示在窗口中。具体代码如下所示。决策树算法案例导入matplotlib库,matplotlib是python上的一个2D绘图库,它可以在夸平台上边出很多高质量的图像。通过matplotlib可以生成绘图、直方图、功率谱、柱状图、误差图、散点图等。importmatplotlib.pyplotasplt
定义文本框和箭头格式,sawtooth波浪方框,round4矩形方框,fc表示字体颜色的深浅0.1~0.9依次变浅。decisionNode=dict(boxstyle="sawtooth",fc="0.8")leafNode=dict(boxstyle="round4",fc="0.8")arrow_args=dict(arrowstyle="<-")获取叶子的数量defgetNumLeafs(myTree):
numLeafs=0
firstStr=list(myTree.keys())[0]
secondDict=myTree[firstStr]
#根节点开始遍历
forkeyinsecondDict.keys():
#判断子节点是否为dict,不是+1决策树算法案例iftype(secondDict[key])isdict:
numLeafs+=getNumLeafs(secondDict[key])
else:
numLeafs+=1
returnnumLeafs
获取树的深度defgetTreeDepth(myTree):
maxDepth=0
firstStr=list(myTree.keys())[0]
secondDict=myTree[firstStr]
#根节点开始遍历
forkeyinsecondDict.keys():
#判断子节点是不是dict,求分枝的深度
iftype(secondDict[key])isdict:
thisDepth=1+getTreeDepth(secondDict[key])决策树算法案例else:
thisDepth=1
maxDepth=max(maxDepth,thisDepth)
returnmaxDepth
画出节点defplotNode(nodeTxt,centerPt,parentPt,nodeType):
createPlot.ax1.annotate(nodeTxt,xy=parentPt,xycoords='axesfraction',xytext=centerPt,textcoords='axesfraction',va="center",ha="center",bbox=nodeType,arrowprops=arrow_args)defplotMidText(cntrPt,parentPt,txtString):
xMid=(parentPt[0]-cntrPt[0])/2+cntrPt[0]
yMid=(parentPt[1]-cntrPt[1])/2+cntrPt[1]
createPlot.ax1.text(xMid,yMid,txtString,va="center",ha="center",rotation=30)
决策树算法案例画出决策树defplotTree(myTree,parentPt,nodeTxt):
#获取叶子节点的数量
numLeafs=getNumLeafs(myTree)
#获取树的深度
#depth=getTreeDepth(myTree)
#找出第1个中心点的位置,然后与parentPt定点进行划线
cntrPt=(plotTree.xOff+(1+numLeafs)/2/plotTree.totalW,plotTree.yOff)
#print(cntrPt)
#并打印输入对应的文字
plotMidText(cntrPt,parentPt,nodeTxt)
firstStr=list(myTree.keys())[0]
#可视化Node分支点
plotNode(firstStr,cntrPt,parentPt,decisionNode)
#根节点的值
secondDict=myTree[firstStr]决策树算法案例#y值=最高点-层数的高度[第二个节点位置]
plotTree.yOff=plotTree.yOff-1/plotTree.totalD
forkeyinsecondDict.keys():
#判断该节点是否是Node节点
iftype(secondDict[key])isdict:
#如果是就递归调用[recursion]
plotTree(secondDict[key],cntrPt,str(key))
else:
#如果不是,就在原来节点一半的地方找到节点的坐标
plotTree.xOff=plotTree.xOff+1/plotTree.totalW
#可视化该节点位置
plotNode(secondDict[key],(plotTree.xOff,plotTree.yOff),cntrPt,leafNode)
#并打印输入对应的文字
plotMidText((plotTree.xOff,plotTree.yOff),cntrPt,str(key))
plotTree.yOff=plotTree.yOff+1/plotTree.totalD决策树算法案例创建决策树defcreatePlot(inTree):
#创建一个figure的模版
fig=plt.figure(1,facecolor='green')
fig.clf()
axprops=dict(xticks=[],yticks=[])
#表示创建一个1行,1列的图,createPlot.ax1为第1个子图,
createPlot.ax1=plt.subplot(111,frameon=False,**axprops)
plotTree.totalW=float(getNumLeafs(inTree))
plotTree.totalD=float(getTreeDepth(inTree))
#半个节点的长度
plotTree.xOff=-0.5/plotTree.totalW
plotTree.yOff=1.0
plotTree(inTree,(0.5,1.0),'')
plt.show()决策树算法案例通过上面的决策树绘画代码,就可以将数据转换成可视化的图片来方便我们进行观察。案例1的决策树图形如图2-3所示。图2-3案例1决策树图形决策树算法案例案例2隐形眼镜类型决策隐形眼镜类型包括硬材质、软材质以及不适合佩戴隐形眼镜。下面我们将通过决策树来预测患者需要佩戴的隐形眼镜类型。决策树算法案例项目流程1.收集数据:提供的文本文件。2.解析数据:解析tab键分隔的数据行。3.分析数据:快速检查数据,确保正确地解析数据内容,使用createPlot()函数绘制最终的树形图。4.训练算法:使用createTree()函数。5.测试算法:编写测试函数验证决策树可以正确分类给定的数据实例。6.使用算法:存储树的数据结构,以便下次使用时无需重新构造树。决策树算法案例收集数据:提供的文本文件,文件格式如下:决策树算法案例解析数据:解析tab键分隔的数据行,并给对应的数据配上标签:在案例1中我们所使用的#加载隐形眼镜相关的文本文件数据
fr=open('./lenses.txt')
#解析数据,获得features数据
lenses=[inst.strip().split('\t')forinstinfr.readlines()]
#得到数据的对应的Labels
lensesLabels=['age','prescript','astigmatic','tearRate']训练算法:训练算法的最终目的是创建树,需要通过以下几个步骤来完成。决策树算法案例
1.计算给定数据集的香农熵defcalcShannonEnt(dataSet):
#求list的长度,表示计算参与训练的数据量
numEntries=len(dataSet)
#计算分类标签label出现的次数
labelCounts={}
forfeatVecindataSet:
#将当前实例的标签存储,即每一行数据的最后一个数据代表的是标签
currentLabel=featVec[-1]
#为所有可能的分类创建字典,如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。
ifcurrentLabelnotinlabelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1
#对于label标签的占比,求出label标签的香农熵决策树算法案例
shannonEnt=0.0
forkeyinlabelCounts:
#使用所有类标签的发生频率计算类别出现的概率。
prob=float(labelCounts[key])/numEntries
#计算香农熵,以2为底求对数
shannonEnt-=prob*log(prob,2)
returnshannonEnt2.按照给定数据集划分
defsplitDataSet(dataSet,index,value):
retDataSet=[]
forfeatVecindataSet:
#index列为value的数据集【该数据集需要排除index列】
#判断index列的值是否为value
iffeatVec[index]==value:
#chopoutindexusedforsplitting决策树算法案例#[:index]表示前index行,即若index为2,就是取featVec的前index行
reducedFeatVec=featVec[:index]
reducedFeatVec.extend(featVec[index+1:])
#[index+1:]表示从跳过index的index+1行,取接下来的数据
#收集结果值index列为value的行【该行需要排除index列】
retDataSet.append(reducedFeatVec)
returnretDataSet3.选择最好的数据集划分方式defchooseBestFeatureToSplit(dataSet):
#求第一行有多少列的Feature,最后一列是label列表
numFeatures=len(dataSet[0])-1
#label的信息熵
baseEntropy=calcShannonEnt(dataSet)
#最优的信息增益值,和最优的Featurn编号
bestInfoGain,bestFeature=0.0,-1决策树算法案例#iterateoverallthefeatures
foriinrange(numFeatures):
#createalistofalltheexamplesofthisfeature
#获取每一个实例的第i+1个feature,组成list集合
featList=[example[i]forexampleindataSet]
#getasetofuniquevalues
#获取剔重后的集合,使用set对list数据进行去重
uniqueVals=set(featList)
#创建一个临时的信息熵
newEntropy=0.0
#遍历某一列的value集合,计算该列的信息熵
#遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。
forvalueinuniqueVals:
subDataSet=splitDataSet(dataSet,i,value)
prob=len(subDataSet)/float(len(dataSet))决策树算法案例newEntropy+=prob*calcShannonEnt(subDataSet)
#gain[信息增益]:划分数据集前后的信息变化,获取信息熵最大的值
#信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。
infoGain=baseEntropy-newEntropy
print('infoGain=',infoGain,'bestFeature=',i,baseEntropy,newEntropy)
if(infoGain>bestInfoGain):
bestInfoGain=infoGain
bestFeature=i
returnbestFeature4.创造树defcreateTree(dataSet,labels):
classList=[example[-1]forexampleindataSet]
#如果数据集的最后一列的第一个值出现的次数=整个集合的数量,也就说只有一个类别,就只直接返回结果就行
#第一个停止条件:所有的类标签完全相同,则直接返回该类标签。
#count()函数是统计括号中的值在list中出现的次数决策树算法案例
ifclassList.count(classList[0])==len(classList):
returnclassList[0]
#如果数据集只有1列,那么最初出现label次数最多的一类,作为结果
#第二个停止条件:使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。
iflen(dataSet[0])==1:
returnmajorityCnt(classList)
#选择最优的列,得到最优列对应的label含义
bestFeat=chooseBestFeatureToSplit(dataSet)
#获取label的名称
bestFeatLabel=labels[bestFeat]
#初始化myTree
myTree={bestFeatLabel:{}}
#注:labels列表是可变对象,在PYTHON函数中作为参数时传址引用,能够被全局修改
#所以这行代码导致函数外的同名变量被删除了元素,造成例句无法执行,提示'nosurfacing'isnotinlist
del(labels[bestFeat])
#取出最优列,然后它的branch做分类决策树算法案例
featValues=[example[bestFeat]forexampleindataSet]
uniqueVals=set(featValues)
forvalueinuniqueVals:
#求出剩余的标签label
subLabels=labels[:]
#遍历当前选择特征包含的所有属性值,在每个数据集划分上递归调用函数createTree()
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
#print('myTree',value,myTree)
returnmyTree5.测试算法:本步骤将对数据进行分类defclassify(inputTree,featLabels,testVec):
#获取tree的根节点对于的key值
firstStr=list(inputTree.keys())[0]
#通过key得到根节点对应的value
secondDict=inputTree[firstStr]决策树算法案例#判断根节点名称获取根节点在label中的先后顺序,这样就知道输入的testVec怎么开始对照树来做分类
featIndex=featLabels.index(firstStr)
#测试数据,找到根节点对应的label位置,也就知道从输入的数据的第几位来开始分类
key=testVec[featIndex]
valueOfFeat=secondDict[key]
print('+++',firstStr,'xxx',secondDict,'---',key,'>>>',valueOfFeat)
#判断分枝是否结束:判断valueOfFeat是否是dict类型
ifisinstance(valueOfFeat,dict):
classLabel=classify(valueOfFeat,featLabels,testVec)
else:
classLabel=valueOfFeat
returnclassLabel决策树算法案例最后通过plotTree函数将决策树画出来,就可以得到如下结果:ThankYou
谢谢观看!第三章k近邻算法
目录CONTENTS基本概念3.1预测算法3.2距离定义3.3k近邻算法案例3.4基本概念3.1基本概念俗话说得好,“物以类聚,人以群分”,判别一个人的品质特征,常常可以从他的朋友入手,所谓观其友,而知其人。K近邻算法就是和此理论类似的一种简单的机器学习算法。要确定一个样本的类别,可以计算它与所有训练样本的距离,然后找出和该样本最接近的k个样本,统计这些样本的类别进行投票,票数最多的那个类就是分类结果。因为直接比较待预测样本和训练样本的距离,kNN算法也被称为基于实例的算法。下面我们举一个简单的例子来进行说明。如图3-1所示,给出两个不同类别的样本数据,其中A类用方框表示,B类用三角形表示。图中心的圆形样本为需要进行判断的样本。图3-1基本概念当K=3时,选定距离需判断样本最近的3个目标,即实线圆圈内的范围。此时A类样本有1个,B类样本有2个,所以判断样本属于B类。当K=5时,选定距离判断样本最近的5个目标,即虚线圈内的范围。此时A类样本有3个,B类样本有2个,所以判断样本属于A类。于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。预测算法3.2预测算法
预测算法kNN算法也可以用于回归问题。假设离测试样本最近的k个训练样本的标签值为yi,则对样本的回归预测输出值为:
即所有邻居的标签均值,在这里最近的k个邻居的贡献被认为是相等的。同样也可以采用带权重的方案。带样本权重的回归预测函数为:
3.3距离定义距离定义
这与几何中的三角不等式吻合。第二个条件是非负性,即距离不能是一个负数:
第三个条件是对称性,即A到B的距离和B到A的距离必须相等:
距离定义第四个条件是区分性,如果两点间的距离为0,则两个点必须相同:
满足上面4个条件的函数都可以用作距离定义。
距离定义这是我们最熟知的距离定义。在使用欧氏距离时应将特征向量的每个分量归一化,以减少因为特征值的尺度范围不同所带来的干扰,否则数值小的特征分量会被数值大的特征分量淹没。例如,特征向量包含两个分量,分别为身高和肺活量,身高的范围是150~200cm,肺活量为2000~9000mL,如果不进行归一化,身高的差异对距离的贡献显然会被肺活量淹没。欧氏距离只是将特征向量看作空间中的点,没有考虑这些样本特征向量的概率分布规律。Mahalanobis距离是一种概率意义上的距离,给定两个向量x和y以及矩阵S,它定义为:
要保证根号内的值非负,即矩阵S必须是半正定的。这种距离度量的是两个随机向量的相似度。当矩阵S为阶单位矩阵I时,Mahalanobis距离退化为欧氏距离。矩阵可以通过计算训练样本集的协方差矩阵得到,也可以通过训练样本学习得到。距离定义kNN算法的精度在很大程度上依赖于所使用的距离度量标准,为此他们提出了一种从带标签的样本集中学习得到距离度量矩阵的方法,称为距离度量学习(DistanceMetricLearning),我们将在3.3.2节中介绍。Bhattacharyya距离定义了两个离散型或连续型概率分布的相似性。对于离散型随机变量的分布,它的定义为:
距离定义3.3.2距离度量学习Mahalanobis距离中的矩阵S可以通过对样本的学习得到,这称为距离度量学习。距离度量学习通过样本集学习到一种线性或非线性变换,它使得变换后每个样本的k个最近邻居都和它是同一个类,而不同类型的样本通过一个大的间隔被分开,这和线性判别分析的思想类似。如果原始的样本点为x,变换之后的点为y,在这里要寻找的是如下线性变换:
其中,L为线性变换矩阵。首先定义目标邻居的概念。一个样本的目标邻居是和该样本同类型的样本。我们希望通过学习得到的线性变换让样本最接近的邻居就是它的目标邻居:
距离定义
其中,L为线性变换矩阵,左乘这个矩阵相当于对向量进行线性变换。根据上面的定义,冒充者就是闯入了一个样本的分类间隔区域并且和该样本标签值不同的样本。这个线性变换实际上确定了一种距离定义:距离定义
推损失函数的作用是把不同类型的样本推开:
距离定义
如果两个样本类型相同,则有
因此,推损失函数只对不同类型的样本起作用。总损失函数由这两部分的加权和构成:
这里μ是人工设定的参数。求解该最小化问题即可得到线性变换矩阵。通过这个线性变换,同类样本尽量都成为最近的邻居节点;而不同类型的样本会拉开距离。这会有效地提高kNN算法的分类精度。距离定义k-近邻算法的一般流程1.收集数据:可以使用任何方法2.准备数据:距离计算所需要的数值,最好是结构化的数据格式3.分析数据:可以使用任何方法4.训练算法:此步骤不适合k-近邻算法5.测试算法:计算错误率6.使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用计算结果进行后续处理k近邻算法案例3.4k近邻算法案例案例1基于k近邻数据分类本案例用已存在的先验数据,通过KNN算法对未知数据进行分类k近邻算法案例下表为已知数据表属性1属性2类别1.00.9A1.01.0A0.10.2B00.1B该数据表一共包含四个样本,分别属于A,B两个类别,通过以下代码将数据生成一个数据集。k近邻算法案例defcreateDataSet():
#生成一个矩阵,每行表示一个样本
group=array([[1.0,0.9],[1.0,1.0],[0.1,0.2],[0.0,0.1]])
#4个样本分别所属的类别
labels=['A','A','B','B']
returngroup,labels数据集生成完成后,需要定义KNN分类算法函数defkNNClassify(newInput,dataSet,labels,k):
numSamples=dataSet.shape[0]#shape[0]表示行数
diff=tile(newInput,(numSampl
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026事业单位工勤技能-贵州-贵州林木种苗工五级(初级工)历年参考题库含答案详解
- 2026事业单位工勤技能-湖南-湖南地质勘查员四级(中级工)历年参考题库含答案详解
- 2026事业单位工勤技能-河南-河南计量检定工三级(高级工)历年参考题库含答案详解
- 2026事业单位工勤技能-江西-江西信号工-机车信号设备维修四级(中级工)历年参考题库含答案详解
- 2026事业单位工勤技能-广东-广东热力运行工三级(高级工)历年参考题库含答案详解
- 2026事业单位工勤技能-安徽-安徽水工监测工三级(高级工)历年参考题库含答案详解
- 2026事业单位工勤技能-内蒙古-内蒙古收银员一级(高级技师)历年参考题库含答案详解
- 2026中国餐饮业职业经理人(CMEP)高级资格证书考试历年参考题库含答案详解
- 2026下半年财会事业编专项训练试卷
- 基于超表面的太赫兹波前调控器件研究报告
- 野村-人工智能如何掩盖美国不断上升的风险溢价-How AI masks America's rising risk premium-20260903
- 第十四章35kV变电站保护整定值计算实例
- 2026秋小学湘美版美术六年级上册(新教材)教学计划附教学进度表
- 岗位匹配度评估表
- 2026年建设工程专业考试(风景园林)副高、高级测试题及答案
- 2026 年高中秋季开学第一课青年理想与家国担当思政教育班会
- 2026年度云南省二级造价工程师职业资格考试土木建筑工程复习题及答案
- ATLS 高级创伤生命支持实践指南(第 11 版 中文版)
- 人教版八年级数学上册单元测试题全套
- 甲状腺癌系统性治疗ASCO指南解读总结2026
- 网球场施工组织设计
评论
0/150
提交评论