凡是过往,皆为序章

0%

机器学习_02(特征工程)

特征工程学习,本篇主要介绍特征工程的数据集特征抽取


数据集

目标

  • 知道数据集分为训练集和测试集
  • 会使用sklearn的数据集

可用数据集

可用数据集很多,网上一查便可搜索到。学习阶段,可能用到的数据集:

  • sklearn
  • kaggle
  • UCI

sklearn工具介绍

  • Python语言的机器学习工具

  • Scikit-learn包括许多知名的机器学习算法的实现

  • Scikit-learn文档完善,容易上手,丰富的API

官网地址:https://scikit-learn.org/stable/

安装sklearn

anaconda里面安装十分容易,搜索scikits-learn,下载该包即可。

sklearn数据集

1、scikits-learn数据集API介绍

sklearn.datasets

  • 加载获取流行数据集

  • datasets.load_*()

    • 获取小规模数据集,数据包含在datasets里
  • datasets.fetch_*(data_home=None)

    • 获取大规模数据集,需要从网络上下载,函数的第一个参数是data_home,表示数据集下载的目录,默认是~/scikit_learn_datal

2、sklearn小数据集

  • sklearn.datasets.load_iris()

    加载并返回鸢尾花数据集

  • sklearn.datasets.load_boston()

    加载并返回波士顿房价数据集

3、sklearn大数据集

  • sklearn.datasets.fetch_20newsgroups(data_home=None,subset=’train’)
    • subset:可选参数 ‘train’,’test’,’all’,训练集的“训练”,测试集的“测试”,两者的全部

4、sklearn数据集的使用

以鸢尾花数据集为例。

  • 特征值-4个:花瓣、花萼的长度、宽度
  • 目标值-3个:setosa,vericolor,virginica

sklearn数据集返回值介绍

load和fetch返回的数据类型datasets.base.Bunch(字典格式,继承自字典)

两种取值方式,value = dict[“key”] 或 value = dict.key

  • data:特征数据数组,是[n_samples * n_features]的二维 numpy.ndarray 数组
  • target:标签数组,是n_samples的一维numpy.ndarray 数组
  • DESCR:数据描述
  • feature_names:特征名。新闻数据、手写数字、回归数据集没有
  • target_names:标签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from sklearn.datasets import load_iris


def datasets_demo():
"""
sklearn 数据集的使用
:return:
"""

# 获取数据集
iris = load_iris()
# print("鸢尾花数据集:\n", iris)
print("查看数据集描述\n", iris.DESCR)
print("查看特征值名字:\n", iris.feature_names)
print("查看特征值:\n", iris.data, iris.data.shape)
print("查看标签数组:\n", iris.target)
print("查看标签名:\n", iris.target_names)


if __name__ == "__main__":
datasets_demo()

思考:拿到的数据是否全部用来训练一个模型?

数据集的划分

机器学习一般的数据集会划分为两个部分:

  • 训练数据:用于训练,构建模型

  • 测试数据:在模型检验时使用,用于评估模型是否有效

划分比例:

  • 训练集:70% 75% 80%

  • 测试集:30% 25% 20%

数据集划分API

sklearn.model_selection.train_test_split(array, *options)

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)

  • x数据集的特征值
  • y数据集的标签值
  • test_size 测试集的大小,一般为float
  • random_state 随机数种子,不同的种子会造成不同的随机采样结果。相同的种子采样结果相同。
  • return结果:训练集特征值(x_train),测试集特征值(x_test),训练集目标值(y_train),测试集目标值(y_test)

x_train,y_train 是原始数据集划分出来作为训练模型的,fit模型的时候用。

x_test,y_test 这部分的数据不参与模型的训练,而是用于评价训练出来的模型好坏,score评分的时候用。

1
2
3
4
5
6
7
8
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split


iris = load_iris()
# 数据集的划分 前两个参数为目标值和特征值
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22)
print("训练集的特征值:\n", x_train, x_train.shape)

特征工程介绍

特征工程是使用专业背景知识和技巧处理数据,使得特征能在机器学习算法上发挥更好的作用的过程。

业界广泛流产:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。

特征工程的位置和数据处理的比较

  • pandas:用于数据处理和数据清洗
  • sklearn:用于特征工程

特征工程包括三部分

  • 特征抽取
  • 特征预处理
  • 特征降维

特征抽取

目标:

  • 应用DictVectorizer实现对类别特征进行数值化、离散化
  • 应用CountVectorizer实现对文本特征进行数值化
  • 应用TfidVectorizer实现对文本特征进行数值化
  • 说出两种文本特征提取的方式区别

