西瓜书习题试答-第11章-特征选择与稀疏学习

试答系列:“西瓜书”-周志华《机器学习》习题试答
系列目录
[第01章:绪论]
[第02章:模型评估与选择]
[第03章:线性模型]
[第04章:决策树]
[第05章:神经网络]
[第06章:支持向量机]
第07章:贝叶斯分类器
第08章:集成学习
第09章:聚类
第10章:降维与度量学习
第11章:特征选择与稀疏学习
第12章:计算学习理论(暂缺)
第13章:半监督学习
第14章:概率图模型
(后续章节更新中...)



11.1 试编程实现Relief算法,并考察其在西瓜数据集3.0上的运行结果。

:详细代码附后。需要注意的是:在计算样本间距离寻找最近邻样本时,由于西瓜数据集3.0中含有离散属性,其中既有“有序属性”,又有“无序属性”,严格来说,可以按照第9章9.3节中介绍的方法进行计算。但是,在这里为了与(11.3)式中的距离计算方法保持一致,简单地处理为:值同为0,值异为1,不考虑“序”关系。
运行结果(按相关统计量从大到小排列):
|特征|纹理|脐部|根蒂|含糖率|密度|敲声|触感|色泽|
|--|--|--|--|--|--|--|--|--|--|
|相关统计量|9|7|4|2.04|-0.5|-1|-4|-7|

11.2 试写出Relief-F的算法描述。

  • 输入:样本数据X,类标记Y
  • 过程
    01:计算样本数m,特征数n,类别数N=|y|,各类样本所占比例p
    02:初始化相关统计量\(\delta=\text{zeros}(n)\)
    03:for \(i\)=1,2,…,m:
    04:  \(x_i\)的所属类别为\(k\)
    05:  在\(x_i\)的同类样本中找到最近邻同类样本\(x_{i,nh}\)
    06:  for \(j\)=1,2,…,n:
    07:    \(δ_j=δ_j-\text{diff}(x_i^j-x_{i,nh}^j)^2\)
    08:  for \(l\)=1,2,...,k-1,k+1,…,N :
    09:    在属于\(l\)类别的样本子集\(D_l\)中找到与\(x_i\)最近邻的样本\(x_{i,l,nm}\)
    10:    for \(j\)=1,2,…,n:
    11:      \(δ_j=δ_j+p_l*\text{diff}(x_i^j-x_{i,l,nm}^j)^2\)
  • 输出:相关统计量\(δ\)

11.3 Relief算法是分别考察每个属性的重要性。试设计一个能考察每一对属性重要性的改进算法。

:只需将计算单个属性相关统计量的(11.3)式扩充为针对两个属性的统计量即可:

\[\delta^{i,j}=\sum_k –\text{diff}(x_k^{i,j},x_{k,nh}^{i,j})^2+ \text{diff}(x_k^{i,j},x_{k,nm}^{i,j})^2 \]

11.4 试为LVW设计一个改进算法,即便有运行时间限制,该算法也一定能给出解。

:当时间到了,但是t≥T的条件未到,将当前搜索到的最佳解A*给出即可。不会这么简单吧,或许没能理解题意?

11.5 结合图11.2,试举例说明L1正则化在何种情况下不能产生稀疏解。


sdd
观察上图左,在\(L_2\)情况下,取得最优解\(ω^*\)时,必然有平方误差等值线和\(L_2\)等值线在\(ω^*\)处相切,或者说,斜率相等,或者说,梯度方向刚好反向。
\(L_2\)等值线是一组圆,在第一象限中,从A点至B点,斜率从0连续变化到-∞。于是,平方误差等值线在第一象限中只要是单调递减曲线,总能够与\(L_2\)等值线相切。
因此,\(L_2\)等值线与平方误差等值线很容易在各个象限中发生相切,无法产生稀疏解。

\(L_1\)的情况下,\(L_1\)等值线在各个象限中的斜率总是等于±1。
参见上图右,观察第一象限的情况:\(L_1\)等值线的斜率为-1,误差等值线1在第一象限中斜率绝对值总是小于1,无法与\(L_1\)等值线相切;误差等值线2的斜率存在k=-1的点,能够与\(L_1\)等值线相切;误差等值线3的斜率绝对值总是大于1,也无法与L1等值线相切。
因此,在\(L_1\)情况下,\(L_1\)等值线和与误差等值线在很多情况下无法相切,最优解只能发生在坐标轴上,对应于稀疏解。
当误差等值线在第1、3象限存在斜率为-1的点,或者在第2、4象限存在斜率为1的点时,能够与\(L_1\)等值线发生相切,此时,无法产生稀疏解。

