什么是特征工程?

有这么一句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。那特征工程到底是什么呢?顾名思义,其本质是一项工程活动,目的是最大限度地从原始数据中提取特征以供算法和模型使用。

Byzer 提供了非常多的特征工程算子,能够很好的解决这一痛点。

Byzer 内置的这些特征工程算子有如下特点:

  1. 训练阶段可用,保证吞吐量
  2. 预测阶段使用,保证性能,一般毫秒级

本章节将具体讲解这些 ET 的使用。

系统需求

启动 Byzer 时,请使用--jars带上 ansj_seg-5.1.6.jar,nlp-lang-1.7.8.jar. 因为在很多示例中,我们需要用到分词相关的功能。

 

特征平滑/ScalerInPlace

特征平滑算子 ScalerInPlace 可以将输入特征中包含异常的数据平滑到一定区间,支持阈值平滑和指数平滑等方式。

ScalerInPlace 支持 min-max, log2logn 等方法对数据进行特征平滑。下面将介绍该算子的应用方式。

1. 数据准备

这里我们创建一些用于测试的数据

-- 创建数据集
set jsonStr='''
{"a":1,    "b":100, "label":0.0},
{"a":100,  "b":100, "label":1.0}
{"a":1000, "b":100, "label":0.0}
{"a":10,   "b":100, "label":0.0}
{"a":1,    "b":100, "label":1.0}
''';
load jsonStr.`jsonStr` as data;

结果如下:

name

2. 对数据进行特征平滑处理

接着我们对 a,b 两列数据都进行平滑:

-- 用 ScalerInPlace 处理数据
train data1 as ScalerInPlace.`/tmp/scaler`
where inputCols="a,b"
and scaleMethod="min-max"
and removeOutlierValue="false"
;

-- 将处理结果 load 出来查看
load parquet.`/tmp/scaler/data` 
as featurize_table;

代码含义

  • 采用 ScalerInPlace 算子对数据集 data 进行训练处理,并将该组设置以特征工程模型的形式保存在/tmp/scaler 路径下。
  • 参数 inputCols 用于设置参与处理的列名。
  • 参数 scaleMethod 用于设置特征平滑的处理方式,可选项还有:log2logn 。
  • 参数 removeOutlierValue 控制是否自动填充异常值。若设置为true,则会自动用中位数填充异常值。

可以使用命令:!show "et/params/ScalerInPlace"; 查看该算子包含的所有参数的使用方式

结果如下:

name

3. API 预测

register ScalerInPlace.`/tmp/scaler` as scale_convert;

通过上面的命令,就可以将该特征平滑模型训练结果通过 register 语句注册成一个函数,这里命名为:scale_convert,注册成功的函数会把训练阶段学习到的东西应用起来。

现在,任意给定两个数字,都可以使用 scale_convert 函数将其平滑:

select scale_convert(array(cast(7.0 as double), cast(8.0 as double))) as features as output;

输出结果为:

features
[0.006006006006006006,0.5]

归一化/NormalizeInPlace

特征归一化本质上是为了统一量纲,让一个向量里的元素变得可以比较。

它应用于任何依赖于距离的算法,比如 KMeans,Nearest Neighbors Methods, RBF Kernels 等等。

1. 数据准备

-- 创建数据集,这里创建一份js string 类型的
set jsonStr='''
{"a":1,    "b":100, "label":0.0},
{"a":100,  "b":100, "label":1.0}
{"a":1000, "b":100, "label":0.0}
{"a":10,   "b":100, "label":0.0}
{"a":1,    "b":100, "label":1.0}
''';
load jsonStr.`jsonStr` as data;

结果如下:

name

2. 训练

对 a,b 两列数据进行归一化操作。

train data as NormalizeInPlace.`/tmp/model`
where inputCols="a,b"
and scaleMethod="standard"
and removeOutlierValue="false"
;

load parquet.`/tmp/model/data` 
as output;

代码含义

  • 采用 NormalizeInPlace 算子对数据集 data 进行训练处理,并将该组设置以特征工程模型的形式保存在/tmp/model 路径下。
  • 参数 inputCols 用于设置参与处理的列名。
  • 参数 scaleMethod 用于设置归一化的处理方式,可选项还有:p-norm 。
  • 参数 removeOutlierValue 控制是否自动填充异常值。若设置为true,则会自动用中位数填充异常值。

