《机器学习》第一次作业——第一至第三章学习记录和心得
一、第一章 基本概念
模式识别
1.数学解释可表示为:y=f(x) 其中x代表了输入模式,f是已有知识的表达,y则为输出类别;
其目标为:在特征空间和解释空间之间找到一种映射关系————称之为假说(假说可以通过监督学习和非监督学习两种方法获得);
2.监督学习:训练样本及输出真值都给定情况下的机器学习算法。可以描述为:{x1,x2,x3...,xn}和{t1,t2,t3...,tn}然后来求解{\(\theta\)1,\(\theta\)2,\(\theta\)3...,\(\theta\)n};
无监督式学习:只给顶训练样本,没有给输入真值情况下的机器学习算法,难度远高于监督式算法。可描述为:{x1,x2,x3...,xn}然后来求解{\(\theta\)1,\(\theta\)2,\(\theta\)3...,\(\theta\)n};
半监督式学习:看做有约会素条件的无监督室学习问题;
3.模型质量的评价:泛化能力(学习算法对新模式的决策能力);
泛化能力低的表现为过拟合,过拟合是指学习模型对训练样本预测得很好,但对新样本预测很差的现象。这通常是由于学习模型能力过于强大,以至于把训练样本自身的一些特点当做了一般性质。
提高泛化能力的思路为:不要过度训练
方法:
- 选择复杂度合适的模型
- 正则化
4.模型性能的评估
- 留出法
随机划分,数据集被分为两组留出法直接将数据集D划分为两个互斥的部分,其中一部分作为训练集S,另一部分用作测试集T。通常训练集和测试集的比例为70%:30%。
同时,训练集测试集的划分有两个注意事项:- 尽可能保持数据分布的一致性。避免因数据划分过程引入的额外偏差而对最终结果产生影响。在分类任务中,保留类别比例的采样方法称为“分层采样”(stratified sampling)。
- 采用若干次随机划分避免单次使用留出法的不稳定性。
- K折交叉验证
交叉验证法先将数据集D划分为k个大小相似的互斥子集,每次采用k − 1个子集的并集作为训练集,剩下的那个子集作为测试集。进行k次训练和测试,最终返回k个测试结果的均值。
- 留一法
留一法是k kk折交叉验证k = m k=mk=m(m mm为样本数)时候的特殊情况。即每次只用一个样本作测试集。该方法计算开销较大。
K折交叉代码:
def k_split(data,iris_type,num):
import random
testSet = []
testType = []
first_cur = []
second_cur = []
third_cur = []
for i in range(len(iris_type)):
if iris_type[i] == 0:
first_cur.append(i)
elif iris_type[i] == 1:
second_cur.append(i)
else:
third_cur.append(i)
match_size = int(len(first_cur)/num)
size = len(first_cur)-1
train_data = []
train_type = []
for i in range(num):
k = match_size
train_data = []
train_type = []
for j in range(match_size):
cur = random.randint(0, size)
train_data.append(data[first_cur[cur]])
train_type.append(iris_type[first_cur[cur]])
first_cur.remove(first_cur[cur])
cur = random.randint(0, size)
train_data.append(data[second_cur[cur]])
train_type.append(iris_type[second_cur[cur]])
second_cur.remove(second_cur[cur])
cur = random.randint(0, size)
train_data.append(data[third_cur[cur]])
train_type.append(iris_type[third_cur[cur]])
third_cur.remove(third_cur[cur])
size = size-1
testSet.append(train_data)
testType.append(train_type)
return np.asarray(testSet),np.asarray(testType)
5.度量性能
二分类问题常用的评价指标时查准率和查全率。
根据预测正确与否,将样例分为以下四种:
- TP(True positive,真正例)——将正类预测为正类数。
- FP(False postive,假正例)——将反类预测为正类数。
- TN(True negative,真反例)——将反类预测为反类数。
- FN(False negative,假反例)——将正类预测为反类数。
其中查准率(precision,精确率):即将正类预测为正类数与预测为正类的总数的比值。
查全率(recall,召回率):即将正类预测为正类数与正类总数的比值。
查准率和查全率是一对矛盾的度量。F1是查准率和查全率的调和平均:当查重率和查准率都高时,F1也会高。
二、第二章 基于距离的分类器
1.MED分类器
把测试样本到每个类之间的距离作为决策模型,将测试样本判定为与其距离最近的类。概念:最小欧式距离分类器(Minimum Euclidean Distance Classifier)
距离衡量:欧式距离
类的原型:均值
类的原型:用来代表这个类的一个模式或者一组量,便于计算该类和测试样本之间的距离。
- &nmsp;其中 均值是对类中所有训练样本代表误差最小的一种表达方式。该类中所有训练样本的均值作为类的原型:
- &nmsp;从一类的训练样本中,选取与测试样本距离最近的一个训练样本,作为该类的原型。类的原型取决于测试样本。
缺陷- 对类的表达误差较大。
- 对噪声和异常样本比较敏感。
MED分类器的决策边界:
MED分类器存在的问题:MED分类器采用欧氏距离作为距离度量,没有考虑特征变化的不同及特征之间的相关性。
代码实现:
def MED_classification(data,iris_type,t,f,flag):
data_linear,iris_type_linear=getIrisLinear(data,iris_type,flag)
train_data,train_type,test_data,test_type = hold_out_way(data_linear,iris_type_linear)
c1 = []
c2 = []
n1=0
n2=0
for i in range(len(train_data)): #均值
if train_type[i] == 1:
n1+=1
c1.append(train_data[i])
else:
n2+=1
c2.append(train_data[i])
c1 = np.asarray(c1)
c2 = np.asarray(c2)
z1 = c1.sum(axis=0)/n1
z2 = c2.sum(axis=0)/n2
test_result = []
for i in range(len(test_data)):
result = np.dot(z2-z1,test_data[i]-(z1+z2)/2)
test_result.append(np.sign(result))
test_result = np.array(test_result)
TP = 0
FN = 0
TN = 0
FP = 0
for i in range(len(test_result)):
if(test_result[i]>=0 and test_type[i]==t):
TP+=1
elif(test_result[i]>=0 and test_type[i]==f):
FN+=1
elif(test_result[i]<0 and test_type[i]==t):
FP+=1
elif(test_result[i]<0 and test_type[i]==f):
TN+=1
Recall = TP/(TP+FN)
Precision = TP/(TP+FP)
print("Recall= %f"% Recall)
print("Specify= %f"% (TN/(TN+FP)))
print("Precision= %f"% Precision)
print("F1 Score= %f"% (2*Recall*Precision/(Recall+Precision)))
#绘图
xx = [[0, 1, 2], [1, 2, 3], [0, 2, 3], [0, 1, 3]]
iris_name =['setosa','vesicolor','virginica']
iris_color = ['r','g','b']
iris_icon = ['o','x','^']
fig = plt.figure(figsize=(20, 20))
feature = ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
for i in range(4):
ax = fig.add_subplot(221 + i, projection="3d")
X = np.arange(test_data.min(axis=0)[xx[i][0]],test_data.max(axis=0)[xx[i][0]],1)
Y = np.arange(test_data.min(axis=0)[xx[i][1]],test_data.max(axis=0)[xx[i][1]],1)
X,Y = np.meshgrid(X,Y)
m1 = [z1[xx[i][0]],z1[xx[i][1]],z1[xx[i][2]]]
m2 = [z2[xx[i][0]], z2[xx[i][1]], z2[xx[i][2]]]
m1 = np.array(m1)
m2 = np.array(m2)
m = m2-m1
#将公式进行化简
Z = (np.dot(m,(m1+m2)/2)-m[0]*X-m[1]*Y)/m[2]
ax.scatter(test_data[test_result >= 0, xx[i][0]], test_data[test_result>=0, xx[i][1]], test_data[test_result >= 0, xx[i][2]],
c=iris_color[t], marker=iris_icon[t], label=iris_name[t])
ax.scatter(test_data[test_result < 0, xx[i][0]], test_data[test_result < 0, xx[i][1]],
test_data[test_result < 0, xx[i][2]],
c=iris_color[f], marker=iris_icon[f], label=iris_name[f])
ax.set_zlabel(feature[xx[i][2]])
ax.set_xlabel(feature[xx[i][0]])
ax.set_ylabel(feature[xx[i][1]])
ax.plot_surface(X,Y,Z,alpha=0.4)
plt.legend(loc=0)
plt.show()
2.特征白化
将原始特征映射到一个新的特征空间,使得在新空间中特征的协方差矩阵为单位矩阵,从而去除特征变化的不同及特征之间的相关性。
特征正交白化
将特征转换分为两步:先去除特征之间的相关性(解耦, Decoupling),然后再对特征进行尺度变换(白化, Whitening),使每维特征的方差相等。
代码实现(以iris数据集为例):
def to_whiten(data):
Ex = np.cov(data,rowvar=False)#这个一定要加……因为我们计算的是特征的协方差
a,w1 = np.linalg.eig(Ex)
w1 = np.real(w1)
module = []
for i in range(w1.shape[1]):
sum = 0
for j in range(w1.shape[0]):
sum += w1[i][j]**2
module.append(sum**0.5)
module = np.asarray(module,dtype="float64")
w1 = w1/module
a = np.real(a)
a=a**(-0.5)
w2 = np.diag(a)
w = np.dot(w2,w1.transpose())
for i in range(w.shape[0]):
for j in range(w.shape[1]):
if np.isnan(w[i][j]):
w[i][j]=0
#print(w)
return np.dot(data,w)
def show_whiten(data,iris_type):
whiten_array = to_whiten(data)
show_out_3D(whiten_array,iris_type)
def show_out_3D(data,iris_type):
xx = [[0, 1, 2], [1, 2, 3], [0, 2, 3], [0, 1, 3]]
fig = plt.figure(figsize=(20, 20))
feature = ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
for i in range(4):
ax = fig.add_subplot(221 + i, projection="3d")
ax.scatter(data[iris_type == 0, xx[i][0]], data[iris_type == 0, xx[i][1]], data[iris_type == 0, xx[i][2]],
c='r', marker='o', label='setosa')
ax.scatter(data[iris_type == 1, xx[i][0]], data[iris_type == 1, xx[i][1]], data[iris_type == 1, xx[i][2]],
c='g', marker='x',
label='vesicolor')
ax.scatter(data[iris_type == 2, xx[i][0]], data[iris_type == 2, xx[i][1]], data[iris_type == 2, xx[i][2]],
c='b', marker='^',
label='virginica')
yy = [feature[xx[i][2]],feature[xx[i][0]],feature[xx[i][1]]]
ax.set_zlabel(yy[0])
ax.set_xlabel(yy[1])
ax.set_ylabel(yy[2])
plt.legend(loc=0)
plt.show()
3.MICD分类器
最小类内距离分类器(Minimum Intra-class Distance Classifier),基于马氏距离的分类器。
距离度量:马氏距离
类的原型:均值
MICD分类器的缺陷是会选择方差较大的类。
MICD分类器的问题:当两个类均值一样时,MICD偏向于方差大的类。在此种情况,决策真值应该是倾向于方差小(分布紧致)的类。
4.基于距离的决策:
- 仅考虑每个类别各自观测到的训练样本的分布情况,例如,均值(MED分类器)和协方差(MICD分类器)。
- 没有考虑类的分布等先验知识,例如,类别之间样本数量的比例,类别之间的相互关系。
5.补充 各种距离的区别
KNN概率密度估计
关于Knn的优缺点:
优点:可以自适应的确定𝒙相关的区域𝑅的范围。
缺点:
- KNN概率密度估计不是连续函数。
- 不是真正的概率密度表达,概率密度函数积分是 ∞ 而不是1。例如,在k=1时。
三、第三章 贝叶斯决策与学习
1.先验概率和后验概率
先验概率:
先验概率:根据以往的经验和分析得到的概率,不依靠观测数据。
表示方式有:
- 常数表达:例如,𝑝 𝐶𝑖 = 0.2
- 参数化解析表达:高斯分布……
- 非参数化表达:直方图、核密度、蒙特卡洛…
后验概率:
从概率的观点看,给定一个测试模式𝒙,决策其属于哪个类别需要依赖于如下条件概率:P(C, x)
输入模式𝒙 :随机变量(单维特征)或向量(高维特征)。类别输出𝑪:随机变量,取值是所有类别标签{𝐶𝑖} 。
针对每个类别𝐶𝑖 ,该条件概率可以写作:P(Ci , x) 该条件概率也称作后验概率(posterior probability) ,表达给定模式𝒙属于类𝐶𝑖可能性 ;
观测似然概率:
观测似然概率:也叫似然概率,这个可以比做成在很多组参数中,选择一组最能拟合观测数据的参数。
如何决策——找找到后验概率最大的那个类。
2.贝叶斯规则
3.MAP分类器
最大后验概率(Maximum posterior probability,MAP)分类器:将测试样本决策分类给后验概率最大的那个类。决策边界指的是两个后验概率相等的地方。单维空间:通常有两条决策边界;高维空间:复杂的非线性边界。
决策误差最小化:MAP分类器决策目标:最小化概率误差,即分类误差最小化。给定所有测试样本,MAP分类器选择后验概率最大的类,等于最小化平均概率误差,即最小化决策误差!
4.高斯观测概率
决策边界:
- 当𝜎𝑖 = 𝜎𝑗 = σ 时,决策边界是线性的,只有一条;
- 如果𝜇𝑖 < 𝜇𝑗,且𝑃 𝐶𝑖 < 𝑃 𝐶𝑗 ,则𝛿 < 0:说明:在方差相同的情况下,MAP决策边界偏向先验可能性较小的类,即分类器决策偏向先验概率高的类。
- 当𝜎𝑖 ≠ 𝜎𝑗时,决策边界有两条(即非线性边界),该决策方程是关于𝒙的二次型函数。
- 当𝜎𝑖 > 𝜎𝑗且先验概率相等时,𝛿 > 0,分类器倾向选择𝐶𝑗类,即方差较小(紧致)的类。
- 总结:因此,MAP分类器可以解决MICD分类器存在的问题:当方差不相同时,设𝜇𝑖 = 𝜇𝑗 = 𝜇,𝜎𝑖 > 𝜎𝑗,MAP分类器倾向选择方差较小的类。
三种分类器比较
- 总结:因此,MAP分类器可以解决MICD分类器存在的问题:当方差不相同时,设𝜇𝑖 = 𝜇𝑗 = 𝜇,𝜎𝑖 > 𝜎𝑗,MAP分类器倾向选择方差较小的类。
对于高维的高斯分布,决策边界是一个超二次型,并且始终偏离MICD的决策边界一定的距离。
5.决策风险与贝叶斯分离器
- 贝叶斯决策不能排除出现错误判断的情况,由此会带来决策风险。更重要的是,不同的错误决策会产生程度完全不一样的风险;
- 给定一个测试样本𝒙,贝叶斯分类器选择决策风险最小的类;
给定单个测试样本,贝叶斯决策损失就是决策风险𝑅(𝛼𝑖|𝒙)。给定所有测试样本(N为样本个数),贝叶斯决策的期望损失:所有样本的决策损失之和。
决策目标:给定所有测试样本 {𝒙},贝叶斯分类器的决策目标:最小化期望损失。
如果出现在决策边界附近的处理方法
为了避免出现错误决策,分类器可以选择拒绝。引入阈值τ :
当τ = 1,所有样本的任何决策都会被拒绝。
当τ < 1/𝐾,所有样本的决策都不会被拒绝,K是类别的个数。
6.最大似然估计
两种监督学习方式:
- 参数化方法:给定概率分布的解析表达,学习这些解析表达函数中的参数。该类方法也称为参数估计。例如,高斯分布的均值(向量)和方差(协方差);
- 非参数化方法:概率密度函数形式未知,基于概率密度估计技术,估计非参数化的概率密度表达。
最大似然估计:整个建模过程需要一个似然函数来描述在不同模型参数下真实数据发生的概率,似然函数是关于模型参数的函数。最大似然估计就是寻找最优参数,使得观测数据发生的概率最大、统计模型与真实数据最相似。
先验概率估计:给定所有类的𝑁个训练样本,假设随机抽取其中一个样本属于𝐶1类的概率为𝑃,则选取到𝑁1个属于𝐶1类样本的概率为先验概率的似然函数(即目标函数)。
7.最大似然的估计偏差
无偏估计:无偏估计意味着只要训练样本个数足够多,该估计值就是参数的真实值。
- 均值的最大似然估计:是无偏估计!
- 协方差的最大似然估计:是有偏估计!
关于协方差的最大似然估计偏差:估计偏差是一个较小的数。当N足够大时,最大似然估计可以看做是一个较好的估计。
在实际计算中,可以通过将训练样本的协方差乘以𝑁/(𝑁 − 1)来修正协方差的估计值。
8.贝叶斯估计
(1)贝叶斯估计:给定参数𝜃分布的先验概率以及训练样本,估计参数θ分布的后验概率。
(2)假设,Ci类的观测似然概率是单维高斯分布,并且方差1已知,那么待估计参数θ就是均值1。并且假设θ的先验概率分布也服从单维高斯分布,方差2和均值2已知。因此可以计算后验概率。
(3)参数𝜃的后验概率是一个高斯分布,其均值和方差为𝜇𝜃和𝜎𝜃;
(4)给定𝐶𝑖类的𝑁𝑖个训练样本,参数θ概率分布的均值等于训练样本均值和该参数先验概率均值的加权和。给定𝐶𝑖类的𝑁𝑖个训练样本,参数θ概率分布的方差是由𝐶𝑖类观测似然分布的方差、该参数的先验概率方差、 𝐶𝑖类的样本个数共同决定。
(5)当𝑁𝑖足够大时,样本均值m就是参数θ的无偏估计。
参数先验对后验概率的影响:
如果参数的先验方差𝜎0 = 0,则𝜇𝜃 → 𝜇0,意味先验的确定性较大,先验均值的影响也更大,使得后续训练样本的不断进入对参数估计没有太多改变。
如果参数的先验方差𝜎0 ≫ 𝜎,则𝜇𝜃 → 𝑚,意味着先验的确定性非常小。刚开始由于样本较少,导致参数估计不准。随着样本的不断增加,后验均值会逼近样本均值。
贝叶斯估计具备不断学习的能力
- 它允许最初的、基于少量训练样本的、不太准的估计。
- 随着训练样本的不断增加,可以串行的不断修正参数的估计值,从而达到该参数的期望真值。
(6)利用的θ的后验概率,再和θ是确定值的情况下的观测似然进行相乘并对θ进行积分,计算得到关于θ的边缘概率。从而得到观测似然概率的估计,该估计也是服从高斯分布的。对比最大似然估计,最大似然估计有明确的目标函数,只需要求偏导就能得到估计值。而贝叶斯估计有多个取值的可能性,在学习的过程中,逐渐缩小取值的范围,直到趋近真值,所以贝叶斯估计计算复杂度很高。
9.无参数概率密度估计
(1)常用的无参数技术主要有:
- K近邻法(K-nearest neighbors)
- 直方图技术(Histogram technique)
- 核密度估计(Kernel density estimation)
(2)给定𝑁个训练样本,在特征空间内估计每个任意取值𝒙的概率密度,即估计以𝒙为中心、在极小的区域𝑅 = (𝒙, 𝒙 + 𝛿𝒙) 内的概率密度函数𝑝(𝒙);
- 无参数估计的任务: 估计概率𝑝(𝒙)。
- 如果区域𝑅足够小,𝑃是𝑝(𝒙)的平滑版本,可以用来估计𝑝(𝒙)。
(3)各种估计对比
- KNN估计:以待估计的任意一个模式为中心,搜寻第𝑘个近邻点,以此来确定区域,易被噪声污染。
- 直方图估计:手动将特征空间划分为若干个区域,待估计模式只能分配到对应的固定区域,缺乏自适应能力。
- 核密度估计:以待估计模式𝒙为中心、自适应确定区域𝑅的位置(类似KNN)。使用所有训练样本,而不是基于第 𝑘 个近邻点来估计概率密度,从而克服KNN估计存在的噪声影响。如果核函数是连续,则估计的概率密度函数也是连续的。
- 与直方图估计相比,核密度估计不提前根据训练样本估计每个格子的统计值,所以它必须要存储所有训练样本。