特征工程(文本特征提取CountVectorizer、TF-IDF 分词jieba、归一化、标准化 )、python示例

特征工程是什么

  • 特征工程是将原始数据转换为更好地代表预测模型的潜在问题的特征的过程,从而提高了模型对未知数据预测的准确性
  • 如把一段文字转化为矩阵:

数据的特征抽取

  • sklearn特征抽取API sklearn.feature_extraction
  • 为了计算机更好的去理解数据

字典特征提取

对字典数据进行特征值化

"""先把要用到的所有包导入"""
from sklearn.feature_extraction import DictVectorizer #对字典数据进行特征值化
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer #频率统计和频率乘以重要性得统计
from sklearn.preprocessing import MinMaxScaler, StandardScaler #归一化 标准化
from sklearn.feature_selection import VarianceThreshold #低方差降维
from sklearn.decomposition import PCA  #decomposition降维
import jieba #中文分词
import numpy as np
from sklearn.impute import SimpleImputer #缺失值处理
# 实例化(实例化的是一个转换器)
# sparse是稀疏矩阵,若为True,输出的是每个不为零位置的坐标,稀疏矩阵可以节省存储空间
dic = DictVectorizer(sparse=True)  

# 每个样本都是一个字典,有三个样本
# 调用fit_transform:适应数据并将数据转化
data = dic.fit_transform([{'city': '北京', 'temperature': 100},
                           {'city': '上海', 'temperature': 60},
                           {'city': '深圳', 'temperature': 30}])
print(f"字典数据转化后的结果是:\n{data}")
print('-' * 50)
print(dic.get_feature_names())  # 字典中的一些类别数据,分别进行转换成特征
print('-' * 50)
print(dic.inverse_transform(data))  #去看每个特征代表的含义,逆转回去


字典数据转化后的结果是:
  (0, 1)	1.0
  (0, 3)	100.0
  (1, 0)	1.0
  (1, 3)	60.0
  (2, 2)	1.0
  (2, 3)	30.0
--------------------------------------------------
['city=上海', 'city=北京', 'city=深圳', 'temperature']
--------------------------------------------------
[{'city=北京': 1.0, 'temperature': 100.0}, {'city=上海': 1.0, 'temperature': 60.0}, {'city=深圳': 1.0, 'temperature': 30.0}]


若 dic = DictVectorizer(sparse=True) 或 dic.toarray(),则 data 的结果为:(只是显示方式不同)
字典数据转化后的结果是:
[[  0.   1.   0. 100.]
 [  1.   0.   0.  60.]
 [  0.   0.   1.  30.]]
  • 这个字典数据有4个特征[‘city=上海’, ‘city=北京’, ‘city=深圳’, ‘temperature’],3个样本,所以转化后是3×4的矩阵。
  • 以第一个字典样本为例,第1个特征(从0开始计)和第三个特征出现,所以data[0,1]=1,data[0,3]=100

文本特征提取

对文本数据进行特征值化

英文文本

"""一段英文文本如何变为数值类型"""
# 实例化CountVectorizer(min_df=2,max_df=1.0),统计样本词频
# max_df, min_df整数:指每个词的所有文档词频数不小于最小值,出现该词的文档数目小于等于max_df
# max_df, min_df小数:某个词的出现的次数/所有文档数量
# 默认会去除单个字母的单词,默认认为这个词对整个样本没有影响
vector = CountVectorizer()

# 调用fit_transform输入并转转换数据
res = vector.fit_transform(
    ["life is  short,i like python life",
     "life is too long,i dislike python",
     "life is short"])

print(res)
print('-'*50)
print(res.toarray())
print('-'*50)
print(vector.get_feature_names())
print('-'*50)
#拿每个样本里的特征进行显示
print(vector.inverse_transform(res))