11.6 试析岭回归与支持向量机的联系。

:岭回归与支持向量机,前者是回归,后者是分类,作为比较,将岭回归与支持向量回归进行比较,更加合适。
岭回归的表达式为(11.6)式:

\[\min_\omega\sum_{i=1}^m(y_i-\omega^Tx_i)^2+\lambda|\omega|_2^2 \]

支持向量回归的表达式为(6.43)式:

\[\min_{\omega,b}\frac{1}{2}||\omega||_2^2+C\sum_{i=1}^m l_\epsilon (f(x_i)-y_i) \]

岭回归和支持向量回归的优化目标表达式非常相近,不同点在于采用的损失函数不同,岭回归采用平方误差损失函数,而支持向量回归采用\(\epsilon\)不敏感损失:

\[l_\epsilon (z)= \begin{cases} 0,&|z|\leq\epsilon\\ |z|-\epsilon, &otherwise \end{cases} \]

在这里插入图片描述
另外,我们知道支持向量回归的结果表达为支持向量的形式,其解是稀疏性的。在本章又知道,岭回归采用\(L_2\)正则化,其结果不稀疏,而LASSO采用\(L_1\)正则化,其结果稀疏。因此,在支持向量机和支持向量回归中,尽管也采用\(L_2\)正则化,其结果的稀疏性是由于所采用的损失函数形式导致的;而在LASSO中,其稀疏性是由\(L_1\)正则化导致的。

11.7 试述直接求解L0范数正则化会遇到的困难。

\(L_0\)范数等于非零元素的个数,亦即\(|\omega|_0=\sum_i (\omega_i\neq 0)\)。考虑二维的情况,此时的等值线比较特殊:在原点,\(L_0\)=0; 在各个坐标轴上\(L_0\)=1; 在各个象限区域,\(L_0\)=2。
在这里插入图片描述
在各个象限区域时,\(L_0\)项为一个常量,等于2,此时求解最优解相当于\(L_0\)项不存在一样。可以设想一下,求解L0正则化下的回归问题大概是这样子的:

  • 先不考虑\(L_0\)项,求解平方误差项的最优解为\(\omega^{*1}\),以及对应的目标函数值\(J_1=\text{erro}_1+2\)
  • 然后限定\(\omega_1=0\),求解此时的最优解为\(\omega^{*2}\),以及对应的目标函数值\(J_2=\text{erro}_2+1\);
  • 然后限定\(\omega_2=0\),求解此时的最优解为\(\omega^{*3}\),以及对应的目标函数值\(J_3=\text{erro}_3+1\);
  • 然后计算\(\omega=0\)时的目标函数值\(J_4=\text{erro}_4\);
  • 最后,比较\(J_1\sim J_4\),择其最小者作为最终结果。

推而广之,在\(L_0\)正则化时的求解方法是,分别设定\(\omega\)中某些元素为零的情况下,求解无正则化的优化问题,最终比较各种情况下的目标函数值,确定最优解。
貌似也没什么困难的吧,只是比较繁杂而已。
设特征数为N,则按照上面的方法,要在\(2^N\)的情况下分别求解优化问题,这个次数随特征数指数级增长,当特征数较多时,比较困难。

11.8 试给出求解L1范数最小化问题中的闭式解(11.14)的详细推导过程。

:(11.13)式可以表示为各个分量相加的形式,各个分量互不影响,因此略去下标i,将x看成标量,于是(11.13)可以改写为:

\[x_{k+1}=argmin_x \frac{L}{2}(x-z)^2+\lambda|x| \]

令等式右边的目标函数为g(x),对其求导有:

\[g^\prime(x)=L(x-z)+\lambda \text{sign}(x) \]

其中sign(x)是符号函数,x为正时等于1,x为负时等于-1,在x=0处存在突变。
如果对\(g^\prime (x)\)函数图像作图,其中\(L(x-z)\)是一条直线,后一部分\(\lambda \text{sign}(x)\)的效果是在x>0时将曲线向上平移\(\lambda\),x<0时曲线向下平移\(\lambda\)。对\(g^\prime (x)\)除以正数L,不影响最小化结果。对\(g^\prime (x)/L\)函数变化曲线分情况作图如下:
在这里插入图片描述
\(g^\prime(x)=0\),或者正负号改变处对应于极小值取值处,于是有(11.14)式的结论:

\[x_{k+1}= \begin{cases} z+\frac{\lambda}{L},&z<-\frac{\lambda}{L}\\ 0,&|z|<\frac{\lambda}{L}\\ z-\frac{\lambda}{L},&z>\frac{\lambda}{L} \end{cases}\]

11.9 试述字典学习与压缩感知对稀疏性利用的异同。(暂缺)

11.10 试改进式(11.15),以学习出具有分组稀疏性的字典。(暂缺)


附:编程代码

习题11.1(Python)

# -*- coding: utf-8 -*-
"""
Created on Mon May 18 11:34:22 2020

@author: MS

11.1 试编程实现Relief算法,并考察其在西瓜数据集3.0上的运行效果
"""
import numpy as np

def Relief(X,Y):
    # Relef算法
    # 输入:
    #     X:样本数据,列表类型,允许连续型和离散型数据,维度为样本数×特征数
    #     Y: 类标记,列表或者numpy.array类型,这里仅考虑2分类情况
    # 输出:
    #     r:计算出的相关统计量,对应于教材上的(11,3)式,长度为特征数
    
    m=len(X)        #样本数
    n=len(X[0])     #特征数
    Y=np.asarray(Y) #转换为numpy.array类型
    
    types=np.array([type(xj) for xj in X[0]])          #各个特征的类型
    d_index=np.where(types==str)[0]                    #离散属性序号
    c_index=np.where((types==int)|(types==float))[0]   #连续属性序号
    Xd=np.array([[x[i] for i in d_index] for x in X])  #X之离散属性部分
    Xc=np.array([[x[i] for i in c_index] for x in X])  #X之连续属性部分
    Xc=(Xc-Xc.min(0))/(Xc.max(0)-Xc.min(0))            #连续值部分规范化到[0,1]区间
    
    r=np.zeros(n)                                      #存储相关统计量
    for i in range(m):
        # 计算xi与所有样本的距离平方(等号右边两项分别为离散和连续特征贡献)
        dist2=(Xd[i,:]!=Xd).sum(1)+((Xc[i,:]-Xc)**2).sum(1)
        # 同类最近邻
        dist2_nh=dist2.copy()                #拷贝距离副本
        dist2_nh[i]=max(dist2)+1             #自身距离本为0,将其强制设为较大值
        dist2_nh[Y!=Y[i]]=max(dist2)+1       #异类距离也设为较大值
        nh_index=np.argmin(dist2_nh)         #同类中最近邻样本的索引号
        r[d_index]-=Xd[i]!=Xd[nh_index]      #r之离散属性部分
        r[c_index]-=(Xc[i]-Xc[nh_index])**2  #r之连续属性部分
        # 异类最近邻
        dist2_nm=dist2.copy()                #拷贝距离副本
        dist2_nm[Y==Y[i]]=max(dist2)+1       #同类距离设为较大值
        nm_index=np.argmin(dist2_nm)         #异类中最近邻样本的索引号
        r[d_index]+=Xd[i]!=Xd[nm_index]      #r之离散属性部分
        r[c_index]+=(Xc[i]-Xc[nm_index])**2  #r之连续属性部分

    return r

#====================================
#              主程序
#====================================   
# 表4.3 西瓜数据集3.0
FeatureName=['色泽','根蒂','敲声','纹理','脐部','触感','密度','含糖率']
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]]
Y=[1]*8+[0]*9
# 计算相关统计量
r=Relief(X,Y)
order=np.argsort(r)[::-1]
print('===================相关统计量排序结果===================')
for i in order:
    print(FeatureName[i]+':'+str(r[i]),end=';  ')
posted @ 2020-09-21 01:24  之始  阅读(2257)  评论(0编辑  收藏  举报