机器学习(1)--特征工程之特征抽取

本文介绍了机器学习中的特征工程,特别是特征抽取的重要性。讲解了如何使用Pandas处理数据,以及scikit-learn中的DictVectorizer和CountVectorizer进行特征抽取。还探讨了文本特征抽取,包括CountVectorizer对文本的词频统计和TfidfVectorizer的TF-IDF计算,以及处理中文文本的预处理步骤,如使用jieba分词。

三者关系:人工智能>机器学习>深度学习

机器学习:

机器学习是从数据中自动分析获得规律(模型),并利用规律对未知数据进行预测

机器学习的数据:文件csv(mysql有性能瓶颈,读取速度慢,格式不符合机器学习所要求的格式)

Pandas:读取工具

数据集结构:

可用数据集

1. Kaggle

特点:

1)大数据竞赛平台            

2)80万科学家              

3)真实数据              

4)数据量巨大

2. UCI

特点:

1)收录了360个数据集              

2)覆盖科学、生活、经济等领域                        

3)数据量几十万

3. scikit-learn

特点:

1)数据量较小              

2)方便学习

常用数据集结构的结构组成

特征值+目标值

数据处理工具

Pandas:一个数据读取非常方便以及基本的处理格式的工具

sklearn:对于特征的处理提供了强大的接口

特征工程

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

包括三大内容:特征抽取,特征预处理和降维

一、特征抽取

目的:将字典、文本或字符串等其他类型的数据转化成数字类型的数据(特征值化)

sklearn特征抽取API:sklearn.feature_extraction

1. 字典特征抽取:sklearn.feature_extraction.DictVectorizer(类,使用需要实例化)

DictVectorizer语法:

1)DictVectorizer.fit_transform(X)      

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

       返回值:返回sparse矩阵,X指sparse参数,其默认为True

2)DictVectorizer.inverse_transform(X)

        X:array数组或者sparse矩阵

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

3)DictVectorizer.get_feature_names()

         返回类别名称

4)DictVectorizer.transform(X)

          按照原先的标准转换

字典特征提取流程:

1)实例化类DictVectorizer

2)调用fit_transform方法输入数据并转换(注意返回格式)

from sklearn.feature_extraction import DictVectorizer


def dictvec():
    """
    字典数据抽取
    :return:None
    “”“
    #实例化
    dict = DictVectorizer()

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

    return None
   
if __name__ == "__main__":
    dictvec()

结果显示:

默认转换为sparse矩阵:节约内存,方便读取处理

将sparse参数=False,转换格式将转变为ndarray二维数组

 

sparse矩阵:只显示值和其位置

ndarray二维数组:空值也会显示

调用DictVectorizer.get_feature_names()

from sklearn.feature_extraction import DictVectorizer


def dictvec():
    """
    字典数据抽取
    :return:None
    “”“
    #实例化
    dict = DictVectorizer()

    #调用fit_transform
    data = dict.fit_transform({'city':'北京',‘temperature’: 100}, {'city': '上海', ‘temperature’: 60}, {'city': '深圳', 'temperature': 30})
    #返回类别名称
    print(dict.get_feature_names())  

    print(data)

    return None
   
if __name__ == "__main__":
    dictvec()

结果显示:

可见,对于类别城市这一类别特征,二维数组第一行代表北京那条数据,前三列代表城市的三种类别,为0则这条数据不是这一城市的, 为1则代表是这个城市的,对于已是数值型的数据,不会转换,第四列就代表这条数据的temperature是多少,既这个城市的温度是多少。 

由此可以看出字典特征提取是把字典中一些类别数据,分别进行转换成特征,已是数值的不会转换

*如果遇到数组形式的数据且有类别的这些特征(像是城市类别),将其转换为字典类型再进行转换

*对于结果没有影响的特征可以人为直接删除

调用DictVectorizer.inverse_transform(X)

结果显示:

One-hot编码

上述打印的ndarray二维数组的前边0,1部分,也就是前三列,使用的one-hot编码

