基于Sklearn处理分类数据

有时候根据某种特征而不是数量来度量对象会更有效。常常使用这种定性的信息来判断一个观察值的属性,比如按照性别、颜色或者车的品牌这样的类别对其进行分类。但并不是所有的分类数据都是这样的。本身没有内在顺序的类别称为nominal,相反,如果一组分类天然拥有内在的顺序性,就被称为ordinal。

1. 对nominal型分类特征编码

存在一个没有内部顺序的nominal型分类特征,现在对其进行处理

  • 利用sklearn的LabelBinarizer对特征进行one-hot编码(独热编码):
import numpy as np 
from sklearn.preprocessing import LabelBinarizer,MultiLabelBinarizer

#创建特征
feature = np.array([["Texas"],
                    ["California"],
                    ["Texas"],
                    ["Delaware"],
                    ["Texas"]])
#创建one-hot编码
one_hot = LabelBinarizer()
#对特征进行one-hot编码
one_hot.fit_transform(feature)

—>

array([[0, 0, 1],
       [1, 0, 0],
       [0, 0, 1],
       [0, 1, 0],
       [0, 0, 1]])
#对one-hot编码逆转换
one_hot.inverse_transform(one_hot.transform(feature))

—>

array(['Texas', 'California', 'Texas', 'Delaware', 'Texas'], dtype='<U10')
  • 使用pandas对特征进行one-hot编码:
import pandas as pd
#创建虚拟变量
pd.get_dummies(feature[:,0])

—>

    California	Delaware	Texas
0	0	        0	        1
1	1	        0	        0
2	0	        0	        1
3	0	        1	        0
4	0	        0	        1

scikit-learn还可以处理每个观察值存在对个分类的情况,使用MultiLabelBinarizer()。

另外,在one-hot编码之后,最好从结果矩阵中删除一个one-hot编码的特征,以避免线性依赖。

2. 对ordinal分类特征编码

问题描述:存在一个ordinal分类特征(例如,高,中等,低),现在要对其编码。

解决方案:使用pandas数据帧的replace方法将字符串标签转换成相应的数字。

import pandas as pd
#创建特征
dataframe = pd.DataFrame({
    
    "score":["Low","Low","Medium","Medium","High"]})
#创建映射器
scale_mapper = {
    
    "Low":1,
                "Medium":2,
                "High":3}
#使用映射器来替换特征
dataframe['score'].replace(scale_mapper)

—>

0    1
1    1
2    2
3    2
4    3

对那些用于机器学习的特征进行编码时,需要将ordinal分类转换成数值,同时保留其顺序。最常见的方法就是,创建一个字典,将分类的字符串映射成一个数字,然后将其映射在特征上。

3. 对特征字典编码

使用DictVectorizer将一个字典转换成一个特征矩阵:

from sklearn.feature_extraction import DictVectorizer
#创建一个字典
data_dict = [{
    
    "Red":2,"Blue":4},
             {
    
    "Red":4,"Blue":3},
             {
    
    "Red":1,"Yello":2},
             {
    
    "Red":2,"Yello":2}]
#创建字典向量化器
dictvectorizer = DictVectorizer(sparse=False)
#将字典转换成特征矩阵
features = dictvectorizer.fit_transform(data_dict)
#查看特征矩阵
features

—>

array([[4., 2., 0.],
       [3., 4., 0.],
       [0., 1., 2.],
       [0., 2., 2.]])

默认情况下,Dictvectorizer会输出一个稀疏矩阵来存储除0以外的元素。如果矩阵很庞大,这么做有助于节省内存。通过指定sparse=False能强制DictVectorizer输出一个稠密矩阵。

使用get_feature_names方法可以获得所生成的特征的名字:

#获取特征的名字
feature_names = dictvectorizer.get_feature_names()
feature_names

—>

['Blue', 'Red', 'Yello']
import pandas as pd
#从特征中创建数据帧
pd.DataFrame(features,columns=feature_names)

—>

    Blue  Red	Yello
0	4.0	  2.0	0.0
1	3.0	  4.0	0.0
2	0.0	  1.0	2.0
3	0.0	  2.0	2.0

4. 填充缺失的分类值

问题描述:有一个分类特征中包含缺失值,需要用预测值来填充。

解决方案:最理想的解决方案是训练一个机器学习分类器来预测缺失值,通常会使用KNN分类器:

import numpy as np
from sklearn.neighbors import KNeighborsClassifier
#用分类特征创建特征矩阵
X = np.array([[0,2.10,1.45],
              [1,1.18,1.33],
              [0,1.22,1.27],
              [1,-0.21,-1.19]])
#创建带缺失值的特征矩阵
X_with_nan = np.array([[np.nan,0.87,1.31],
                       [np.nan,-0.67,-0.22]])
#训练KNN分类器
clf = KNeighborsClassifier(3,weights='distance')
trained_model = clf.fit(X[:,1:],X[:,0])
#预测缺失值的分类
imputed_values = trained_model.predict(X_with_nan[:,1:])
#将所预测的分类和它们的其他特征连接起来
X_with_imputed = np.hstack((imputed_values.reshape(-1,1),X_with_nan[:,1:]))
#连接两个特征矩阵
np.vstack((X_with_imputed,X))

—>

array([[ 0.  ,  0.87,  1.31],
       [ 1.  , -0.67, -0.22],
       [ 0.  ,  2.1 ,  1.45],
       [ 1.  ,  1.18,  1.33],
       [ 0.  ,  1.22,  1.27],
       [ 1.  , -0.21, -1.19]])

另一个解决方案是用特征中出现次数最多的值来填充缺失值

from sklearn.impute import SimpleImputer
#连接两个特征矩阵
X_complete = np.vstack((X_with_nan,X))
imputer = SimpleImputer(missing_values=np.nan,strategy='most_frequent')
imputer.fit_transform(X_complete)

—>

array([[ 0.  ,  0.87,  1.31],
       [ 0.  , -0.67, -0.22],
       [ 0.  ,  2.1 ,  1.45],
       [ 1.  ,  1.18,  1.33],
       [ 0.  ,  1.22,  1.27],
       [ 1.  , -0.21, -1.19]])

当分类特征中存在缺失值时,最好的解决方案是利用机器学习算法预测缺失值。将带缺失值的特征作为目标向量,将其他特征作为特征矩阵,就能完成预测。常用的算法是KNN,它会将k个最近的观察值的中位数作为缺失值的填充值。

另外,可以用特征中出现次数最多的分类来填充缺失值。虽然比使用KNN效果差一些,但是能更容易地扩展到大数据集上。

5. 处理不均衡分类

猜你喜欢

转载自blog.csdn.net/weixin_44127327/article/details/108783830
今日推荐