上篇:机器学习(二) -- 数据预处理(3)
下篇:机器学习(三) -- 特征工程(2)
前言
tips:标题前有“***”的内容为补充内容,是给好奇心重的宝宝看的,可自行跳过。文章内容被“
文章内容”删除线标记的,也可以自行跳过。“!!!”一般需要特别注意或者容易出错的地方。
本系列文章是作者边学习边总结的,内容有不对的地方还请多多指正,同时本系列文章会不断完善,每篇文章不定时会有修改。
一、特征工程简介
其实数据预处理和特征工程,两者并无明显的界限,都是为了更好的探索数据集的结构,获得更多的信息,将数据送入模型中之前进行整理。可以说数据预处理是初级的特征处理,特征工程是高级的数据预处理,也可以说这里的预处理过程是广义的,包含所有的建模前的数据预处理过程。
(简单理解,就是数据预处理是数据本身的问题,如数据缺失;特征工程是为了更好的让数据进行机器学习(将原始数据转换为更好地代表预测模型的潜在问题的特征的过程,从而提高了模型对未知数据预测的准确性),如进行降维)
为什么需要特征工程?
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
所以需要在特征上下功夫。
1、特征工程定义:
特征工程是使用一定技巧处理数据,使得特征能在机器学习算法上发挥更好的作用的过程。
意义:会直接影响机器学习的效果。
2、特征工程包含内容:
特征提取(特征抽取)、特征预处理、特征降维
(基本上==特征构建、特征变换(特征缩放)、特征选择)
二、Scikit-learn库介绍
- Python语言的机器学习工具
- Scikit-learn包括许多知名的机器学习算法的实现
- Scikit-learn文档完善,容易上手,丰富的API,使其在学术界颇受欢迎。
1、安装
pip install sklearn
检查是否安装好:
1.通过导入命令查看是否可以使用
import sklearn
2.pip list查看安装列表
(在终端和在IDE里面是一样的效果哈)
2、模块
主要包括以下几个模块。
!!!补充:转换器与预估器
转换器(transformer):特征工程的父类
步骤:
1、实例化 (实例化的是一个转换器类(Transformer))
2、调用fit_transform()
fit_transform():输入数据直接转换
fit():输入数据,但不做事情
transform():进行数据转换
***预估器(估计器,estimator,算法模型):机器学习算法的实现
(后面会详细讲这里可以先做了解)
分类器和回归器都属于预估器,是一类实现了算法的API
所有的这些算法都被是继承自estimator,自封装再估计器的子类当中。所有他们都有一个统一的流程。
流程:
1、实例化一个estimator
2、estimator.fit(x_train, y_train) 计算
—— 调用完毕,模型生成
3、模型评估:
1)直接比对真实值和预测值
y_predict = estimator.predict(x_test)
y_test == y_predict
2)计算准确率
accuracy = estimator.score(x_test, y_test)
二、特征提取(特征抽取)
1、定义
将任意数据(如文本或图像)转换为可用于机器学习的数字特征。
注:特征值是为了计算机更好的去理解数据。
主要分为字典特征提取(特征离散化)、文本特征提取、图像特征提取(深度学习再介绍)
特征提取API:
sklearn.feature_extraction
2、字典特征提取
字典特征提取API:(Vectorizer:矢量化器)关于语法后面会详细说到。
sklearn.feature_extraction.DictVectorizer
导入:
from sklearn.feature_extraction import DictVectorizer
语法:
DictVectorizer(sparse=True,…)
DictVectorizer.fit_transform(X)
X:字典或者包含字典的迭代器
返回值:返回sparse矩阵
DictVectorizer.inverse_transform(X)
X:array数组或者sparse矩阵
返回值:转换之前数据格式
# DictVectorizer.get_feature_names() # 已改为如下接口
DictVectorizer.get_feature_names_out()
返回类别名称
DictVectorizer.transform(X)
按照原先的标准转换
流程:导入数据 --> 实例化转换器DictVectorizer() --> 通过fit_transform()转换 --> 得到转换后数据
# 创建数据集
data = [{'name':'薰悟空', 'age':1160},
{'name':'朱八姐', 'age':235},
{'name':'傻无能', 'age':9000}]
(fit_transform:自适应的转换)
# 提取特征值,转化为稀疏矩阵
# 1、实例化转换器类
transfer = DictVectorizer()
# 2、提取特征值
feature_data = transfer.fit_transform(data)
print('稀疏矩阵特征值\n', feature_data)
print('特征名字:', transfer.get_feature_names())
!!!注意
最新的transfer.get_feature_names()无法使用要换 成transfer.get_feature_names_out()
DictVectorizer()使用默认参数会返回一个稀疏矩阵(sparse矩阵)。其实就是一个和下面的操作出现的一样的矩阵,只是采用三元组的格式保存,能减少存储空间的开销。
三元组:(行号,列号,元素值)
上面稀疏矩阵特征值换为矩阵为:
0(age) | 1(name=傻无能) | 2(name=朱八姐) | 3(name=薰悟空) | |
---|---|---|---|---|
0 | 1160 | 0 | 0 | 1 |
1 | 235 | 0 | 1 | 0 |
2 | 9000 | 1 | 0 | 0 |
然后特征名称对应的就是分别的列号,即0为‘age’,1为‘name=傻无能’,2为‘name=朱八姐’,3为‘name=薰悟空’。
DictVectorizer(sparse=False)返回一个One-hot编码(独热)矩阵。
# 提取特征值,转化为二维矩阵
# 1、实例化转换器类
transfer = DictVectorizer(sparse=False)
# 2、提取特征值
feature_data = transfer.fit_transform(data)
print('二维矩阵特征值:\n', feature_data)
print('特征名字:', transfer.get_feature_names())
一般这样使用。
inverse_transform():输入转换后的数据,逆转回去
训练集上用 fit_transform()
测试集上用 transform()
3、文本特征提取
文本特征提取API
sklearn.feature_extraction.text.CountVectorizer
导入:
from sklearn.feature_extraction.text import CountVectorizer
语法:
CountVectorizer(max_df=1.0,min_df=1,…)# 默认为1
返回词频矩阵
# max_df, min_df整数:指每个词的所有文档词频数不小于最小值,出现该词的文档数目小于等于max_df
# max_df, min_df小数:每个词的次数/所有文档数量
CountVectorizer.fit_transform(X,y)
X:文本或者包含文本字符串的可迭代对象
返回值:返回sparse矩阵
CountVectorizer.inverse_transform(X)
X:array数组或者sparse矩阵
返回值:转换之前数据格式
CountVectorizer.get_feature_names_out()
返回值:单词列表
3.1、 英文文本分词
流程:导入数据 --> 实例化转换器CountVectorizer() --> 通过fit_transform()转换 --> 得到转换后数据
# “导入”数据
data = ['life is short,i like like python',
'life is too long,i dislike python']
# 1、实例化一个转换器类
transfer = CountVectorizer()
# 2、调用fit_transform
data_new = transfer.fit_transform(data)
print("data_new:\n", data_new.toarray()) # toarray转换为二维数组
print("特征名字:\n", transfer.get_feature_names())
一样把特征名字和列名对应上去
0(dislike) | 1(is) | 2(life) | 3(like) | 4(long) | 5(python) | 6(short) | 7(too) | |
---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 2 | 0 | 1 | 1 | 0 |
2 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
3.1.1、停用词方法
给转换器传入停用词的列表,stop_words=['is', 'too'],其中的词不会被提取。
transfer = CountVectorizer(stop_words=['is', 'too'])
3.2、中文文本分词
3.2.1、普通方法
这种实现只能通过给中文加空格才行。
流程:导入数据 --> 实例化转换器CountVectorizer() --> 通过fit_transform()转换 --> 得到转换后数据
# “导入”数据
data = ['我 爱 北京 天安门',
'天安门 上 太阳 升']
# 1、实例化一个转换器类
transfer = CountVectorizer()
# 2、调用fit_transform
data_new = transfer.fit_transform(data)
print("data_new:\n", data_new.toarray()) # toarray转换为二维数组
print("特征名字:\n", transfer.get_feature_names())
3.2.2、jieba实现自动分词
需要先下载jieba哟
pip install jieba
# “导入”数据
data = ['一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。',
'我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。',
'如果只用一种方式了解某件事物,他就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。']
data_new = []
流程:导入数据 --> 利用jieba.cut进行分词 --> 实例化转换器CountVectorizer() --> 通过fit_transform()转换 --> 得到转换后数据
def cut_word(text):
return ' '.join(jieba.cut(text))
def count_chinese_demo2():
for sent in data:
data_new.append(cut_word(sent))
print(data_new)
# 1、实例化一个转换器类
transfer = CountVectorizer()
# 2、调用fit_transform
data_final = transfer.fit_transform(data_new)
print("data_final:\n", data_final.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None
count_chinese_demo2()
3.2.3、Tf-idf文本特征提取
Tf-idf文本特征提取API:
sklearn.feature_extraction.text.TfidfVectorizer
导入:
from sklearn.feature_extraction.text import TfidfVectorizer
语法:
TfidfVectorizer(stop_words=None,…)
返回词的权重矩阵
TfidfVectorizer.fit_transform(X,y)
X:文本或者包含文本字符串的可迭代对象
返回值:返回sparse矩阵
TfidfVectorizer.inverse_transform(X)
X:array数组或者sparse矩阵
返回值:转换之前数据格式
TfidfVectorizer.get_feature_names()
返回值:单词列表
Tf-idf的主要思想:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TF:词频(term frequency,tf),指的是某一个给定的词语在该文件中出现的频率。
IDF:逆向文档频率(inverse document frequency,idf),是一个词语普遍重要性的度量,某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到。
,其得出结果可以理解为重要程度
TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
流程:导入数据 --> 利用jieba.cut进行分词--> 实例化转换器TfidfVectorizer() --> 通过fit_transform()转换 --> 得到转换后数据
data = ['一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。',
'我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。',
'如果只用一种方式了解某件事物,他就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。']
data_new = []
def cut_word(text):
return ' '.join(jieba.cut(text))
def tfidf_demo():
for sent in data:
data_new.append(cut_word(sent))
print(data_new)
# 1、实例化一个转换器类
transfer = TfidfVectorizer()
# 2、调用fit_transform
data_final = transfer.fit_transform(data_new)
print("data_final:\n", data_final.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None
tfidf_demo()
旧梦可以重温,且看:机器学习(二) -- 数据预处理(3)
欲知后事如何,且看:机器学习(三) -- 特征工程(2)