ML_From_Scratch-master 读书笔记(1)

按照上一篇博客中搭建好环境后,我们正式进入ML算法的学习。首先看第一个adaboost。

本文包含以下几个方面的内容:

  1. adaboost算法的基础知识
  2. python3的实现过程
  3. 实现过程中学习到的python3技巧

adaboost算法的基本知识

    adaboost的源头在《A Decision-Theoretic Generalization of On-Line Learning and an Application to Boosting》这篇论文里,是1996年的工作,关于这篇论文的解读笔记,会在接下来的几天里整理好,写成博客。这里引用一下其他人的解读点击打开链接还有这个,做一个快速的入门。

    (1)补充一下大家看点击打开链接的一些先验知识:

    分类器:二分类,标签+1;-1

    误差计算方法:,y是标签如【-1,-1,+1】,G(x)是分类器计算结果如【+1,-1,+1】,错的越多指数越大,loss越大

    样本权重*当前弱分类器的分类误差==强分类器的分类误差

    

    最后算出来的分类器权重,是以loss最小为目标的。

    这一步的推导中,下面的那个公式中F的下标应该是m-2

    

    (2)粘贴博客中关于adaboost中比较重要的一些概念,详细内容大家还是看博客原文:

  1. Adaboost算法基本原理就是将多个弱分类器(弱分类器一般选用单层决策树)进行合理的结合,使其成为一个强分类器。
  2. Adaboost采用迭代的思想,每次迭代只训练一个弱分类器,训练好的弱分类器将参与下一次迭代的使用。也就是说,在第N次迭代中,一共就有N个弱分类器,其中N-1个是以前训练好的,其各种参数都不再改变,本次训练第N个分类器。其中弱分类器的关系是第N个弱分类器更可能分对前N-1个弱分类器没分对的数据,最终分类输出要看这N个分类器的综合效果。
  3. AdaBoost改变了训练数据的权值,也就是样本的概率分布,其思想是将关注点放在被错误分类的样本上,减小上一轮被正确分类的样本权值,提高那些被错误分类的样本权值。
  4. Adaboost算法中有两种权重,一种是数据的权重,另一种是弱分类器的权重。其中,数据的权重主要用于弱分类器寻找其分类误差最小的决策点,找到之后用这个最小误差计算出该弱分类器的权重(发言权),分类器权重越大说明该弱分类器在最终决策时拥有更大的发言权
  5. 迭代过程:
  •         第i轮迭代要做这么几件事: 
  •         1. 新增弱分类器WeakClassifier(i)与弱分类器权重alpha(i) 
  •         2. 通过数据集data与数据权重W(i)训练弱分类器WeakClassifier(i),并得出其分类错误率,以此计算出其弱分类器权重alpha(i) 


  •         3. 通过加权投票表决的方法,让所有弱分类器进行加权投票表决的方法得到最终预测输出,计算最终分类错误率,如果最终错误率低于设定阈值(比如5%),那么迭代结束;如果最终错误率高于设定阈值,那么更新数据权重得到W(i+1)


Python3的实现过程

首先看一下实验结果:



8*8的图片识别数字,正确率达到90%,速度也快。值得学习一下

(1)训练数据测试数据的获取

数据集取自sklearn中的手写数字datasets

选择两个数字1和8的图片(大小8*8),并将他们的标签设置为1和-1,训练一个二分类的分类器

训练集和测试集之间没有交集,数量都是178个

(2)开始训练

创建一个Adaboos对象,指定参数(弱分类器数量n_clf=5),进入fit函数,传入训练数据


初始化样本权重w

进入for循环,遍历每个弱分类器(再次出现蓝字的时候表明循环结束)


创建弱分类器——决策树(其实就是一个二分类器)

clf = DecisionStump()

遍历64个特征(一次处理178个样本的值),寻找哪一个特征分类效果最好,以及最优分类阈值(计算分类误差的时候考虑了样本权重(代码62行)),记录在clf中

for feature_i in range(n_features):

建立好一个clf后

循环结束

         根据这个clf的分类误差,计算它在强分类器中的权重

clf.alpha = 0.5 * math.log((1.0 - min_error) / (min_error + 1e-10))

计算样本权重(看基本知识中的公式)

            # Set all predictions to '1' initially
            predictions = np.ones(np.shape(y))
            # The indexes where the sample values are below threshold
            negative_idx = (clf.polarity * X[:, clf.feature_index] < clf.polarity * clf.threshold)
            # Label those as '-1'
            predictions[negative_idx] = -1
            # Calculate new weights 
            # Missclassified samples gets larger weights and correctly classified samples smaller
            w *= np.exp(-clf.alpha * y * predictions)
            # Normalize to one
            w /= np.sum(w)

保存这个clf到self.clfs中

循环结束

python3中的技术

内容顺序按照代码调试过程中出现的顺序,包含所有使用到的知识点,并做一点点扩展

(1)ndarray


(1)ndarray最基本的定义方式

(2)这是(1)中定义的ndarray的转置

(3)shape=(4,3),4是指这个ndarray的最外面的第一层的'[]'中的元素的数量,3是第二层,以此类推

(4)先行后列,行代表第一层的元素,列代表第二层

(2)np的一些函数

数组拼接点击查看详细内容

  • np.append()

    numpy提供了numpy.append(arr, values, axis=None)函数。对于参数规定,要么一个数组和一个数值;要么两个数组,不能三个及以上数组直接append拼接。append函数返回的始终是一个一维数组。

    numpy的数组没有动态改变大小的功能,numpy.append()函数每次都会重新分配整个数组,并把原来的数组复制到新数组中。

  • np.concatenate()

    numpy提供了numpy.concatenate((a1,a2,...), axis=0)函数。能够一次完成多个数组的拼接。其中a1,a2,...是数组类型的参数

    拼接shpae=[2,3][2,3]的两个数组,axis=0的时候拼接的是最外层,得到的结果的shape是[4,3],4是2+2的结果;axis=1的时候拼接的是第二层,得到的结果的shape是[2,6],6是3+3的结果;

    效率问题有疑点,普遍认为numpy.concatenate效率高,不过实验的时候有异议。

  • np.where()

  • np.expand_dims

例子

    expand_dims(a, axis)针对的是a的shape,结果就是返回一个a的一个拷贝a‘,不过a’在axis的维度上插入一个1。例如 原本shape为 (2,3),当axis=0,则shape变为(1,2,3),当axis=1则shape变为(2,1,3)

 
 
  • np.unique()

(3)python中的类

这里有一些例子

self在类的函数定义时需要传入,但是在调用时会自动传入。

self的名字并不是规定死的,但是最好还是按照约定是用self

self总是指调用时的类的实例。

__init()__详解


class 类名(父类名)

self指向子类实例,所以实现了多态

创建对象时会进入子类的__init__(),如果子类没有重写父类的__init__,就会进入父类的








猜你喜欢

转载自blog.csdn.net/duyue3052/article/details/81032082