特征工程之特征提取

特征提取即将任意数据(如文本或图像)转换为可用于机器学习的数字特征
:特征值化是为了计算机更好的去理解数据

  • 字典特征提取(特征离散化)
  • 文本特征提取
  • 图像特征提取(深度学习将介绍)

特征提取API

sklearn.feature_extraction

应用DictVectorizer实现对类别特征进行数值化、离散化

  • sklearn.feature_extraction.DictVectorizer(sparse=True,...)
    • DictVectorizer.fit_transform(X), X : 字典或者包含字典的迭代器,返回值:返回sparse矩阵
    • DictVectorizer.inverse_transform(X): X : array数组或者sparse矩阵 返回值:转换之前数据格式
    • DictVectorizer.get_feature_names() 返回类别名称

应用

我们对以下数据进行特征提取

data = [
    {'city': '北京', 'value' : 150},
    {'city': '浙江', 'value': 10},
    {'city': '上海', 'value': 50}
]

流程分析

  • 实例化类 DictVectorizer
  • 调用 fit_transform 方法输入数据并转化 (注意返回格式)
from  sklearn.feature_extraction import DictVectorizer


if __name__ == '__main__':
    data = [
        {'city': '北京', 'value' : 150},
        {'city': '浙江', 'value': 10},
        {'city': '上海', 'value': 50}
    ]

    # 示例化一个转化器类
    transfer = DictVectorizer(sparse=False)
    # 调用 transfer.fit_transform
    data = transfer.fit_transform(data)
    print('返回结果为:', data)
    # 输出特征名字
    print('特征名字为:', transfer.get_feature_names())


# 输出结果为
'''
返回结果为: [[  0.   1.   0. 150.]
 [  0.   0.   1.  10.]
 [  1.   0.   0.  50.]]
特征名字为: ['city=上海', 'city=北京', 'city=浙江', 'value']
'''

注意观察没有加上 sparse=False 参数的结果

from  sklearn.feature_extraction import DictVectorizer


if __name__ == '__main__':
    data = [
        {'city': '北京', 'value' : 150},
        {'city': '浙江', 'value': 10},
        {'city': '上海', 'value': 50}
    ]

    # 示例化一个转化器类
    transfer = DictVectorizer()
    # 调用 transfer.fit_transform
    data = transfer.fit_transform(data)
    print('返回结果为:', data)
    # 输出特征名字
    print('特征名字为:', transfer.get_feature_names())


# 输出结果为
'''
返回结果为:   (0, 1)	1.0
  (0, 3)	150.0
  (1, 2)	1.0
  (1, 3)	10.0
  (2, 0)	1.0
  (2, 3)	50.0
特征名字为: ['city=上海', 'city=北京', 'city=浙江', 'value']
'''

可以看到没有加上 sparse=False 参数的结果为 sparse 矩阵,sparse 稀疏,将非零值 按位置表示出来,可以节省内存,提高加载效果

应用CountVectorizer实现对文本特征进行数值化

  • sklearn.feature_extraction.text.CountVectorizer(stop_words=[])
    • 返回词频矩阵
    • stop_words 参数表示停用的词
  • CountVectorizer.fit_transform(X)
    • X:文本或者包含文本字符串的可迭代对象
    • 返回值:返回sparse矩阵
  • CountVectorizer.inverse_transform(X)
    • X : array数组或者sparse矩阵
    • 返回值:转换之前数据格
  • CountVectorizer.get_feature_names()
    • 返回值:单词列表
  • sklearn.feature_extraction.text.TfidfVectorizer

应用

我们对以下数据进行特征提取

data = [
    'Everyone is fighting their own battle.', 
    'To be free from their past.', 
    'To live in their present.',
    'And to create their future.'
]

流程分析

  • 实例化类 CountVectorizer
  • 调用 fit_transform 方法输入数据并转化 (注意返回格式,利用 toarray() 进行 sparse 矩阵转化为 array 数组)
from  sklearn.feature_extraction.text import CountVectorizer 


