Python机器学习及实践——进阶篇:模型实用技巧(特征提升)

所谓特征抽取,就是逐条将原始数据转化为特征向量的形式,这个过程同时涉及对数据特征的量化表示;而特征筛选则进一步,在高维度、已量化的特征向量中选择对指定任务更有效的特征组合,进一步提升模型性能。

1.特征抽取

原始数据的种类有很多种,除了数字化的信号数据(声纹、图像),还有大量符号化的文本。然而,我们无法直接将符号化的文本本身用于计算任务,而是需要通过某些处理手段,预先将文本量化为特征向量。

有些用符号表示的数据特征已经相对结构化,并且以字典这种数据结构进行存储。这时,使用DictVectorizer对特征进行抽取和向量化。

DictVectorizer对使用字典存储的数据进行特征抽取与向量化

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : FeatureExtraction.py
@Author: Xinzhe.Pang
@Date  : 2019/7/23 20:59
@Desc  :
"""
# 定义一组字典列表,用来表示多个数据样本(每个字典代表一个数据样本)
measurements = [{'city': 'Dubai', 'temperature': 33.}, {'city': 'London', 'temperature': 12.},{'city': 'San Fransisco', 'temperature': 18.}]
# 从sklearn.feature_extraction中导入DictVectorizer
from sklearn.feature_extraction import DictVectorizer# 初始化DictVectorizer特征抽取器
vec = DictVectorizer()
# 输出转化之后的特征矩阵
print(vec.fit_transform(measurements).toarray())
# 输出各个维度的特征含义
print(vec.get_feature_names())

在特征向量化的过程中,DictVectorizer对于类别型(Categorical)与数值型(Numerical)特征的处理方式有很大差异。由于类别型特征无法直接数字化表示,因此需要借助原特征的名称,组合产生新的特征,并采用0/1二值方式进行量化;而数值型特征的转化则相对方便,一般情况下只需要维持原始特征值即可。

另外一些文本数据则表现得更为原始,几乎没有使用特殊的数据结构进行存储,只是一系列字符串。我们处理这些数据,比较常用的文本特征表示方法为词袋法(Bag of Words):即不考虑词语出现的顺序,只是将训练文本中的每个出现过的词汇单独视作一列特征。称这些不重复的词汇集合为词表(Vocabulary),于是每条训练文本都可以在高维度的词表上映射出一个特征向量。特征数值的常见计算方式有两种:CountVectorizer和TfidfVectorizer。对于每一条训练文本,CountVectorizer只考虑每种词汇(Term)在该条训练文本中出现的概率(Term Frequency)。而TfidfVectorizer除了考虑某一词汇在当前文本中出现的频率(Term Frequency)之外,同时关注包含这个词汇的文本条数的倒数(Inverse Document Frequency)。相比之下,训练文本的条目越多,TfidfVectorizer这种特征量化方式就更有优势。因为我们计算词频(Term Frequency)的目的在于找出对所在文本的含义更有贡献的重要词汇。然而,如果一个词汇几乎在每篇文本种出现,说明这是一个常用词汇,反而不会帮助模型对文本的分类;在训练文本量较多的时候,利用TfidfVectorizer压制这些常用词汇的对分类决策的干扰,往往可以起到提升模型性能的作用。

通常称这些在每条文本中都出现的常用词汇为停用词(Stop Words)。这些停用词在文本特征抽取中经常以黑名单的方式过滤掉,并且用来提高模型的性能表现。

使用CountVectorizer并且不去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : CountVectorizer.py
@Author: Xinzhe.Pang
@Date  : 2019/7/23 22:08
@Desc  :
"""
# 从sklearn.datasets里导入20类新闻文本数据抓取器。
from sklearn.datasets import fetch_20newsgroups# 从互联网上即时下载新闻样本,subset='all'参数代表下载全部近2万条文本存储在变量news中。
news = fetch_20newsgroups(subset='all')# 从sklearn.cross_validation导入train_test_split模块用于分割数据集。
from sklearn.model_selection import train_test_split# 对news中的数据data进行分割,25%的文本用作测试集;75%作为训练集。
X_train, X_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=33)# 从sklearn.feature_extraction.text里导入CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer# 采用默认的配置对CountVectorizer进行初始化(默认配置不去除英文停用词),并且赋值给变量count_vec。
count_vec = CountVectorizer()# 只使用词频统计的方式将原始训练和测试文本转化为特征向量。
X_count_train = count_vec.fit_transform(X_train)
X_count_test = count_vec.transform(X_test)# 从sklearn.naive_bayes里导入朴素贝叶斯分类器。
from sklearn.naive_bayes import MultinomialNB# 使用默认的配置对分类器进行初始化。
mnb_count = MultinomialNB()
# 使用朴素贝叶斯分类器,对CountVectorizer(不去除停用词)后的训练样本进行参数学习。
mnb_count.fit(X_count_train, y_train)# 输出模型准确性结果。
print('The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer without filtering stopwords):',mnb_count.score(X_count_test, y_test))
# 将分类预测的结果存储在变量y_count_predict中。
y_count_predict = mnb_count.predict(X_count_test)
# 从sklearn.metrics 导入 classification_report。
from sklearn.metrics import classification_report# 输出更加详细的其他评价分类性能的指标。
print(classification_report(y_test, y_count_predict, target_names=news.target_names))