目的: 

2. 文本特征抽取:sklearn.feature_extraction.text.CountVectorizer(类,使用需要实例化)

目的:对文本数据进行特征化

CountVectorizer语法:(无参数)

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

           返回词频矩阵

2)CountVectorizer.fit_transform(X,y)      

            X:文本或者包含文本字符串的可迭代对象

            返回值:返回sparse矩阵

3)CountVectorizer.inverse_transform(X)

             X:array数组或者sparse矩阵

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

4)CountVectorizer.get_feature_names()

              返回值:单词列表      

文本特征抽取流程:

1)实例化类CountVectorizer

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

(注意返回格式,利用toarray()进行sparse矩阵转换array数组)

from sklearn.feature_extraction.text import CountVectorizer


def countvec():
    """
    对文本进行特征化
    :return None
    """
    cv = CountVectorizer()##括号里可以加一些参数设定,设定特征化的原则
    data = cv.fit_transform(["life is short, i like python", "life is too long, i dislike python"])##用列表表示文本,列表里的一个元素代表一个文本

    print(data)

    return None 

if __name__ == "__main__":
    countvec()

*用列表表示文本,列表里的一个元素代表一个文本 

结果显示:

很明显,结果依然是sparse矩阵的形式,我们要想得到二维数组的形式,就要使用一个基于numpy的toarray()的方法 

print(data.toarray())

结果显示:

通过cv.get_feature_names() (注意这里是cv,使用的是实例化对象,不是用的类对象)

结果显示:

由此可见,这里的feature name是单词,这个列表是统计所有文章所有的词,重复的只看作一次,数字代表每篇文本每个单词出现的次数,这里的数字是计数功能,不同于类别的one-hot编码,0,1代表是否有,不是计数功能

*单个字母不统计 (因为一个英文字母不会反映文章的主题,没有意义)

文本是中文文本的转换:

from sklearn.feature_extraction.text import CountVectorizer


def countvec():
    """
    对文本进行特征化
    :return None
    """
    cv = CountVectorizer()
    data = cv.fit_transform(["人生苦短,我喜欢python", "人生漫长,我不喜欢python"])##用列表表示文本,列表里的一个元素代表一个文本
    print(cv.get_feature_name())

    print(data.toarray())

    return None 

if __name__ == "__main__":
    countvec()

结果显示:

这显然不是我们想要的结果,不是一个词一个词的,所以这不支持中文文本,要想转换转换中文文本,需要使用空格对句子进行拆分,例如(英文默认有分词功能)

人生 苦短,我 喜欢 python, 人生漫长,我 不喜欢 python

中文文本分词工具

jieba分词

        下载:pip3 install jieba

        使用:import jieba jieba.cut(“我是一个好程序员”)

        注意:返回值:词语生成器

from sklearn.feature_extraction.text import CountVectorizer
import jieba


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

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

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

#转换成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)
#把列表转换成用空格隔开的字符串(以空格隔开的字符串)#英文的transform的对象也是字符串组成的列

    c1 = ‘ ’.join(content1)
    c2 = ‘ ’.join(content2)
    c3 = ‘ ’.join(content3)

return c1,c2,c3


def countvec():
    """
    对文本进行特征化
    :return None
    """
    c1, c2, c3 = cutword()#接收cutword方法的返回值
 
    print(c2,c2,c3)
    cv = CountVectorizer()
    data = cv.fit_transform([c1, c2, c3])##用列表表示文本,列表里的一个元素代表一个文本,这里既是是英文文本时候,列表里元素存储的也是字符串的形式,因此要在前边的步骤里将中文文本转换为字符串形式
    print(cv.get_feature_name())

    print(data.toarray())

    return None 


if __name__ == "__main__":
    countvec()

结果显示:

 解析将中文文本变为字符串的过程:

1)先使用jieba这一工具将原本的中文文本进行分词,

con1 = jieba.cut("文本1")

2)将文本转化为列表

content1 = list(con1)

3)到这步的打印结果(单个的字符是没有被筛掉的)---列表形式,

