首要的任务是机器学习前的数据处理部分,这里讲解构建特征工程
字符串数据尽量转换为数值型的数据,这里的工具采用sk-learn
#sparse矩阵转换成数组的形式
from sklearn.feature_extraction import DictVectorizer
alist = [
{'city':'BeiJing','temp':33},
{'city':'GZ','temp':42},
{'city':'SH','temp':40}
]
#创建工具对象
d = DictVectorizer(sparse=False)
#使用该工具对象进行特征值化
result = d.fit_transform(alist)
names = d.get_feature_names()
print(names)
print(result) #返回的结果是一个sparse矩阵
结果:
[[ 1. 0. 0. 33.]
[ 0. 1. 0. 42.]
[ 0. 0. 1. 40.]]
OneHot编码
基于pandas实现独热编码(Onehot编码)
# 创建数据集
import pandas as pd
df = pd.DataFrame([
['green', 'M', 20, 'class1'],
['red', 'L', 21, 'class2'],
['blue', 'XL',30, 'class3']])
df.columns = ['color', 'size', 'weight', 'class label']
# 编码转换颜色和大小
r1 = pd.get_dummies(df['color']) # 将颜色转换为独热编码
new_df = pd.concat((df,r1),axis=1).drop(labels='color',axis=1)
new_df['new_size'] = new_df['size'].map({'M':1,'L':2,'XL':3})
new_df = new_df.drop(labels='size',axis=1)
- 作用:对文本数据进行特征值化
- API:from sklearn.feature_extraction.text import CountVectorizer
- fit_transform(X):X为文本或者包含文本字符串的可迭代对象,返回sparse矩阵
- inverse_transform(X):X为array数组或者sparse矩阵,返回转换之前的格式数据
- get_feature_names()
- toarray():将sparse矩阵换成数组
from sklearn.feature_extraction.text import CountVectorizer
alist = [
'left is is short,i love python',
'left is too long,i hate python'
]
c = CountVectorizer()
result = c.fit_transform(alist)
print(c.get_feature_names())
#toarray可以将sparse矩阵转换为数组
print(result.toarray())
结果:每个单词出现的次数,一个字母的不计数
['hate', 'is', 'left', 'long', 'love', 'python', 'short', 'too']
[[0 2 1 0 1 1 1 0]
[1 1 1 1 0 1 0 1]]
没有包需要导入:pip install jieba
为什么需要引入jieba分词,是因为文本识别只能对符合和空格分隔,一段文字不能分开
import jieba
from sklearn.feature_extraction.text import CountVectorizer
text = [
'因为在自然语言处理中,我们是需要将一段中文文本中相关的词语,成语,形容词......都要进行抽取的',
'目前CountVectorizer只可以对有标点符号和用分隔符对应的文本进行特征抽取,显然这是满足不了我们日常需求的'
]
new_text = []
for t in text:
r = list(jieba.cut(t))
s = ' '.join(r)
new_text.append(s)
c = CountVectorizer()
result = c.fit_transform(new_text)
print(c.get_feature_names())
print(result.toarray())
如果认为每一个特征具有同等大小的权重都同等重要,则必须要对其进行归一化处理。
通过对原始数据进行变换将数据映射到0-1之间(默认),归一化后的数据服从正态分布
# 归一化处理
from sklearn.preprocessing import MinMaxScaler
mm = MinMaxScaler()
result = mm.fit_transform(feature)
print(result)
标准化的处理
API
# 标准化处理
from sklearn.preprocessing import StandardScaler
s = StandardScaler()
result = s.fit_transform(feature)
print(result)
归一化和标准化总结:
StandardScaler和MinMaxScaler选哪个?
# 过滤方差小于阈值的
from sklearn.feature_selection import VarianceThreshold
# threshold:方差的阈值
v = VarianceThreshold(threshold=0.2)
result = v.fit_transform(feature)
一般的手法是过滤一半,所以会选择所有特征的方差中位数作为方差阈值过滤的条件
import numpy as np
median_value = np.median(feature.var(axis=0).values)
v = VarianceThreshold(threshold=median_value)
result = v.fit_transform(feature)
一般衡量的方法也就看其最后模型训练的精度以及耗时
在误差较小的情况下,用低维度表示高纬度的事物
目的:特征数量达到上百,上千的时候,考虑数据的优化。使数据维度压缩,尽可能降低源数据的维度(复杂度),损失少量信息。
作用:可以削减回归分析或者聚类分析中特征的数量
矩阵分解:
PCA语法
from sklearn.decomposition import PCA
#将数据分解为较低维度的空间
#n_components可以为小数(保留特征的百分比),整数(减少到的特征数量)
pca = PCA(n_components=2)
pca.fit_transform([[0,2,4,3],[0,3,7,3],[0,9,6,3]])
用于分类的问题,计算特征的重要性
实则就是将连续型数据转换为离散型
分箱的作用&意义
分箱的实现
import pandas as pd
import numpy as np
# 1、cut:等距分箱:每个范围大小一致
ages = np.random.randint(1,80,size=(25,)) #连续型变量
#使用分箱对连续性变量进行离散化
#bins:分箱的个数(分组的个数)
cut_resutl = pd.cut(ages,bins=5) # [(16.0, 30.0], (16.0, 30.0], (16.0, 30.0], (1.93, 16.0], (1.93, 16.0], ..., (30.0, 44.0], (1.93, 16.0], (16.0, 30.0], (1.93, 16.0], (44.0, 58.0]] Length: 25 Categories (5, interval[float64, right]): [(1.93, 16.0] < (16.0, 30.0] < (30.0, 44.0] < (44.0, 58.0] < (58.0, 72.0]]
#labels可以替换原先箱子/组的名称
cut_result = pd.cut(ages,bins=5,labels=['a','b','c','d','e'])
v_result = cut_result.value_counts()
# 结果
a 7
b 6
c 3
d 4
e 5
# 2、等频分箱-qcut
ages = np.random.randint(1,80,size=(25,)) #连续型变量
#q表示箱子的个数
qcut_result = pd.qcut(ages,q=5)
qcut_result.value_counts()
# 结果:
(3.999, 16.8] 5
(16.8, 46.2] 5
(46.2, 61.4] 5
(61.4, 69.0] 5
(69.0, 79.0] 5
概念:
IV其核心就是要理解“用IV去衡量变量预测能力”这句话。
我们假设在一个分类问题中,目标变量的类别有两类:Y1,Y2。对于一个待预测的样本A,要判断A属于Y1还是Y2,我们是需要一定的信息,假设这个信息总量是I,而这些所需要的信息,就蕴含在所有的待预测样本的特征C1,C2,C3,……,Cn中,那么,对于其中的一个特征Ci来说,其蕴含的信息越多,那么它对于判断A属于Y1还是Y2的贡献就越大,Ci的信息价值就越大,Ci的IV就越大,它就越应该进入到入模变量列表中。
计算woe和iv
再计算该特征的总值IV,按照阈值划分:
IV | 预测能力 |
---|---|
<0.03 | 无 |
0.03-0.09 | 低 |
0.1-0.29 | 中 |
0.3-0.49 | 高 |
>=0.5 | 极高 |
练习测试
import sklearn.datasets as dt
import numpy as np
cancer = dt.load_breast_cancer()
feature = cancer['data']
target = cancer['target']
#通过value_counts检测特征是否为连续性变量
pd.Series(feature[:,0]).value_counts()
#函数的封装,最终返回一个特征的总IV值
def get_iv(f,bins,target):
#f表示一个维度的特征,bins表示分箱的箱数,taget表示样本标签
target_count = pd.Series(target).value_counts()
s_p = target_count[1]#样本中正例样本的数量
s_n = target_count[0]#样本中反例样本的数量
#对f1特征进行分箱
f1_cut = pd.qcut(f,q=bins)
#依次求出5个箱子中正反例样本的数量
c_result_df = pd.crosstab(f1_cut,target)
ivs = 0
for index in c_result_df.index:
#当前组中正例样本的数量
n_count = c_result_df.loc[index][1]
#当前组中反例样本的数量
p_count = c_result_df.loc[index][0]
woe = np.log((n_count/s_p)/(p_count/s_n))
iv = ((n_count/s_p)-(p_count/s_n))*woe
ivs += iv
return ivs
#可以将每一个维度特征都进行iv计算
for col in range(0,30):
f1 = feature[:,col]
result = get_iv(f=f1,bins=3,target=target)
print(result)
一般划分数据集分为训练集和测试集,也有验证集的部分,这里主要阐述训练集和验证集
训练集:训练模型
测试集:评估模型
数据集划分的API
sklearn自带相关数据集
#获取小规模数据集
import sklearn.datasets as datasets
# 红酒数据集,有三类
data = datasets.load_wine()
#提取特征数据和标签数据
feature = data['data']
target = data['target']
#返回大规模数据集
#data_home:将数据存储到位置
#subset:all,train,test
#random_state:随机种子
datasets.fetch_20newsgroups(data_home='./datasets',subset='test')
切分数据集
#如何切分数据集
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
feature = iris['data']
target = iris['target']
# x_train:训练集的特征数据
# y_train:训练集的标签数据
# x_test:测试集的特征数据
# y_test:测试集的标签数据
# random_state就是为了保证程序每次运行都分割一样的训练集和测试集。否则,同样的算法模型在不同的训练集和测试集上的效果不一样
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)