如果 inputCols 只有一列,那么该列可以为 double 数组

可以使用命令:!show "et/params/NormalizeInPlace"; 查看该算子包含的所有参数的使用方式

结果如下:

name

3. API 预测

register NormalizeInPlace.`/tmp/model` as convert;

通过上面的命令,就可以将该归一化模型训练结果通过 register 语句注册成一个函数,这里命名为:convert,注册成功的函数会把训练阶段学习到的东西应用起来。

现在,任意给定两个数字,都可以使用 convert 函数将内容归一化处理。

select convert(array(cast(7.0 as double), cast(8.0 as double))) as features as output;

输出结果为:

features
[ -0.4932558994483363, 0 ]

 

混淆矩阵/ConfusionMatrix

什么是混淆矩阵呢?

混淆矩阵其实就是把所有类别的预测结果与真实结果按类别放置到了同一矩阵中,在这个矩阵中我们可以清楚看到每个类别正确识别的数量和错误识别的数量。在分类算法里用处很多,用户可以直观看到数据的错误分布情况。

name

1. 数据准备

假设我们有动物分类,两列中一列是实际值,另一列是预测值,内容如下:

set rawData='''
{"label":"cat","predict":"rabbit"}
{"label":"cat","predict":"dog"}
{"label":"cat","predict":"cat"}
{"label":"dog","predict":"dog"}
{"label":"cat","predict":"dog"} 
''';
load jsonStr.`rawData` as data;

结果如下:

name

2. 训练

使用混淆矩阵来查看最后的预测结果分布:

train data as ConfusionMatrix.`/tmp/model` 
where actualCol="label" 
and predictCol="predict";

load parquet.`/tmp/model/data` as output;

代码含义

  • 采用 ConfusionMatrix 算子对数据集 data 进行训练处理,并将该组设置以特征工程模型的形式保存在/tmp/model 路径下。
  • 参数 actualCol 用于指定实际值所在列名。
  • 参数 predictCol 用于指定预测值所在列名。

结果如下:

name

另外我们也可以看到一些统计值:

load parquet.`/tmp/model/detail` as output;

结果如下:

name

 

数据集切分/RateSampler

在做算法时,我们需要经常对数据切分成 训练集 和 测试集。 RateSampler 算子支持对数据集进行按比例切分。

1. 数据准备

-- 创建数据集
set jsonStr='''
{"features":[5.1,3.5,1.4,0.2],"label":0.0},
{"features":[5.1,3.5,1.4,0.2],"label":1.0}
{"features":[5.1,3.5,1.4,0.2],"label":0.0}
{"features":[4.4,2.9,1.4,0.2],"label":0.0}
{"features":[5.1,3.5,1.4,0.2],"label":1.0}
{"features":[5.1,3.5,1.4,0.2],"label":0.0}
{"features":[5.1,3.5,1.4,0.2],"label":0.0}
{"features":[4.7,3.2,1.3,0.2],"label":1.0}
{"features":[5.1,3.5,1.4,0.2],"label":0.0}
{"features":[5.1,3.5,1.4,0.2],"label":0.0}
''';
load jsonStr.`jsonStr` as data;

结果如下:

name

2. 切分数据集

现在我们使用 RateSampler 进行切分:

train data as RateSampler.`/tmp/model` 
where labelCol="label"
and sampleRate="0.7,0.3" as marked_dataset;

select * from marked_dataset as output;

代码含义

  • 采用 RateSampler 算子对数据集 data 进行训练处理,并将该组设置以特征工程模型的形式保存在/tmp/model 路径下。
  • 参数 labelCol 用于指定切分的字段。
  • 参数 sampleRate 用于指定切分的比例。

可以使用命令:!show "et/params/RateSampler"; 查看该算子包含的所有参数的使用方式

结果如下:

name

数据集多出了一个字段 __split__, 0 表示前一个集合(训练集), 1 表示后一个集合(测试集)。

接着,可以这样切分出训练集和测试集:

-- 筛选出训练集
select * from marked_dataset where __split__=0
as trainingTable;

-- 筛选出测试集
select * from marked_dataset where __split__=1
as validateTable;

默认 RateSampler 采用估算算法。 如果数据集较小,可以通过设置参数 isSplitWithSubLabel="true" 获得非常精确的划分。

3. API 预测

该模块暂不提供 API 预测。

Logo

更多推荐