特征工程

特征工程是将原始数据转换为更好地代表预测模型的潜在问题的特征的过程,从而提高了对未知数据的模型准确性

数据抽取

字典抽取
sklearn.feature_extraction.DictVectorizer(sparse = True)

将映射列表转换为Numpy数组或scipy.sparse矩阵

  • sparse 是否转换为scipy.sparse矩阵表示,默认开启

方法

fit_transform(X,y)
应用并转化映射列表X,y为目标类型

inverse_transform(X[, dict_type])
将Numpy数组或scipy.sparse矩阵转换为映射列表

get_feature_names()
返回类别标签名称

transform(X)
按照原先的标准转换

from sklearn.feature_extraction import DictVectorizer
# 实例化
dict = DictVectorizer(sparse=False)

# 调用fit_transform
data = dict.fit_transform([{'city': '北京','temperature': 100}, 
                           {'city': '上海','temperature':60}, 
                           {'city': '深圳','temperature': 30}])

print(dict.get_feature_names())   

print(data)

print(dict.inverse_transform(data))

运行结果

['city=上海', 'city=北京', 'city=深圳', 'temperature']
[[  0.   1.   0. 100.]
 [  1.   0.   0.  60.]
 [  0.   0.   1.  30.]]
[{'city=北京': 1.0, 'temperature': 100.0}, {'city=上海': 1.0, 'temperature': 60.0}, {'city=深圳': 1.0, 'temperature': 30.0}]

会把字典中值为非数字也就是字符串类型的展开,形成多个类别(将字典中值为文字的部分展开为键值配对形式,有几种值就增加几个特征)-one-hot编码:没有顺序价值,用来标记是否

文本特征抽取-count

count对于所有的词进行统计,没办法确定那个词比较重要

sklearn.feature_extraction.text.CountVectorizer(max_df=1.0,min_df=1,…)

将文本文档的集合转换为计数矩阵(scipy.sparse matrices)

方法

fit_transform(raw_documents,y)
学习词汇词典并返回词汇文档矩阵
对于有空格的文章来说可以直接使用

from sklearn.feature_extraction.text import CountVectorizer
#对文本进行特征值化

cv = CountVectorizer()

data = cv.fit_transform(["人生 苦短,我 喜欢 python", "人生漫长,不用 python"])
# 单个词不会体现,因为没有分析价值
print(cv.get_feature_names())

print(data.toarray())  #需要toarray()方法转变为numpy的数组形式

运行结果

['python', '不用', '人生', '人生漫长', '喜欢', '苦短']
[[1 0 1 0 1 1]
 [1 1 0 1 0 0]]

按照空格切分每个单词,单个词不会体现,因为没有分析价值

对于中文类型的,没有空格分隔词语的,需要使用jieba

import jieba
def cutword():

    con1 = jieba.cut("今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。")

    con2 = jieba.cut("我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。")

    con3 = jieba.cut("如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。")

    # 转换成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)

    # 吧列表转换成字符串
    c1 = ' '.join(content1)
    c2 = ' '.join(content2)
    c3 = ' '.join(content3)

    return c1, c2, c3


def hanzivec():
    """
    中文特征值化
    :return: None
    """
    c1, c2, c3 = cutword()

    print(c1, c2, c3)

    cv = CountVectorizer()

    data = cv.fit_transform([c1, c2, c3])

    print(cv.get_feature_names())

    print(data.toarray())

    return None

hanzivec()

运行结果

今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。 我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。 如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']
[[0 0 1 0 0 0 2 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 2 0 1 0 2 1 0 0 0 1 1 0 0 0]
 [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 1 1]
 [1 1 0 0 4 3 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0]]
文本特征抽取-TF-IDF

tf:term frequency :词的频率 计算出现的次数
idf:inverse document frequency:逆文档频率 log(总文档数/该词出现的文档数量)-数值越小,结果越小

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。

sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None,…)

返回词的权重矩阵

方法

fit_transform(raw_documents,y)
文本或者包含文本字符串的可迭代对象,返回术语文档矩阵。sparse矩阵

inverse_transform(X)
X:array数组或者sparse矩阵,转换之前数据格式

get_feature_names()
返回值:单词列表

from sklearn.feature_extraction.text import TfidfVectorizer
content = ["life is short,i like python","life is too long,i dislike python"]
vectorizer = TfidfVectorizer(stop_words='english')
# stop_words='english' 将英文中的无意义单词去除
print(vectorizer.fit_transform(content).toarray())
print(vectorizer.vocabulary_)
print(vectorizer.get_feature_names())

返回结果

[[0.         0.40993715 0.57615236 0.         0.40993715 0.57615236]
 [0.57615236 0.40993715 0.         0.57615236 0.40993715 0.        ]]
{'life': 1, 'short': 5, 'like': 2, 'python': 4, 'long': 3, 'dislike': 0}
['dislike', 'life', 'like', 'long', 'python', 'short']

特征预处理

单个特征

(1)归一化
归一化首先在特征(维度)非常多的时候,可以防止某一维或某几维对数据影响过大,也是为了把不同来源的数据统一到一个参考区间下,这样比较起来才有意义,其次可以程序可以运行更快

min-max方法
常用的方法是通过对原始数据进行线性变换把数据映射到[0,1]之间,变换的函数为:
X ′ = X − m i n m a x − m i n X' = \frac{X - min}{max - min} X=maxminXmin
其中 m i n min min是样本中最小值, m a x max max是样本中最大值