结果:
  (0, 2)	2
  (0, 1)	1
  (0, 6)	1
  (0, 3)	1
  (0, 5)	1
  (1, 2)	1
  (1, 1)	1
  (1, 5)	1
  (1, 7)	1
  (1, 4)	1
  (1, 0)	1
  (2, 2)	1
  (2, 1)	1
  (2, 6)	1
--------------------------------------------------
[[0 1 2 1 0 1 1 0]
 [1 1 1 0 1 1 0 1]
 [0 1 1 0 0 0 1 0]]
--------------------------------------------------
['dislike', 'is', 'life', 'like', 'long', 'python', 'short', 'too']
--------------------------------------------------
[array(['life', 'is', 'short', 'like', 'python'], dtype='<U7'), 
 array(['life', 'is', 'python', 'too', 'long', 'dislike'], dtype='<U7'), 
 array(['life', 'is', 'short'], dtype='<U7')]
  • 解释:在第一个样本中,第1个特征(is)出现1次,第2个特征(life)出现2次,…
  • 英文文本是按照空格进行分隔的,但是这种分割方式不适用于中文,所以要先用jieba包把中文文本分词,再按照空格连接起来,再统计词频。

中文文本

""" 通过jieba对中文进行分词"""
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)

# 统计词频
cv = CountVectorizer()
data = cv.fit_transform([c1, c2, c3])

print(content1)
print('-' * 50)
print(data.toarray())
print('-' * 50)
print(cv.get_feature_names())
                 
                 
结果:
今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。
--------------------------------------------------
[[0 0 1 0 0 0 2 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 2 0 1 0 2 1 0 0 0 1 1 0 0 0]
 [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 1 1]
 [1 1 0 0 4 3 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0]]
--------------------------------------------------
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', 
 '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', 
 '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个',
 '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']                 
  • 若现在要对文章进行分类,如果某些词在别的文章也经常出现,那这种词就是没价值的;如果某些词在别的文章很少出现或不出现,那么这种词就是有价值的。所以不能仅仅以词频作为标准,还得有一个权重,这个权重就是IDF:逆向文件频率

IDF=lg(总文件数目/包含该词语的文件数目)
TfidfVectorizer()可以直接实现"词频×IDF"

TF-IDF

"""中文特征值化,计算tfidf值"""
#c1,c2,c3用上一个例子的文本
tf = TfidfVectorizer()
data = tf.fit_transform([c1, c2, c3])
print(data.toarray())
print('-'*50)
print(tf.get_feature_names())

结果:
[[0.         0.         0.21821789 0.         0.         0.
  0.43643578 0.         0.         0.         0.         0.
  0.21821789 0.         0.21821789 0.         0.         0.
  0.         0.21821789 0.21821789 0.         0.43643578 0.
  0.21821789 0.         0.43643578 0.21821789 0.         0.
  0.         0.21821789 0.21821789 0.         0.         0.        ]
 [0.         0.         0.         0.2410822  0.         0.
  0.         0.2410822  0.2410822  0.2410822  0.         0.
  0.         0.         0.         0.         0.         0.2410822
  0.55004769 0.         0.         0.         0.         0.2410822
  0.         0.         0.         0.         0.48216441 0.
  0.         0.         0.         0.         0.2410822  0.2410822 ]
 [0.15698297 0.15698297 0.         0.         0.62793188 0.47094891
  0.         0.         0.         0.         0.15698297 0.15698297
  0.         0.15698297 0.         0.15698297 0.15698297 0.
  0.1193896  0.         0.         0.15698297 0.         0.
  0.         0.15698297 0.         0.         0.         0.31396594
  0.15698297 0.         0.         0.15698297 0.         0.        ]]
--------------------------------------------------
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']

数据的特征处理

  1. 数值型数据:
    1. 归一化
    2. 标准化
    3. 缺失值
  2. 类别型数据:one-hot编码
  3. 时间类型:时间的切分

归一化

  • 通过对原始数据进行变换把数据映射到(默认为[0,1])之间
  • 公式:

𝑋 ′ = 𝑥 − 𝑚 𝑖 𝑛 𝑚 𝑎 𝑥 − 𝑚 𝑖 𝑛 𝑋 ′ ′ = 𝑋 ′ ∗ ( 𝑚 𝑥 − 𝑚 𝑖 ) + 𝑚 𝑖 𝑋^′= \frac{𝑥−𝑚𝑖𝑛}{𝑚𝑎𝑥−𝑚𝑖𝑛}\\ 𝑋^′′=𝑋^′∗(𝑚𝑥−𝑚𝑖)+𝑚𝑖 X=maxminxminX=X(mxmi)+mi
注:作用于每一列,max为一列的最大值,min为一列的最小值,那么X’’为最终结果,mx,mi分别为指定区间值默认mx为1,mi为0

# 归一化缺点 容易受极值的影响
#feature_range代表特征值范围,一般设置为[0,1],或者[-1,1],默认是[0,1]
mm = MinMaxScaler(feature_range=(0, 
data = mm.fit_transform([[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46
print(data)
    
[[1.         0.         0.         0.        ]
 [0.         1.         1.         0.83333333]
 [0.5        0.5        0.6        1.        ]]

标准化

  • 通过对原始数据进行变换把数据变换到均值为0,标准差为1范围内
  • 公式:

Font metrics not found for font: .

std = StandardScale
data = std.fit_transform([[1., -1., 3.], [2., 4., 2.], [4., 6., -1.
print(data)
                                                        
[[-1.06904497 -1.35873244  0.98058068]
 [-0.26726124  0.33968311  0.39223227]
 [ 1.33630621  1.01904933 -1.37281295]]                                                        

对于归一化来说:如果出现异常点,影响了最大值和最小值,那么结果显然会发生改变
对于标准化来说:如果出现异常点,由于具有一定数据量,少量的异常点对于平均值的影响并不大,从而方差改变较小。

缺失值

  1. 删除:如果每列或者行数据缺失值达到一定的比例,建议放弃整行或者整列
  2. 插补:可以通过缺失值每行或者每列的平均值、中位数来填充
# NaN, nan,缺失值必须是这种形式,如果是?号(或者其他符号),就要replace换成这种
im = SimpleImputer(missing_values=np.nan, strategy='median') #均值,众数,中位
data = im.fit_transform([[1, 2], [np.nan, 3], [7, 6], [3, 2
print(data)
    
    
[[1. 2.]
 [3. 3.]
 [7. 6.]
 [3. 2.]]

特征选取

特征选取原因

  1. 冗余:部分特征的相关度高,容易消耗计算性能
  2. 噪声:部分特征对预测结果有负影响

特征选取是什么

  • 特征选择就是单纯地从提取到的所有特征中选择部分特征作为训练集特征,特征在选择前和选择后可以改变值、也可以不改变值,但是选择后的特征维数肯定比选择前小,毕竟我们只选择了其中的一部分特征。
  • 主要方法:
    • Filter(过滤式):VarianceThreshold
    • Embedded(嵌入式):正则化、决策树
    • Wrapper(包裹式)

删除低方差的特征

#默认只删除方差为0,threshold是方差阈值,删除比这个值小的那些特征
var = VarianceThreshold(threshold
data = var.fit_transform([[0, 2, 0, 3],
                          [0, 1, 4, 3],
                          [0, 1, 1, 3
print(data)
# 获得剩余的特征的列编号
print('The surport is %s' % var.get_support(True))
                           
                           
结果:
[[2 0]
 [1 4]
 [1 1]]
The surport is [1 2]                           

主成分分析进行特征降维

# n_ components:小数 0~1 90% 业界选择 90~95%
#
# 如果是整数   减少到的特
pca = PCA(n_components=0
data = pca.fit_transform([[2, 8, 4, 5], [6, 3, 0, 8], [5, 4, 9, 1
print(data)
                                                       
结果:                                                       
[[ 1.28620952e-15]
 [ 5.74456265e+00]
 [-5.74456265e+00]]                                                       
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_961876584

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值