这章节主要涉及以下内容:
-
线性回归(line regression)
- 线性回归试图学得 f=wx+b,使得f=y
- 基于均方误差最小化来进行模型求解的方法称为“最小二乘法”。在线性回归中,最小二乘法就是试图找到一条直线,使所有样本到直线上的欧式距离之和最小。
-
对数几率回归(logit regression)
- 这是一种分类学习方法
- 这种方法的优点1:直接对分类可能性进行建模,无需事先假设数据分布,这样就避免了假设分布不准确所带来的问题。
- 优点2:不仅预测出“类别”,还可得到近似概率预测
- 优点3:对数几率回归求解的目标函数时任意阶可导的凸函数,有很好的数学性质,现有的许多数值优化算法都可直接用于求解最优解。
-
线性判别分析(LDA)
- LDA假设了各样本的协方差矩阵相同且满秩。
-
多分类学习
- 多分类学习的基本思路是“拆解法”,即将多分类任务拆为若干个二分类任务求解。
- 最经典的拆分策略:一对一(OvO)、一对其余(OvR)、多对多(MvM)。
- OvO的存储开销和测试时间开销通常比OvR更大。
- 在类别很多时,OvO的训练时间开销通常比OvR更小。
- ECOC(纠错输出码)是将编码的思想引入类别拆分,并尽可能在解码过程中具有容错性。ECOC工作分为两步:编码、解码。
-
类别不平衡问题
- 类别不平衡就是指分类任务中不同类别的训练样例数目差别很大的情况。
- 需要注意的是,不是说分类任务中不同类别的训练样例数目差别很大的时候就需要进行类别不平衡处理,而是,当较小类的代价更高的时候才需要进行特殊处理,即采取欠采样或者过采样或者阈值移动的方法来纠正类别不平衡现象。
- 过采样法不能简单地对初始正例样本进行重复采样,否则会导致严重的过拟合。
- 过采样法的代表性算法:SMOTE,是通过对训练集里的正例进行插值来产生额外的正例。
- 欠采样法的代表性算法:EasyEnsemble则是利用集成学习机制,将反例划分为若干个集合供不同学习器使用,这样对每个学习器来看都是欠采样,但是在全局来看却不会丢失重要信息。
- 这里需要提到一个概念——再缩放。分类器是假设正例和反例的可能性相同,即只要预测出的y,这个y介于0-1之间,只要 y/(1-y)>1,则说明预测为正例,但是训练集中的正例和反例的数目并不一定相等,假设正例m+,反例m-,则采用再缩放的方式纠正,即[y/(1-y)]*[m-/m+]>1,则说明预测为正例。
部分课后习题详解
1、使用OvR和MvM将多分类任务分解为二分类任务求解时,试述为何无需专门针对类别不平衡性进行处理。
答:因为OvR或者MvM在输出结果阶段,是对各个二分类器的结果进行汇总,汇总的这个过程就会消除不平衡带来的影响(因为总和总是1)。
2、LDA仅在线性可分数据上能获得理想结果,试设计一个改进方法,使其能较好地用于非线性可分数据
答:利用核方法即可以将LDA用于非线性可分数据,即KLDA(核线性判别分析方法)。见教材的P137。
3、编程实现线性判别分析,并给出西瓜数据集3.0α上的结果。
LDA的编程主要参考书上P62的3.39 以及P61的3.33这两个式子。由于用公式可以直接算出,因此比较简单。代码如下:
# -*- coding: cp936 -*-
from numpy import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df=pd.read_csv('watermelon_3a.csv')
def calulate_w():
df1=df[df.label==1]
df2=df[df.label==0]
X1=df1.values[:,1:3]
X0=df2.values[:,1:3]
mean1=array([mean(X1[:,0]),mean(X1[:,1])])
mean0=array([mean(X0[:,0]),mean(X0[:,1])])
m1=shape(X1)[0]
sw=zeros(shape=(2,2))
for i in range(m1):
xsmean=mat(X1[i,:]-mean1)
sw+=xsmean.transpose()*xsmean
m0=shape(X0)[0]
for i in range(m0):
xsmean=mat(X0[i,:]-mean0)
sw+=xsmean.transpose()*xsmean
w=(mean0-mean1)*(mat(sw).I)
return w
def plot(w):
dataMat=array(df[['density','ratio_sugar']].values[:,:])
labelMat=mat(df['label'].values[:]).transpose()
m=shape(dataMat)[0]
xcord1=[]
ycord1=[]
xcord2=[]
ycord2=[]
for i in range(m):
if labelMat[i]==1:
xcord1.append(dataMat[i,0])
ycord1.append(dataMat[i,1])
else:
xcord2.append(dataMat[i,0])
ycord2.append(dataMat[i,1])
plt.figure(1)
ax=plt.subplot(111)
ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
ax.scatter(xcord2,ycord2,s=30,c='green')
x=arange(-0.2,0.8,0.1)
y=array((-w[0,0]*x)/w[0,1])
print shape(x)
print shape(y)
plt.sca(ax)
#plt.plot(x,y) #ramdomgradAscent
plt.plot(x,y) #gradAscent
plt.xlabel('density')
plt.ylabel('ratio_sugar')
plt.title('LDA')
plt.show()
w=calulate_w()
plot(w)