特征工程-特征构造

1 特征构建引言

如下数据如何放入机器学习算法中
在这里插入图片描述
可以看出数据中有分类数据,还有缺失值,非数值型的数据,目前的大部分机器学习算法是不能处理有缺失值的数据,机器学习使用的都是数学和统计学的方法,所以需要对这份数据进行特征构建,使它能够放入到机器学习中去。

2.分类数据的填充

识别每列的类型和等级

boolean (布尔值):此列是二元分类数据(是/否),定类等级。
city(城市):此列是分类数据,也是定类等级。
ordinal_column(顺序列):顾名思义,此列是顺序数据,定序等级
quantitative_column(定量列):此列是整数,定比等级。

import pandas as pd
X = pd.DataFrame(
    {
        'city': ['tokyo', None, 'london', 'seattle', 'san francisco','tokyo'],
        'boolean': ['yes', 'no', None, 'no', 'no', 'yes'],
        'ordinal_column': ['somewhat like', 'like', 'somewhat like', 'like', 'somewhat like', 'dislike'],
        'quantitative_column': [1, 11, -.5, 10, None, 20]
    }
)

在这里插入图片描述首先对分类数据进行处理,分类数据最常见的是众数填充

X['city'].fillna(X['city'].value_counts().index[0])   # 众数填充

在这里插入图片描述fillna()不会对原数据进行修改,要想修改原数据,加上参数inplace=True
如果分类数据很多,不想一个一个的填充可以

3 自定义分类数据填充器

利用scikit-learn的TransformerMixin基类创建自定义分类填充器。

from sklearn.base import TransformerMixin
class CustomCategoryImputer(TransformerMixin):   # 自定义分类填充器
    def __init__(self, cols=None):
        self.cols = cols

    def transform(self, df):
        X = df.copy()
        for col in self.cols:
            X[col].fillna(X[col].value_counts().index[0], inplace=True)
        return X

    def fit(self, *_):
        return self

TransformerMixin使用说明
这个类就只有一个方法,下面是它的源码

class TransformerMixin:
    """Mixin class for all transformers in scikit-learn."""

    def fit_transform(self, X, y=None, **fit_params):
        """
        Fit to data, then transform it.
        Fits transformer to `X` and `y` with optional parameters `fit_params`
        and returns a transformed version of `X`.
        Parameters
        ----------
        X : array-like of shape (n_samples, n_features)
            Input samples.
        y :  array-like of shape (n_samples,) or (n_samples, n_outputs), \
                default=None
            Target values (None for unsupervised transformations).
        **fit_params : dict
            Additional fit parameters.
        Returns
        -------
        X_new : ndarray array of shape (n_samples, n_features_new)
            Transformed array.
        """
        # non-optimized default implementation; override when a better
        # method is possible for a given clustering algorithm
        if y is None:
            # fit method of arity 1 (unsupervised transformation)
            return self.fit(X, **fit_params).transform(X)
        else:
            # fit method of arity 2 (supervised transformation)
            return self.fit(X, y, **fit_params).transform(X)

下面进行填充

cci = CustomCategoryImputer(cols=['city', 'boolean'])
cci.fit_transform(X)

在这里插入图片描述city和boolean没有缺失值了。写成类的形式是为了可以应用到后面的机器学习流水线上简化代码

4 自定义定量数据填充器

from sklearn.impute import SimpleImputer
class CustomQuantitativeImputer(TransformerMixin):    # 自定义定量填充器
    def __init__(self, cols=None, strategy='mean'):
        self.cols = cols
        self.strategy = strategy

    def transform(self, df):
        X = df.copy()
        impute = SimpleImputer(strategy=self.strategy)
        for col in self.cols:
            X[col] = impute.fit_transform(X[[col]])
        return X

    def fit(self, *_):
        return self
cqi = CustomQuantitativeImputer(cols=['quantitative_column'], strategy='mean')
cqi.fit_transform(X)

在这里插入图片描述定量数据也填充完了,接下来进行流水线的组装