使用TfidfVectorizer并且在不去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : TfidfVectorizer.py
@Author: Xinzhe.Pang
@Date  : 2019/7/23 22:26
@Desc  :
"""
# 从sklearn.datasets里导入20类新闻文本数据抓取器。
from sklearn.datasets import fetch_20newsgroups# 从互联网上即时下载新闻样本,subset='all'参数代表下载全部近2万条文本存储在变量news中。
news = fetch_20newsgroups(subset='all')# 从sklearn.cross_validation导入train_test_split模块用于分割数据集。
from sklearn.model_selection import train_test_split# 对news中的数据data进行分割,25%的文本用作测试集;75%作为训练集。
X_train, X_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=33)# 从sklearn.feature_extraction.text里导入TfidfVectorizer。
from sklearn.feature_extraction.text import TfidfVectorizer# 采用默认的配置对TfidfVectorizer进行初始化(默认配置不去除英文停用词),并且赋值给变量tfidf_vec。
tfidf_vec = TfidfVectorizer()# 使用tfidf的方式,将原始训练和测试文本转化为特征向量。
X_tfidf_train = tfidf_vec.fit_transform(X_train)
X_tfidf_test = tfidf_vec.transform(X_test)from sklearn.naive_bayes import MultinomialNB
# 从sklearn.metrics 导入 classification_report。
from sklearn.metrics import classification_report# 依然使用默认配置的朴素贝叶斯分类器,在相同的训练和测试数据上,对新的特征量化方式进行性能评估。
mnb_tfidf = MultinomialNB()
mnb_tfidf.fit(X_tfidf_train, y_train)
print('The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer without filtering stopwords):',mnb_tfidf.score(X_tfidf_test, y_test))
y_tfidf_predict = mnb_tfidf.predict(X_tfidf_test)
print(classification_report(y_test, y_tfidf_predict, target_names=news.target_names))

说明在训练文本量较多的情况下,使用TfidfVectorizer能够减少常用词汇对分类决策的影响,往往可以起到提升模型性能的作用。

分别使用CountVectorizer和TfidfVectorizer,并且去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试

# 去掉停用词
print("去掉停用词之后:")
count_filter_vec = CountVectorizer(analyzer='word', stop_words='english')# 使用带有停用词过滤的CountVectorizer对训练和测试文本分别进行量化处理
X_count_filter_train = count_filter_vec.fit_transform(X_train)
X_count_filter_test = count_filter_vec.transform(X_test)# 初始化默认参数的朴素贝叶斯分类器,并对CountVectorizer后的数据进行预测与准确性评估
mnb_count_filter = MultinomialNB()
mnb_count_filter.fit(X_count_filter_train, y_train)print('The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer by filtering stopwords):',mnb_count_filter.score(X_count_filter_test, y_test))
y_count_filter_pred = mnb_count_filter.predict(X_count_filter_test)
# 输出更加详细的其他评价分类性能的指标
print(classification_report(y_test, y_count_filter_pred, target_names=news.target_names))

# 去掉停用词
print("去掉停用词之后:")
tfidf_filter_vec = TfidfVectorizer(analyzer='word', stop_words='english')# 使用带有停用词过滤的TfidfVectorizer对训练和测试文本分别进行量化处理
X_tfidf_filter_train = tfidf_filter_vec.fit_transform(X_train)
X_tfidf_filter_test = tfidf_filter_vec.transform(X_test)# 初始化默认参数的朴素贝叶斯分类器,并对TfidfVectorizer后的数据进行预测和准确性评估
mnb_tfidf_filter = MultinomialNB()
mnb_tfidf_filter.fit(X_tfidf_filter_train, y_train)
print('The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer by filtering stopwords):',mnb_tfidf_filter.score(X_tfidf_filter_test, y_test))
y_tfidf_filter_predict = mnb_tfidf_filter.predict(X_tfidf_filter_test)
# 输出更加详细的其他评价分类性能的指标
print(classification_report(y_test, y_tfidf_filter_predict, target_names=news.target_names))

结果表明,对停用词进行过滤的文本特征抽取方法,平均要比不过滤停用词的模型综合性能高出3%~4%。

2.特征筛选

总体来讲,良好的数据特征组合不需太多,便可以使得模型的性能表现突出。

特征筛选与PCA这类通过选择主成分对特征进行重建的方法略有区别:对于PCA,经常无法解释重建之后的特征;但是特征筛选不存在对特征值的修改,而更加侧重于寻找那些对模型的性能提升较大的少量特征。

使用Titanic数据集,通过特征筛选的方法一步步提升决策树的预测性能

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : FeatureSelctionbyDT.py
@Author: Xinzhe.Pang
@Date  : 2019/7/23 22:53
@Desc  :
"""
import pandas as pdtitanic = pd.read_csv('./titanic.txt')# 分离数据特征与预测目标
y = titanic['survived']
X = titanic.drop(['row.names', 'name', 'survived'], axis=1)# 对缺失数据进行填充
X['age'].fillna(X['age'].mean(), inplace=True)
X.fillna('UNKNOWN', inplace=True)# 分割数据
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=33)# 类别特征向量化
from sklearn.feature_extraction import DictVectorizervec = DictVectorizer()
X_train = vec.fit_transform(X_train.to_dict(orient='record'))
X_test = vec.transform(X_test.to_dict(orient='record'))# 输出处理后特征向量的维度
print("处理后特征向量的维度:")
print(len(vec.feature_names_))# 使用决策树模型依靠所有特征进行预测,并做出性能评估
from sklearn.tree import DecisionTreeClassifierdt = DecisionTreeClassifier(criterion='entropy')
dt.fit(X_train, y_train)
print("使用决策树模型依靠所有特征进行预测:")
print(dt.score(X_test, y_test))# 从sklearn导入特征筛选器
from sklearn import feature_selection# 筛选前20%的特征,使用相同配置的决策树模型进行预测,并评估性能
fs = feature_selection.SelectPercentile(feature_selection.chi2, percentile=20)
X_train_fs = fs.fit_transform(X_train, y_train)
dt.fit(X_train_fs, y_train)
X_test_fs = fs.transform(X_test)
print("筛选前20%的特征,使用相同配置的决策树模型进行预测")
print(dt.score(X_test_fs, y_test))# 通过交叉验证的方法,按照固定间隔的百分比筛选特征,并作图展示性能随特征筛选比例的变化
from sklearn.model_selection import cross_val_score
import numpy as nppercentiles = range(1, 100, 2)
results = []
for i in percentiles:fs = feature_selection.SelectPercentile(feature_selection.chi2, percentile=i)X_train_fs = fs.fit_transform(X_train, y_train)scores = cross_val_score(dt, X_train_fs, y_train, cv=5)results = np.append(results, scores.mean())print(results)# 找到体现最佳性能的特征筛选的百分比
opt = np.where(results == results.max())[0]
print('Optimal number of features %d' % np.array(percentiles)[opt])# 绘制变化曲线图
import pylab as plpl.plot(percentiles, results)
pl.xlabel('percentiles of features')
pl.ylabel('accuracy')
pl.show()# 使用最佳筛选后的特征,利用相同参数的模型在测试集上进行性能评估
fs = feature_selection.SelectPercentile(feature_selection.chi2, percentile=opt)
X_train_fs = fs.fit_transform(X_train, y_train)
dt.fit(X_train_fs, y_train)
X_test_fs = fs.transform(X_test)
print("使用最佳筛选后的特征,利用相同参数的模型在测试集上进行性能评估结果:")
print(dt.score(X_test_fs, y_test))