至于为什么转化成列表形式而不直接转化为字符串形式,jieba.cut后得到的con1是列表迭代器,尽管迭代器很好用,但仍然不具备某些功能,例如,通过索引获取某个元素,进行分片操作。这些操作都是列表的专利,所以在很多时候,需要将迭代器转换为列表。但有很多迭代器都是无限迭代的。因此,在讲迭代器转换为列表时,需要给迭代器能够迭代的元素限定一个范围,否则内存就会溢出。要想让迭代器停止迭代,值需要抛出StopIteration异常即可。通过list函数可以直接将迭代器转换为列表。为何转为列表我认为有三个原因:一是字符串不可修改,在添加空格时,需要重新分配内存空间,消耗大,其次,列表安全性更高,其三,在实际操作中,操作序列常在列表上进行,也是一种习惯吧。

['今天', '很', '残酷', ',', '明天', '更', '残酷', ',', '后天', '很', '美好', ',', '但', '绝对', '大部分

4)把列表转换成用空格隔开的字符串(以空格隔开的字符串),英文的transform需要对象是字符串组成的列表,且中文必须有空格分词才能识别,这里所以要转为空格连接jieba分词后词组组成的字符串,可见如下,不是列表形式了

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

5)使用文本特征化方法特征化中文文本

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

可以看到,在这步又将第四步的字符串变成了列表进行特征化操作

这个展示了完整的中文文本的预处理操作:



中文文本预处理之结巴分词及特征化 - hahahaer - 博客园

文本特征抽取应用:

1)计数Count:文本分类/情感分析…【不常用,因为一些中性词语像是我们,明天等不能反映文本之间关系】

2)TF-IDF:常用做文本分类

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

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

tf:term frequencey(词频)

idf:inverse document frequency(逆文档频率)log(总文档数量/该词出现的文档数量)、

       log(数值):输入的数值越小,值越小

tf*idf:重要性程度,对所有在文章出现的词作重要性分析

为什么需要TfidfVectorizer:分类机器学习算法的的重要依据

:sklearn.feature_extraction.text.TfidfVectorizer

TfidfVectorizer语法

1)TfidfVectorizer(stop_words=None,…)

           返回词的权重矩阵

2)TfidfVectorizer.fit_transform(X,y)      

            X:文本或者包含文本字符串的可迭代对象

            返回值:返回sparse矩阵

3)TfidfVectorizer.inverse_transform(X)

             X:array数组或者sparse矩阵

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

4)TfidfVectorizer.get_feature_names()

            返回值:单词列表

# 导入包
# from sklearn.feature_extraction.text import CountVectorizer
#
# # 实例化CountVectorizer
#
# vector = CountVectorizer()
#
# # 调用fit_transform输入并转换数据
#
# res = vector.fit_transform(["life is short,i like python","life is too long,i dislike python"])
#
# # 打印结果
# print(vector.get_feature_names())
#
# print(res.toarray())


def dictvec():
    """
    字典数据抽取
    :return: None
    """
    # 实例化
    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(dict.inverse_transform(data))

    print(data)

    return None


def countvec():
    """
    对文本进行特征值化
    :return: None
    """
    cv = CountVectorizer()

    data = cv.fit_transform(["人生 苦短,我 喜欢 python", "人生漫长,不用 python"])

    print(cv.get_feature_names())

    print(data.toarray())

    return None



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



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

    print(c1, c2, c3)

    tf = TfidfVectorizer()

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

    print(tf.get_feature_names())

    print(data.toarray())

    return None

Scikit-learn库

  1. Python语言的机器学习工具
  2. Scikit-learn包括许多知名的机器学习算法的实现
  3. Scikit-learn文档完善,容易上手,丰富的API,使其在学术界颇受欢迎。
  4. 目前稳定版本0.18
  5. 内容包括:分类、回归、聚类(Clustering)、降维(Dimensionality Reduction)、模型选择(Model Selection)、特征工程(Preprocessing)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值