介绍

1、将任意数据(文本或图像)转换为可用于机器学习的数字特征

注意:特征值化 是为了计算机更好的去理解数据

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

2、特征提取API

1
sklearn.feature_extraction

字典特征提取

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

应用场景:

  • 数据集当中类别特征比较多
    • 将数据集的特征 – > 字典类型
    • DictVectorizer转换
  • 本身拿到的数据就是字典类型

API

sklearn.feature_extraction.DictVectorizer(sparse=True,…) sparse : 是否采用稀疏矩阵

  • DictVectorizer.fit_transform(X) X:字典或者包含字典的迭代器。返回值:返回sparse矩阵

  • DictVectorizer.inverse_transform(X) X:array数组或sparse(稀疏)矩阵。返回值:转换之间的数据格式

  • DictVectorizer.get_feature_names() 返回类别名称

字典特征提取 –> 类别 –> one-hot编码,当类别非常多时,矩阵会有非常多的 0,使用稀疏矩阵可以减少内存开销。

案例

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

1
2
3
[{'city':'北京', 'temperature': 10}, 
{'city':'上海', 'temperature': 20},
{'city':'深圳', 'temperature': 30}]

代码实现:

  • 实例化DictVectorizer
  • 调用fit_transform输入数据并转换(注意返回格式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.feature_extraction import DictVectorizer


def dict_demo():
"""
字典特征抽取
:return:
"""
data = [{'city':'北京', 'temperature': 10}, {'city':'上海', 'temperature': 20}, {'city':'深圳', 'temperature': 30}]
# 1. 实例化一个转换器类
transfer = DictVectorizer(sparse=False)

# 2. 调用fit_transform()
data_new = transfer.fit_transform(data)
print(data_new)

结果

稀疏矩阵:

非稀疏矩阵:

总结

对于特征当中存在类别信息的我们都会做one-hot编码处理

文本特征提取

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

对于一段文字,我们一般用单词作为特征,进行提取。

  • sklearn.feature_extraction.text.CountVectorizer(stop_words=[])
    • 返回词频矩阵
    • stop_words:停用词,使用后便不显示
  • CountVectorizer.inverse_transform(X) X:array数组或者sparse矩阵 返回值:转换之前的数据格式
  • CountVectorizer.get_feature_names() 返回值:单词列表
  • sklearn.feature_extraction.text.TfidfVectorizer

英文分词实例

对以下数据进行特征提取

data = [“Life is short, I like python.”, “Life is too long, I don’t like python python.”]

流程分析

  • 实例化类CountVectorizer类
  • 调用fit_transform方法输出数据并转换(注意返回格式,利用 toarray() 进行 sparse 矩阵转换为 array 数组)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from sklearn.feature_extraction.text import CountVectorizer


def count_demo():
"""
文本特征抽取
:return:
"""
data = ["Life is short, I like python.", "Life is too long, I don't like python python."]
# 1. 实例化一个转换器类
transfer = CountVectorizer()

# 2. 调用fit_transform
data_new = transfer.fit_transform(data)
print("data_new:\n", data_new)
print("data_new(数组形式):\n", data_new.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
data_new:
(0, 2) 1
(0, 1) 1
(0, 6) 1
(0, 3) 1
(0, 5) 1
(1, 2) 1
(1, 1) 1
(1, 3) 1
(1, 5) 2
(1, 7) 1
(1, 4) 1
(1, 0) 1
data_new(数组形式):
[[0 1 1 1 0 1 1 0]
[1 1 1 1 1 2 0 1]]
特征名字:
['don', 'is', 'life', 'like', 'long', 'python', 'short', 'too']

拓展

若对中文进行特征提取,需要分词,可用结巴分词等等…

中文分词实例

需要使用pip命令下载jieba包,在anaconda的navigator中搜索不到。

1
pip install jieba

实现:

  • 利用jieba包 ,定义分词方法cut_word()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import CountVectorizer
import jieba


def cut_word(text):
"""
进行中文分词:“我爱北京天安门” 转换为 “我 爱 北京 天安门”
:param text:
:return:
"""
a = jieba.cut(text) # 返回一个生成器对象
# print(a) # <generator object Tokenizer.cut at 0x0000028FFE894C80>
b = list(a) # 强转为列表类型
# print(b) # ['我', '爱', '北京', '天安门']
c = " ".join(b) # 继续转换
# print(c) # 我 爱 北京 天安门
return c


def count_chinese():
"""
中文文本特征抽取,自动分词
:return:
"""
# 1. 将中文文本进行分词
data = ["在分类中,机器被训练成将一个组划分为特定的类。分类的一个简单例子是电子邮件帐户上的垃圾邮件过滤器。",
"过滤器分析你以前标记为垃圾邮件的电子邮件,并将它们与新邮件进行比较。",
"如果它们匹配一定的百分比,这些新邮件将被标记为垃圾邮件并发送到适当的文件夹。",
"那些比较不相似的电子邮件被归类为正常邮件并发送到你的邮箱。"]

data_new = []
for sentence in data:
data_new.append(cut_word(sentence))
# print(data_new)

# 2. 实例化转换器类
transfer = CountVectorizer()

# 3. 调用fit_transform
data_final = transfer.fit_transform(data_new)
print("data_final:\n", data_final.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None

思考

关键词:在某一个类别的文章中,出现的次数很多,但是在其他类别的文章中出现次数很少

所以,我们该如何处理某个词或短语在多篇文章中出现的次数高这一情况?

Tf-idf文本特征提取

  • TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
  • TF-IDF作用:用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
  • 字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

总结就是, 一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。

公式

  • 词频(term frequency,tf) 指的是某一个给定的词语在该文件中出现的频率

  • 逆向文档频率(inverse document frequency, idf) 是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到。

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

1
TF−IDF = 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()
      • 返回值:单词列表

实例

根据上个中文分词实例,使用TF-IDF进行特征提取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer # Tfidf的引入
import jieba


def cut_word(text):
"""
进行中文分词:“我爱北京天安门” 转换为 “我 爱 北京 天安门”
:param text:
:return:
"""
a = jieba.cut(text) # 返回一个生成器对象
# print(a) # <generator object Tokenizer.cut at 0x0000028FFE894C80>
b = list(a) # 强转为列表类型
# print(b) # ['我', '爱', '北京', '天安门']
c = " ".join(b) # 继续转换
# print(c) # 我 爱 北京 天安门
return c


def count_chinese():
"""
用tfidf的方法进行文本特征抽取
:return:
"""
# 1. 将中文文本进行分词
data = ["在分类中,机器被训练成将一个组划分为特定的类。分类的一个简单例子是电子邮件帐户上的垃圾邮件过滤器。",
"过滤器分析你以前标记为垃圾邮件的电子邮件,并将它们与新邮件进行比较。",
"如果它们匹配一定的百分比,这些新邮件将被标记为垃圾邮件并发送到适当的文件夹。",
"那些比较不相似的电子邮件被归类为正常邮件并发送到你的邮箱。"]

data_new = []
for sentence in data:
data_new.append(cut_word(sentence))
# print(data_new)

# 2. 实例化转换器类
transfer = TfidfVectorizer()

# 3. 调用fit_transform
data_final = transfer.fit_transform(data_new)
print("data_final:\n", data_final.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None

得到结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
data_final:
[[0.25452286 0.25452286 0. 0. 0.25452286 0.
0.50904573 0.25452286 0. 0.16245865 0. 0.
0.25452286 0. 0. 0.25452286 0. 0.
0.25452286 0. 0. 0. 0.25452286 0.16245865
0. 0. 0.25452286 0.25452286 0.20066875 0.
0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0.38006651 0. 0.38006651
0. 0. 0. 0.24259153 0. 0.29964881
0. 0. 0. 0. 0. 0.29964881
0. 0.29964881 0. 0.29964881 0. 0.24259153
0. 0. 0. 0. 0.29964881 0.
0.38006651 0. 0. 0. 0. 0. ]
[0. 0. 0.30838102 0. 0. 0.
0. 0. 0.30838102 0.19683561 0.30838102 0.24313114
0. 0.24313114 0. 0. 0.30838102 0.24313114
0. 0.24313114 0. 0. 0. 0.
0.30838102 0. 0. 0. 0. 0.30838102
0. 0.24313114 0.30838102 0. 0. 0. ]
[0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.
0. 0.27412127 0.34768807 0. 0. 0.
0. 0. 0.34768807 0.27412127 0. 0.22192479
0. 0.34768807 0. 0. 0. 0.
0. 0.27412127 0. 0.34768807 0.34768807 0.34768807]]

重要性

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

总结

特征抽取

  • 字典特征抽取
    • sklearn.feature_extraction.DictVectorizer
  • 文本特征抽取
    • sklearn.feature_extraction.text.CountVectorizer
    • sklearn.feature_extraction.text.TfidfVectorizer
~感谢你请我吃糖果~
-------------本文结束,感谢您的阅读,欢迎评论留言!-------------