问题1:Traceback (most recent call last):
  File "E:/python_learning/MyKagglePath/Advanced/PracticalSkills/Feature Selection/FeatureSelctionbyDT.py", line 72, in <module>
    print('Optimal number of features %d' %percentiles[opt])
TypeError: only integer scalar arrays can be converted to a scalar index

解决办法:print 'Optimal number of features',np.array(percentiles)[opt]

使用前7%维度的特征,最终的测试结果比最初使用全部特征的性能高出接近3个百分点。

【Python机器学习及实践】进阶篇:模型实用技巧(特征提升)相关推荐

  1. Python机器学习与实践——简介篇

    周四晚上胡哥给大家简单培训了一下nlp的一些算法,感觉受益匪浅.回去之后反省了一下,有段时间没看机器学习的东西了,nlp要抓,机器学习也要学.开个坑,记录和分享一下学习内容(书籍为<python ...

  2. Python机器学习及实践——简介篇3(逻辑回归)

    前面两篇都是介绍性的文字,这篇详细介绍完整的"良/恶性乳腺癌肿瘤预测"问题的Python源代码. 根据前两篇的描述,大家可以确定"良/恶性乳腺癌肿瘤预测"的问题 ...

  3. Python机器学习及实践——基础篇9(SVM回归)

    小贴士:核函数是一项非常有用的特征映射技巧,同时在数学描述上也略为复杂.因此这里不做过度引申.简单一些理解,便是通过某种函数计算,将原有的特征映射到更高维度的空间,从而尽可能达到新的高维度特征线性可分 ...

  4. python机器学习及实践_机器学习入门之《Python机器学习及实践:从零开始通往Kaggle竞赛之路》...

    本文主要向大家介绍了机器学习入门之<Python机器学习及实践:从零开始通往Kaggle竞赛之路>,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助. <Python 机 ...

  5. 《python机器学习及实践-从零开始通往kaggle竞赛之路》——代码整理

    代码目录 2.1 监督学习经典模型 2.1.1 分类学习 2.1.1.1 线性分类器 2.1.1.2 支持向量机 2.1.1.3 朴素贝叶斯 2.1.1.4 K近邻 2.1.1.5&2.1.1 ...

  6. python机器学习及实践_Python机器学习及实践

    Python机器学习及实践/Chapter_1/.ipynb_checkpoints/Chapter_1.1-checkpoint.ipynb Python机器学习及实践/Chapter_1/.ipy ...

  7. Python:Excel自动化实践入门篇 甲【留言点赞领图书门票】

    *以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s?__biz=MzUxMTgxMzExNQ==&mid=22 ...

  8. 《Python机器学习及实践》----良/恶性乳腺癌肿瘤预测

    本片博客是根据<Python机器学习及实践>一书中的实例,所有代码均在本地编译通过.数据为从该书指定的百度网盘上下载的. 代码片段: import pandas as pd import ...

  9. Python趣味百题-进阶篇-刘硕-专题视频课程

    Python趣味百题-进阶篇-11679人已学习 课程介绍         精选的30个实例都从趣味编程的角度出发,并兼顾实用性.实例涵盖了Python程序设计的基础知识和常用算法,很多实例来自编程大 ...

最新文章

  1. mysql怎么用命令行导出sql文件_使用mysql命令行导出sql_MySQL
  2. Linux基础 —— Linux终端命令格式
  3. win10万能触摸屏驱动_教你win10系统设置usb鼠标驱动的方法
  4. ps制作20种特效文字_用PS制作裂、火、电特效——电
  5. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形定义
  6. CASE WHEN语句中加IN应该如何使用
  7. 浏览器向服务器发送的消息称为,网络是怎样连接之浏览器的探索之旅读书笔记(一)...
  8. 只有绩效,才是检验创新的唯一标准
  9. 使用CodeBlocks编译64位程序(用的编译器仅仅是windows sdk的)
  10. 如何用Latex合并两个pdf
  11. Redis哨兵原理详解
  12. 全球最顶级的十大创新公司
  13. 如何让C盘可用空间变大
  14. Ubuntu 测网速
  15. php报表插件,excel插件
  16. Java万字长文基础知识总结
  17. python模块和包_(三)运用Python模块和包
  18. TPLINK WR941N V2_090803 路由器 后门
  19. 关于可能的OPPO HR面
  20. Linux cma内存的使用

热门文章

  1. thingsboard 编译失败,报错 Failed to execute goal com.mycila:license-maven-plugin:3.0
  2. 2019上海ICPC H.Tree Partition
  3. C#语言实例源码系列-虚拟键盘
  4. Vue+SpringBoot介绍
  5. 计算机四级 信息安全工程师 题库 前言
  6. python_爬虫_七麦网
  7. 首师大附中科创教育平台 我的刷题记录 0324 99999999海岛帝国:运输资源
  8. 解决:用电脑在B站看视频声音太小的问题
  9. c++语言 构造函数,C++中构造函数的写法
  10. 二叉树:先序遍历,中序遍历,后序遍历,层序/层次遍历