第一版还没看完,《统计学习方法》第二版就上线啦?

发布时间:2019-05-20 21:34:28   来源:自考网
统计学习即机器学习,是计算机及其应用领域的一门重要学科。此前,李航老师完成的《统计学习方法》是了解机器学习最好的教材之一,该书从 2005 年开始写作一直到 2012 年完成,包含了众多主要的监督学习算法与模型。最近,《统计学习方法》第二版正式发布,通过 6 年时间的努力,在第一版的基础上又增加了无监督学习的主要算法与模型。
李航博士告诉机器之心,《统计学习方法》第二版新加了无监督学习方面的内容,并对第一版的监督学习方法做了一些修改。总体而言,第二版可以分为监督学习和无监督学习两篇。从这两大块出发,基本上传统机器学习的主要概念就能一步步掌握了。
具体而言,第一篇介绍了感知机、朴素贝叶斯法、决策树、支持向量机、提升方法、EM 算法、隐马尔可夫模型和条件随机场等算法,它们都是非常经典的监督学习方法。第二篇主要讨论了聚类方法、奇异值分解、主成分分析、潜在语义分析、马尔可夫链蒙特卡罗法和潜在狄利克雷分配等算法,它们都是非常经典的无监督学习方法。
除有关统计学习、监督学习和无监督学习的概论和总结的四章外,每章介绍一种方法。叙述力求从具体问题或实例入手,由浅入深,阐明思路,给出必要的数学推导,便于读者掌握统计学习方法的实质,学会运用。
为满足读者进一步学习的需要,书中还介绍了一些相关研究,给出了少量习题,列出了主要参考文献。
站在经典之上的《统计学习方法》
在第一版中,很多同学会发现整本书的数学气息非常浓厚,大部分算法都给出了推导过程。这些算法都是非常基础与经典的机器学习方法,理解它们需要有比较坚实的数学基础。但是在深度学习时代,这些经典算法被大家关注得比较少,反观常见的深度学习方法与技巧,却不一定有传统方法那样的理论。
在深度学习时代,我们更多的是根据经验、实验和「启发式」方法理解模型。那么,站在经典机器学习之上的《统计学习方法》,又能怎样帮助我们学习前沿的算法与技巧呢
李航老师表示他会继续写深度学习、强化学习相关的内容,包括前馈神经网络和卷积、循环神经网络等,他也会保留前面几版的数学风格。但是对于传统机器学习与深度学习之间的关系,李航老师表示:「它们两者在技术上是一脉相承的,中间并不可以割裂。」理解经典 ML 的数学原理,也是为前沿 DL 提供新的背景知识或洞见。
李航老师说:「在我面试员工的时候,也会发现这样的问题,大家对深度学习了解得很多,但对传统机器学习了解得非常少。这种现象并不好,例如我们在 TensorFlow 上实现某个模型,然后就直接跑实验,这样对很多基本概念了解得都不够。理想情况下,我们应该更全面地理解机器学习的概念与理论,再做深度学习实践,也就是说对传统 ML 的理解有助于更好地跑 DL 模型。」
当然每一个研究者或开发者的精力都是有限的,因此李航老师表示:「这本书的每一章都是相对比较独立的,大家可以有选择地阅读相关章节。在以后加入深度学习与强化学习后,不同章节也应该是相互独立的。当然还是把这些章节联系起来一起看,这样就能掌握整个脉络和发展。」
此外,尽管深度学习在众多任务上都有极好的效果,但也不能说传统机器学习就没什么用了。李航老师说:「例如在小数据集或简单问题上,SVM 或 GBDT 这些方法在实践中用得还是挺多的,我们对这些基础方法最好有一个深入的理解。」
正确理解《统计学习方法》的定位
在第二版的序言中,上面描述到「本书是统计机器学习及相关课程的教学参考书,适用于高等院校文本数据挖掘、信息检索及自然语言处理等的大学生、研究生,也可供从事计算机应用相关的研发人员参考。」
对于书本的整体定位,李航老师说:「这本书的内容本身是最基础的,也就是机器学习领域大家都应该掌握的东西,从这种意义上来说确实是一本入门书籍。但是我并没有从入门的角度写这本书,而是更多地把一些最基本的概念,提纲挈领地整理出来。你也可以认为是从教材的角度来写这些内容,因此这本书适合多次阅读,需要经常查看,而不是看一遍就了事。」
很多读者也会反馈这本书的阅读体验,有的认为数学太多、有的认为数学太少或不够详细等等。李航老师认为,如果没有足够的相关数学知识,那么看这本书会比较吃力。他说:「听到了一些概念,但又不了解细节,想要更详细地从头理解,那么这个时候阅读这本书是合适的。」
这本书比较适合有一定基础的读者,不论是 ML 基础还是数学基础。它不太适合特别入门的初学者,也不太适合概率论、统计学都不太了解的入门者,但这些基础知识可以通过其它课程或教材快速补全,再来学习《统计学习方法》就非常合适了。当然,读者也可以一边阅读《统计学习方法》,一边补全基础知识,这样学习可能效率更高。
一步步走来的《统计学习方法》
其实《统计学习方法》第一版内容主要涵盖的是监督学习,为大家提供了极为精炼的介绍。当时,李航博士完成这本书花费了 7 年时间,涵盖了工业上最常见与最实用的各种算法。
如今又经过 6 年写作,第二版上线,增加了经典无监督学习的相关内容。李航博士表示这其中有读者的期待,他也希望这本新书能为大家提供更多的帮助。
而关于如今比较热门的深度学习、强化学习等内容,李航博士可能会在未来的三至四年内加进来,发布新的版本。
「其实跟我当初设想的也不太一样,也是阴差阳错走到这一步。我本来没计划写这么多,就是有读者的期待,还有这本书对大家有一定的帮助,所以下决心之后把深度学习和强化学习也再加上。因为我都是业余时间写的,所以花的时间比较多。」
总体而言,李航老师希望在未来的时间内把深度学习和强化学习写完,希望国内读者在了解机器学习基本方法时,有一本比较完善的参考书籍。李航说:「我知道这本书在工业界参考地比较多,因为我一直在业界工作,站在应用的角度可以了解哪些方法是重要的。」
所以,李航老师最后表示:「我希望《统计学习方法》不仅仅是教材,它还能为业界的工程师提供一些有用的帮助。」
第一版还没看完的看过来啦
第一版代码来源于以前小编 发现的一个 GitHub 项目,不仅包含了该书的详细笔记,同时提供了各章节机器学习算法详细的 Python 代码。
> > > >
前言
李航老师的这本书,真的很薄,但是几乎每句话都会带出很多点,值得反复研读。希望在反复研读的过程中,将整个这本书看厚,变薄。这个系列的所有的文档,以及代码,没有特殊说明的情况下"书中"这个描述指代的都是李航老师的《统计学习方法》。 其他参考文献中的内容如果引用会给出链接。
方便参考文献下载, 添加了ref_downloader.sh,可以用来下载书中列举的参考文献。
该项目中还包含了math_markdown.pdf,基本覆盖了书中用到的数学公式的 LaTeX 表达方式。方便读者对照理解。
> > > >
课程笔记
关于《统计学习方法》的篇幅,其中 SVM 是大部头,占了很大的篇幅,另外DT,HMM,CRF 也占了相对较大的篇幅。如下图所示:
章节之间彼此又有联系,比如 NB 和 LR,DT 和 AdaBoost,Perceptron 和SVM,HMM 和 CRF 等等,如果有大章节遇到困难,可以回顾前面章节的内容,或查看具体章节的参考文献,一般都给出了对这个问题描述更详细的参考文献,可能会解释你卡住的地方。
这份详细笔记整理成 markdown 文件格式。大致提纲如下:
CH01 统计学习方法概论
统计学习方法三要素:
模型
策略
算法
CH02 感知机
感知机是二类分类的线性分类模型
感知机对应于特征空间中将实例划分为正负两类的分离超平面
CH03 k近邻法
kNN是一种基本的分类与回归方法
k值的选择, 距离度量及分类决策规则是kNN的三个基本要素
CH04 朴素贝叶斯法
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法
x 的某种组合在先验中没有出现的情况, 会出现概率为0的情况, 对应平滑处理方案:
λ=0 对应极大似然估计,λ=1 对应拉普拉斯平滑
朴素贝叶斯法实际上学习到生成数据的机制, 所以属于生成模型
CH05 决策树
决策树是一种基本的分类与回归方法
CH06 逻辑斯谛回归与最大熵模型
逻辑斯谛回归是统计学中的经典分类方法
最大熵是概率模型学习的一个准则, 将其推广到分类问题得到最大熵模型
CH07 支持向量机
支持向量机是一种二分类模型。
基本模型是定义在特征空间上的间隔最大化的线性分类器, 间隔最大使他有别于感知机
这一章占了很大篇幅,因为 margin 这个思想几乎可以串起来整个分类问题。
CH08 提升方法
提升方法是一种常用的统计学习方法, 应用广泛且有效
CH09 EM算法及其推广
EM 算法是一种迭代算法, 用于含有隐变量的概率模型参数极大似然估计, 或者极大后验概率估计(这里的极大似然估计和极大后验概率估计是学习策略)
如果概率模型的变量都是观测变量, 那么给定数据, 可以直接用极大似然估计法, 或贝叶斯估计法估计模型参数(注意书上这个描述如果不理解,参考 CH04 中朴素贝叶斯法的参数估计部分)
这部分代码实现了 BMM 和 GMM, 值得看下
关于 EM, 这个章节写的不多, EM是十大算法之一, EM 和 Hinton 关系紧密, Hinton 在 2018 年 ICLR 上发表了 Capsule Network 的第二篇文章《Matrix Capsules with EM Routing》
CH10 隐马尔可夫模型
隐马尔可夫模型是可用于标注问题的统计学习模型, 描述由隐藏的马尔可夫链随机生成观测序列的过程, 属于生成模型
隐马尔可夫模型是关于时序的概率模型, 描述由一个隐藏的马尔可夫链随机生成不可观测的状态的序列, 再由各个状态速记生成一个观测而产生观测的序列的过程
可用于标注(Tagging)问题, 状态对应标记
三个基本问题: 概率计算问题, 学习问题, 预测问题
CH11 条件随机场
条件随机场是给定一组输入随机变量条件下另一组输出随机变量的条件概率分布模型, 其特点是假设输出随机变量构成马尔可夫随机场
概率无向图模型, 又称为马尔可夫随机场, 是一个可以由无向图表示的联合概率分布
三个基本问题: 概率计算问题, 学习问题, 预测问题
CH12 统计学习方法总结
这章就简单的几页, 可以考虑如下阅读套路
和第一章一起看
在前面的学习中遇到不清楚的问题的时候,过一遍这个章节
将这一章看厚, 从这一章展开到其他十个章节
李老师这本书真的是每次刷都会有新的收获
> > > >
随书 Python 代码
该项目除了有详细的讲解笔记之外,每一章还配备了完整可直接运行的 Python 代码 以及测试代码。下面以 感知机和k 近邻为例,演示代码。
感知机:
import numpy as np import random import argparse import logging class Perceptron ( object ): def __init__ ( self , max_iter= 5000 , eta= 0 . 00001 , verbose=True) : self .eta _ = eta self .max_iter _ = max_iter self .w = 0 self .verbose = verbose def fit ( self , X, y) : self .w = np.zeros(X.shape[ 1 ] + 1 ) correct_count = 0 n_iter _ = 0 while n_iter _ < self . max_iter_: index = random.randint( 0 , y.shape[ 0 ] - 1 ) xx _ = np.hstack([X[index], 1 ]) yy _ = 2 * y[index] - 1 wx = np.dot( self .w, xx _ ) if wx * yy _ > 0 : correct_count += 1 if correct_count > self . max_iter_: break continue self .w += self .eta _ * yy _ * xx _ n_iter _ += 1 if self . verbose: print(n_iter _ ) def predict ( self , X) : # for b X = np.hstack([X, np.ones(X.shape[ 0 ]).reshape((- 1 , 1 ))]) # activation function for perceptron: sign rst = np.array([ 1 if rst else - 1 for rst in np.dot(X, self .w) > 0 ]) # np.sign(0) == 0 # rst = np.sign(np.dot(X, self.w)) return rst if __name_ _ == '__main__' : logging.basicConfig(level=logging.INFO, format= '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name_ _ ) ap = argparse.ArgumentParser() ap.add_argument( "-p" , "--path" , required=False, help= "path to input data file" ) args = vars(ap.parse_args())