# 放入流水线中
from sklearn.pipeline import Pipeline
imputer = Pipeline([('quant', cqi), ('category', cci)])
imputer.fit_transform(X)

在这里插入图片描述

5 编码定类数据

经过以上的处理已经没有缺失值了,接下来就要处理非数值型的数据了
任何机器学习算法,需要的输入特征都必须是数值。
定类等级的编码
定序等级的编码

定类编码
主要方法是将分类数据转换为虚拟变量(dummy variable),有两种选择:
1.用Pandas自动找到分类变量并进行编码;
2.创建自定义虚拟变量编码器,在流水线中工作。
虚拟变量的取值是1或0,代表某个类别的有无,是定性数据的代理。

pd.get_dummies(X,
               columns = ['city', 'boolean'],  # 要虚拟化的列
               prefix_sep='__'  # 前缀(列名)和单元格值之间的分隔符
              )

在这里插入图片描述定义分类填充类

class CustomDummifier(TransformerMixin):   # 自定义虚拟变量编码器
    def __init__(self, cols=None):
        self.cols = cols

    def transform(self, X):
        return pd.get_dummies(X, columns=self.cols)

    def fit(self, *_):
        return self
cd = CustomDummifier(cols=['boolean', 'city'])
cd.fit_transform(X)

在这里插入图片描述

ordinal_column是定序数据,有大小的区分的,like>somelike>dislike

6 编码定序变量

定序等级的编码

标签编码器:顺序数据的每个标签都会有一个相关数值。
dislike、somewhat like和like 用0、1、2来表示。
X[‘ordinal_column’].map(lambda x: ordering.index(x))

ordering = ['dislike', 'somewhat like', 'like']               # 0是dislike,1是somewhat like,2是like
print(X['ordinal_column'].map(lambda x: ordering.index(x)))   # 将ordering映射到顺序列

在这里插入图片描述这里的数值映射要设置的合理,这个数值要参与模型的训练。本来ordinal_column是定序变量,数据间的差值没有意义,所以设置数据时差别不要太大。

class CustomEncoder(TransformerMixin):  # 还是将自定义标签编码器放进流水线中:
    def __init__(self, col, ordering=None):
        self.ordering = ordering
        self.col = col

    def transform(self, df):
        X = df.copy()
        X[self.col] = X[self.col].map(lambda x: self.ordering.index(x))
        return X

    def fit(self, *_):
        return self
ce = CustomEncoder(col='ordinal_column', ordering=['dislike', 'somewhat like', 'like'])
ce.fit_transform(X)

在这里插入图片描述

7 连续变量分箱

有时需要将数值数据转换为分类变量,如年龄段可能比具体年龄更有用。

pd.cut(X['quantitative_column'], bins=3)

在这里插入图片描述

class CustomCutter(TransformerMixin):
    def __init__(self, col, bins, labels=False):
        self.labels = labels
        self.bins = bins
        self.col = col

    def transform(self, df):
        X = df.copy()
        X[self.col] = pd.cut(X[self.col], bins=self.bins, labels=self.labels)
        return X

    def fit(self, *_):
        return self
cc = CustomCutter(col='quantitative_column', bins=3)
cc.fit_transform(X)

在这里插入图片描述

8 在流水线中封装预处理操作

先是SimpleImputer
然后是虚拟变量
接着编码顺序列
最后分箱定量列
拟合流水线
pipe = Pipeline([("imputer", imputer), ('dummify', cd), ('encode', ce), ('cut', cc)])
pipe.fit(X)
pipe.transform(X)

在这里插入图片描述

9 拓展数值特征的模型基线

动作识别
胸部加速度计识别动作数据集

15名参与者的7种动作:序号;轴加速度;轴加速度;轴加速度;标签。
数据集按参与者划分,标签是数字,每个数字代表一种动作(activity) .
根据智能手机等设备上加速度计的x、y、z读数识别用户的当前动作。

