CHS与LBA寻址转换实战:3步公式推导与Python代码实现
2026/7/9 0:28:14
Bucketizer 会把输入列(连续值)按你配置的splitsArray切分成区间,并输出区间编号:
[0, numSplitsInThisColumn - 2](也就是区间数量-1)[0, numSplitsInThisColumn - 1],但通常 splits 的长度为 N,会产生 N-1 个区间,因此索引通常落在[0, N-2](你可以以实际输出为准)例如 splits 为[-0.5, 0.0, 0.5]:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
inputCols | Number | null | 需要分桶的连续特征列(可多列) |
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
outputCols | Double | null | 分桶后的离散特征(桶索引)列(可多列) |
输出是 Double 类型的桶索引(有些场景你也会想转成 Int/Long 或进一步 one-hot)。
| Key | 默认值 | 必填 | 说明 |
|---|---|---|---|
inputCols | null | ✅ | 输入列名数组 |
outputCols | null | ✅ | 输出列名数组 |
splitsArray | null | ✅ | 每个输入列的切分点数组(二维数组) |
handleInvalid | ERROR_INVALID | 否 | 遇到非法值(NaN、越界等)如何处理 |
splitsArray是Double[][],它的长度必须等于inputCols.length,每个子数组对应一个输入列的切分点。
要求/建议:
-INF/+INF包住,避免边界外数据出错[-INF, 10.0, +INF]常见策略(示例中使用了SKIP_INVALID):
ERROR_INVALID:遇到非法值直接报错(默认)SKIP_INVALID:跳过包含非法值的记录(整行被丢弃)KEEP_INVALID(保留并映射到特殊桶),具体以 Flink ML 实现为准工程建议:
ERROR_INVALID,尽早暴露数据质量问题SKIP_INVALID或“先做清洗再分桶”,避免任务被脏数据打挂你的示例做了 4 列特征同时分桶:
DataStream<Row>inputStream=env.fromElements(Row.of(-0.5,0.0,1.0,0.0));TableinputTable=tEnv.fromDataStream(inputStream).as("f1","f2","f3","f4");只有一行数据,四个连续特征:f1=-0.5, f2=0.0, f3=1.0, f4=0.0
Double[][]splitsArray=newDouble[][]{newDouble[]{-0.5,0.0,0.5},// f1:两段newDouble[]{-1.0,0.0,2.0},// f2:两段newDouble[]{Double.NEGATIVE_INFINITY,10.0,Double.POSITIVE_INFINITY},// f3:两段newDouble[]{Double.NEGATIVE_INFINITY,1.5,Double.POSITIVE_INFINITY}// f4:两段};可以把它理解为:
f1在 [-0.5,0) 或 [0,0.5] -> bucket 0/1f2在 [-1,0) 或 [0,2] -> bucket 0/1f3在 (-inf,10) 或 [10,inf) -> bucket 0/1f4在 (-inf,1.5) 或 [1.5,inf) -> bucket 0/1Bucketizerbucketizer=newBucketizer().setInputCols("f1","f2","f3","f4").setOutputCols("o1","o2","o3","o4").setSplitsArray(splitsArray).setHandleInvalid(HasHandleInvalid.SKIP_INVALID);TableoutputTable=bucketizer.transform(inputTable)[0];输出表会保留原列 + 新增o1~o4四个桶索引列。
示例把每列输入与输出读出来并打印:
inputValues[i]=(double)row.getField(bucketizer.getInputCols()[i]);outputValues[i]=(double)row.getField(bucketizer.getOutputCols()[i]);最终打印类似:
避免线上出现“越界数据导致报错”。
常见做法:
分桶后的输出是“桶索引”,很多模型更喜欢 one-hot 或 embedding: