目录
L1正则化问题的求解——近端梯度下降(Proximal Gradient Descent, PGD)
其核心思想是:利用“泰勒展开”将目标函数的求解问题,变为一个“二次函数的求解问题”。
11.1 子集搜索与评价
对一个学习任务来说,给定属性集,其中有些属性可能很关键、很有用,另一些属性则可能没什么用.我们将属性称为"特征" (feature) ,对当前学习任务有用的属性称为"相关特征" (relevant feature) 、没什么用的属性称为"无关特征" (irrelevant feature). 从给远的特征集合中选择出相关特征于集的过程,称为"特征选择" (feature selection)。
为什么要进行特征选择:
- 减轻维数灾难问题(与降维的原因相同)
- 去除不相关特征往往会降低学习任务的难度
我们不能直接用排列组合进行遍历所有可能子集,这样会遭遇组合爆炸。所以我们选择产生一个“候选子集”,评价它的好坏,然后根据评价结果产生下一个候选特征子集,再进行评价,持续进行直到无法找到一个更好的子集为止。
如何根据评价结果获取下一个候选特征子集?
- 前向搜索:初始将每个特征当做一个候选特征子集,然后从当前所有的候选子集中选择出最佳的特征子集;接着在上一轮选出的特征子集中添加一个新的特征,同样地选出最佳特征子集;最后直至选不出比上一轮更好的特征子集。
- 后向搜索:从完整的特征集合开始,每次尝试去掉一个无关特征。
- 双向搜索:前向后向结合,每一轮逐渐增加选定相关特征,同时减少无关特征(前面增加的特征不会被去除)。
- 优点:思路简单,速度快,不用全部情况都遍历一遍。
- 缺点:使用贪心算法,不从总体上考虑其它可能情况,每次选取局部最优解,不再进行回溯处理,结果不一定是最好的。
如何评价候选特征子集的好坏?
\(\mathrm{Gain}(A)=\mathrm{Ent}(D)-\sum_{v=1}^V\frac{|D^v|}{|D|}\mathrm{Ent}(D^v)\)
信息熵定义为:
\(\mathrm{Ent}(D)=-\sum_{i=1}^{|\mathcal{Y}|}p_k\log_2p_k\)
信息增益Gain(A)越大,特征子集A包含的有助于分类的信息越多。对每个候选特征子集,可基于训练数据集D来计算其信息增益,以此作为评价准则。信息熵也是同理,只要能判断两个划分差异的机制都能用于特征子集评价。
将特征子集搜索机制和子集评价机制相结合,即可得到特征选择方法。
11.2 过滤式选择(Relief)
过滤式方法是一种将特征选择与学习器训练相分离的特征选择技术,即首先将相关特征挑选出来,再使用选择出的数据子集来训练学习器。Relief是其中著名的代表性算法,它使用一个“相关统计量”来度量特征的重要性,该统计量是一个向量,其中每个分量代表着相应特征的重要性,因此我们最终可以根据这个统计量各个分量的大小来选择出合适的特征子集。
Relief算法的关键是如何确定相关统计量。对于数据集中的每个样例xi,Relief首先找出与xi同类别的最近邻与不同类别的最近邻,分别称为猜中近邻(near-hit)与猜错近邻(near-miss),接着便可以分别计算出相关统计量中的每个分量。对于j分量:
\(\delta^j=\sum_i-\mathrm{diff}(x_i^j,x_{i,\mathrm{nh}}^j)^2+\mathrm{diff}(x_i^j,x_{i,\mathrm{nm}}^j)^2\)
直观上理解:对于猜中近邻,两者j属性的距离越小越好,对于猜错近邻,j属性距离越大越好。更一般地,若xi为离散属性,diff取海明距离,即相同取0,不同取1;若xi为连续属性,则diff为曼哈顿距离,即取差的绝对值。分别计算每个分量,最终取平均便得到了整个相关统计量。
标准的Relief算法只用于二分类问题,后续产生的拓展变体Relief-F则解决了多分类问题。对于j分量,新的计算公式如下:
\(\delta^{j}=\sum_{i}-\mathrm{diff}(x_{i}^{j},x_{i,\mathrm{nh}}^{j})^{2}+\sum_{l\neq k}\left(p_{l}\times\mathrm{diff}(x_{i}^{j},x_{i,l,\mathrm{nm}}^{j})^{2}\right)\)
其中\(p_l\)表示第\(l\)类样本在数据集中所占的比例,易知两者的不同之处在于:标准Relief 只有一个猜错近邻,而Relief-F有多个猜错近邻。
11.3 包裹式选择(LVW)
与过滤式选择不同的是,包裹式选择将后续的学习器也考虑进来作为特征选择的评价准则。因此包裹式选择可以看作是为某种学习器量身定做的特征选择方法,由于在每一轮迭代中,包裹式选择都需要训练学习器,因此在获得较好性能的同时也产生了较大的开销。
拉斯维加斯方法和蒙特卡罗方法是两个以著名赌城名字命名的随机化方法.两者的主要区别是:若有时间限制,则拉斯维加斯方法或者给出满足要求的解,或者不给出解,而蒙特卡罗方法一定会给出解,虽然给出的解未必满足要求;若无时间限制,则两者都能给出满足要求的解。
LVW(Las Vegas Wrapper),它在拉斯维加斯框架下使用随机策略来进行特征子集的搜索,并以最终分类器的误差为特征子集评价准则。
- 初始化:
- \(E\):算法误差,初始化为无穷大
- \(d\):特征子集的特征(属性)个数,初始化为特征集的特征个数
- \(A^*\):特征子集,初始化为特征集
- \(t\):连续没有优化效果的特征子集数,初始化为0
- 循环部分:
- 随机产生一个特征子集\(A'\),用\(A'\)的特征个数更新\(d\)
- 使用交叉验证法计算学习器\(\mathfrak{L}\)在\(A'\)下的误差
- \(\left.\left\{\begin{array}{l}\text{更新}t,E,d,A^*;\text{ 较目前最好的算法误差}E\text{小或者精度无提升但特征数变少}\\t=t+1, else\end{array}\right.\right.\)
- 重复循环部分,直到满足停止条件控制参数,输出当前最好的特征子集\(A^*\)
调用LVW函数,传入鸢尾花数据集的特征和目标变量。打印最佳分数和最佳特征子集。
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectKBest, f_classif
from itertools import combinations
import numpy as np
# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
# 定义LVW函数
def LVW(X, y, max_iter=100, threshold=0.01, learning_alg=LogisticRegression()):
best_score = 0.0
best_features = None
best_estimator = None
# 初始化特征全集
full_features = np.arange(X.shape[1])
for i in range(max_iter):
# 随机选择特征子集
random_features = np.random.choice(full_features, size=int(np.sqrt(X.shape[1])), replace=False)
X_subset = X[:, random_features]
# 评估特征子集
estimator = learning_alg.fit(X_subset, y)
scores = cross_val_score(estimator, X_subset, y, cv=5)
mean_score = np.mean(scores)
# 记录并比较性能
if mean_score - best_score > threshold:
best_score = mean_score
best_features = random_features
best_estimator = estimator
return best_score, best_features, best_estimator
# 运行LVW算法
score, features, estimator = LVW(X, y)
print(f"Best score: {score:.4f}")
print(f"Best features: {features}")
Best score表示通过LVW算法找到的最佳模型性能分数为0.9600。Best features表示通过LVW算法找到的最佳特征子集包含索引为2和3的特征。这意味着,在鸢尾花数据集的四个特征中,算法认为索引为2和3的特征组合能够给出最佳的模型性能。
11.4 嵌入式选择与正则化
将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动进行了特征选择。
L1/L2正则化:
- 线性回归模型以平方误差为损失函数的优化目标:\(\min_w\sum_{i=1}^m(y_i-w^\mathrm{T}x_i)^2\)
样本特征很多而样本数目相对较少时很容易陷入过拟合
引入L2正则化(岭回归):\(\min_w\sum_{i=1}^m(y_i -w^\mathbf{T}x_i )^2+\lambda\|w\|_2^2\),(\(\lambda\) 决定惩罚力度,过高可能会欠拟合,过小无法解决过拟合)
作用:L1正则化有特征筛选的作用,对所有参数的惩罚力度都一样,可以让一部分权重变为零(降维),因此产生稀疏模型,能够去除某些特征(权重为0则等效于去除)- 引入L1正则化(LASSO):\(\min_w\sum_{i=1}^m(y_i-w^\mathrm{T}x_i)^2+\lambda\|w\|_1\)
作用:使各个维度权重普遍变小,减少了权重的固定比例,使权重平滑
L1 和 L2 正则化都有助于降低过拟合风险,但L1还会带来一个额外的好处:它比L2更易于获得 “稀疏”解,即求得的w会有更少的非零分量(即抹除了更多的特征属性)。
意味着初始的d个特征中仅有对应着w的非零分量的特征才会出现在最终模型中,于是求解L1范数正则化的结果是得到了仅采用一部分初始特征的模型,即基于L1正则化的学习方法就是一种嵌入式特征选择方法。
- L1范数会趋向产生少量的特征,其他特征的权值都是0;
- L2会选择更多的特征,这些特征的权值都会接近于0。
L1正则化问题的求解——近端梯度下降(Proximal Gradient Descent, PGD)
其核心思想是:利用“泰勒展开”将目标函数的求解问题,变为一个“二次函数的求解问题”。
利普希茨连续条件(L-Lipschitz条件)
\(K\)对于\(f:D\subseteq\mathbb{R}\to\mathbb{R}\), 若存在常数\(k\)使得\(\|f(a)-f(b)\|\leq K|a-b|\quad\forall a,b\in D\),\(f\)符合利普希茨条件,对于\(f\)最小的常数\(K\)称为\(f\)的利普希茨常数。
简单说来就是:存在一个实数\(K\),使得对于函数\(f\)上的任意两点的连线的斜率的绝对值不大于 \(K\),最小的\(K\)称为该函数的Lipschitz常数。直观上,Lipschitz连续函数限制了函数改变的速度。符合利普希茨条件的函数的斜率,必小于一个称为利普希茨常数的实数(该常数依函数而定)。
11.5 稀疏表示与字典学习
当样本数据是一个稀疏矩阵时,对学习任务来说会有不少的好处,例如很多问题变得线性可分,储存更为高效等。这便是稀疏表示与字典学习的基本出发点。稀疏矩阵即矩阵的每一行/列中都包含了大量的零元素,且这些零元素没有出现在同一行/列,对于一个给定的稠密矩阵,若我们能通过某种方法找到其合适的稀疏表示,则可以使得学习任务更加简单高效,我们称之为稀疏编码(sparse coding)或字典学习(dictionary learning)。
不妨把数据集D考虑成一个矩阵,其每行对应于一个样本,每列对应于一个特征
- 特征选择所考虑的问题是特征具有“稀疏性”:即矩阵中的许多列与当前学习任务无关,通过特征选择去除这些列,则学习器训练过程仅需在较小的矩阵上进行,学习任务的难度可能有所降低,涉及的计算和存储开销会减少,学得模型的可解释性也会提高.
- 样本稀疏表达:样本矩阵D中存在许多零元素,但不是整行整列的出现。样本拥有这样的稀疏表达形式时,使大多数问题变得线性可分,并且利于存储(稀疏矩阵有很多高效存储方法)。
字典学习 :
给定数据集\(\{x_1,x_2,\dots,x_m\}\),字典学习最简单的形式为:
\(\min_{\mathbf{B},\alpha_1}\sum_{i=1}^m\|x_i-\mathbf{B}\alpha_i\|^2+\lambda\sum_{i=1}^m\|\alpha_i\|_1\)
其中:
- \(\mathbf{B}\in\mathbb{R}^{d\times k}\):字典矩阵
- \(k\) :字典的词汇量,通常由用户指定
- \(\alpha_i\in\mathbb{R}^k\):样本\(x_i\in\mathbb{R}^d\) 的稀疏表示
第一项希望能由\(\alpha_i\)很好地重构\(x_i\),第二项希望\(\alpha_i\)尽量稀疏。
上式的解法可采用变量交替优化的策略:
- 第一步,固定字典\(B\),将上式按分量展开,可参照LASSO的解法求解下式,从而为每个样本\(x_i\)找到相对应的\(a_i\)。
- 第二步,再以\(a_i\)为初值,更新字典\(B\)。
初始化字典矩阵\(B\)之后反复迭代上述两步,最终即可求得字典\(B\)和样本\(x_i\)的稀疏表示 \(\alpha_i\) 。在上述字典学习过程中,用户能通过设置词汇量\(k\)的大小来控制字典的规模,从而影响到稀疏程度。
11.6 压缩感知
关注的是如何利用信号本身所具有的稀疏性,从部分观测样本中恢复原信号,通常压缩感知分为:
- 感知测量(关注如何对原始信号进行处理以获得稀疏样本表示)
- 重构恢复(关注的是如何基于稀疏性从少量观测中恢复原信号,通常压缩感知指的是这部分)两个阶段。
鸢尾花数据集分类任务的特征选择
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets
from sklearn.feature_selection import SelectKBest, chi2, SelectFromModel
from sklearn.svm import LinearSVC
if __name__ == '__main__':
# 加载数据
iris = datasets.load_iris()
# 使用样本的所有特征(150, 4)
x = iris.data
y = iris.target
label_dict = iris.target_names
feature_dict = iris.feature_names
# 数据预处理 - 单变量特征选择, k=2选择最好的两个特征
x_best = SelectKBest(chi2, k=2).fit_transform(x, y)
print('特征选择后的维数', x_best.shape) # (150, 2)
# 基于 L1 的特征选取;在 SVM 和逻辑回归中,参数 C 是用来控制稀疏性的:小的 C 会导致少的特征被选择
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False, max_iter=2000).fit(x, y)
model = SelectFromModel(lsvc, prefit=True)
x_model = model.transform(x)
print('特征选择后的维数', x_model.shape) # (150, 3)
# 单变量特征选择的数据散点图
for label, marker, color in zip(range(0, 3), ('*', 's', 'o'), ('blue', 'red', 'green')):
plt.scatter(x=x_best[y == label][:, 0],
y=x_best[y == label][:, 1],
marker=marker,
color=color,
alpha=0.5,
label='label_{}'.format(label))
plt.title('Iris feature selection')
plt.xlabel('xr', fontsize=14)
plt.ylabel('yr', fontsize=14)
plt.legend(loc='upper right', fancybox=True)
plt.tick_params(labelsize=10)
# plt.show()
# SelectFromModel 选取特征特征绘图
fig = plt.figure()
ax3d = Axes3D(fig, rect=[0, 0, 1, 1], elev=20, azim=20)
ax3d.scatter(x_model[:, 0], x_model[:, 1], x_model[:, 2], c=y, cmap='brg')
plt.show()
单变量特征选择和使用 SelectFromModel 选取特征的标准是不一样的,除了一个坐标轴刻度相同外,其他坐标轴数据不同。即:SelectFromModel 选择的特征不是“最好”的(SelectKBest)