动作识别
activity列的数字有如下意义。
1:在电脑前工作
2:站立、走路和上下楼梯
3:站立
4:走路
5:上下楼梯
6:与人边走边聊
7:站立着讲话
数据获取提取码:y4fz
我们要做的就是通过x,y,z。识别出人的动作
仅仅凭借这三个特征是很难进行预测的,我们需要做的是根据这三个特征进行交互,构建新的特征

data = pd.read_csv('1.csv', header=None)
data.columns = ['index', 'x', 'y', 'z', 'activity']
data['activity'].value_counts(normalize=True)

在这里插入图片描述

X = data[['x', 'y', 'z']]   # 删除响应变量,建立特征矩阵
y = data['activity']

先构建一个基础模型

# 网格搜索所需的变量和实例
# 需要试验的KNN模型参数
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
knn_params = {'n_neighbors':[3, 4, 5, 6]}
knn = KNeighborsClassifier()
grid = GridSearchCV(knn, knn_params)
grid.fit(X, y)

在这里插入图片描述查看模型的性能

grid.best_score_, grid.best_params_

在这里插入图片描述扩展特征

10 多项式特征模型性能

poly = PolynomialFeatures(degree=2, include_bias=False, interaction_only=False)
根据原有列的乘积创建新列,用于捕获特征交互,[a, b]->[1, a, b, a^2, ab, b^2]

from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2, include_bias=False, interaction_only=False)  # 二项式特征
X_poly = poly.fit_transform(X)
pd.DataFrame(X_poly, columns=poly.get_feature_names()).head()

在这里插入图片描述看模型是否提升

pipe_params = {'poly_features__degree':[1, 2, 3], 'poly_features__interaction_only':[True, False], 'classify__n_neighbors':[3, 4, 5, 6]}
pipe = Pipeline([('poly_features', poly), ('classify', knn)])
grid = GridSearchCV(pipe, pipe_params)
grid.fit(X, y)
grid.best_score_, grid.best_params_

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这是opencv svm图像分类的整个工程代码,在VS2010下打开即可。整个工程文件以及我的所有训练的图片存放在这里,需要的可以下载,自己在找训练图片写代码花了很多时间,下载完后自行解压,训练图片和测试图片可以从这免费下载http://download.csdn.net/detail/always2015/8944959,project data文件夹直接放在D盘就行,里面存放训练的图片和待测试图片,以及训练过程中生成的中间文件,现在这个下载object_classfication_end则是工程文件,我用的是vs2010打开即可,下面工程里有几个要注意的地方: 1、在这个模块中使用到了c++的boost库,但是在这里有一个版本的限制。这个模块的代码只能在boost版本1.46以上使用,这个版本以下的就不能用了,直接运行就会出错,这是最需要注意的。因为在1.46版本以上中对比CsSVM这个类一些成员函数做了一些私有化的修改,所以在使用该类初始化对象时候需要注意。 2、我的模块所使用到的函数和产生的中间结果都是在一个categorizer类中声明的,由于不同的执行阶段中间结果有很多个,例如:训练图片聚类后所得到单词表矩阵,svm分类器的训练的结果等,中间结果的产生是相当耗时的,所以在刚开始就考虑到第一次运行时候把他以文件XML的格式保存下来,下次使用到的时候在读取。将一个矩阵存入文本的时候可以直接用输出流的方式将一个矩阵存入,但是读取时候如果用输入流直接一个矩阵变量的形式读取,那就肯定报错,因为输入流不支持直接对矩阵的操作,所以这时候只能对矩阵的元素一个一个进行读取了。 3、在测试的时候,如果输入的图片太小,或者全为黑色,当经过特征提取和单词构造完成使用svm进行分类时候会出现错误。经过调试代码,发现上述图片在生成该图片的单词的时候所得到的单词矩阵会是一个空矩阵,即该矩阵的行列数都为0,所以在使用svm分类器时候就出错。所以在使用每个输入图片的单词矩阵的时候先做一个判断,如果该矩阵行列数都为0,那么该图片直接跳过。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

开始King

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

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

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

打赏作者

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

抵扣说明:

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

余额充值