第一章 模式识别基本概念
1.1 什么是模式识别
模式识别:根据已有知识的表达,针对待识别模式,判别决策其所属的类别或者预测其对应的回归值。
-
根据任务,模式识别可以划分为"分类”和"回归”两种形式。
-
分类(Classification): 输出量是离散的类别表达,即输出待识别模式所属的类别
-
回归(Regression): 输出量是连续的信号表达(回归值)
-
1.2 模式识别数学表达
- 数学解释:模式识别可以看做一-种函数映射f(x), 将待识别模式x从输入空间映射到输出空间。函数f(x)是关于已有知识的表达。
以二分类为例
判别公式:
(
xin left{
egin{array}{l}
C_1 quad if quad f(x)>0 \
C_2 quad if quad f(x)<0
end{array}
ight.
)
决策边界:
(
f(x)=0
)
- 特征向量
1.3 特征向量的相关性
-
夹角:反映两个向量在方向上的差异性。
$ cos heta = frac{x^Ty}{Vert xVertVert yVert}$ -
投影: 向量x到y的投影(projection) :将向量x垂直投射到向量y方向上的长度(标量)。
(x_0 = Vert x Vert cos heta) -
残差向量(residual vector) :向量x分解到向量y方向上得到的投影向量与原向量x的误差。
(r_x = x-x_0=x-frac{Vert xVert cos heta}{Vert yVert}y)
1.4 机器学习基本概念
-
训练样本
-
模型
-
目标函数
-
优化算法
机器学习的分类
-
监督式学习:训练样本及其输出真值都给定情况下的机器学习算法。
-
无监督式学习:只给定训练样本、没有给输出真值情况下的机器学习算法。
1.5 模型的泛化能力
-
泛化能力:训练得到的模型不仅要对训练样本具有决策能力,也要对新的(训练过程中未看见)的模式具有决策能力。
-
过拟合
解决方案
- 选择复杂度适合的模型(tradeoff) :模型选择。
- 正则化(regularization) : 在目标函数中加入正则项。
1.6 评估方法与性能指标
评估方法
-
留出法(Hold-out):随机划分:将数据集随机分为两组:训练集和测试集。利用训练集训练模型,然后利用测试集评估模型的量化指标。
-
K折交叉验证(K-Folds Cross Validation):将数据集分割成K个子集,从其中选取单个子集作为测试集,其他K - 1个子集作为训练集。
-
留一验证(leave- one-out cross-validation):每次只取数据集中的一个样本做测试集,剩余的做训练集。
性能指标
-
F1-score
(F_1=frac{2*precision*recall}{precison+recall}) -
混淆矩阵
-
P-R曲线
-
ROC
-
AUC
第二章 基于距离的分类器
2.1 MED分类器
-
基于距离的决策:把测试样本到每个类之间的距离作为决策模型,将测试样本判定为与其距离最近的类。
-
类的原型:用来代表这个类的一个模式或者一组量,便于计算该类和测试样本之间的距离。
常用原型:均值
(z_i=mu i=frac{Sigma_{xin C_i}x}{N_i})
常用距离度量:
MED分类器
- 概念:最小欧式距离分类器(Minimum Euclidean Distance Classifier)
- 距离衡量:欧式距离
- 类的原型:均值
- 决策边界: ((mu_2-mu_1)^T(x-frac{mu_1+mu_2}{2})=0)
代码见MICD分类器
2.2 特征白化
- 特征白化的目的: 将原始特征映射到一个新的特征空间,使得在新空间中特征的协方差矩阵为单位矩阵,从而去除特征变化的不同及特征之间的相关性。
步骤
将特征转换分为两步:先去除特征之间的相关性(解耦, Decoupling),然后再对特征进行尺度变换(白化,Whitening),使每维特征的方差相等。
令(W = W_2W_1)
解耦:通过(W)实现协方差矩阵对角化,去除特征之间的相关性。
白化:通过(W_2)对上一步变换后的特征再进行尺度变换,实现所有
特征具有相同方差。
转换矩阵(W_1)的求法
第一步:求解协方差矩阵(Sigma_x)的特征值和特征向量。
第二步:由特征向量构建转换矩阵(W_1)。
转换矩阵(W_2)的求法
2.3 MICD分类器
- 马氏距离
(d = (x_1-x_2)^TSigma_x^{-1}(x_1-x_2))
MICD分类器
- 最小类内距离分类器(Minimum Intra-class Distance Classifier) ,基于马氏距离的分类器。
- 距离度量:马氏距离
- 类的原型: 均值
实现
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# distance传入'mahalanobis'代表马氏距离,其他代表欧式距离
class MED(object):
def __init__(self, distance='mahalanobis', prototype='mean'):
# 实际上可以自己实现不同的distance和prototype函数以实现不同的分类器,目前就实现了一两种,所以这里的赋值作了简化
# 设置距离度量
if distance == 'mahalanobis':
self.__distance = self.__distance_mahalanobis
else:
self.__distance = self.__distance_euclidean
# 设置类的原型
if True:
self.__prototype = self.__prototype_mean
# 是否训练完成
self.__has_fit = False
# 存储类的标签
self.__tag = None
# 训练集
self.__train_data = []
# 协方差矩阵的逆矩阵
self.__cov_inv = []
# 类的中心
self.__center = []
# 马氏距离
# X_train是 n*m 的矩阵,代表n个元素,m个特征, index代表第几类
def __distance_mahalanobis(self, X, index):
return np.dot(np.dot((X - self.__center[index]).T, self.__cov_inv[index]), X - self.__center[index])
# 欧式距离
# X_train是 n*m 的矩阵,代表n个元素,m个特征, index代表第几类
def __distance_euclidean(self, X, index):
return np.dot((X - self.__center[index]).T, X - self.__center[index])
# 均值
def __prototype_mean(self, X):
return np.mean(X, axis=0)
# 训练, X_train是 n*m 的矩阵,代表n个元素,m个特征,Y_train为1维列向量,代表标签
def fit(self, X_train, Y_train):
self.__tag = np.unique(Y_train)
for i in range(len(self.__tag)):
# 划分当前数据
cur_data = X_train[np.where(Y_train == self.__tag[i])]
self.__train_data.append(cur_data)
# 计算中心
cur_center = self.__prototype(self.__train_data[i])
self.__center.append(cur_center)
# 如果距离度量为马氏距离,计算协方差矩阵
if self.__distance == self.__distance_mahalanobis:
cur_cov = np.linalg.pinv(np.cov(self.__train_data[i].T))
self.__cov_inv.append(cur_cov)
self.__has_fit = True
# 预测单个数据 x为n维列向量
def predict(self, x):
if not self.__has_fit:
print("模型还未训练")
return
dis = [self.__distance(x, i) for i in range(len(self.__tag))]
return self.__tag[np.argmin(dis)]
# 评估一组数据 X_test是 n*m 的矩阵,代表n个元素,m个特征,Y_test为1维列向量,代表标签
def score(self, X_test, Y_test):
if not self.__has_fit:
print("模型还未训练")
return
if X_test.shape[0] == 0 or X_test.shape[0] != Y_test.shape[0]:
print("参数不正确")
return
# pass
correct = 0
total = X_test.shape[0]
for i in range(X_test.shape[0]):
cur_tag = self.predict(X_test[i])
if cur_tag == Y_test[i]:
correct += 1
# print(cur_tag)
return correct / total
# 使用乳腺癌数据集进行测试
def main():
cancer = load_breast_cancer()
X = cancer.data
Y = cancer.target
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=100)
# 欧式距离 euclidean; 马氏距离 mahalanobis
med = MED(distance="mahalanobis")
med.fit(X_train, Y_train)
print(med.score(X_train, Y_train))
print(med.score(X_test, Y_test))
main()
第三章 贝叶斯决策与学习
3.1 贝叶斯决策与MAP分类器
- 基于距离的分类器存在的不足: 仅考虑每个类别各自观测到的训练样本的分布情况,没有考虑类的分布等先验知识
贝叶斯派的观点
决策条件
MAP分类器
-
定义: 最大后验概率(Maximum posterior probability, MAP)分类器:将测试样本决策分类给后验概率最大的那个类。
-
特点: 给定所有测试样本,MAP分类器选择后验概率最大的类,等于最小化平均概率误差即最小化决策误差!
3.2 MAP分类器:高斯观测概率
先验和观测概率的表达方式
- 常数表达:例如,(P(C_i)=0.2)
- 参数化解析表达:高斯分布..
- 非参数化表达:直方图、核密度、蒙特卡洛..
我们将高斯分布作为观测概率
-
当(sigma_i=sigma_j)时,决策边界是线性的。在方差相同的情况下,MAP决策边界偏向先验可能性较小的类,即分类器决策偏向先验概率高的类。
-
当(sigma_i eqsigma_j)时,决策边界是关于x的二次型函数,分类器倾向于方差较小(紧致)的类。
3.3 决策风险与贝叶斯分类器
- 贝叶斯决策不能排除出现错误判断的情况,由此会带来决策风险。
- 我们定义一个惩罚量,用来表征当前决策动作相对于其他候选类别的风险程度,即损失(loss)。
贝叶斯分类器
定义损失 (R(alpha_i|x)=Sigma_jlambda_{ij}p(C_j|x))
贝叶斯分类器会选择风险最小的类
- 期望损失
朴素贝叶斯
- 假设特征之间相互独立
实现
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import numpy as np
class BayesClassifier(object):
def __init__(self):
# 是否训练完成
self.__has_fit = False
# 存储类的标签
self.__tag = None
# 训练集
self.__train_data = []
# 方差
self.var = []
# 类的中心
self.center = []
def Gaussian(self, X, tag):
on = 1/(np.sqrt(2*np.pi * self.var[tag])*np.exp((X - self.center[tag]) ** 2/(2 * self.var[tag])))
return np.prod(on)
# 均值
def __mean(self, X):
return np.mean(X, axis=0)
def fit(self, X_train, Y_train):
self.__tag = np.unique(Y_train)
for i in range(len(self.__tag)):
# 划分当前数据
cur_data = X_train[np.where(Y_train == self.__tag[i])]
self.__train_data.append(cur_data)
# 计算中心
cur_center = self.__mean(self.__train_data[i])
self.center.append(cur_center)
# 计算方差
cur_var = np.var(self.__train_data[i].T, axis=1)
self.var.append(cur_var)
self.__has_fit = True
# 预测单个数据 x为n维列向量
def predict(self, x):
if not self.__has_fit:
print("模型还未训练")
return
dis = [self.Gaussian(x, i) for i in range(len(self.__tag))]
# print(dis)
return self.__tag[np.argmax(dis)]
# 评估一组数据 X_test是 n*m 的矩阵,代表n个元素,m个特征,Y_test为1维列向量,代表标签
def score(self, X_test, Y_test):
if not self.__has_fit:
print("模型还未训练")
return
if X_test.shape[0] == 0 or X_test.shape[0] != Y_test.shape[0]:
print("参数不正确")
return
# pass
correct = 0
total = X_test.shape[0]
for i in range(X_test.shape[0]):
cur_tag = self.predict(X_test[i])
if cur_tag == Y_test[i]:
correct += 1
# print(cur_tag)
return correct / total
# 使用乳腺癌数据集进行测试
def main():
cancer = load_iris()
X = cancer.data
Y = cancer.target
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=100)
# 欧式距离 euclidean; 马氏距离 mahalanobis
bayes = BayesClassifier()
bayes.fit(X_train, Y_train)
print(bayes.score(X_train, Y_train))
print(bayes.score(X_test, Y_test))
main()
3.4 最大似然估计
常用的参数估计方法
- 最大似然估计
- 贝叶斯估计
极大似然估计(具体可参考概率论相关教材)
- 之后,对参数求偏导,并令偏导为0即刻得到解
3.5 最大似然的估计偏差
- 如果一个参数的估计量的数学期望是该参数的真值,则该估计量称作无偏估计(unbiased estimates)。
对于高斯分布
- 在实际计算中,可以通过将训练样本的协方差乘以N/(N- 1)来修正协方差的估计值
3.6&3.7 贝叶斯估计
- 概率分布中待学习的参数也可以当做随机变量。
- 贝叶斯估计:给定参数分布的先验概率以及训练样本,估计参数分布的后验概率。
以高斯分布为例,假设待估计参数( heta)是高斯分布的均值(mu) ,并假设( hetasim N(mu_0, sigma_0^2))
经过整理,可以解得
将贝叶斯估计用于MAP分类器
将之前得到的结果带入
极大似然估计与贝叶斯估计的对比
- 前者将参数视为一个确定值,通过优化技术来求解参数
- 后者将参数视为随机变量,通过求取边缘概率来得到观测似然
3.8 KNN估计
- 如果概率分布形式未知,可以通过无参数(non -parametric)技术来实现概率密度估计。
3.9 直方图与核密度估计
直方图估计
knn存在的问题:
- 在推理测试阶段,仍然需要存储所有训练样本,因为针对任意一个模式x,需要以其为中心,在训练样本中寻找k个相邻点来估计该模式的概率。
- 易受噪声影响。
- 原理:(p(x)approxfrac{k}{NV})
优点
- 不需要存储训练数据
- 减小了噪声污染
核密度估计
常用核函数:高斯分布、均匀分布、三角分布
优点:
- 使用所有训练样本,而不是基于第k个近邻点来估计概率密度,从而克服KNN估计存在的噪声影响。
- 如果核函数是连续,则估计的概率密度函数也是连续的。