diff --git a/README.md b/README.md index 2cb4a14d..d77b5c1c 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ * 4.) [基于概率论的分类方法:朴素贝叶斯](./docs/4.朴素贝叶斯.md) * 5.) [Logistic回归](./docs/5.Logistic回归.md) * 6.) [支持向量机](./docs/6.支持向量机.md) -* 7.1) [利用AdaBoost元算法提高分类](./docs/7.利用AdaBoost元算法提高分类.md) -* 7.2) [随机森林的使用(非课本内容)](./docs/7.随机森林的使用.md) +* 7.1) [利用AdaBoost元算法提高分类](./docs/7.1.利用AdaBoost元算法提高分类.md) +* 7.2) [随机森林的使用(非课本内容)](./docs/7.2.随机森林的使用.md) ## 第二部分 利用回归预测数值型数据 diff --git a/docs/1.机器学习基础.md b/docs/1.机器学习基础.md index 5f515f2f..a8956b37 100644 --- a/docs/1.机器学习基础.md +++ b/docs/1.机器学习基础.md @@ -15,7 +15,7 @@ 在90年代初,人们开始意识到一种可以更有效地构建模式识别算法的方法,那就是用数据(可以通过廉价劳动力采集获得)去替换专家(具有很多图像方面知识的人)。 “机器学习”强调的是,在给计算机程序(或者机器)输入一些数据后,它必须做一些事情,那就是学习这些数据,而这个学习的步骤是明确的。 机器学习(Machine Learning)是一门专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能的学科。 -深度学习(deep learning): 深度学习是非常崭新和有影响力的前沿领域,我们甚至不会去思考后深度学习时代 +深度学习(deep learning): 深度学习是非常崭新和有影响力的前沿领域,我们甚至不会去思考-后深度学习时代。 深度学习是机器学习研究中的一个新的领域,其动机在于建立、模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本。 参考地址: @@ -29,7 +29,7 @@ http://baike.baidu.com/link?url=76P-uA4EBrC3G-I__P1tqeO7eoDS709Kp4wYuHxc7GNkz_xn * 搜索引擎,根据你的搜索点击,优化你下次的搜索结果。 * 垃圾邮件,会自动的过滤垃圾广告邮件到垃圾箱内。 -* 超市优惠券,你会发现,你在购买小孩子的尿布的时候,售货员会赠送你一张优惠券可以兑换6罐啤酒。 +* 超市优惠券,你会发现,你在购买小孩子尿布的时候,售货员会赠送你一张优惠券可以兑换6罐啤酒。 * 邮局邮寄,手写软件自动识别寄送贺卡的地址。 * 申请贷款 或 进入赌场,通过你最近的金融活动信息进行综合评定,决定你是否合格。 @@ -43,7 +43,7 @@ http://baike.baidu.com/link?url=76P-uA4EBrC3G-I__P1tqeO7eoDS709Kp4wYuHxc7GNkz_xn > 机器学习的主要任务就是分类和回归 -* 分类:将实例数据划分到合适的分类中。 +* 分类:将实例数据划分到合适的类别中。 * 回归:主要用于预测数值型数据。(例子———数据拟合曲线:通过给定数据点的最优拟合曲线) * 目标变量 * 目标变量是机器学习预测算法的测试结果。 @@ -60,15 +60,15 @@ http://baike.baidu.com/link?url=76P-uA4EBrC3G-I__P1tqeO7eoDS709Kp4wYuHxc7GNkz_xn * 训练样本的集合称为训练样本集,训练样本集必须确定知道目标变量的值,以便机器学习算法可以发现特征和目标变量之间的关系。 * 特征(feature-是否有缺失情况) + 目标变量(分类-离散值/回归-连续值<0~100、 -999~999>) * 特征或者属性通常是训练样本集的列,它们是独立测量得到的结果,多个特征联系在一起共同组成一个训练样本。 -* `知识表示`:机器已经学会如何识别鸟类的过程 +* `知识表示`:(例如-机器已经学会如何识别鸟类的过程) * 1.可以采用规则集的形式【例如:数学成绩大于90分为优秀】 - * 2.可以采用概率分布的形式【例如:通过统计分布发现,90%的同学数学成绩,在70分一下,那么大于70分定为优秀】 - * 3.可以使训练样本集中的一个实例【例如:通过样本集合,我们训练出一个模型实例,得出 年轻,数学成绩中高等,谈吐优雅,我们认为是优秀】 + * 2.可以采用概率分布的形式【例如:通过统计分布发现,90%的同学数学成绩,在70分以下,那么大于70分定为优秀】 + * 3.可以使用训练样本集中的一个实例【例如:通过样本集合,我们训练出一个模型实例,得出 年轻,数学成绩中高等,谈吐优雅,我们认为是优秀】 > 非监督学习 * 数据没有类别信息,也不会给定目标值。 -* 聚类:在无监督学习中,将数据集合分成由类似的对象组成的多个类的过程称为聚类。 +* 聚类:在无监督学习中,将数据集合分成由类似的对象组成多个类的过程称为聚类。 * 密度估计:将寻找描述数据统计值的过程称之为密度估计。【就是:根据训练样本确定x的概率分布】 * 此外,无监督学习还可以减少数据特征的维度,以便我们可以使用二维或三维图形更加直观地展示数据信息。 diff --git a/docs/6.支持向量机.md b/docs/6.支持向量机.md index 2252c626..097161d0 100644 --- a/docs/6.支持向量机.md +++ b/docs/6.支持向量机.md @@ -99,7 +99,7 @@ This is the simplest kind of SVM (Called an LSVM) Support Vectors are those data > 松弛变量(slack variable) -* 我们知道几乎所有的数据都不那么干净, 通过引入松弛变量来允许数据点可以处于分隔面错误的一侧。 +* 我们知道几乎所有的数据都不那么干净, 通过引入松弛变量来`允许数据点可以处于分隔面错误的一侧`。 * 约束条件: \\(C>=a>=0,\ and\ \sum_{i=1}^{m} a_i·label_i=0\\) * 这里常量C用于控制“最大化间隔”和“保证大部分点的函数间隔小于1.0” 这两个目标的权重。 * 常量C是一个常数,我们通过调节该参数得到不同的结果。一旦求出了所有的alpha,那么分隔超平面就可以通过这些alpha来表示。 @@ -126,7 +126,7 @@ SVM的一般流程 * 创建时间:1996年 * SMO用途:用于训练SVM * SMO目标:求出一系列alpha和b,一旦求出alpha,就很容易计算出权重向量w并得到分隔超平面。 -* SMO思想:是讲大优化问题分解为多个小优化问题来求解的。 +* SMO思想:是将大优化问题分解为多个小优化问题来求解的。 * SMO原理:每次循环选择两个alpha进行优化处理,一旦找出一对合适的alpha,那么就增大一个同时减少一个。 * 这里指的合适必须要符合一定的条件 * 1.这两个alpha必须要在间隔边界之外 diff --git a/docs/7.1.利用AdaBoost元算法提高分类.md b/docs/7.1.利用AdaBoost元算法提高分类.md new file mode 100644 index 00000000..75a3a2ff --- /dev/null +++ b/docs/7.1.利用AdaBoost元算法提高分类.md @@ -0,0 +1,131 @@ +# 第7章 利用AdaBoost元算法提高分类 + +![利用AdaBoost元算法提高分类](/images/7.AdaBoost/adaboost_headPage.jpg "利用AdaBoost元算法提高分类") + +## 组合相似的分类器来提高分类性能 + +> 元算法(meta-algorithm) 或 集成方法(ensemble method) + +* 概念:是对其他算法进行组合的一种形式。 +* 通俗来说: 当做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见。 + 机器学习处理问题时又何尝不是如此? 这就是元算法(meta-algorithm)背后的思想。 +* 集成方法: 1. 投票选举 2. 再学习 + +> bagging:基于数据随机重抽样的分类起构造方法 + +* 自举汇聚法(bootstrap aggregating),也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。 + 1. 新数据集和原数据集的大小相等。 + 2. 每个数据集都是通过在原始数据集中随机选择一个样本来进行替换(替换:意味着可以多次选择同一个样本,也就有重复值)而得到的。 + 3. 该算法作用的数据集就会得到S个分类器,与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。 + 4. 例如:随机森林(random forest) +* 追美女:美女选择择偶对象的时候,会问几个闺蜜的建议,最后选择一个综合得分最高的一个作为男朋友 + +> boosting + +* boosting是一种与bagging很类似的技术。 +* 不过boosting分类的结果是基于所有分类器的加权求和结果的。不论是boosting还是bagging当中,所使用的多个分类器的类型都是一致的。 +* 区别是什么? + 1. bagging:不同的分类器是通过串形训练而获得的,每个新分类器斗根据已训练出的分类器的性能来进行训练。 + 2. boosting:是通过集中关注被已有分类器错分的那些数据来获得新的分类器。 + 3. 由于boosting分类的结果是基于所有分类器的加权求和结果的,因此boosting与bagging不太一样。 + 4. bagging中的分类器权重是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。 +* 目前boosting方法最流行的版本是: AdaBoost。 +* 追美女:第1个帅哥失败->(传授经验:姓名、家庭情况) 第2个帅哥失败->(传授经验:兴趣爱好、性格特点) 第3个帅哥成功 + +## 应用AdaBoost算法 + +> AdaBoost(adaptive boosting: 自适应boosting) + +``` +能否使用弱分类器和多个实例来构建一个强分类器? 这是一个非常有趣的理论问题。 + +* 优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调节。 +* 缺点:对离群点敏感。 +* 适用数据类型:数值型和标称型数据。 +``` + +> AdaBoost的一般流程 + +``` +收集数据:可以使用任意方法 +准备数据:依赖于所使用的弱分类器类型,本章使用的是单层决策树,这种分类器可以处理任何数据类型。当然也可以使用任意分类器作为弱分类器,第2章到第6章中的任一分类器都可以充当弱分类器。作为弱分类器,简单分类器的效果更好。 +分析数据:可以使用任意方法。 +训练数据:AdaBoost的大部分时间都用在训练上,分类器将多次在同一数据集上训练弱分类器。 +测试数据:计算分类的错误率。 +使用算法:通SVM一样,AdaBoost预测两个类别中的一个。如果想把它应用到多个类别的场景,那么就要像多类SVM中的做法一样对AdaBoost进行修改。 +``` + +* 训练算法: 基于错误提升分类器的性能 +* 基于单层决策树构建弱分类器 + * 单层决策树(decision stump, 也称决策树桩)是一种简单的决策树。 +* 过拟合(overfitting, 也称为过学习) + * 发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。 +* ![过拟合](/images/7.AdaBoost/过拟合.png) + +> AdaBoost的算法示意图 + +![AdaBoost算法示意图](/images/7.AdaBoost/adaboost_illustration.png "AdaBoost算法示意图") + +> 训练算法:基于错误提升分类器的性能 + +``` +发现: +alpha目的主要是计算每一个分类器实例的权重(组合就是分类结果) + 分类的权重值:最大的值,为alpha的加和,最小值为-最大值 +D的目的是为了计算错误概率: weightedError = D.T*errArr,求最佳分类器 + 特征的权重值:如果一个值误判的几率越小,那么D的特征权重越少 +``` + +![AdaBoost算法权重计算公式](/images/7.AdaBoost/adaboost_alpha.png "AdaBoost算法权重计算公式") + +## 完整AdaBoost算法的实现 + +整个实现的伪代码如下: + +``` +对每次迭代: + 利用buildStump()函数找到最佳的单层决策树 + 将最佳单层决策树加入到单层决策树数组 + 计算alpha + 计算新的权重向量D + 更新累计类别估计值 + 如果错误率等于0.0,则退出循环 +``` + +## 处理非均衡分类问题 + +> 概念 + +在分类器训练时,正例数目和反例数目不相等(相差很大) + +> 非均衡现象: + +* 判断马是否能继续生存(不可误杀) +* 过滤垃圾邮件(不可漏判) +* 不能放过传染病的人 +* 不能随便认为别人犯罪 + +> ROC评估方法 + +* ROC曲线: 最佳的分类器应该尽可能地处于左上角 +* ![ROC曲线](/images/7.AdaBoost/ROC曲线.png) + * 对不同的ROC曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve, AUC). + * AUC给出的是分类器的平均性能值,当然它并不能完全代替对整条曲线的观察。 + * 一个完美分类器的AUC为1,而随机猜测的AUC则为0.5。 + +> 代价函数 + +* 基于代价函数的分类器决策控制:`TP*(-5)+FN*1+FP*50+TN*0` +* ![代价函数](/images/7.AdaBoost/代价函数.png) + +> 抽样 + +* 欠抽样(undersampling)或者过抽样(oversampling) + * 欠抽样: 意味着删除样例 + * 过抽样: 意味着复制样例(重复使用) + +* * * + +* **作者:[片刻](http://www.apache.wiki/display/~jiangzhonglian)** +* [GitHub地址](https://github.com/apachecn/MachineLearning): +* **版权声明:欢迎转载学习 => 请标注信息来源于 [ApacheCN](http://www.apache.wiki)** diff --git a/docs/7.随机森林的使用.md b/docs/7.2.随机森林的使用.md similarity index 100% rename from docs/7.随机森林的使用.md rename to docs/7.2.随机森林的使用.md diff --git a/docs/7.利用AdaBoost元算法提高分类.md b/docs/7.利用AdaBoost元算法提高分类.md deleted file mode 100644 index b6d50c11..00000000 --- a/docs/7.利用AdaBoost元算法提高分类.md +++ /dev/null @@ -1,55 +0,0 @@ - -# 7) 利用AdaBoost元算法提高分类 - -* 元算法(meta-algorithm) 或 集成方法(ensemble method) - * 概念:是对其他算法进行组合的一种形式。 - * 通俗来说: 当做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见。 - 机器学习处理问题时又何尝不是如此? 这就是元算法(meta-algorithm)背后的思想。 -* bagging:基于数据随机重抽样的分类起构造方法 - * 自举汇聚法(bootstrap aggregating),也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。 - * 1. 新数据集和原数据集的大小相等。 - * 2. 每个数据集都是通过在原始数据集中随机选择一个样本来进行替换(替换:意味着可以多次选择同一个样本,也就有重复值)而得到的。 - * 3. 该算法作用的数据集就会得到S个分类器,与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。 - * 4. 例如:随机森林(random forest) - * 追美女:美女选择择偶对象的时候,会问几个闺蜜的建议,最后选择一个综合得分最高的一个作为男朋友 -* boosting - * boosting是一种与bagging很类似的技术。不论是boosting还是bagging当中,所使用的多个分类器的类型都是一致的。 - * 区别是什么? - * 1. bagging:不同的分类器是通过串形训练而获得的,每个新分类器斗根据已训练出的分类器的性能来进行训练。 - * 2. boosting:是通过集中关注被已有分类器错分的那些数据来获得新的分类器。 - * 3. 由于boosting分类的结果是基于所有分类器的加权求和结果的,因此boosting与bagging不太一样。 - * 4. bagging中的分类器权重是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。 - * 目前boosting方法最流行的版本是: AdaBoost。 - * 追美女:第1个帅哥失败->(传授经验:姓名、家庭情况) 第2个帅哥失败->(传授经验:兴趣爱好、性格特点) 第3个帅哥成功 -* AdaBoost(adaptive boosting: 自适应boosting) - * 能否使用弱分类器和多个实例来构建一个强分类器? 这是一个非常有趣的理论问题。 - * 优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调节。 - * 缺点:对离群点敏感。 - * 适用数据类型:数值型和标称型数据。 -* AdaBoost的一般流程 - * 训练算法: 基于错误提升分类器的性能 - * 基于单层决策树构建弱分类器 - * 单层决策树(decision stump, 也称决策树桩)是一种简单的决策树。 - * 过拟合(overfitting, 也称为过学习) - * 发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。 - * ![过拟合](/images/7.AdaBoost/过拟合.png) -* 非均衡分类问题 - * 现象: - * 判断马是否能继续生存 - * 过滤垃圾邮件 - * ROC曲线: 最佳的分类器应该尽可能地处于左上角 - * ![ROC曲线](/images/7.AdaBoost/ROC曲线.png) - * 对不同的ROC曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve, AUC). - * AUC给出的是分类器的平均性能值,当然它并不能完全代替对整条曲线的观察。 - * 一个完美分类器的AUC为1,而随机猜测的AUC则为0.5。 - * 基于代价函数的分类器决策控制:`TP*(-5)+FN*1+FP*50+TN*0` - * ![代价函数](/images/7.AdaBoost/代价函数.png) - * 欠抽样(undersampling)或者过抽样(oversampling) - * 欠抽样: 意味着删除样例 - * 过抽样: 意味着复制样例(重复使用) - -* * * - -* **作者:[片刻](http://www.apache.wiki/display/~jiangzhonglian)** -* [GitHub地址](https://github.com/apachecn/MachineLearning): -* **版权声明:欢迎转载学习 => 请标注信息来源于 [ApacheCN](http://www.apache.wiki)** diff --git a/images/7.AdaBoost/adaboost_alpha.png b/images/7.AdaBoost/adaboost_alpha.png new file mode 100644 index 00000000..8a391258 Binary files /dev/null and b/images/7.AdaBoost/adaboost_alpha.png differ diff --git a/images/7.AdaBoost/adaboost_headPage.jpg b/images/7.AdaBoost/adaboost_headPage.jpg new file mode 100644 index 00000000..7dbfe633 Binary files /dev/null and b/images/7.AdaBoost/adaboost_headPage.jpg differ diff --git a/images/7.AdaBoost/adaboost_illustration.png b/images/7.AdaBoost/adaboost_illustration.png new file mode 100644 index 00000000..cfa9362c Binary files /dev/null and b/images/7.AdaBoost/adaboost_illustration.png differ diff --git a/src/python/6.SVM/sklearn-svm-demo.py b/src/python/6.SVM/sklearn-svm-demo.py new file mode 100644 index 00000000..88e7aa28 --- /dev/null +++ b/src/python/6.SVM/sklearn-svm-demo.py @@ -0,0 +1,80 @@ +#!/usr/bin/python +# coding:utf8 + +""" +Created on 2017-06-28 +Updated on 2017-06-28 +SVM:最大边距分离超平面 +@author: 片刻 +《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning +""" +import numpy as np +import matplotlib.pyplot as plt +from sklearn import svm +print(__doc__) + + +# 创建40个分离点 +np.random.seed(0) +# X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]] +# Y = [0] * 20 + [1] * 20 + + +def loadDataSet(fileName): + """ + 对文件进行逐行解析,从而得到第行的类标签和整个数据矩阵 + Args: + fileName 文件名 + Returns: + dataMat 数据矩阵 + labelMat 类标签 + """ + dataMat = [] + labelMat = [] + fr = open(fileName) + for line in fr.readlines(): + lineArr = line.strip().split('\t') + dataMat.append([float(lineArr[0]), float(lineArr[1])]) + labelMat.append(float(lineArr[2])) + return dataMat, labelMat + + +X, Y = loadDataSet('input/6.SVM/testSet.txt') +X = np.mat(X) + +print("X=", X) +print("Y=", Y) + +# 拟合一个SVM模型 +clf = svm.SVC(kernel='linear') +clf.fit(X, Y) + +# 获取分割超平面 +w = clf.coef_[0] +# 斜率 +a = -w[0] / w[1] +# 从-5到5,顺序间隔采样50个样本,默认是num=50 +# xx = np.linspace(-5, 5) # , num=50) +xx = np.linspace(-2, 10) # , num=50) +# 二维的直线方程 +yy = a * xx - (clf.intercept_[0]) / w[1] +print("yy=", yy) + +# plot the parallels to the separating hyperplane that pass through the support vectors +# 通过支持向量绘制分割超平面 +print("support_vectors_=", clf.support_vectors_) +b = clf.support_vectors_[0] +yy_down = a * xx + (b[1] - a * b[0]) +b = clf.support_vectors_[-1] +yy_up = a * xx + (b[1] - a * b[0]) + +# plot the line, the points, and the nearest vectors to the plane +plt.plot(xx, yy, 'k-') +plt.plot(xx, yy_down, 'k--') +plt.plot(xx, yy_up, 'k--') + +plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=80, facecolors='none') +plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired) + +plt.axis('tight') +plt.show() diff --git a/src/python/6.SVM/svm-complete.py b/src/python/6.SVM/svm-complete.py index 44286375..f20977aa 100644 --- a/src/python/6.SVM/svm-complete.py +++ b/src/python/6.SVM/svm-complete.py @@ -497,26 +497,26 @@ def plotfig_SVM(xArr, yArr, ws, b, alphas): if __name__ == "__main__": - # # 无核函数的测试 - # # 获取特征和目标变量 - # dataArr, labelArr = loadDataSet('input/6.SVM/testSet.txt') - # # print labelArr + # 无核函数的测试 + # 获取特征和目标变量 + dataArr, labelArr = loadDataSet('input/6.SVM/testSet.txt') + # print labelArr - # # b是常量值, alphas是拉格朗日乘子 - # b, alphas = smoP(dataArr, labelArr, 0.6, 0.001, 40) - # print '/n/n/n' - # print 'b=', b - # print 'alphas[alphas>0]=', alphas[alphas > 0] - # print 'shape(alphas[alphas > 0])=', shape(alphas[alphas > 0]) - # for i in range(100): - # if alphas[i] > 0: - # print dataArr[i], labelArr[i] - # # 画图 - # ws = calcWs(alphas, dataArr, labelArr) - # plotfig_SVM(dataArr, labelArr, ws, b, alphas) + # b是常量值, alphas是拉格朗日乘子 + b, alphas = smoP(dataArr, labelArr, 0.6, 0.001, 40) + print '/n/n/n' + print 'b=', b + print 'alphas[alphas>0]=', alphas[alphas > 0] + print 'shape(alphas[alphas > 0])=', shape(alphas[alphas > 0]) + for i in range(100): + if alphas[i] > 0: + print dataArr[i], labelArr[i] + # 画图 + ws = calcWs(alphas, dataArr, labelArr) + plotfig_SVM(dataArr, labelArr, ws, b, alphas) # # 有核函数的测试 - testRbf(0.8) + # testRbf(0.8) # 项目实战 # 示例:手写识别问题回顾 diff --git a/src/python/6.SVM/svm-complete_Non-Kernel.py b/src/python/6.SVM/svm-complete_Non-Kernel.py index d40a25f0..fe1eafbb 100644 --- a/src/python/6.SVM/svm-complete_Non-Kernel.py +++ b/src/python/6.SVM/svm-complete_Non-Kernel.py @@ -203,7 +203,7 @@ def innerL(i, oS): print("eta>=0") return 0 - # 计算出一个新的alphas[j]值 + # 计算出一个新的alphas[j]值 oS.alphas[j] -= oS.labelMat[j] * (Ei - Ej) / eta # 并使用辅助函数,以及L和H对其进行调整 oS.alphas[j] = clipAlpha(oS.alphas[j], H, L) diff --git a/src/python/6.SVM/svm-simple.py b/src/python/6.SVM/svm-simple.py index 815942ef..51fb4fb9 100644 --- a/src/python/6.SVM/svm-simple.py +++ b/src/python/6.SVM/svm-simple.py @@ -71,14 +71,14 @@ def smoSimple(dataMatIn, classLabels, C, toler, maxIter): C 松弛变量(常量值),允许有些数据点可以处于分隔面的错误一侧。 控制最大化间隔和保证大部分的函数间隔小于1.0这两个目标的权重。 可以通过调节该参数达到不同的结果。 - toler 容错率 + toler 容错率(是指在某个体系中能减小一些因素或选择对某个系统产生不稳定的概率。) maxIter 退出前最大的循环次数 Returns: b 模型的常量值 alphas 拉格朗日乘子 """ dataMatrix = mat(dataMatIn) - # 矩阵转制 和 .T 一样的功能 + # 矩阵转置 和 .T 一样的功能 labelMat = mat(classLabels).transpose() m, n = shape(dataMatrix) @@ -98,7 +98,7 @@ def smoSimple(dataMatIn, classLabels, C, toler, maxIter): # print 'alphas=', alphas # print 'labelMat=', labelMat # print 'multiply(alphas, labelMat)=', multiply(alphas, labelMat) - # 我们预测的类别 y = w^Tx[i]+b; 其中因为 w = Σ(1~n) a[n]lable[n]x[n] + # 我们预测的类别 y = w^Tx[i]+b; 其中因为 w = Σ(1~n) a[n]*lable[n]*x[n] fXi = float(multiply(alphas, labelMat).T*(dataMatrix*dataMatrix[i, :].T)) + b # 预测结果与真实结果比对,计算误差Ei Ei = fXi - float(labelMat[i]) @@ -106,6 +106,8 @@ def smoSimple(dataMatIn, classLabels, C, toler, maxIter): # 约束条件 (KKT条件是解决最优化问题的时用到的一种方法。我们这里提到的最优化问题通常是指对于给定的某一函数,求其在指定作用域上的全局最小值。) # 0<=alphas[i]<=C,但由于0和C是边界值,我们无法进行优化,因为需要增加一个alphas和降低一个alphas。 # 表示发生错误的概率:labelMat[i]*Ei 如果超出了 toler, 才需要优化。至于正负号,我们考虑绝对值就对了。 + # 如果你大于 负错误的概率,那么要求你小于C,这样才可以只优化一边 + # 如果你大于 正错误的概率,那么要求你大于0,这样才可以只优化一边 if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)): # 如果满足优化的条件,我们就随机选取非i的一个点,进行优化比较 @@ -117,12 +119,14 @@ def smoSimple(dataMatIn, classLabels, C, toler, maxIter): alphaJold = alphas[j].copy() # L和H用于将alphas[j]调整到0-C之间。如果L==H,就不做任何改变,直接执行continue语句 + # labelMat[i] != labelMat[j] 表示异侧,就相减,否则是同侧,就相加。 if (labelMat[i] != labelMat[j]): L = max(0, alphas[j] - alphas[i]) H = min(C, C + alphas[j] - alphas[i]) else: L = max(0, alphas[j] + alphas[i] - C) H = min(C, alphas[j] + alphas[i]) + # 如果相同,就没发优化了 if L == H: print("L==H") continue