1. 输入列(Input Columns)
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
featuresCol |
Vector | "features" |
特征向量列 |
labelCol |
Integer | "label" |
标签列(要预测的类别标签) |
weightCol |
Double | "weight" |
样本权重(可选,用于处理样本不均衡等) |
说明:featuresCol 必须是 Flink ML 的 Vector 类型(DenseVector/SparseVector)。
2. 输出列(Output Columns)
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
predictionCol |
Integer | "prediction" |
预测标签(最终分类结果) |
rawPredictionCol |
Vector | "rawPrediction" |
每个 label 的"原始预测向量"(可理解为得分/概率相关向量) |
注意:文档里把 predictionCol 描述成 "Label of the max probability"。从工程角度建议你这样理解:
rawPrediction:模型对各类别的打分向量(可能是 margin/score,也可能被映射为概率形式,具体依实现而定)prediction:在rawPrediction基础上做阈值/最大值选择后的最终标签
3. 参数(Parameters)详解
3.1 LinearSVCModel 参数(预测侧)
| Key | 默认值 | 类型 | 说明 |
|---|---|---|---|
featuresCol |
"features" |
String | 特征列名 |
predictionCol |
"prediction" |
String | 预测列名 |
rawPredictionCol |
"rawPrediction" |
String | 原始预测列名 |
threshold |
0.0 | Double | 二分类阈值:作用于 rawPrediction 来决定预测为 0 还是 1 |
threshold 只在二分类时特别重要:
- rawPrediction 代表某种"置信/得分",阈值决定了分类边界偏向哪个类别
- 你可以通过调节 threshold 来控制召回/精度的取舍
3.2 LinearSVC 训练参数(训练侧)
| Key | 默认值 | 类型 | 说明 |
|---|---|---|---|
labelCol |
"label" |
String | 标签列名 |
weightCol |
null | String | 权重列名(不设置就不用权重) |
maxIter |
20 | Integer | 最大迭代次数 |
reg |
0.0 | Double | 正则化强度(防止过拟合) |
elasticNet |
0.0 | Double | ElasticNet 参数(0=L2,1=L1,介于其中混合) |
learningRate |
0.1 | Double | 学习率 |
globalBatchSize |
32 | Integer | 全局 batch size |
tol |
1e-6 | Double | 收敛容差(迭代停止条件之一) |
你可以把这些参数看作"线性模型 + 梯度优化"的通用训练配置:
maxIter + tol控制训练何时停止learningRate + batchSize控制优化步伐reg + elasticNet控制模型复杂度与稀疏性
4. Java 示例代码流程解读
你给的示例代码做了这几件事:
- 构造训练数据(features, label, weight)
- 设置
weightCol,训练 LinearSVC - 用训练后的模型对输入数据做 transform
- 打印 features / expected label / prediction / rawPrediction
示例代码的关键片段
4.1 构造输入表
java
DataStream<Row> inputStream =
env.fromElements(
Row.of(Vectors.dense(1, 2, 3, 4), 0., 1.),
...
Row.of(Vectors.dense(15, 2, 3, 4), 1., 5.)
);
Table inputTable = tEnv.fromDataStream(inputStream).as("features", "label", "weight");
这份数据大致表达:
- 第一类 label=0:features 的第一个维度在 1~5
- 第二类 label=1:features 的第一个维度在 11~15
因此线性可分,非常适合用线性 SVM 学到一个简单分割平面。
4.2 训练模型
java
LinearSVC linearSVC = new LinearSVC().setWeightCol("weight");
LinearSVCModel linearSVCModel = linearSVC.fit(inputTable);
设置 weightCol 表示不同样本对损失函数贡献不同权重。
在样本不均衡、或者你希望某些样本更重要时很有用。
4.3 预测并输出 rawPrediction
java
Table outputTable = linearSVCModel.transform(inputTable)[0];
模型输出一般会包含:
- 原始列:features / label / weight
- 新增列:prediction / rawPrediction
5. 一个很容易踩的坑:label 类型与示例的"不一致"
文档写的是:
labelCol类型:IntegerpredictionCol类型:Integer
但示例里 label 使用的是 0. / 1.(Double),打印时也 cast 成 Double:
java
double expectedResult = (Double) row.getField(linearSVC.getLabelCol());
double predictionResult = (Double) row.getField(linearSVC.getPredictionCol());
为了少踩坑,建议你自己的工程里做两件事:
- 标签列
label用 Integer(0/1)更规范 - 输出 prediction 也按 Integer 读取
如果你沿用 Double,也要保证 train/predict/读取类型统一,否则容易出现类型转换异常或 schema 不匹配。
6. 实战建议:Linear SVC 在生产环境怎么用更稳
1)强烈建议做特征缩放(StandardScaler)
SVM 依赖 margin 和距离尺度,特征量纲差异会显著影响结果。典型做法:
- VectorAssembler(拼特征)
- StandardScaler(标准化)
- LinearSVC(训练)
这能明显提升收敛速度与模型稳定性。
2)调 threshold 来平衡召回与精度
二分类任务里,你可以把 threshold 当成"偏向正类/负类"的旋钮:
- threshold 调低:更容易预测为正类(召回↑,误报↑)
- threshold 调高:更保守(精度↑,漏报↑)
3)样本不均衡优先用 weightCol
比如正样本远少于负样本时:
- 给正样本更高权重
- 或给负样本更低权重
一般比盲目调参更直接有效。
4)正则化 reg + elasticNet 控制过拟合与稀疏
- 想要更稳定:提高
reg(偏 L2) - 想要更稀疏特征选择:提高
elasticNet(偏 L1)
7. 小结
Linear SVC 在 Flink ML 中的使用非常符合 Flink ML 的统一设计:
- 用 Table API 输入特征向量
features - 用
fit()训练得到LinearSVCModel - 用
transform()输出prediction和rawPrediction
理解这三点,你就能把它顺利放进 Pipeline 或 Graph 里,和特征工程、数据清洗、结果下游输出串起来。