为什么需要特征工程(Feature Engineering)
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已
什么是特征工程
帮助我们使得算法性能更好发挥性能而已
sklearn主要用于特征工程
pandas主要用于数据清洗、数据处理
特征工程包含如下3个内容:
1、特征抽取/特征提取
|__>字典特征抽取
|__>文本特征抽取
|__>图像特征抽取(深度学习)
2、特征预处理
3、特征降维
- 特征抽取/特征提取
我们常说的机器学习算法实际上就是我们统计学上的统计方法也就是我们数学上的数学公式
即 机器学习算法--》统计方法--》数学公式
字典特征抽取的应用场景:
1)pclass, sex 数据集当中类别特征比较多
1、将数据集的特征 转换为字典类型
2、利用DictVectorizer转换为二维数组
2)本身拿到的数据就是字典类型
1- 字典特征提取:
当我们调用sklearn.feature_extraction.DictVectorizer(sparse=True,…)的时候,实际上就是初始化了一个父类的转换器对象,然后调用实例进行fit_transform(X),进行字典和数值的转换。
(下图)有多少行数据就有多少个向量(有方向和大小),向量在计算机中以矩阵存储(二维数组),而矩阵的行和列都可以看做一个一维数组。下图中一行数据可以看做一个向量,n个样本有n个向量,即将字典转换为了计算机识别的二维数组。每一个样本有2个特征(城市+temperature),正常应该返回一个3行2列的矩阵,但是字典特征抽取后,样本量没有变(3个样本),但是特征量变成了4个(当特征中有类别的时候,要想表示成数值,又想要公平的表示数据,我们采用one-hot编码,有3个类别,就占用3列,如果是北京,则第二列的特征值就是1,最后添加上temperature就是4个特征了)。
字典特征抽取DEMO:
from sklearn.feature_extraction.dict_vectorizer import DictVectorizer # 字典特征提取 def dic_demo(): data = [{'city': '北京', 'temperature': 100}, {'city': '上海', 'temperature': 60}, {'city': '深圳', 'temperature': 30}] # 1、实例化一个转换器对象 # transform = DictVectorizer(sparse=True) # 默认开启稀疏矩阵 transform = DictVectorizer(sparse=False) # 默认sparse=True, # 2、调用fit_transform() new_data = transform.fit_transform(data) # 3、获取特征名称 print("特征名字:\n", transform.get_feature_names()) # 特征名字:['city=上海', 'city=北京', 'city=深圳', 'temperature'] print('转换后的结果:\n', new_data) ''' # sparse=True时候的new_data的值:返回的new_data是一个sparse的稀疏矩阵 (0, 1) 1.0 (0, 3) 100.0 (1, 0) 1.0 (1, 3) 60.0 (2, 2) 1.0 (2, 3) 30.0 # sparse=True时候的new_data的值,返回的是一个二维数组 [[ 0. 1. 0. 100.] [ 1. 0. 0. 60.] [ 0. 0. 1. 30.]] # 总结: 稀疏矩阵将非零值按位置表示出来,这样做可以节省内存 - 提高加载效率 ''' if __name__ == '__main__': dic_demo()
结果截图:
附:
one-hot编码:
对特征中的类别信息,为了公平的表示每一组样本数据,我们处理的时候,就是根据类别进行划分,样本中几个类别就有几列,是这个数据则置该列的数值为1,否则为0
2- 文本特征提取:
文本特征提取就是将单词、字母、短语作为主要的特征词进行特征提取
可以利用如下方法统计:
CountVectorizer:统计的是文本中出现的特征词次数,stop_words停用的停词表,toarray()可以转换为二维数组
英文的测试DEMO
from sklearn.feature_extraction.text import CountVectorizer # 文本特征提取 def text_count_demo(): data = ["life is short,i like like python", "life is too long, i dislike python"] # 1、实例化一个转换器类 transfer = CountVectorizer() # transfer = CountVectorizer(stop_words=["is", "too"]) ''' 不添加stop_words的效果:transfer = CountVectorizer() data_new: [[0 1 1 2 0 1 1 0] [1 1 1 0 1 1 0 1]] 特征名字: ['dislike', 'is', 'life', 'like', 'long', 'python', 'short', 'too'] 添加stop_words的效果: transfer = CountVectorizer(stop_words=["is", "too"]) data_new: [[0 1 2 0 1 1] [1 1 0 1 1 0]] 特征名字: ['dislike', 'life', 'like', 'long', 'python', 'short'] ''' # 2、调用fit_transform data_new = transfer.fit_transform(data) # data_new返回的是一个sparse矩阵, print("矩阵_data_new:\n", data_new) # data_new.toarray()返回的是一个二维数组 print("数组_data_new:\n", data_new.toarray()) ''' 矩阵_data_new: (0, 5) 1 (0, 3) 2 (0, 6) 1 (0, 1) 1 (0, 2) 1 (1, 0) 1 (1, 4) 1 (1, 7) 1 (1, 5) 1 (1, 1) 1 (1, 2) 1 数组_data_new.toarray(): [[0 1 1 2 0 1 1 0] [1 1 1 0 1 1 0 1]] ''' print("特征名字:\n", transfer.get_feature_names()) return None if __name__ =='__main__': text_count_demo()
中文的手动分词DEMO效果(这里是手动用空格进行的中文分词,麻烦):
from sklearn.feature_extraction.text import CountVectorizer # 中文的需要进行分词,否则是以整句作为分词的 def chinese_text_count_demo(): data = ["我爱北京*", "*上太阳升"] # data = ["我 爱 北京 *", "* 上 太阳 升"] # 添加了空格的中文分词 ''' 未添加空格的中文分词: data_new: [[0 1] [1 0]] 特征名字: ['*上太阳升', '我爱北京*'] 添加了空格的中文分词: [[1 1 0] [0 1 1]] 特征名字: ['北京', '*', '太阳'] ''' # 1、实例化一个转换器类 transfer = CountVectorizer() # 2、调用fit_transform data_new = transfer.fit_transform(data) print("data_new:\n", data_new.toarray()) print("特征名字:\n", transfer.get_feature_names()) return None if __name__ =='__main__': chinese_text_count_demo()
中文的自动分词统计的DEMO效果
from sklearn.feature_extraction.text import CountVectorizer import jieba # pip3 install jieba # 利用jieba可以进行jieba分词 def cut_word(text): """ 进行中文分词:"我爱北京*" --> "我 爱 北京 *" :param text: :return: """ return " ".join(list(jieba.cut(text))) # jieba.cut(text)返回的是一个生成器对象,需要转换为迭代器 def auto_chinese_text_count_demo(): data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。", "我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。", "如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"] data_new = [] for sent in data: data_new.append(cut_word(sent)) # print(data_new) # 1、实例化一个转换器类 transfer = CountVectorizer(stop_words=["一种", "所以"]) # 2、调用fit_transform data_final = transfer.fit_transform(data_new) print("data_new:\n", data_final.toarray()) print("特征名字:\n", transfer.get_feature_names()) return None if __name__ =='__main__': auto_chinese_text_count_demo()
- 特征预处理
- 特征降维