21/8/13 读书笔记 高质量的类 支持向量机

21/8/13 读书笔记

Code Complete 高质量类

书中涉及的类的接口指的是类的公用方法。

类的接口应该在抽象层次上一致,即对于每个接口都应该基于类名的抽象层次而不是实际实现上的抽象层次,比如管理MemberList类时添加新成员的接口应该是AddMember而不是AddItemOnStackTop,后者暴露了采用栈来维护该类的事实,栈和MemberList不属于同一个抽象层次。

尽可能限制类和成员的可访问性。

警惕有超过7个成员变量的类。根据该类的抽象复杂性,可以在5~9之间考虑。

类的接口应该是可编程(programmatic)的而不是基于语义(semantic)的。可编程意味着它被调用时的行为可以被编译器检测,而基于语义的接口调用情况应该通过注释进行说明,但是最好通过断言将语义上的联系转变为可编程的联系。比如queryStudentRank()在接受一个未初始化的Student对象时会出现异常,这是语义上的限制,需要通过注释说明,而我们通过断言检测传入的参数是否初始化并抛出异常,就将该问题转变成了可编程问题。

如果不考虑对某个类使用继承,那么就声明成final的。反之,如果一个类没有声明final,那么它一定要被继承。

公用的接口、数据和行为尽可能放到更高的抽象层次,直到我们认为层次再高就会破坏其本身的抽象性时为止。

Liskov原则:对于基类中的所有子程序,在其任何一个派生类中的含义应该一致。

派生类中的成员函数不要和基类中不可覆盖的函数(比如声明为private)重名

我们设计类的基础是对类的抽象做了一定的假设,如果发现这个假设出现了问题,我们应该从本质上修改这个类而不是采用其他方法来规避。比如我们假设猫都有尾巴,但是业务中出现了没有尾巴的猫,我们应该修改猫本身的定义(比如新增一个Tail类成员),而不是试图用一个派生类来描述没有尾巴的猫。

函数的多态能够使得我们避免大量的类型检查,语言会帮我们自动根据对象类型找到所需要的调用的具体函数。

多重继承的主要用途是支持mixin,通过多重继承一些简单类,为对象附加一组属性。这些父类应该是抽象的,而且不应该独立实例化。


机器学习 支持向量机

对于线性可分的二分类问题,直观上认为应该去找到处于两类样本“正中间”的划分超平面。我们定义距离超平面最近的几个训练样本称为支持向量,当我们定义超平面为\(\bold w^T\bold x+b\)​时,支持向量(\(\bold x,\pm1\)​)满足\(\bold w^T\bold x+b=\pm1\)​。正反类各自的支持向量到超平面的距离之和称之为间隔,其间接描述了超平面的鲁棒性。因此我们的目标是找到最大间隔的划分超平面,这也就是支持向量机(Support Vector Machine, SVM)的目标。

如果样本是非线性可分的,那么将原始样本空间映射到一个更高维度的特征空间,使得样本在这个特征空间内线性可分即可。假设\(\bold x_1,\bold x_2\)在映射后成为\(\phi(\bold x_1),\phi(\bold x_2)\),称\(\kappa(\bold x_1,\bold x_2)=\phi(\bold x_1)^T\phi(\bold x_2)\)​​​​为核函数,其对原始空间内的向量进行运算,得到的结果是对应特征空间内映射后向量的内积。每个核函数对应特定一种映射关系,也因此对应一个特征空间,这个空间称为该向量的再生核希尔伯特空间(Reproducing Kernel Hilbert Space, RKHS)。显然,我们在映射前并不清楚如何映射才能使得样本在特征空间内线性可分,也因此不知道应该选择什么样的核函数,故核函数选择称为支持向量机中最大的变数。通常使用的核函数是几种常用核函数以及他们的函数组合。

如果我们严格要求所有样本均处在间隔外,那么这是硬间隔;反之,我们允许部分样本落在间隔以内,则称为软间隔

支持向量机在算法上有一些有趣的特点,其优化目标能够被描述为:

\[\underset{f}{min}\ \Omega(f)+C\sum_{i=1}^{m}\ell(f(\bold x_i),y_i) \]

其中\(\Omega(f)\)​描述模型的复杂度,称为结构风险,而\(\sum_{i=1}^{m}\ell(f(\bold x_i),y_i)\)​描述了模型和训练样本的契合程度,称为经验风险\(\ell(f(\bold x_i),y_i)\)是损失函数,\(C\)是一个表示取向性的调和项。进一步看,这是一个正则化问题,\(\Omega(f)\)是正则化项,\(C\)是正则化常数。如果损失函数定义为样本落在间隔带以外(即不满足约束时)取正值,否则为0,那么当\(C\)​​​无限大时,模型不能容忍任何样本不满足约束,因此是硬间隔;反之,当C适当小时,模型是软间隔的。

支持向量回归(Support Vector Regression, SVR),与传统线性回归的区别在于,容忍\(f(\bold x)\)与目标\(y\)之间存在不超过\(\epsilon\)的偏差,这就使得在样本空间内找到一个宽度为\(2\epsilon\)​的间隔带,并尽可能让样本落入该间隔带。因此SVR的目标也可以被描述为上述的一个优化目标,其中的损失函数根据样本是否落在间隔带内进行定义,称为ε-不敏感损失函数。可见只要损失函数需要根据我们的实际问题进行定义,那么上述的优化目标对于SVR和SVM来说都是同质的。

无论SVR还是SVM,为了解决非线性可分的问题都需要使用核函数。对于核函数,从理论上证明了存在表示定理,简要来说就是对于上述的优化目标,其最终的解都能表示为核函数\(\kappa(\bold x,\bold x_i)\)​​​​​的线性组合。而且表示定理对损失函数不做限制,要求正则化项单调递增即可。这启发了人们利用核函数将线性学习器拓展为非线性学习器,这一系列学习方法称为核方法这些方法的困难程度对我而言构成了核威慑

posted @ 2021-08-13 17:08  neumy  阅读(89)  评论(0)    收藏  举报