1. 输入列与输出列
输入列(Input Columns)
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
featuresCol |
Vector | "features" |
特征向量列 |
labelCol |
Integer | "label" |
标签列(要预测的类别) |
输出列(Output Columns)
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
predictionCol |
Integer | "prediction" |
预测标签 |
2. 参数(Parameters)详解
2.1 NaiveBayesModel(预测侧)参数
| Key | 默认值 | 类型 | 说明 |
|---|---|---|---|
modelType |
"multinomial" |
String | 模型类型(目前支持 multinomial) |
featuresCol |
"features" |
String | 特征列名 |
predictionCol |
"prediction" |
String | 预测列名 |
2.2 NaiveBayes(训练侧)额外参数
| Key | 默认值 | 类型 | 说明 |
|---|---|---|---|
labelCol |
"label" |
String | 标签列名 |
smoothing |
1.0 | Double | 平滑参数(拉普拉斯平滑,避免零概率) |
smoothing 是干什么的?
在 multinomial 朴素贝叶斯里,经常会遇到某类样本中某个特征从未出现过的情况,这会导致该条件概率为 0,从而让整个后验概率变成 0。
smoothing 的作用就是避免这种"零概率"问题,让模型更稳健。
工程上:
1.0是最常见的默认选择- 数据稀疏、类别较多时,适当提高 smoothing 往往更稳定
3. Java 示例代码解读
你贴的示例逻辑非常标准,分四步:
1)构造训练数据(features, label)
2)构造预测数据(features)
3)创建 NaiveBayes 并设置参数
4)fit 训练模型 → transform 预测 → collect 打印结果
3.1 训练数据
java
DataStream<Row> trainStream =
env.fromElements(
Row.of(Vectors.dense(0, 0.), 11),
Row.of(Vectors.dense(1, 0), 10),
Row.of(Vectors.dense(1, 1.), 10));
Table trainTable = tEnv.fromDataStream(trainStream).as("features", "label");
这里的标签是 10 和 11(多分类不一定要从 0 开始),特征向量是 2 维。
3.2 预测数据
java
DataStream<Row> predictStream =
env.fromElements(
Row.of(Vectors.dense(0, 1.)),
Row.of(Vectors.dense(0, 0.)),
Row.of(Vectors.dense(1, 0)),
Row.of(Vectors.dense(1, 1.)));
Table predictTable = tEnv.fromDataStream(predictStream).as("features");
预测表只有 features 列,符合朴素贝叶斯的推理输入。
3.3 创建与训练
java
NaiveBayes naiveBayes =
new NaiveBayes()
.setSmoothing(1.0)
.setFeaturesCol("features")
.setLabelCol("label")
.setPredictionCol("prediction")
.setModelType("multinomial");
NaiveBayesModel naiveBayesModel = naiveBayes.fit(trainTable);
3.4 预测输出
java
Table outputTable = naiveBayesModel.transform(predictTable)[0];
输出表会新增 prediction 列。
4. 一个小坑:prediction 类型读取
文档定义 predictionCol 是 Integer,但示例中用:
java
double predictionResult = (Double) row.getField(naiveBayes.getPredictionCol());
这容易让人误会 prediction 是 Double。更稳的写法是按 Integer 读取:
java
Integer prediction = (Integer) row.getField(naiveBayes.getPredictionCol());
建议你在工程里把 label 与 prediction 都保持 Integer 类型,减少类型转换问题。
5. multinomial 朴素贝叶斯的"工程适配"建议
1)multinomial 更适合"计数/频次类特征"
multinomial Naive Bayes 常见于:
- 词袋计数(word counts)
- TF/TF-IDF(有时也用,但严格上更像连续值,需要注意分布假设)
- 事件次数、出现频次等离散统计特征
如果你的 features 是非常连续的实数(如温度、金额、时长),multinomial 的假设可能不够贴合,效果未必好。此时你可以考虑:
- 先做分桶(binning)
- 或选择 Logistic Regression / LinearSVC 等线性模型
2)特征必须非负更稳
multinomial 模型通常假设特征类似"出现次数/频次",因此:
- 负数特征会让概率解释变得很奇怪
- 工程上建议保证 features >= 0(或做平移/分桶)
3)smoothing 的调参思路
- 类别多、数据稀疏:smoothing 可以适当大一些
- 数据充足:smoothing=1.0 往往足够
6. 总结
Flink ML 的 Naive Bayes 非常适合做多分类 baseline,尤其在文本/稀疏特征场景下优势明显:
- 输入:
features(Vector)+label(Integer) - 输出:
prediction(Integer) - 关键参数:
modelType=multinomial、smoothing平滑避免零概率 - 用法:
fit()训练 →transform()预测,完全遵循 Flink ML 的 Table API 体系