3. 线性模型(2)
3.1 线性判别分析
- 概念
- 线性判别分析 (Linear Discriminant Analysis , 简称 LDA)。
- 是一种经典的线性学习方法。
- 最早由 Fisher 提出,亦称 "Fisher" 判别分析。
- LDA 的思想
1. 给定训练样例集
2. 设法将样例投影到一条直线上
3. 使得同类样例的投影点尽可能接近。
4. 异类样例的投影点尽可能远离。
- 在对新样本进行分类时,将其投影
- 根据投影的点的位置确定新的样本类别。
- 如何使相似样本的投影点尽可能接近?
分析
已知:
给定数据集 D = {(x1,y1), ..., (xm,ym)}, yi ∈ {0, 1}。这是一个二分类问题。
令:
Xk, Uk, ∑K 分别表示第 k ∈ {0, 1}类示例的,
集合,均值向量,协方差矩阵
操作:
将数据投影到直线 W 上
直线 w 是已知训练好的直线。
结论:
一、两类样本的中心在直线上的投影分别为:
0类:W^T*U0
1类:W^T*U1
二、两类样本的协方差分别为:
0类:W^T*∑0W
1类:W^T*∑1W
公式
综上所述
1. 欲使同类样例的投影点尽可能接近
即 W^T*∑0W+W^T*∑1W 尽可能小
2. 欲使异类样例的投影点尽可能远离
||W^T*U0-W^T*U1|| 尽可能大
- 最优线性(最大化线性判别分析的条件)
使 J 值最大
类内散度矩阵
类间散度矩阵
重写 J 值
确定 w
3.2 多分类学习
- 想法
拆解法
即将多分类任务拆分为若干个二分类任务求解。
具体来讲就是:
先对问题进行拆分,然后为拆分出的每个二分类任务训练一个分类器。
- 分裂策略
1. 一对一,One vs One, OvO
- 两两配对组成一个新样本,一个作为正例,一个作为反例。
- 新样本将同时提交给所有的分类器。
- 把预测结果最多的作为最终的分类结果。
2. 一对其余,One vs Rest, OvR
- 每次将一个类作为正例,其余类作为反例。
- 若有一个分类器预测为正例,则对应类标记为最终结果。
3. 多对多,Many vs Many, MvM
- 将若干个类作为正类,若干个作为反类。
- 但正,反类构造必须有特殊的设计。
- 有一种常用的 MvM 技术:纠错输出码,简称 ECOC
3.3 类别不平衡问题
- 问题导入
- 前面介绍的分类学习方法都有一个共同的基本假设,即不同类别的训练样例数目相当.
- 如果不同类别的训练样例数目稍有差别,通常影响不大,
- 但若差别很大,则会对学习过程造成困扰.
- 例如有 998 个反例,但正例只有2个,
- 那么学习方法只需返回一个永远将新样本预测为反例的学习器,就能达到 99.8% 的精度;
- 然而这样的学习器往往没有价值,因为它不能预测出任何正例.
- 类别不平衡
- 类别不平衡(class imbalance) 就是指分类任务中不同类别的训练样例数目差别很大的情况.
- 本节假定正类样例较少,反类样例较多.
- 解决方案
过去的评论
观察概率
当训练集中正、反例的数目不同时。
令m+表示正例数目,m-表示反例数目
则观测几率是 m+/m-,
只要分类器的预测几率
高于
观测几率就应判定为 正例
数学公式
综上所述
- 我们的分类器是基于 y/(1-y) > 1来进行决策的。
- 因此,需对其预测值进行调整。
- 同时对两边乘以 m-/m+(观测几率的倒数)
- 这就是类别不平衡学习的一个基本策略一"再缩放" (rescaling).
- 实际情况
实际操作并不简单
- 主要因为"训练集是真实样本总体的无偏采样"这个假设往往并不成立。
- 也就是说 我们未必能有效地基于训练集观测几率来推断出真实几率。
现有技术中一般有三种方式
1. 第一类
- 是直接对训练集里的反类样例进行"欠采样" (undersampling) ,
- 即去除一些反倒使得正、反例数日接近然后再进行学习;
2. 第二类
- 是对训练集里的正类样例进行"过来样" (oversampling) ,
- 即增加一些正例使得正、反例数目接近,然后再进行学习;
3. 第三类
- 是直接基于原始训练集进行学习,
- 但在用训练好的分类器进行预测时,将式(3.48) 嵌入到其决策过程中,称为"阔值移动" (threshold-moving).
4. 第三章线性模型课后习题
- 题3.1
试析在什么情况下f(x)=w^(T)+b中不必考虑偏置项b。
- 为什么要加偏置项,它的作用是什么?
1. 加偏置项是为了更好的拟合数据。
2. 在f(x)进行归一化处理时消除偏置。
3. 当只需要考虑x的取值对y的影响的话,则可以不用考虑b。
- 题3.2
试证明,对于参数 w,对率回归的目标函数(3.18) 是非凸的,但其对数似然函数(3.27) 是凸的。
提供个思路:
求二阶导,二阶导小于零,图像为凸。反之。
过程:后面我写到纸上
- 题3.3
编程实现对率回归,并给出西瓜数据集3.0a上的结果。
python 代码
# as 重命名
# numpy 支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
import numpy as np
import math
# Matplotlib(绘图库)
import matplotlib.pyplot as plt
data_x = [[0.697, 0.460], [0.774, 0.376], [0.634, 0.264], [0.608, 0.318], [0.556, 0.215], [0.403, 0.237],
[0.481, 0.149], [0.437, 0.211], [0.666, 0.091], [0.243, 0.267], [0.245, 0.057], [0.343, 0.099],
[0.639, 0.161], [0.657, 0.198], [0.360, 0.370], [0.593, 0.042], [0.719, 0.103]
]
data_y = [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# 线性回归模型的基本公式 y = w^Tx + b
# b 在这里省略了
def combine(param_w, param_x):
# 创建矩阵 np.mat([1, 2, 3]) -> matrix([1, 2, 3])
param_x = np.mat(param_x + [1.]).T # .T作用于矩阵,用作球矩阵的转置
return param_w.T * param_x # w^Tx
# 对数几率函数 : y = 1 / (1 + e^-z)
# z 在这里是为上面的线性回归模型的基本公式 w^Tx + b
def logistic_function(param_w, param_x):
return 1 / (1 + math.exp(-combine(param_w, param_x))) # math.exp( x ) 返回x的指数,e^x。
# 对数几率回归模型 : y = 1 / (1 + e^-(w^Tx+b))
def predict(param_w, param_x):
return math.exp(combine(param_w, param_x)) / (1 + math.exp(combine(param_w, param_x)))
# 这里用 w 来代表 欧米噶,形似
w = np.mat([0.] * 3).T
steps = 50
# 训练样本
for step in range(steps):
# >>> np.zeros((3,1))
# array([[0.],
# [0.],
# [0.]])
param_1 = np.zeros((3, 1)) # 生成一个3*1的全0数组
for i in range(len(data_x)):
x = np.mat(data_x[i] + [1.]).T
param_1 = param_1 - x * (data_y[i] - predict(w, data_x[i]))
param_2 = np.zeros((3, 3)) # 生成一个3*3的全0数组
for i in range(len(data_x)):
x = np.mat(data_x[i] + [1.]).T
param_2 = param_2 + x * x.T * predict(w, data_x[i]) * (1 - predict(w, data_x[i]))
last_w = w
w = last_w - param_2.I * param_1 # param_2.I ???
# norm则表示范数,范数是一种强化了的距离概念
if np.linalg.norm(last_w.T - w.T) < 1e-6: # 1e-6已经被认为是可处理的最小
print(step)
break
# 绘图
for i in range(len(data_x)):
if data_y[i] == 1:
# 蓝色园点表示好瓜
plt.plot(data_x[i][0], data_x[i][1], 'ob') # "b"为蓝色, "o"为圆点, ":"为点线
else:
# 绿色三角表示坏瓜
plt.plot(data_x[i][0], data_x[i][1], '^g') # '^g' : 上三角形状,绿色 #详情搜 plt.plot()函数详解
w_0 = w[0, 0]
w_1 = w[1, 0]
b = w[2, 0]
print(w_0, w_1, b)
x_0 = -b / w_0 # (x_0, 0)
x_1 = -b / w_1 # (0, x_1)
plt.plot([x_0, 0], [0, x_1])
plt.show()
文章出处登录后可见!
已经登录?立即刷新