缺点 :最大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景。

  • min-max的scikit-learn处理
from sklearn import preprocessing
import numpy as np
X_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])
min_max_scaler = preprocessing.MinMaxScaler()
X_train_minmax = min_max_scaler.fit_transform(X_train)
X_train_minmax

运行结果

array([[0.5       , 0.        , 1.        ],
       [1.        , 0.5       , 0.33333333],
       [0.        , 1.        , 0.        ]])

(2)标准化
常用的方法是z-score标准化,经过处理后的数据均值为0,标准差为1,处理方法是:
X ′ = x − μ σ X' = \frac{x-\mu }{\sigma } X=σxμ
σ = s t d \sigma = \sqrt{std} σ=std
s t d = ( x 1 − μ ) 2 + ( x 2 − μ ) 2 + . . . n std = \frac{(x1-\mu)^2+(x2-\mu)^2+...}{n} std=n(x1μ)2+(x2μ)2+...
其中 μ \mu μ是样本的均值, σ \sigma σ是样本的标准差, n n n是每个特征的样本数
在已有的样本足够多的情况下比较稳定,适合嘈杂的数据场景

  • sklearn中提供了StandardScalar类实现列标准化:
import numpy as np
from sklearn.preprocessing import StandardScaler
X_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])
std = StandardScaler()
X_train_std = std.fit_transform(X_train)
X_train_std

运行结果

array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])

对于归一化来说:如果出现异常点,影响了最大值和最小值,那么结果显然会发生改变
对于标准化来说:如果出现异常点,由于具有一定数据量,少量的异常点对于平均值的影响并不大,从而方差改变较小。

(3)缺失值

  • 填充缺失值 使用sklearn.preprocessing中的Imputer类进行数据的填充
Imputer(missing_values='NaN', strategy='mean', axis=0)
    """
    用于完成缺失值的补充

    :param param missing_values: integer or "NaN", optional (default="NaN")
        丢失值的占位符,对于编码为np.nan的缺失值,使用字符串值“NaN”

    :param strategy: string, optional (default="mean")
        插补策略
        如果是“平均值”,则使用沿轴的平均值替换缺失值
        如果为“中位数”,则使用沿轴的中位数替换缺失值
        如果“most_frequent”,则使用沿轴最频繁的值替换缺失

    :param axis: integer, optional (default=0)
        插补的轴
        如果axis = 0,则沿列排列
        如果axis = 1,则沿行排列
    """

方法
Imputer.fit_transform(X,y)
X:numpy array格式的数据[n_samples,n_features],返回值:转换后的形状相同的array

import numpy as np
from sklearn.preprocessing import Imputer

# NaN, nan
im = Imputer(missing_values='NaN', strategy='mean', axis=0)

data = im.fit_transform([[1, 2], [np.nan, 3], [7, 6]])

print(data)

运行结果

[[1. 2.]
 [4. 3.]
 [7. 6.]]
  • 删除
    如果每列或者行数据缺失值达到一定的比例,建议放弃整行或者整列
多个特征 - 降维

特征选择
特征选择就是单纯地从提取到的所有特征中选择部分特征作为训练集特征,特征在选择前和选择后可以改变值、也不改变值,但是选择后的特征维数肯定比选择前小,毕竟我们只选择了其中的一部分特征。
特征选择标准:
- 冗余:部分特征的相关度高,容易消耗计算性能
- 噪声:部分特征对预测结果有负影响

主要方法(三大武器):

  • Filter(过滤式):Variance(方差)Threshold
  • Embedded(嵌入式):正则化、决策树
  • Wrapper(包裹式)

VarianceThreshold 是特征选择中的一项基本方法。它会移除所有方差不满足阈值的特征。默认设置下,它将移除所有方差为0的特征,即那些在所有样本中数值完全相同的特征。

sklearn.feature_selection
去掉取值变化小的特征(删除低方差特征)
假设我们要移除那些超过80%的数据都为1或0的特征

from sklearn.feature_selection import VarianceThreshold
X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
sel.fit_transform(X)

运行结果

array([[0, 1],
       [1, 0],
       [0, 0],
       [1, 1],
       [1, 0],
       [1, 1]])

主成分分析(PCA)
目的:数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
作用:可以削减回归分析或者聚类分析中特征的数量

class PCA(sklearn.decomposition.base)
   """
   主成成分分析

   :param n_components: int, float, None or string
       这个参数可以帮我们指定希望PCA降维后的特征维度数目。最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于1的整数。
       我们也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)

   :param whiten: bool, optional (default False)
      判断是否进行白化。所谓白化,就是对降维后的数据的每个特征进行归一化。对于PCA降维本身来说一般不需要白化,如果你PCA降维后有后续的数据处理动作,可以考虑白化,默认值是False,即不进行白化

   :param svd_solver:
      选择一个合适的SVD算法来降维,一般来说,使用默认值就够了。
    """
import numpy as np
from sklearn.decomposition import PCA
# 主成分分析进行特征降维e

pca = PCA(n_components=0.9)

data = pca.fit_transform([[2,8,4,5],
                          [6,3,0,8],
                          [5,4,9,1]])

print(data)

运行结果

[[ 1.22879107e-15  3.82970843e+00]
 [ 5.74456265e+00 -1.91485422e+00]
 [-5.74456265e+00 -1.91485422e+00]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值