数据的特征工程

特征工程的意义

  • 更好的特征意味着更强的鲁棒性
  • 更好的特征意味着只需用简单模型
  • 更好的特征意味着更好的结果

特征工程之特征处理

特征工程中最重要的一个环节就是特征处理,特征处理包含了很多具体的专业技巧

  • 特征预处理
    • 单个特征
      • 归一化
      • 标准化
      • 缺失值
    • 多个特征
      • 降维
        • PCA

特征工程之特征抽取与特征选择

如果说特征处理其实就是在对已有的数据进行运算达到我们目标的数据标准。特征抽取则是将任意数据格式(例如文本和图像)转换为机器学习的数字特征。而特征选择是在已有的特征中选择更好的特征。后面会详细介绍特征选择主要区别于降维。

数据的来源与类型

大部分的数据都来自已有的数据库,如果没有的话也可以交给很多爬虫工程师去采集,来提供。也可以来自平时的记录,反正数据无处不在,大都是可用的。

数据的类型

按照机器学习的数据分类我们可以将数据分成:

  • 标称型:标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类)
  • 数值型:数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析)

按照数据的本身分布特性

  • 离散型
  • 连续型

那么什么是离散型和连续型数据呢?首先连续型数据是有规律的,离散型数据是没有规律的

  • 离散变量是指其数值只能用自然数或整数单位计算的则为离散变量.例如,班级人数、进球个数、是否是某个类别等等

  • 连续型数据是指在指定区间内可以是任意一个数值,例如,票房数据、花瓣大小分布数据

数据的特征预处理

字典特征抽取

  作用:对字典数据进行特征值化 

  类:sklearn.feature_extraction.DictVectorizer

DictVectorizer语法

  DictVectorizer(sparse=True,…)

    DictVectorizer.fit_transform(X)

      X:字典或者包含字典的迭代器

      返回值:返回sparse矩阵

    DictVectorizer.inverse_transform(X)

      X:array数组或者sparse矩阵

      返回值:转换之前数据格式

    DictVectorizer.get_feature_names()

      返回类别名称

    DictVectorizer.transform(X)

      按照原先的标准转换

流程

  1.实例化类DictVectorizer

  2.调用fit_transform方法输入数据并转换

from sklearn.feature_extraction import DictVectorizer

def dictvec():
    '''
    字段数据抽取
    :return:  None
    '''
    # dict = DictVectorizer()
    dict = DictVectorizer(sparse=False)
    # 调用fit_transform
    data = dict.fit_transform([
        {'city': '北京', 'temperature': 100},
        {'city': '上海', 'temperature': 60},
        {'city': '深圳', 'temperature': 30}, ]
    )
    print(data)
    print(dict.get_feature_names())
    print(dict.inverse_transform(data))

if __name__ == '__main__':
    dictvec()


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

  

文本特征抽取

  作用:对文本数据进行特征值化

  类:sklearn.feature_extraction.text.CountVectorizer

CountVectorizer语法

  CountVectorizer(max_df=1.0,min_df=1,…)

  返回词频矩阵   

    CountVectorizer.fit_transform(X,y)
      X:文本或者包含文本字符串的可迭代对象
      返回值:返回sparse矩阵
    CountVectorizer.inverse_transform(X)
      X:array数组或者sparse矩阵
      返回值:转换之前数据格式
    CountVectorizer.get_feature_names()
      返回值:单词列表

流程

  1.实例化类CountVectorizer

  2.调用fit_transform方法输入数据并转换   注意返回格式,利用toarray()进行sparse矩阵转换array数组

from sklearn.feature_extraction.text import CountVectorizer

def countcev():
    '''
    对文本数据的特征值化
    :return:  None
    '''
    cv = CountVectorizer()
    data = cv.fit_transform(['lift is short is, i like python', 'lift is too long,i dislike python'])
    print(cv.get_feature_names())
    print(cv.inverse_transform(data))
    print(data.toarray())
    return None


if __name__ == '__main__':
    countcev()

# 结果
['dislike', 'is', 'lift', 'like', 'long', 'python', 'short', 'too']
[array(['python', 'like', 'short', 'is', 'lift'], dtype='<U7'), array(['dislike', 'long', 'too', 'python', 'is', 'lift'], dtype='<U7')]
[[0 2 1 1 0 1 1 0]
 [1 1 1 0 1 1 0 1]]

中文的文本处理

from sklearn.feature_extraction.text import CountVectorizer
import jieba

def hanzivec():
    '''
    中文特征值化
    :return: pass
    '''

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

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

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

    content1 = list(cot1)
    content2 = list(cot2)
    content3 = list(cot3)

    ct1 = ' '.join(content1)
    ct2 = ' '.join(content2)
    ct3 = ' '.join(content3)

    print(ct1)
    print(ct2)
    print(ct3)
    cv = CountVectorizer()
    data = cv.fit_transform([ct1, ct2, ct3])
    # data = cv.fit_transform(['lift is short is, i like python', 'lift is too long,i dislike python'])
    # data = cv.fit_transform(['今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。', '我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。', '如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的'])
    # print(cv.inverse_transform(data))
    print(cv.get_feature_names())
    print(data.toarray())
    return None

if __name__ == '__main__':
    hanzivec()


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

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

  类:sklearn.feature_extraction.text.TfidfVectorizer