if __name__ == '__main__':
    data = [
        'Everyone is fighting their own battle.',
        'To be free from their past.',
        'To live in their present.',
        'And to create their future.'
    ]

    # 示例化一个转化器类
    transfer = CountVectorizer()
    # 调用 transfer.fit_transform
    data_new = transfer.fit_transform(data)
    print('返回结果为:', data_new.toarray())
    # 输出特征名字
    print('特征名字为:', transfer.get_feature_names())

# 输出结果为
'''
返回结果为: [[0 1 0 0 1 1 0 0 0 0 1 0 1 0 0 1 0]
 [0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 1]
 [0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1]
 [1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1]]
特征名字为: ['and', 'battle', 'be', 'create', 'everyone', 'fighting', 'free', 'from', 'future', 'in', 'is', 'live', 'own', 'past', 'present', 'their', 'to']
'''

然而,当文本为中文时,由于每个字之间没有空格,所以在面对中文文本的时候,我们需要先进行分词:

jieba 分词处理

  • jieba.cut()
    • 返回词语组成的生成器

需要安装 jieba

pip install jieba

案例分析

我们对python 之禅 进行特征提取

data = [
    '优美胜于丑陋(Python以编写优美的代码为目标)',
    '明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
    '简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
    '复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
    '扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
    '间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
    '可读性很重要(优美的代码是可读的)',
    '即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
    '不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
    '当存在多种可能,不要尝试去猜测',
    '而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
    '做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
    '如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
    '命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
]
  • 分析
    • 准备句子,利用 jieba.cut 进行分词
    • 实例化 CountVectorizer
    • 将分词结果变成字符串当作fit_transform的输入值
import jieba
from sklearn.feature_extraction.text import CountVectorizer


def cut_word(text):
    return ' '.join(list(jieba.cut(text)))


if __name__ == '__main__':
    data = [
        '优美胜于丑陋(Python以编写优美的代码为目标)',
        '明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
        '简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
        '复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
        '扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
        '间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
        '可读性很重要(优美的代码是可读的)',
        '即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
        '不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
        '当存在多种可能,不要尝试去猜测',
        '而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
        '做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
        '如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
        '命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
    ]
    data_new = [cut_word(sent) for sent in data]
    # print(data_new)
    # 示例化一个转化器类
    transfer = CountVectorizer(stop_words=['except', 'pass', '(', ')'])
    # 调用 transfer.fit_transform
    data_final = transfer.fit_transform(data)
    print('返回结果为:', data_final.toarray())
    # 输出特征名字
    print('特征名字为:', transfer.get_feature_names())

应用TfidfVectorizer实现对文本特征进行数值化

Tf-idf文本特征提取

  • TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
  • TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。

公式

  • 词频(term frequency,tf)指的是某一个给定的词语在该文件中出现的频率
  • 逆向文档频率(inverse document frequency,idf)是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到
  • tfidf = tf * idf
  • 最终结果可以理解为重要程度

API

  • sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None,...)
    • 返回词的权重矩阵
  • TfidfVectorizer.fit_transform(X)
    • X:文本或者包含文本字符串的可迭代对象
    • 返回值:返回sparse矩阵
  • TfidfVectorizer.inverse_transform(X)
    • X : array数组或者sparse矩阵
    • 返回值:转换之前数据格式
  • TfidfVectorizer.get_feature_names()
    • 返回值:单词列表
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer


def cut_word(text):
    return ' '.join(list(jieba.cut(text)))


if __name__ == '__main__':
    data = [
        '优美胜于丑陋(Python以编写优美的代码为目标)',
        '明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
        '简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
        '复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
        '扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
        '间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
        '可读性很重要(优美的代码是可读的)',
        '即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
        '不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
        '当存在多种可能,不要尝试去猜测',
        '而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
        '做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
        '如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
        '命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
    ]
    data_new = [cut_word(sent) for sent in data]
    # print(data_new)
    # 示例化一个转化器类
    transfer = TfidfVectorizer(stop_words=['except', 'pass', '(', ')'])
    # 调用 transfer.fit_transform
    data_final = transfer.fit_transform(data)
    print('返回结果为:', data_final.toarray())
    # 输出特征名字
    print('特征名字为:', transfer.get_feature_names())

Tf-idf 的重要性

分类机器学习算法进行文章分类中前期数据处理方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏安   

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值