数据分析过程中,往往需要处理很多类型的数据,数值型和非数值型,无论是在回归问题还是分类问题中,特征工程都是重中之重。
我们都知道,特征值和特征向量在高等数学和线性代数中极为关键,特征工程,从表面上来说,就是从大大小小的数据中,筛选出有意义或者有用的条目,进而转换成一种数学表达,让机器和算法能够理解其中的意义。好比一个班上的每个学生,都有性别、年龄、身高、体重、成绩、性格特点等等特征,年龄、身高、体重、成绩属于数值型的特征,可以直接为我们所用,性别、性格特点属于非数值型特征,需要通过转换才能被算法理解。
python的sklearn包,包含了特征工程常用的工具和api,主要有以下几个方面:
特征抽取
sklearn.feature_extraction:包含了常用的用于特征抽取的api
- DictVectorizer(dtype=<class ‘numpy.float64’>, separator=’=’, sparse=True, sort=True)
通过字典传入抽取特征,用于将标签型或非数值型数据的抽取和转换,sparse参数表示是否转换为稀疏矩阵>>> from sklearn.feature_extraction import DictVectorizer >>> v = DictVectorizer(sparse=False) >>> D = [{'foo': 1, 'bar': 2}, {'foo': 3, 'baz': 1}] >>> X = v.fit_transform(D) >>> X array([[2., 0., 1.], [0., 1., 3.]])
- FeatureHasher(n_features=1048576, input_type=’dict’, dtype=<class ‘numpy.float64’>, alternate_sign=True)
将输入转换为hash矩阵,n_features为特征的列数,也就是特征维数,input_type为输入的python数据类型,通常用于处理特征的维度较大的问题。>>> from sklearn.feature_extraction import FeatureHasher >>> h = FeatureHasher(n_features=10) >>> D = [{'dog': 1, 'cat':2, 'elephant':4},{'dog': 2, 'run': 5}] >>> f = h.transform(D) >>> f.toarray() array([[ 0., 0., -4., -1., 0., 0., 0., 0., 0., 2.], [ 0., 0., 0., -2., -5., 0., 0., 0., 0., 0.]])
- image
从图像中直接抽取特征- image.extract_patches_2d(image, patch_size, max_patches=None, random_state=None)
从二维图像中抽取特征,patch_size为输出的色块或图像块的维度,是一个二维元祖,max_patches表示最大的色块维度,random_state表示当max_patches不为none时,是否采用随机数采样填充色块的值。输出的每个图像块均为一个RGB三通道构成
>>> from sklearn.datasets import load_sample_image >>> from sklearn.feature_extraction import image >>> # Use the array data from the first image in this dataset: >>> one_image = load_sample_image("china.jpg") >>> print('Image shape: {}'.format(one_image.shape)) Image shape: (427, 640, 3) >>> patches = image.extract_patches_2d(one_image, (2, 2)) >>> print('Patches shape: {}'.format(patches.shape)) Patches shape: (272214, 2, 2, 3) >>> # Here are just two of these patches: >>> print(patches[1]) [[[174 201 231] [174 201 231]] [[173 200 230] [173 200 230]]] >>> print(patches[800]) [[[187 214 243] [188 215 244]] [[187 214 243] [188 215 244]]]
- image.grid_to_graph(n_x, n_y, n_z=1, mask=None, return_as=<class ‘scipy.sparse.coo.coo_matrix’>, dtype=<class ‘int’>)
- image.img_to_graph(img, mask=None, return_as=<class ‘scipy.sparse.coo.coo_matrix’>, dtype=None)
图像转换为连通图矩阵 - image.reconstruct_from_patches_2d(patches, image_size)
用图像块矩阵构造图片 - image.PatchExtractor(patch_size=None, max_patches=None, random_state=None)
同extract_patches_2d,用法不同>>> from sklearn.datasets import load_sample_images >>> from sklearn.feature_extraction import image >>> # Use the array data from the second image in this dataset: >>> X = load_sample_images().images[1] >>> print('Image shape: {}'.format(X.shape)) Image shape: (427, 640, 3) >>> pe = image.PatchExtractor(patch_size=(2, 2)) >>> pe_fit = pe.fit(X) >>> pe_trans = pe.transform(X) >>> print('Patches shape: {}'.format(pe_trans.shape)) Patches shape: (545706, 2, 2)
- image.extract_patches_2d(image, patch_size, max_patches=None, random_state=None)
- text
- text.CountVectorizer(input=’content’, encoding=’utf-8’, decode_error=’strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), analyzer=’word’, max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.int64’>)
根据词典,矢量词频统计
>>> from sklearn.feature_extraction.text import CountVectorizer >>> corpus = [ ... 'This is the first document.', ... 'This document is the second document.', ... 'And this is the third one.', ... 'Is this the first document?', ... ] >>> vectorizer = CountVectorizer() >>> X = vectorizer.fit_transform(corpus) >>> print(vectorizer.get_feature_names()) ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this'] >>> print(X.toarray()) [[0 1 1 1 0 0 1 0 1] [0 2 0 1 0 1 1 0 1] [1 0 0 1 1 0 1 1 1] [0 1 1 1 0 0 1 0 1]]
- text.HashingVectorizer(input=’content’, encoding=’utf-8’, decode_error=’strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), analyzer=’word’, n_features=1048576, binary=False, norm=’l2’, alternate_sign=True, dtype=<class ‘numpy.float64’>)
矢量词频统计,词典自动生成
>>> from sklearn.feature_extraction.text import HashingVectorizer >>> corpus = [ ... 'This is the first document.', ... 'This document is the second document.', ... 'And this is the third one.', ... 'Is this the first document?', ... ] >>> vectorizer = HashingVectorizer(n_features=2**4) >>> X = vectorizer.fit_transform(corpus) >>> print(X.shape) (4, 16)
-
text.TfidfTransformer(norm=’l2’, use_idf=True, smooth_idf=True, sublinear_tf=False)
-
text.TfidfVectorizer(input=’content’, encoding=’utf-8’, decode_error=’strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, analyzer=’word’, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.float64’>, norm=’l2’, use_idf=True, smooth_idf=True, sublinear_tf=False)
- text.CountVectorizer(input=’content’, encoding=’utf-8’, decode_error=’strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), analyzer=’word’, max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.int64’>)
特征筛选
sklearn.feature_selection,包含了特征筛选所用的api
-
GenericUnivariateSelect(score_func=, mode=’percentile’, param=1e-05)
单变量筛选器,score_func为评价函数,mode为筛选策略,主要有{‘percentile’, ‘k_best’, ‘fpr’, ‘fdr’, ‘fwe’}几种,具体有什么意义见下文。param筛选策略的参数。>>> from sklearn.datasets import load_breast_cancer >>> from sklearn.feature_selection import GenericUnivariateSelect, chi2 >>> X, y = load_breast_cancer(return_X_y=True) >>> X.shape (569, 30) >>> transformer = GenericUnivariateSelect(chi2, 'k_best', param=20) >>> X_new = transformer.fit_transform(X, y) >>> X_new.shape (569, 20)
评价函数分为以下几种:
- f_classif
方差分析中f值,也就是通常说的F检验,主要用于判断两个样本之间方差是否存在明显差异,主要用于特征对类别(标记)的分类任务中。 - mutual_info_classif
变量和目标值之间的互信息,用于分类任务,计算公式如下。互信息是一种有用的信息度量,它可以看成是一个随机变量中包含的关于另一个随机变量的信息量,或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性。
- chi2
卡方检验,主要用于分类任务中。 - f_regression
特征和类别(标记)的F值,主要用于回归分析。 - mutual_info_regression
互信息,用于目标值为连续变量(非标记或类别)的分类任务。
- f_classif
-
SelectPercentile(score_func=, percentile=10)
基于评价函数结果的百分位数来筛选特征,score_func为评价函数,percentile是百分比。例如选择卡方检验,选择10百分数,则输出结果会筛选出卡方检验值的前10%的特征作出输出特征。>>> from sklearn.datasets import load_digits >>> from sklearn.feature_selection import SelectPercentile, chi2 >>> X, y = load_digits(return_X_y=True) >>> X.shape (1797, 64) >>> X_new = SelectPercentile(chi2, percentile=10).fit_transform(X, y) >>> X_new.shape (1797, 7)
-
SelectKBest(score_func=, k=10)
基于评价函数结果筛选出最高的前K个特征 -
SelectFpr(score_func=, alpha=0.05)
基于特征的假正率测试,筛选特征。假正率=被模型预测为正的负样本/(被模型预测为正的负样本+被模型预测为负的负样本),具体如下,主要用于二分类任务。score_func为评价函数,默认为f_classif,alpha评价函数的p值的上限值。预正 预负 实正 真正(TP) 假负(FN) 实负 假正(FP) 正负(TN)) - True Positive Rate(真正率 , TPR)或灵敏度(sensitivity)
TPR = TP /(TP + FN)
正样本预测结果数 / 正样本实际数 - True Negative Rate(真负率 , TNR)或特指度(specificity)
TNR = TN /(TN + FP)
负样本预测结果数 / 负样本实际数 - False Positive Rate (假正率, FPR)
FPR = FP /(FP + TN)
被预测为正的负样本结果数 /负样本实际数 - False Negative Rate(假负率 , FNR)
FNR = FN /(TP + FN)
被预测为负的正样本结果数 / 正样本实际数
- True Positive Rate(真正率 , TPR)或灵敏度(sensitivity)
-
SelectFdr(score_func=, alpha=0.05)
基于错误发现率(fdr)进行特征筛选,定义是错误拒绝(拒绝真的原假设)的个数占所有被拒绝的原假设个数的比例的期望值。通俗一点理解,就是实际为负的那部分样本中,通过特征计算得出的为负的样本所占的比例。alpha为p值的上限值。同样用于二分类任务。 -
SelectFwe(score_func=, alpha=0.05)
基于总Ⅰ型错误率筛选特征,关于FDR和FWE的知识,可参考链接 -
SelectFromModel(estimator, threshold=None, prefit=False, norm_order=1, max_features=None)
基于模型选择特征,简单理解就是先采用模型对每个特征进行一次分类或回归任务,通过错误率或者误差筛选特征,estimator为评价器,也就是回归或分类模型,必须带有特征权重feature_importances_或者系数coef_;threshold为阈值,特征的权重大于或等于阈值的将会保留,否则就会被剔除;prefit是否直接fit筛选器;norm_order:规定的系数的个数;max_features=最大筛选特征量。 -
RFE(estimator, n_features_to_select=None, step=1, verbose=0)
递归筛选特征,给定一个带权重或系数的评价器,RFE会对权重进行排序,首先对所有特征进行评价计算,进行迭代计算,每次迭代计算筛选出step个权重或系数最小的特征,直到剩余的特征数等于n_features_to_select。verbose用于是否输出过程。>>> from sklearn.datasets import make_friedman1 >>> from sklearn.feature_selection import RFE >>> from sklearn.svm import SVR >>> X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) >>> estimator = SVR(kernel="linear") >>> selector = RFE(estimator, 5, step=1) >>> selector = selector.fit(X, y) >>> selector.support_ array([ True, True, True, True, True, False, False, False, False, False]) >>> selector.ranking_ array([1, 1, 1, 1, 1, 6, 4, 3, 2, 5])
-
RFECV(estimator, step=1, min_features_to_select=1, cv=’warn’, scoring=None, verbose=0, n_jobs=None)
同RFE,加入了交叉验证的过程。 -
VarianceThreshold(threshold=0.0)
方差阈值筛选,threshold是方差的阈值