TfidfVectorizer语法  

  TfidfVectorizer(stop_words=None,…)

  返回词频权重矩阵     

    TfidfVectorizer.fit_transform(X,y) 
      X:文本或者包含文本字符串的可迭代对象
      返回值:返回sparse矩阵
    TfidfVectorizer.inverse_transform(X)
      X:array数组或者sparse矩阵
      返回值:转换之前数据格式
    TfidfVectorizer.get_feature_names()
      返回值:单词列表

流程

  1.实例化类TfidfVectorizer

  2.调用fit_transform方法输入数据并转换

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer

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

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

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

    content1 = list(cot1)
    content2 = list(cot2)
    content3 = list(cot3)

    ct1 = ' '.join(content1)
    ct2 = ' '.join(content2)
    ct3 = ' '.join(content3)

    tf = TfidfVectorizer()
    data = tf.fit_transform([ct1, ct2, ct3])
    print(tf.get_feature_names())
    print(data.toarray())

if __name__ == '__main__':
    tfidfver()

# 结果
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']
[[0.         0.         0.21821789 0.         0.         0.
  0.43643578 0.         0.         0.         0.         0.
  0.21821789 0.         0.21821789 0.         0.         0.
  0.         0.21821789 0.21821789 0.         0.43643578 0.
  0.21821789 0.         0.43643578 0.21821789 0.         0.
  0.         0.21821789 0.21821789 0.         0.         0.        ]
 [0.         0.         0.         0.2410822  0.         0.
  0.         0.2410822  0.2410822  0.2410822  0.         0.
  0.         0.         0.         0.         0.         0.2410822
  0.55004769 0.         0.         0.         0.         0.2410822
  0.         0.         0.         0.         0.48216441 0.
  0.         0.         0.         0.         0.2410822  0.2410822 ]
 [0.15698297 0.15698297 0.         0.         0.62793188 0.47094891
  0.         0.         0.         0.         0.15698297 0.15698297
  0.         0.15698297 0.         0.15698297 0.15698297 0.
  0.1193896  0.         0.         0.15698297 0.         0.
  0.         0.15698297 0.         0.         0.         0.31396594
  0.15698297 0.         0.         0.15698297 0.         0.        ]]

数据的特征处理

 

from sklearn.preprocessing import MinMaxScaler

def minmax():
    mm = MinMaxScaler()
    # mm = MinMaxScaler(feature_range=(2, 3))
    data = mm.fit_transform([[90, 2, 10, 40],
                             [60, 4, 15, 45],
                             [75, 3, 13, 46]]
                            )
    print(data)

if __name__ == '__main__':
    minmax()


# 结果
[[1.         0.         0.         0.        ]
 [0.         1.         1.         0.83333333]
 [0.5        0.5        0.6        1.        ]]

from sklearn.preprocessing import MinMaxScaler, StandardScaler

def standard():
    st = StandardScaler()
    data = st.fit_transform([[90, 2, 10, 40],
                             [60, 4, 15, 45],
                             [75, 3, 13, 46]])
    print(data)
    print(st.mean_)
    print(st.var_)


if __name__ == '__main__':
    standard()

# 结果
[[ 1.22474487 -1.22474487 -1.29777137 -1.3970014 ]
 [-1.22474487  1.22474487  1.13554995  0.50800051]
 [ 0.          0.          0.16222142  0.88900089]]
[75.          3.         12.66666667 43.66666667]
[150.           0.66666667   4.22222222   6.88888889]

缺失值

由于各种原因,许多现实世界的数据集包含缺少的值,通常编码为空白,NaN或其他占位符。然而,这样的数据集与scikit的分类器不兼容,它们假设数组中的所有值都是数字,并且都具有和保持含义。使用不完整数据集的基本策略是丢弃包含缺失值的整个行和/或列。然而,这是以丢失可能是有价值的数据(即使不完整)的代价。更好的策略是估算缺失值,即从已知部分的数据中推断它们。

class Imputer(sklearn.base.BaseEstimator, sklearn.base.TransformerMixin)
    """
    用于完成缺失值的补充

    :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,则沿行排列

  

from sklearn.preprocessing import Imputer

def im():
    """
    缺失值处理
    :return:NOne
    """
    # NaN, nan
    im = Imputer(missing_values='NaN', strategy='mean', axis=0)

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

    print(data)

    return None

if __name__ == "__main__":
    im()

# 结果
[[1. 2.]
[4. 3.]
 [7. 6.]]

降维

删除低方差特征

 

from sklearn.feature_selection import VarianceThreshold


def var():
    """
    特征选择-删除低方差的特征
    :return: None
    """
    var = VarianceThreshold(threshold=1.0)

    data = var.fit_transform([[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]])

    print(data)
    return None


if __name__ == "__main__":
    var()


# 结果
[[0]
 [4]
 [1]]

 

PCA 

PCA(Principal component analysis),主成分分析。特点是保存数据集中对方差影响最大的那些特征,PCA极其容易受到数据中特征范围影响,所以在运用PCA前一定要做特征标准化,这样才能保证每维度特征的重要性等同。

clclass 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算法来降维,一般来说,使用默认值就够了。

  

from sklearn.decomposition import PCA


def pca():
    """
    主成分分析进行特征降维
    :return: None
    """
    pca = PCA(n_components=0.9)
    # n_components=0.9 保留90%的特征

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

    print(data)

    return None


if __name__ == "__main__":
    pca()


# 结果
[[ 1.28620952e-15  3.82970843e+00]
 [ 5.74456265e+00 -1.91485422e+00]
 [-5.74456265e+00 -1.91485422e+00]]

  

原文地址:https://www.cnblogs.com/yoyo1216/p/10183280.html