k 近邻:
from collections import namedtuple from pprint import pformat import numpy as np class Node (namedtuple ( 'Node' , 'location left_child right_child' ) ) : def __repr__ (self) : return pformat(tuple(self)) class KNN (object) : def __init__ (self, k= 1 , p= 2 ) : """ :param k: knn :param p: """ self.k = k self.p = p self.kdtree = None @staticmethod def _fit (X, depth= 0 ) : try : k = X.shape[ 1 ] except IndexError as e: return None # todo: 这里可以展开,通过方差选择 axis = depth % k X = X[X[:, axis].argsort()] median = X.shape[ 0 ] // 2 try : X[median] except IndexError: return None return Node( location=X[median], left_child=KNN._fit(X[:median], depth + 1 ), right_child=KNN._fit(X[median + 1 :], depth + 1 ) ) def _distance (self, x, y) : return np.linalg.norm(x-y, ord=self.p) def _search (self, point, tree=None, depth= 0 , best=None) : if tree is None : return best k = point.shape[ 0 ] # update best if best is None or self._distance(point, tree.location) < self._distance(best, tree.location): next_best = tree.location else : next_best = best # update branch if point[depth%k] < tree.location[depth%k]: next_branch = tree.left_child else : next_branch = tree.right_child return self._search(point, tree=next_branch, depth=depth+ 1 , best=next_best) def fit (self, X) : self.kdtree = KNN._fit(X) return self.kdtree def predict (self, X) : rst = self._search(X, self.kdtree) return rst def predict_proba (self, X) : pass if __name__ == '__main__' : pass
> > > >
后记
整个这本书里面各章节也不是完全独立的,这部分希望整理章节之间的联系以及适用的数据集。算法到底实现到什么程度,能跑什么数据集也是一方面。
推荐文章