1、字典学习与稀疏编码
- 简单来说,稀疏编码就是把输入向量(信号)/ 矩阵(图像)表示为稀疏的系数向量和一组超完备基向量(字典)的线性组合。
- 因此,稀疏编码通过上述方式以后,就可以将输入数据重构为稀疏的向量:即向量内部元素满足只有很少的几个非零元素或只有很少的几个远大于零的元素。
- 一般情况下要求超完备基向量的个数k非常大(远大于输入数据的维度n),因为这样的基向量组合才能更容易的学到输入数据内在的结构和特征。
- 为什么要转换为稀疏向量?
1)特征选择(Feature Selection): 直接对原始图像提取的特征很多情况下其实是有冗余成分的,就是说我们只需要关键特征识别就可以,没有必要用那么多特征,更多情况下,那些冗余信息会干扰我们最后的识别结果!而稀疏编码可以实现特征的自动选择,它会学习地去掉这些没有信息的特征,也就是把这些特征对应的权重置为0。
2)可解释性(Interpretability):另一个青睐于稀疏的理由是,模型更容易解释,即只有那几个关键特征会影响最终的结果,更容易解释。例如患某种病的概率是y,然后我们收集到的数据x是1000维的,也就是我们需要寻找这1000种因素到底是怎么影响患上这种病的概率的。通过学习,如果最后学习到的w*就只有很少的非零元素,例如只有5个非零的wi,那么我们就有理由相信,这些对应的特征在患病分析上面提供的信息是巨大的,决策性的。也就是说,患不患这种病只和这5个因素有关,那医生就好分析多了。
2、sklearn的实现
- 通过MiniBatchDictionaryLearning来实现字典学习与稀疏编码
class sklearn.decomposition.MiniBatchDictionaryLearning(n_components=None, *, alpha=1, n_iter='deprecated',
max_iter=None, fit_algorithm='lars', n_jobs=None, batch_size=256, shuffle=True, dict_init=None,
transform_algorithm='omp', transform_n_nonzero_coefs=None, transform_alpha=None, verbose=False,
split_sign=False, random_state=None, positive_code=False, positive_dict=False, transform_max_iter=1000,
callback=None, tol=0.001, max_no_improvement=10)
1)n_components:int, default=None,要提取的字典中每个基向量/atoms的个数,每个基向量的维度应该为输入向量的维度,因此字典的维度应该是(n_components, n_features)
2)alpha:float, default=1,正则化项(Lasso回归项)的权重,用于平衡稀疏性和重构误差
3)n_iter:int, default=1000,迭代的总次数,1.1版本弃用,改用max_iter
4)max_iter:int, default=None,迭代的最大次数(早停策略之前),不为None时,n_iter将被忽略
5)fit_algorithm:{‘lars’, ‘cd’}, default=’lars’,解决优化问题的算法(首先使用fit算法训练出字典), 默认为lars,最小角度回归
6)n_jobs:int, default=None,并行jobs的数量,默认为None,就是1
7)batch_size:int, default=256,每个mini-batch中的样本数量
8)shuffle:bool, default=True,在构建batch之前是否打乱样本
9)dict_init:ndarray of shape (n_components, n_features), default=None,字典的初始化值
10)transform_algorithm:{‘lasso_lars’, ‘lasso_cd’, ‘lars’, ‘omp’, ‘threshold’}, default=’omp’,用于变换数据的算法,即该算法用于学习每个样本的稀疏的系数向量(即稀疏编码的结果),再对原始输入数据进行变换。每个样本的稀疏向量的维度应该等于字典中的基向量的个数,即n_components,因此对输入数据变换后的维度应该是(n_samples,n_components),每个向量都具有稀疏性。
11)transform_n_nonzero_coefs:int, default=None,在解的每一列中非零系数的数目。这只适用于algorithm='lars’和algorithm=‘omp’。如果None,则transform_n_nonzero_coefs=int(n_features / 10)。
12)transform_alpha:float, default=None,如果algorithm='lasso_lars’或algorithm=‘lasso_cd’, alpha是应用于L1范数的惩罚。如果algorithm=‘threshold’, alpha是阈值的绝对值,低于该阈值,系数将被压扁为零。如果为None,默认为alpha。
13)split_sign:bool, default=False,是否将稀疏特征向量拆分为其负部分与正部分的拼接。这可以提高下游分类器的性能。
14)random_state:int, RandomState instance or None, default=None,当dict_init未被指定时,用于初始化字典
15)positive_code:bool, default=False,是否强制编码为正
16)positive_dict:bool, default=False,是否强制字典为正
17)transform_max_iter:int, default=1000,如果algorithm=‘lasso_cd’或’lasso_lars’,执行的最大迭代次数。
-
该类的成员变量:
-
components_是学习到的字典,[n_components, n_features],表示有n_components个基向量/atom,每个基向量的维度等于输入向量的维度
-
该类常用的的方法为:
1、fit(X, y=None)
拟合X中的数据,即学习到shape为[n_components, n_features]的字典
X:待学习/待训练的样本,[n_samples, n_featues]的ndarray
返回MiniBatchDictionaryLearning类实例本身
2、transform(X)
将数据X编码为字典atom/基向量的稀疏组合,返回的就是稀疏编码的结果
X:待编码的样本,[n_samples, n_featues]的ndarray
返回:编码后的结果,[n_samples, n_components]的ndarray,需要先进行fit后学习到字典再进行稀疏编码
3、fit_transform(X)
字典学习+稀疏编码,就是上述两个函数的结合
X:待学习/待训练的样本,[n_samples, n_featues]的ndarray
返回:编码后的结果,[n_samples, n_features_new]的ndarray
3、示例
- 先使用make_sparse_coded_signal构建训练样本X,是由dictionary和code相乘得到的
- 构建字典学习/稀疏编码 dict_learner,学习到的字典为:
- 最后对输入数据进行变换:
import numpy as np
from sklearn.datasets import make_sparse_coded_signal
from sklearn.decomposition import MiniBatchDictionaryLearning
X, dictionary, code = make_sparse_coded_signal(n_samples=100, n_components=300, n_features=20,
n_nonzero_coefs=10, random_state=42)
dict_learner = MiniBatchDictionaryLearning(n_components=300, batch_size=4, transform_algorithm='lasso_lars',
transform_alpha=0.1, random_state=42, shuffle=False)
X_transformed = dict_learner.fit_transform(np.transpose(X))
print(X_transformed)