This is an automated email from the ASF dual-hosted git repository.

lindong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-ml.git


The following commit(s) were added to refs/heads/master by this push:
     new 981d36a  [FLINK-27742] Fix compatibility issue between stages
981d36a is described below

commit 981d36a9ef9c68464184c525de2c9bfd48fdc4e1
Author: yunfengzhou-hub <[email protected]>
AuthorDate: Mon May 23 19:46:46 2022 +0800

    [FLINK-27742] Fix compatibility issue between stages
    
    This closes #103.
---
 .../org/apache/flink/ml/linalg/DenseMatrix.java    |   5 +
 .../org/apache/flink/ml/linalg/DenseVector.java    |  29 +++++
 .../java/org/apache/flink/ml/linalg/Matrix.java    |   3 +
 .../org/apache/flink/ml/linalg/SparseVector.java   |  10 ++
 .../java/org/apache/flink/ml/linalg/Vector.java    |   7 +-
 .../apache/flink/ml/classification/knn/Knn.java    |   5 +-
 .../flink/ml/classification/knn/KnnModel.java      |   3 +-
 .../flink/ml/classification/knn/KnnModelData.java  |   8 +-
 .../ml/classification/linearsvc/LinearSVC.java     |  11 +-
 .../classification/linearsvc/LinearSVCModel.java   |   3 +-
 .../linearsvc/LinearSVCModelData.java              |   3 +-
 .../logisticregression/LogisticRegression.java     |  11 +-
 .../LogisticRegressionModel.java                   |   3 +-
 .../LogisticRegressionModelData.java               |   3 +-
 .../naivebayes/NaiveBayesModelData.java            |   5 +-
 .../apache/flink/ml/clustering/kmeans/KMeans.java  |   3 +-
 .../flink/ml/clustering/kmeans/KMeansModel.java    |   3 +-
 .../ml/clustering/kmeans/KMeansModelData.java      |   7 +-
 .../flink/ml/clustering/kmeans/OnlineKMeans.java   |   3 +-
 .../ml/clustering/kmeans/OnlineKMeansModel.java    |   3 +-
 .../BinaryClassificationEvaluator.java             |  11 +-
 .../flink/ml/feature/bucketizer/Bucketizer.java    |   6 +-
 .../ml/feature/minmaxscaler/MinMaxScaler.java      |   3 +-
 .../ml/feature/minmaxscaler/MinMaxScalerModel.java |   3 +-
 .../feature/stringindexer/StringIndexerModel.java  |  12 +--
 .../linearregression/LinearRegression.java         |  11 +-
 .../linearregression/LinearRegressionModel.java    |   3 +-
 .../apache/flink/ml/classification/KnnTest.java    |  31 ++++--
 .../flink/ml/classification/LinearSVCTest.java     |  29 +++--
 .../ml/classification/LogisticRegressionTest.java  |  26 ++++-
 .../flink/ml/classification/NaiveBayesTest.java    |  54 ++++++----
 .../org/apache/flink/ml/clustering/KMeansTest.java |  34 ++++--
 .../flink/ml/clustering/OnlineKMeansTest.java      |  53 ++++++++--
 .../BinaryClassificationEvaluatorTest.java         |  33 +++++-
 .../apache/flink/ml/feature/BucketizerTest.java    |  36 ++++++-
 .../apache/flink/ml/feature/MinMaxScalerTest.java  |  24 ++++-
 .../apache/flink/ml/feature/OneHotEncoderTest.java |  22 +++-
 .../flink/ml/feature/StandardScalerTest.java       |  18 +++-
 .../flink/ml/feature/VectorAssemblerTest.java      |  25 ++++-
 .../stringindexer/IndexToStringModelTest.java      |   4 +-
 .../feature/stringindexer/StringIndexerTest.java   |  38 ++++---
 .../flink/ml/regression/LinearRegressionTest.java  |  22 +++-
 .../org/apache/flink/ml/util/StageTestUtils.java   |  52 ---------
 .../java/org/apache/flink/ml/util/TestUtils.java   | 117 +++++++++++++++++++++
 44 files changed, 610 insertions(+), 185 deletions(-)

diff --git 
a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseMatrix.java 
b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseMatrix.java
index 80c85b0..b37462d 100644
--- a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseMatrix.java
+++ b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseMatrix.java
@@ -82,4 +82,9 @@ public class DenseMatrix implements Matrix {
         Preconditions.checkArgument(i >= 0 && i < numRows && j >= 0 && j < 
numCols);
         return values[numRows * j + i];
     }
+
+    @Override
+    public DenseMatrix toDense() {
+        return this;
+    }
 }
diff --git 
a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseVector.java 
b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseVector.java
index a4ccf9c..b4f0603 100644
--- a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseVector.java
+++ b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/DenseVector.java
@@ -51,6 +51,35 @@ public class DenseVector implements Vector {
         return values;
     }
 
+    @Override
+    public DenseVector toDense() {
+        return this;
+    }
+
+    @Override
+    public SparseVector toSparse() {
+        int numNonZeros = 0;
+        for (double value : values) {
+            if (value != 0.0) {
+                numNonZeros++;
+            }
+        }
+
+        int[] nonZeroIndices = new int[numNonZeros];
+        double[] numZeroValues = new double[numNonZeros];
+        int k = 0;
+        for (int i = 0; i < values.length; i++) {
+            if (values[i] == 0.0) {
+                continue;
+            }
+            nonZeroIndices[k] = i;
+            numZeroValues[k] = values[i];
+            k++;
+        }
+
+        return new SparseVector(size(), nonZeroIndices, numZeroValues);
+    }
+
     @Override
     public String toString() {
         return Arrays.toString(values);
diff --git a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Matrix.java 
b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Matrix.java
index d4e0897..d1bf1af 100644
--- a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Matrix.java
+++ b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Matrix.java
@@ -31,4 +31,7 @@ public interface Matrix extends Serializable {
 
     /** Gets value of the (i,j) element. */
     double get(int i, int j);
+
+    /** Converts the instance to a dense matrix. */
+    DenseMatrix toDense();
 }
diff --git 
a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/SparseVector.java 
b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/SparseVector.java
index 6f7d128..f241e30 100644
--- a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/SparseVector.java
+++ b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/SparseVector.java
@@ -65,6 +65,16 @@ public class SparseVector implements Vector {
         return result;
     }
 
+    @Override
+    public DenseVector toDense() {
+        return new DenseVector(toArray());
+    }
+
+    @Override
+    public SparseVector toSparse() {
+        return this;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Vector.java 
b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Vector.java
index d5cce04..21718b3 100644
--- a/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Vector.java
+++ b/flink-ml-core/src/main/java/org/apache/flink/ml/linalg/Vector.java
@@ -33,9 +33,10 @@ public interface Vector extends Serializable {
     double[] toArray();
 
     /** Converts the instance to a dense vector. */
-    default DenseVector toDense() {
-        return new DenseVector(toArray());
-    }
+    DenseVector toDense();
+
+    /** Converts the instance to a sparse vector. */
+    SparseVector toSparse();
 
     /** Makes a deep copy of the vector. */
     Vector clone();
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/Knn.java 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/Knn.java
index 93c0e5c..36e9d37 100644
--- a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/Knn.java
+++ b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/Knn.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.datastream.DataStreamUtils;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseMatrix;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -147,8 +148,8 @@ public class Knn implements Estimator<Knn, KnnModel>, 
KnnParams<Knn> {
                 new MapFunction<Row, Tuple3<DenseVector, Double, Double>>() {
                     @Override
                     public Tuple3<DenseVector, Double, Double> map(Row value) {
-                        Double label = (Double) value.getField(getLabelCol());
-                        DenseVector feature = (DenseVector) 
value.getField(getFeaturesCol());
+                        Double label = ((Number) 
value.getField(getLabelCol())).doubleValue();
+                        DenseVector feature = ((Vector) 
value.getField(getFeaturesCol())).toDense();
                         return Tuple3.of(feature, label, 
Math.pow(BLAS.norm2(feature), 2));
                     }
                 });
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModel.java
index 28dcaea..3194fbb 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModel.java
@@ -27,6 +27,7 @@ import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -145,7 +146,7 @@ public class KnnModel implements Model<KnnModel>, 
KnnModelParams<KnnModel> {
                                 
getRuntimeContext().getBroadcastVariable(broadcastKey).get(0);
                 distanceVector = new DenseVector(knnModelData.labels.size());
             }
-            DenseVector feature = (DenseVector) row.getField(featureCol);
+            DenseVector feature = ((Vector) 
row.getField(featureCol)).toDense();
             double prediction = predictLabel(feature);
             return Row.join(row, Row.of(prediction));
         }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModelData.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModelData.java
index 4bf0adb..d07859a 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModelData.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/knn/KnnModelData.java
@@ -29,6 +29,8 @@ import org.apache.flink.core.memory.DataOutputView;
 import org.apache.flink.core.memory.DataOutputViewStreamWrapper;
 import org.apache.flink.ml.linalg.DenseMatrix;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Matrix;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseMatrixSerializer;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorSerializer;
 import org.apache.flink.streaming.api.datastream.DataStream;
@@ -74,9 +76,9 @@ public class KnnModelData {
                 .map(
                         x ->
                                 new KnnModelData(
-                                        (DenseMatrix) x.getField(0),
-                                        (DenseVector) x.getField(1),
-                                        (DenseVector) x.getField(2)));
+                                        ((Matrix) x.getField(0)).toDense(),
+                                        ((Vector) x.getField(1)).toDense(),
+                                        ((Vector) x.getField(2)).toDense()));
     }
 
     /** Encoder for {@link KnnModelData}. */
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVC.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVC.java
index 4169d48..8a8d1cb 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVC.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVC.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.lossfunc.HingeLoss;
 import org.apache.flink.ml.common.optimizer.Optimizer;
 import org.apache.flink.ml.common.optimizer.SGD;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -66,15 +67,19 @@ public class LinearSVC implements Estimator<LinearSVC, 
LinearSVCModel>, LinearSV
                                     double weight =
                                             getWeightCol() == null
                                                     ? 1.0
-                                                    : (Double) 
dataPoint.getField(getWeightCol());
-                                    double label = (Double) 
dataPoint.getField(getLabelCol());
+                                                    : ((Number) 
dataPoint.getField(getWeightCol()))
+                                                            .doubleValue();
+                                    double label =
+                                            ((Number) 
dataPoint.getField(getLabelCol()))
+                                                    .doubleValue();
                                     Preconditions.checkState(
                                             Double.compare(0.0, label) == 0
                                                     || Double.compare(1.0, 
label) == 0,
                                             "LinearSVC only supports binary 
classification. But detected label: %s.",
                                             label);
                                     DenseVector features =
-                                            (DenseVector) 
dataPoint.getField(getFeaturesCol());
+                                            ((Vector) 
dataPoint.getField(getFeaturesCol()))
+                                                    .toDense();
                                     return new 
LabeledPointWithWeight(features, label, weight);
                                 });
 
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModel.java
index 253bbcc..a7da2e3 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModel.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.param.Param;
@@ -152,7 +153,7 @@ public class LinearSVCModel implements 
Model<LinearSVCModel>, LinearSVCModelPara
                                 
getRuntimeContext().getBroadcastVariable(broadcastModelKey).get(0);
                 coefficient = modelData.coefficient;
             }
-            DenseVector features = (DenseVector) 
dataPoint.getField(featuresCol);
+            DenseVector features = ((Vector) 
dataPoint.getField(featuresCol)).toDense();
             Row predictionResult = predictOneDataPoint(features, coefficient, 
threshold);
             return Row.join(dataPoint, predictionResult);
         }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModelData.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModelData.java
index 96e8a27..d181c6c 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModelData.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/linearsvc/LinearSVCModelData.java
@@ -26,6 +26,7 @@ import org.apache.flink.core.fs.FSDataInputStream;
 import org.apache.flink.core.memory.DataInputViewStreamWrapper;
 import org.apache.flink.core.memory.DataOutputViewStreamWrapper;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorSerializer;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.table.api.Table;
@@ -62,7 +63,7 @@ public class LinearSVCModelData {
         StreamTableEnvironment tEnv =
                 (StreamTableEnvironment) ((TableImpl) 
modelData).getTableEnvironment();
         return tEnv.toDataStream(modelData)
-                .map(x -> new LinearSVCModelData((DenseVector) x.getField(0)));
+                .map(x -> new LinearSVCModelData(((Vector) 
x.getField(0)).toDense()));
     }
 
     /** Data encoder for {@link LinearSVCModel}. */
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegression.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegression.java
index f64fc10..df8c386 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegression.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegression.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.lossfunc.BinaryLogisticLoss;
 import org.apache.flink.ml.common.optimizer.Optimizer;
 import org.apache.flink.ml.common.optimizer.SGD;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -72,8 +73,11 @@ public class LogisticRegression
                                     double weight =
                                             getWeightCol() == null
                                                     ? 1.0
-                                                    : (Double) 
dataPoint.getField(getWeightCol());
-                                    double label = (Double) 
dataPoint.getField(getLabelCol());
+                                                    : ((Number) 
dataPoint.getField(getWeightCol()))
+                                                            .doubleValue();
+                                    double label =
+                                            ((Number) 
dataPoint.getField(getLabelCol()))
+                                                    .doubleValue();
                                     boolean isBinomial =
                                             Double.compare(0., label) == 0
                                                     || Double.compare(1., 
label) == 0;
@@ -82,7 +86,8 @@ public class LogisticRegression
                                                 "Multinomial classification is 
not supported yet. Supported options: [auto, binomial].");
                                     }
                                     DenseVector features =
-                                            (DenseVector) 
dataPoint.getField(getFeaturesCol());
+                                            ((Vector) 
dataPoint.getField(getFeaturesCol()))
+                                                    .toDense();
                                     return new 
LabeledPointWithWeight(features, label, weight);
                                 });
 
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModel.java
index 247a4d5..ac42142 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModel.java
@@ -27,6 +27,7 @@ import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
@@ -148,7 +149,7 @@ public class LogisticRegressionModel
                                 
getRuntimeContext().getBroadcastVariable(broadcastModelKey).get(0);
                 coefficient = modelData.coefficient;
             }
-            DenseVector features = (DenseVector) 
dataPoint.getField(featuresCol);
+            DenseVector features = ((Vector) 
dataPoint.getField(featuresCol)).toDense();
             Row predictionResult = predictOneDataPoint(features, coefficient);
             return Row.join(dataPoint, predictionResult);
         }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModelData.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModelData.java
index 774c19e..d2f451f 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModelData.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/logisticregression/LogisticRegressionModelData.java
@@ -26,6 +26,7 @@ import org.apache.flink.core.fs.FSDataInputStream;
 import org.apache.flink.core.memory.DataInputViewStreamWrapper;
 import org.apache.flink.core.memory.DataOutputViewStreamWrapper;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorSerializer;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.table.api.Table;
@@ -62,7 +63,7 @@ public class LogisticRegressionModelData {
         StreamTableEnvironment tEnv =
                 (StreamTableEnvironment) ((TableImpl) 
modelData).getTableEnvironment();
         return tEnv.toDataStream(modelData)
-                .map(x -> new LogisticRegressionModelData((DenseVector) 
x.getField(0)));
+                .map(x -> new LogisticRegressionModelData(((Vector) 
x.getField(0)).toDense()));
     }
 
     /** Data encoder for {@link LogisticRegressionModel}. */
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/naivebayes/NaiveBayesModelData.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/naivebayes/NaiveBayesModelData.java
index a03141d..80ff835 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/naivebayes/NaiveBayesModelData.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/classification/naivebayes/NaiveBayesModelData.java
@@ -29,6 +29,7 @@ import org.apache.flink.core.fs.FSDataInputStream;
 import org.apache.flink.core.memory.DataInputViewStreamWrapper;
 import org.apache.flink.core.memory.DataOutputViewStreamWrapper;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorSerializer;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.table.api.Table;
@@ -85,8 +86,8 @@ public class NaiveBayesModelData {
                                 row ->
                                         new NaiveBayesModelData(
                                                 (Map<Double, Double>[][]) 
row.getField(0),
-                                                (DenseVector) row.getField(1),
-                                                (DenseVector) 
row.getField(2)));
+                                                ((Vector) 
row.getField(1)).toDense(),
+                                                ((Vector) 
row.getField(2)).toDense()));
     }
 
     /** Data encoder for the {@link NaiveBayesModelData}. */
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeans.java 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeans.java
index 31e6d6c..2aa2c3c 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeans.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeans.java
@@ -44,6 +44,7 @@ import org.apache.flink.ml.common.distance.DistanceMeasure;
 import org.apache.flink.ml.common.iteration.ForwardInputsOfLastRound;
 import org.apache.flink.ml.common.iteration.TerminateOnMaxIter;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
@@ -92,7 +93,7 @@ public class KMeans implements Estimator<KMeans, 
KMeansModel>, KMeansParams<KMea
                 (StreamTableEnvironment) ((TableImpl) 
inputs[0]).getTableEnvironment();
         DataStream<DenseVector> points =
                 tEnv.toDataStream(inputs[0])
-                        .map(row -> (DenseVector) 
row.getField(getFeaturesCol()));
+                        .map(row -> ((Vector) 
row.getField(getFeaturesCol())).toDense());
 
         DataStream<DenseVector[]> initCentroids = 
selectRandomCentroids(points, getK(), getSeed());
 
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModel.java
index d569d97..9cfea62 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModel.java
@@ -27,6 +27,7 @@ import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.common.distance.DistanceMeasure;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -132,7 +133,7 @@ public class KMeansModel implements Model<KMeansModel>, 
KMeansModelParams<KMeans
                 Preconditions.checkArgument(modelData.centroids.length <= k);
                 centroids = modelData.centroids;
             }
-            DenseVector point = (DenseVector) dataPoint.getField(featuresCol);
+            DenseVector point = ((Vector) 
dataPoint.getField(featuresCol)).toDense();
             int closestCentroidId = KMeans.findClosestCentroidId(centroids, 
point, distanceMeasure);
             return Row.join(dataPoint, Row.of(closestCentroidId));
         }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModelData.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModelData.java
index a7a62c7..34c69ac 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModelData.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/KMeansModelData.java
@@ -29,6 +29,7 @@ import 
org.apache.flink.core.memory.DataInputViewStreamWrapper;
 import org.apache.flink.core.memory.DataOutputViewStreamWrapper;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorSerializer;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -129,8 +130,10 @@ public class KMeansModelData {
                 .map(
                         x ->
                                 new KMeansModelData(
-                                        (DenseVector[]) x.getField(0),
-                                        (DenseVector) x.getField(1)));
+                                        Arrays.stream(((Vector[]) 
x.getField(0)))
+                                                .map(Vector::toDense)
+                                                .toArray(DenseVector[]::new),
+                                        ((Vector) x.getField(1)).toDense()));
     }
 
     /** Data encoder for {@link KMeansModelData}. */
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeans.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeans.java
index 7ede3e4..b876b13 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeans.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeans.java
@@ -34,6 +34,7 @@ import org.apache.flink.ml.api.Estimator;
 import org.apache.flink.ml.common.distance.DistanceMeasure;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
@@ -335,7 +336,7 @@ public class OnlineKMeans
 
         @Override
         public DenseVector map(Row row) {
-            return (DenseVector) row.getField(featuresCol);
+            return ((Vector) row.getField(featuresCol)).toDense();
         }
     }
 
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeansModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeansModel.java
index 3643d19..6a7c852 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeansModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/clustering/kmeans/OnlineKMeansModel.java
@@ -27,6 +27,7 @@ import org.apache.flink.ml.api.Model;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.common.distance.DistanceMeasure;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -171,7 +172,7 @@ public class OnlineKMeansModel
                 bufferedPointsState.add(dataPoint);
                 return;
             }
-            DenseVector point = (DenseVector) dataPoint.getField(featuresCol);
+            DenseVector point = ((Vector) 
dataPoint.getField(featuresCol)).toDense();
             int closestCentroidId = KMeans.findClosestCentroidId(centroids, 
point, distanceMeasure);
             output.collect(new StreamRecord<>(Row.join(dataPoint, 
Row.of(closestCentroidId))));
         }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/evaluation/binaryclassification/BinaryClassificationEvaluator.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/evaluation/binaryclassification/BinaryClassificationEvaluator.java
index 49cf4ae..a80fc7e 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/evaluation/binaryclassification/BinaryClassificationEvaluator.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/evaluation/binaryclassification/BinaryClassificationEvaluator.java
@@ -35,7 +35,7 @@ import org.apache.flink.iteration.operator.OperatorStateUtils;
 import org.apache.flink.ml.api.AlgoOperator;
 import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.DataStreamUtils;
-import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -658,10 +658,11 @@ public class BinaryClassificationEvaluator
             double label = ((Number) value.getFieldAs(labelCol)).doubleValue();
             Object probOrigin = value.getField(rawPredictionCol);
             double prob =
-                    probOrigin instanceof DenseVector
-                            ? ((DenseVector) probOrigin).get(1)
-                            : (double) probOrigin;
-            double weight = weightCol == null ? 1.0 : 
value.getFieldAs(weightCol);
+                    probOrigin instanceof Vector
+                            ? ((Vector) probOrigin).get(1)
+                            : ((Number) probOrigin).doubleValue();
+            double weight =
+                    weightCol == null ? 1.0 : ((Number) 
value.getField(weightCol)).doubleValue();
             return Tuple3.of(prob, label == 1.0, weight);
         }
     }
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/bucketizer/Bucketizer.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/bucketizer/Bucketizer.java
index 8afefcb..1382963 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/bucketizer/Bucketizer.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/bucketizer/Bucketizer.java
@@ -71,7 +71,7 @@ public class Bucketizer implements Transformer<Bucketizer>, 
BucketizerParams<Buc
 
         RowTypeInfo inputTypeInfo = 
TableUtils.getRowTypeInfo(inputs[0].getResolvedSchema());
         TypeInformation<?>[] outputTypes = new 
TypeInformation[outputCols.length];
-        Arrays.fill(outputTypes, BasicTypeInfo.INT_TYPE_INFO);
+        Arrays.fill(outputTypes, BasicTypeInfo.DOUBLE_TYPE_INFO);
         RowTypeInfo outputTypeInfo =
                 new RowTypeInfo(
                         ArrayUtils.addAll(inputTypeInfo.getFieldTypes(), 
outputTypes),
@@ -108,7 +108,7 @@ public class Bucketizer implements Transformer<Bucketizer>, 
BucketizerParams<Buc
                 boolean isInvalid = false;
 
                 if (!Double.isNaN(feature)) {
-                    int index = Arrays.binarySearch(splits, feature);
+                    double index = Arrays.binarySearch(splits, feature);
                     if (index >= 0) {
                         if (index == splits.length - 1) {
                             index--;
@@ -136,7 +136,7 @@ public class Bucketizer implements Transformer<Bucketizer>, 
BucketizerParams<Buc
                         case SKIP_INVALID:
                             return;
                         case KEEP_INVALID:
-                            outputRow.setField(i, splits.length - 1);
+                            outputRow.setField(i, (double) splits.length - 1);
                             break;
                         default:
                             throw new UnsupportedOperationException(
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScaler.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScaler.java
index 43c5ac9..0ba885b 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScaler.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScaler.java
@@ -27,6 +27,7 @@ import org.apache.flink.iteration.operator.OperatorStateUtils;
 import org.apache.flink.ml.api.Estimator;
 import org.apache.flink.ml.common.datastream.DataStreamUtils;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -81,7 +82,7 @@ public class MinMaxScaler
                 tEnv.toDataStream(inputs[0])
                         .map(
                                 (MapFunction<Row, DenseVector>)
-                                        value -> (DenseVector) 
value.getField(inputCol));
+                                        value -> ((Vector) 
value.getField(inputCol)).toDense());
         DataStream<DenseVector> minMaxValues =
                 inputData
                         .transform(
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScalerModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScalerModel.java
index 87b5993..59b6aa0 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScalerModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/minmaxscaler/MinMaxScalerModel.java
@@ -25,6 +25,7 @@ import org.apache.flink.ml.api.Model;
 import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -166,7 +167,7 @@ public class MinMaxScalerModel
                     }
                 }
             }
-            DenseVector inputVec = (DenseVector) row.getField(inputCol);
+            DenseVector inputVec = ((Vector) row.getField(inputCol)).toDense();
             DenseVector outputVec = new DenseVector(scaleVector.size());
             for (int i = 0; i < scaleVector.size(); ++i) {
                 outputVec.values[i] =
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/stringindexer/StringIndexerModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/stringindexer/StringIndexerModel.java
index f1257cc..4781966 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/stringindexer/StringIndexerModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/feature/stringindexer/StringIndexerModel.java
@@ -46,7 +46,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * A Model which transforms input string/numeric column(s) to integer 
column(s) using the model data
+ * A Model which transforms input string/numeric column(s) to double column(s) 
using the model data
  * computed by {@link StringIndexer}.
  *
  * <p>The `keep` option of {@link HasHandleInvalid} means that we put the 
invalid entries in a
@@ -107,7 +107,7 @@ public class StringIndexerModel
 
         RowTypeInfo inputTypeInfo = 
TableUtils.getRowTypeInfo(inputs[0].getResolvedSchema());
         TypeInformation<?>[] outputTypes = new 
TypeInformation[outputCols.length];
-        Arrays.fill(outputTypes, BasicTypeInfo.INT_TYPE_INFO);
+        Arrays.fill(outputTypes, BasicTypeInfo.DOUBLE_TYPE_INFO);
         RowTypeInfo outputTypeInfo =
                 new RowTypeInfo(
                         ArrayUtils.addAll(inputTypeInfo.getFieldTypes(), 
outputTypes),
@@ -132,9 +132,9 @@ public class StringIndexerModel
         return new Table[] {tEnv.fromDataStream(result)};
     }
 
-    /** Maps the input columns to integer values according to the model data. 
*/
+    /** Maps the input columns to double values according to the model data. */
     private static class String2Index extends RichFlatMapFunction<Row, Row> {
-        private HashMap<String, Integer>[] modelDataMap;
+        private HashMap<String, Double>[] modelDataMap;
         private final String broadcastModelKey;
         private final String[] inputCols;
         private final String handleInValid;
@@ -155,7 +155,7 @@ public class StringIndexerModel
                                 
getRuntimeContext().getBroadcastVariable(broadcastModelKey).get(0);
                 String[][] stringsArray = modelData.stringArrays;
                 for (int i = 0; i < stringsArray.length; i++) {
-                    int idx = 0;
+                    double idx = 0.0;
                     modelDataMap[i] = new HashMap<>(stringsArray[i].length);
                     for (String string : stringsArray[i]) {
                         modelDataMap[i].put(string, idx++);
@@ -190,7 +190,7 @@ public class StringIndexerModel
                                             + HANDLE_INVALID
                                             + " parameter for more options.");
                         case KEEP_INVALID:
-                            outputIndices.setField(i, modelDataMap[i].size());
+                            outputIndices.setField(i, (double) 
modelDataMap[i].size());
                             break;
                         default:
                             throw new UnsupportedOperationException(
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegression.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegression.java
index 7edffc4..3de4804 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegression.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegression.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.lossfunc.LeastSquareLoss;
 import org.apache.flink.ml.common.optimizer.Optimizer;
 import org.apache.flink.ml.common.optimizer.SGD;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -67,10 +68,14 @@ public class LinearRegression
                                     double weight =
                                             getWeightCol() == null
                                                     ? 1.0
-                                                    : (Double) 
dataPoint.getField(getWeightCol());
-                                    double label = (Double) 
dataPoint.getField(getLabelCol());
+                                                    : ((Number) 
dataPoint.getField(getWeightCol()))
+                                                            .doubleValue();
+                                    double label =
+                                            ((Number) 
dataPoint.getField(getLabelCol()))
+                                                    .doubleValue();
                                     DenseVector features =
-                                            (DenseVector) 
dataPoint.getField(getFeaturesCol());
+                                            ((Vector) 
dataPoint.getField(getFeaturesCol()))
+                                                    .toDense();
                                     return new 
LabeledPointWithWeight(features, label, weight);
                                 });
 
diff --git 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegressionModel.java
 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegressionModel.java
index 7fb9019..dec2f43 100644
--- 
a/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegressionModel.java
+++ 
b/flink-ml-lib/src/main/java/org/apache/flink/ml/regression/linearregression/LinearRegressionModel.java
@@ -26,6 +26,7 @@ import org.apache.flink.ml.common.broadcast.BroadcastUtils;
 import org.apache.flink.ml.common.datastream.TableUtils;
 import org.apache.flink.ml.linalg.BLAS;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.param.Param;
 import org.apache.flink.ml.util.ParamUtils;
 import org.apache.flink.ml.util.ReadWriteUtils;
@@ -141,7 +142,7 @@ public class LinearRegressionModel
                                 
getRuntimeContext().getBroadcastVariable(broadcastModelKey).get(0);
                 coefficient = modelData.coefficient;
             }
-            DenseVector features = (DenseVector) 
dataPoint.getField(featuresCol);
+            DenseVector features = ((Vector) 
dataPoint.getField(featuresCol)).toDense();
             Row predictionResult = predictOneDataPoint(features, coefficient);
             return Row.join(dataPoint, predictionResult);
         }
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/KnnTest.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/KnnTest.java
index e395951..6121725 100644
--- a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/KnnTest.java
+++ b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/KnnTest.java
@@ -27,9 +27,10 @@ import org.apache.flink.ml.classification.knn.KnnModel;
 import org.apache.flink.ml.classification.knn.KnnModelData;
 import org.apache.flink.ml.linalg.DenseMatrix;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -51,6 +52,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 /** Tests {@link Knn} and {@link KnnModel}. */
@@ -121,7 +123,7 @@ public class KnnTest {
                                     @Override
                                     public Tuple2<Double, Double> map(Row row) 
{
                                         return Tuple2.of(
-                                                (Double) 
row.getField(labelCol),
+                                                ((Number) 
row.getField(labelCol)).doubleValue(),
                                                 (Double) 
row.getField(predictionCol));
                                     }
                                 });
@@ -179,15 +181,31 @@ public class KnnTest {
         verifyPredictionResult(output, knn.getLabelCol(), 
knn.getPredictionCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        trainData = TestUtils.convertDataTypesToSparseInt(tEnv, trainData);
+        predictData = TestUtils.convertDataTypesToSparseInt(tEnv, predictData);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class},
+                TestUtils.getColumnDataTypes(trainData));
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class},
+                TestUtils.getColumnDataTypes(predictData));
+
+        Knn knn = new Knn();
+        KnnModel knnModel = knn.fit(trainData);
+        Table output = knnModel.transform(predictData)[0];
+        verifyPredictionResult(output, knn.getLabelCol(), 
knn.getPredictionCol());
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         Knn knn = new Knn();
         Knn loadedKnn =
-                StageTestUtils.saveAndReload(tEnv, knn, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, knn, 
tempFolder.newFolder().getAbsolutePath());
         KnnModel knnModel = loadedKnn.fit(trainData);
         knnModel =
-                StageTestUtils.saveAndReload(
-                        tEnv, knnModel, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, knnModel, 
tempFolder.newFolder().getAbsolutePath());
         assertEquals(
                 Arrays.asList("packedFeatures", "featureNormSquares", 
"labels"),
                 
knnModel.getModelData()[0].getResolvedSchema().getColumnNames());
@@ -200,8 +218,7 @@ public class KnnTest {
         Knn knn = new Knn();
         KnnModel knnModel = knn.fit(trainData);
         KnnModel newModel =
-                StageTestUtils.saveAndReload(
-                        tEnv, knnModel, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, knnModel, 
tempFolder.newFolder().getAbsolutePath());
         Table output = newModel.transform(predictData)[0];
         verifyPredictionResult(output, knn.getLabelCol(), 
knn.getPredictionCol());
     }
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LinearSVCTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LinearSVCTest.java
index 156244e..2c03919 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LinearSVCTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LinearSVCTest.java
@@ -27,10 +27,12 @@ import 
org.apache.flink.ml.classification.linearsvc.LinearSVC;
 import org.apache.flink.ml.classification.linearsvc.LinearSVCModel;
 import org.apache.flink.ml.classification.linearsvc.LinearSVCModelData;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -109,8 +111,8 @@ public class LinearSVCTest {
             throws Exception {
         List<Row> predResult = 
IteratorUtils.toList(tEnv.toDataStream(output).executeAndCollect());
         for (Row predictionRow : predResult) {
-            DenseVector feature = (DenseVector) 
predictionRow.getField(featuresCol);
-            double prediction = (double) predictionRow.getField(predictionCol);
+            DenseVector feature = ((Vector) 
predictionRow.getField(featuresCol)).toDense();
+            double prediction = (Double) predictionRow.getField(predictionCol);
             DenseVector rawPrediction = (DenseVector) 
predictionRow.getField(rawPredictionCol);
             if (feature.get(0) <= 5) {
                 assertEquals(0, prediction, TOLERANCE);
@@ -197,14 +199,29 @@ public class LinearSVCTest {
                 linearSVC.getRawPredictionCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        trainDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
trainDataTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class, 
Integer.class},
+                TestUtils.getColumnDataTypes(trainDataTable));
+
+        LinearSVC linearSVC = new LinearSVC().setWeightCol("weight");
+        Table output = 
linearSVC.fit(trainDataTable).transform(trainDataTable)[0];
+        verifyPredictionResult(
+                output,
+                linearSVC.getFeaturesCol(),
+                linearSVC.getPredictionCol(),
+                linearSVC.getRawPredictionCol());
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         LinearSVC linearSVC = new LinearSVC().setWeightCol("weight");
         linearSVC =
-                StageTestUtils.saveAndReload(
-                        tEnv, linearSVC, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, linearSVC, 
tempFolder.newFolder().getAbsolutePath());
         LinearSVCModel model = linearSVC.fit(trainDataTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         assertEquals(
                 Collections.singletonList("coefficient"),
                 model.getModelData()[0].getResolvedSchema().getColumnNames());
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LogisticRegressionTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LogisticRegressionTest.java
index 4bdab6b..129fd2e 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LogisticRegressionTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/LogisticRegressionTest.java
@@ -27,10 +27,12 @@ import 
org.apache.flink.ml.classification.logisticregression.LogisticRegression;
 import 
org.apache.flink.ml.classification.logisticregression.LogisticRegressionModel;
 import 
org.apache.flink.ml.classification.logisticregression.LogisticRegressionModelData;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -135,7 +137,7 @@ public class LogisticRegressionTest {
             throws Exception {
         List<Row> predResult = 
IteratorUtils.toList(tEnv.toDataStream(output).executeAndCollect());
         for (Row predictionRow : predResult) {
-            DenseVector feature = (DenseVector) 
predictionRow.getField(featuresCol);
+            DenseVector feature = ((Vector) 
predictionRow.getField(featuresCol)).toDense();
             double prediction = (double) predictionRow.getField(predictionCol);
             DenseVector rawPrediction = (DenseVector) 
predictionRow.getField(rawPredictionCol);
             if (feature.get(0) <= 5) {
@@ -223,14 +225,30 @@ public class LogisticRegressionTest {
                 logisticRegression.getRawPredictionCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        binomialDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
binomialDataTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class, 
Integer.class},
+                TestUtils.getColumnDataTypes(binomialDataTable));
+
+        LogisticRegression logisticRegression = new 
LogisticRegression().setWeightCol("weight");
+        Table output = 
logisticRegression.fit(binomialDataTable).transform(binomialDataTable)[0];
+        verifyPredictionResult(
+                output,
+                logisticRegression.getFeaturesCol(),
+                logisticRegression.getPredictionCol(),
+                logisticRegression.getRawPredictionCol());
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         LogisticRegression logisticRegression = new 
LogisticRegression().setWeightCol("weight");
         logisticRegression =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
                         tEnv, logisticRegression, 
tempFolder.newFolder().getAbsolutePath());
         LogisticRegressionModel model = 
logisticRegression.fit(binomialDataTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         assertEquals(
                 Collections.singletonList("coefficient"),
                 model.getModelData()[0].getResolvedSchema().getColumnNames());
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/NaiveBayesTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/NaiveBayesTest.java
index c481fbb..bffb40a 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/NaiveBayesTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/classification/NaiveBayesTest.java
@@ -23,10 +23,11 @@ import org.apache.flink.configuration.Configuration;
 import org.apache.flink.ml.classification.naivebayes.NaiveBayes;
 import org.apache.flink.ml.classification.naivebayes.NaiveBayesModel;
 import org.apache.flink.ml.classification.naivebayes.NaiveBayesModelData;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -57,7 +58,7 @@ public class NaiveBayesTest {
     private StreamTableEnvironment tEnv;
     private Table trainTable;
     private Table predictTable;
-    private Map<Vector, Integer> expectedOutput;
+    private Map<Vector, Double> expectedOutput;
     private NaiveBayes estimator;
 
     @Before
@@ -88,12 +89,12 @@ public class NaiveBayesTest {
         predictTable = 
tEnv.fromDataStream(env.fromCollection(predictData)).as("features");
 
         expectedOutput =
-                new HashMap<Vector, Integer>() {
+                new HashMap<Vector, Double>() {
                     {
-                        put(Vectors.dense(0, 1.), 11);
-                        put(Vectors.dense(0, 0.), 11);
-                        put(Vectors.dense(1, 0.), 10);
-                        put(Vectors.dense(1, 1.), 10);
+                        put(Vectors.dense(0, 1.), 11.0);
+                        put(Vectors.dense(0, 0.), 11.0);
+                        put(Vectors.dense(1, 0.), 10.0);
+                        put(Vectors.dense(1, 1.), 10.0);
                     }
                 };
 
@@ -115,14 +116,14 @@ public class NaiveBayesTest {
      * @param predictionCol Name of the column in the table that contains the 
prediction result
      * @return A map containing the collected results
      */
-    private static Map<Vector, Integer> executeAndCollect(
+    private static Map<Vector, Double> executeAndCollect(
             Table table, String featuresCol, String predictionCol) {
-        Map<Vector, Integer> map = new HashMap<>();
+        Map<Vector, Double> map = new HashMap<>();
         for (CloseableIterator<Row> it = table.execute().collect(); 
it.hasNext(); ) {
             Row row = it.next();
             map.put(
-                    (Vector) row.getField(featuresCol),
-                    ((Number) row.getField(predictionCol)).intValue());
+                    ((Vector) row.getField(featuresCol)).toDense(),
+                    (Double) row.getField(predictionCol));
         }
 
         return map;
@@ -165,7 +166,25 @@ public class NaiveBayesTest {
     public void testFitAndPredict() {
         NaiveBayesModel model = estimator.fit(trainTable);
         Table outputTable = model.transform(predictTable)[0];
-        Map<Vector, Integer> actualOutput =
+        Map<Vector, Double> actualOutput =
+                executeAndCollect(outputTable, model.getFeaturesCol(), 
model.getPredictionCol());
+        assertEquals(expectedOutput, actualOutput);
+    }
+
+    @Test
+    public void testInputTypeConversion() {
+        trainTable = TestUtils.convertDataTypesToSparseInt(tEnv, trainTable);
+        predictTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
predictTable);
+
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class},
+                TestUtils.getColumnDataTypes(trainTable));
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class}, 
TestUtils.getColumnDataTypes(predictTable));
+
+        NaiveBayesModel model = estimator.fit(trainTable);
+        Table outputTable = model.transform(predictTable)[0];
+        Map<Vector, Double> actualOutput =
                 executeAndCollect(outputTable, model.getFeaturesCol(), 
model.getPredictionCol());
         assertEquals(expectedOutput, actualOutput);
     }
@@ -182,7 +201,7 @@ public class NaiveBayesTest {
 
         NaiveBayesModel model = estimator.fit(trainTable);
         Table outputTable = model.transform(predictTable)[0];
-        Map<Vector, Integer> actualOutput =
+        Map<Vector, Double> actualOutput =
                 executeAndCollect(outputTable, model.getFeaturesCol(), 
model.getPredictionCol());
         assertEquals(expectedOutput, actualOutput);
     }
@@ -253,16 +272,15 @@ public class NaiveBayesTest {
     @Test
     public void testSaveLoad() throws Exception {
         estimator =
-                StageTestUtils.saveAndReload(
-                        tEnv, estimator, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, estimator, 
tempFolder.newFolder().getAbsolutePath());
 
         NaiveBayesModel model = estimator.fit(trainTable);
 
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
 
         Table outputTable = model.transform(predictTable)[0];
 
-        Map<Vector, Integer> actualOutput =
+        Map<Vector, Double> actualOutput =
                 executeAndCollect(outputTable, model.getFeaturesCol(), 
model.getPredictionCol());
         assertEquals(expectedOutput, actualOutput);
     }
@@ -299,7 +317,7 @@ public class NaiveBayesTest {
 
         Table outputTable = modelB.transform(predictTable)[0];
 
-        Map<Vector, Integer> actualOutput =
+        Map<Vector, Double> actualOutput =
                 executeAndCollect(outputTable, modelB.getFeaturesCol(), 
modelB.getPredictionCol());
         assertEquals(expectedOutput, actualOutput);
     }
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/KMeansTest.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/KMeansTest.java
index ac2cdb4..d1fb1c3 100644
--- a/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/KMeansTest.java
+++ b/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/KMeansTest.java
@@ -25,9 +25,11 @@ import org.apache.flink.ml.clustering.kmeans.KMeansModel;
 import org.apache.flink.ml.clustering.kmeans.KMeansModelData;
 import org.apache.flink.ml.common.distance.EuclideanDistanceMeasure;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
+import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -97,8 +99,7 @@ public class KMeansTest extends AbstractTestBase {
         env.setRestartStrategy(RestartStrategies.noRestart());
         tEnv = StreamTableEnvironment.create(env);
 
-        Schema schema = Schema.newBuilder().column("f0", 
DataTypes.of(DenseVector.class)).build();
-        dataTable = tEnv.fromDataStream(env.fromCollection(DATA), 
schema).as("features");
+        dataTable = 
tEnv.fromDataStream(env.fromCollection(DATA)).as("features");
     }
 
     /**
@@ -114,7 +115,7 @@ public class KMeansTest extends AbstractTestBase {
             List<Row> rows, String featuresCol, String predictionCol) {
         Map<Integer, Set<DenseVector>> map = new HashMap<>();
         for (Row row : rows) {
-            DenseVector vector = (DenseVector) row.getField(featuresCol);
+            DenseVector vector = ((Vector) 
row.getField(featuresCol)).toDense();
             int predict = (Integer) row.getField(predictionCol);
             map.putIfAbsent(predict, new HashSet<>());
             map.get(predict).add(vector);
@@ -203,15 +204,34 @@ public class KMeansTest extends AbstractTestBase {
         assertTrue(CollectionUtils.isEqualCollection(expectedGroups, 
actualGroups));
     }
 
+    @Test
+    public void testInputTypeConversion() {
+        dataTable = TestUtils.convertDataTypesToSparseInt(tEnv, dataTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class}, 
TestUtils.getColumnDataTypes(dataTable));
+
+        KMeans kmeans = new KMeans().setMaxIter(2).setK(2);
+        KMeansModel model = kmeans.fit(dataTable);
+        Table output = model.transform(dataTable)[0];
+
+        assertEquals(
+                Arrays.asList("features", "prediction"),
+                output.getResolvedSchema().getColumnNames());
+        List<Row> results = IteratorUtils.toList(output.execute().collect());
+        List<Set<DenseVector>> actualGroups =
+                groupFeaturesByPrediction(
+                        results, kmeans.getFeaturesCol(), 
kmeans.getPredictionCol());
+        assertTrue(CollectionUtils.isEqualCollection(expectedGroups, 
actualGroups));
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         KMeans kmeans = new KMeans().setMaxIter(2).setK(2);
         KMeans loadedKmeans =
-                StageTestUtils.saveAndReload(
-                        tEnv, kmeans, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, kmeans, 
tempFolder.newFolder().getAbsolutePath());
         KMeansModel model = loadedKmeans.fit(dataTable);
         KMeansModel loadedModel =
-                StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         Table output = loadedModel.transform(dataTable)[0];
         assertEquals(
                 Arrays.asList("centroids", "weights"),
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/OnlineKMeansTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/OnlineKMeansTest.java
index cd4af68..b56528f 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/OnlineKMeansTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/clustering/OnlineKMeansTest.java
@@ -32,10 +32,12 @@ import org.apache.flink.ml.clustering.kmeans.OnlineKMeans;
 import org.apache.flink.ml.clustering.kmeans.OnlineKMeansModel;
 import org.apache.flink.ml.common.distance.EuclideanDistanceMeasure;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.util.InMemorySinkFunction;
 import org.apache.flink.ml.util.InMemorySourceFunction;
+import org.apache.flink.ml.util.TestUtils;
 import org.apache.flink.runtime.jobgraph.JobGraph;
 import org.apache.flink.runtime.minicluster.MiniCluster;
 import org.apache.flink.runtime.minicluster.MiniClusterConfiguration;
@@ -66,6 +68,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import static 
org.apache.flink.ml.clustering.KMeansTest.groupFeaturesByPrediction;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 /** Tests {@link OnlineKMeans} and {@link OnlineKMeansModel}. */
@@ -307,6 +310,46 @@ public class OnlineKMeansTest extends TestLogger {
                 expectedGroups2, onlineKMeans.getFeaturesCol(), 
onlineKMeans.getPredictionCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        offlineTrainTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
offlineTrainTable);
+        onlineTrainTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
onlineTrainTable);
+        onlinePredictTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
onlinePredictTable);
+
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class},
+                TestUtils.getColumnDataTypes(offlineTrainTable));
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class},
+                TestUtils.getColumnDataTypes(onlineTrainTable));
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class},
+                TestUtils.getColumnDataTypes(onlinePredictTable));
+
+        OnlineKMeans onlineKMeans =
+                new OnlineKMeans()
+                        .setFeaturesCol("features")
+                        .setPredictionCol("prediction")
+                        .setGlobalBatchSize(6)
+                        .setInitialModelData(
+                                KMeansModelData.generateRandomModelData(tEnv, 
2, 2, 0.0, 0));
+        OnlineKMeansModel onlineModel = onlineKMeans.fit(onlineTrainTable);
+        transformAndOutputData(onlineModel);
+
+        final JobID jobID = submitJob(env.getStreamGraph().getJobGraph());
+        waitInitModelDataSetup(jobID);
+
+        trainSource.addAll(trainData1);
+        waitModelDataUpdate(jobID);
+        predictAndAssert(
+                expectedGroups1, onlineKMeans.getFeaturesCol(), 
onlineKMeans.getPredictionCol());
+
+        trainSource.addAll(trainData2);
+        waitModelDataUpdate(jobID);
+        predictAndAssert(
+                expectedGroups2, onlineKMeans.getFeaturesCol(), 
onlineKMeans.getPredictionCol());
+    }
+
     @Test
     public void testInitWithKMeans() throws Exception {
         KMeans kMeans = new 
KMeans().setFeaturesCol("features").setPredictionCol("prediction");
@@ -361,12 +404,11 @@ public class OnlineKMeansTest extends TestLogger {
                         },
                         Vectors.dense(4.5, 4.5));
 
-        Assert.assertArrayEquals(
-                expectedModelData.weights.values, 
actualModelData.weights.values, 1e-5);
+        assertArrayEquals(expectedModelData.weights.values, 
actualModelData.weights.values, 1e-5);
         Assert.assertEquals(expectedModelData.centroids.length, 
actualModelData.centroids.length);
         Arrays.sort(actualModelData.centroids, 
Comparator.comparingDouble(vector -> vector.get(0)));
         for (int i = 0; i < expectedModelData.centroids.length; i++) {
-            Assert.assertArrayEquals(
+            assertArrayEquals(
                     expectedModelData.centroids[i].values,
                     actualModelData.centroids[i].values,
                     1e-5);
@@ -456,12 +498,11 @@ public class OnlineKMeansTest extends TestLogger {
                         new DenseVector[] {Vectors.dense(-10.2, 0.2), 
Vectors.dense(10.1, 0.1)},
                         Vectors.dense(3, 3));
 
-        Assert.assertArrayEquals(
-                expectedModelData.weights.values, 
actualModelData.weights.values, 1e-5);
+        assertArrayEquals(expectedModelData.weights.values, 
actualModelData.weights.values, 1e-5);
         Assert.assertEquals(expectedModelData.centroids.length, 
actualModelData.centroids.length);
         Arrays.sort(actualModelData.centroids, 
Comparator.comparingDouble(vector -> vector.get(0)));
         for (int i = 0; i < expectedModelData.centroids.length; i++) {
-            Assert.assertArrayEquals(
+            assertArrayEquals(
                     expectedModelData.centroids[i].values,
                     actualModelData.centroids[i].values,
                     1e-5);
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/evaluation/BinaryClassificationEvaluatorTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/evaluation/BinaryClassificationEvaluatorTest.java
index e40502f..787a024 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/evaluation/BinaryClassificationEvaluatorTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/evaluation/BinaryClassificationEvaluatorTest.java
@@ -22,8 +22,9 @@ import 
org.apache.flink.api.common.restartstrategy.RestartStrategies;
 import org.apache.flink.configuration.Configuration;
 import 
org.apache.flink.ml.evaluation.binaryclassification.BinaryClassificationEvaluator;
 import 
org.apache.flink.ml.evaluation.binaryclassification.BinaryClassificationEvaluatorParams;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -193,6 +194,34 @@ public class BinaryClassificationEvaluatorTest {
         }
     }
 
+    @Test
+    public void testInputTypeConversion() {
+        inputDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
inputDataTable);
+        assertArrayEquals(
+                new Class<?>[] {Integer.class, SparseVector.class},
+                TestUtils.getColumnDataTypes(inputDataTable));
+
+        BinaryClassificationEvaluator eval =
+                new BinaryClassificationEvaluator()
+                        .setMetricsNames(
+                                
BinaryClassificationEvaluatorParams.AREA_UNDER_PR,
+                                BinaryClassificationEvaluatorParams.KS,
+                                
BinaryClassificationEvaluatorParams.AREA_UNDER_ROC);
+        Table evalResult = eval.transform(inputDataTable)[0];
+        List<Row> results = 
IteratorUtils.toList(evalResult.execute().collect());
+        assertArrayEquals(
+                new String[] {
+                    BinaryClassificationEvaluatorParams.AREA_UNDER_PR,
+                    BinaryClassificationEvaluatorParams.KS,
+                    BinaryClassificationEvaluatorParams.AREA_UNDER_ROC
+                },
+                evalResult.getResolvedSchema().getColumnNames().toArray());
+        Row result = results.get(0);
+        for (int i = 0; i < EXPECTED_DATA.length; ++i) {
+            assertEquals(EXPECTED_DATA[i], result.getFieldAs(i), EPS);
+        }
+    }
+
     @Test
     public void testEvaluateWithDoubleRaw() {
         BinaryClassificationEvaluator eval =
@@ -288,7 +317,7 @@ public class BinaryClassificationEvaluatorTest {
                                 BinaryClassificationEvaluatorParams.KS,
                                 
BinaryClassificationEvaluatorParams.AREA_UNDER_ROC);
         BinaryClassificationEvaluator loadedEval =
-                StageTestUtils.saveAndReload(tEnv, eval, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, eval, 
tempFolder.newFolder().getAbsolutePath());
         Table evalResult = loadedEval.transform(inputDataTable)[0];
         assertArrayEquals(
                 new String[] {
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/BucketizerTest.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/BucketizerTest.java
index 7170103..6f64a2e 100644
--- a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/BucketizerTest.java
+++ b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/BucketizerTest.java
@@ -22,7 +22,7 @@ import 
org.apache.flink.api.common.restartstrategy.RestartStrategies;
 import org.apache.flink.configuration.Configuration;
 import org.apache.flink.ml.common.param.HasHandleInvalid;
 import org.apache.flink.ml.feature.bucketizer.Bucketizer;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -68,9 +68,13 @@ public class BucketizerTest extends AbstractTestBase {
             };
 
     private final List<Row> expectedKeepResult =
-            Arrays.asList(Row.of(1, 0, 1, 0, 0), Row.of(2, 2, 1, 1, 0), 
Row.of(3, 2, 0, 0, 1));
+            Arrays.asList(
+                    Row.of(1, 0.0, 1.0, 0.0, 0.0),
+                    Row.of(2, 2.0, 1.0, 1.0, 0.0),
+                    Row.of(3, 2.0, 0.0, 0.0, 1.0));
 
-    private final List<Row> expectedSkipResult = 
Collections.singletonList(Row.of(1, 0, 1, 0, 0));
+    private final List<Row> expectedSkipResult =
+            Collections.singletonList(Row.of(1, 0.0, 1.0, 0.0, 0.0));
 
     @Before
     public void before() {
@@ -175,6 +179,29 @@ public class BucketizerTest extends AbstractTestBase {
         }
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        inputTable = TestUtils.convertDataTypesToSparseInt(tEnv, inputTable);
+        assertArrayEquals(
+                new Class<?>[] {
+                    Integer.class, Integer.class, Integer.class, 
Integer.class, Integer.class
+                },
+                TestUtils.getColumnDataTypes(inputTable));
+
+        Bucketizer bucketizer =
+                new Bucketizer()
+                        .setInputCols("f1", "f2", "f3", "f4")
+                        .setOutputCols("o1", "o2", "o3", "o4")
+                        .setSplitsArray(splitsArray);
+
+        bucketizer.setHandleInvalid(HasHandleInvalid.SKIP_INVALID);
+        Table output = bucketizer.transform(inputTable)[0];
+
+        List<Row> expectedResult =
+                Arrays.asList(Row.of(1, 1.0, 1.0, 0.0, 0.0), Row.of(3, 1.0, 
1.0, 0.0, 1.0));
+        verifyOutputResult(output, bucketizer.getOutputCols(), expectedResult);
+    }
+
     @Test
     public void testSaveLoadAndTransform() throws Exception {
         Bucketizer bucketizer =
@@ -184,8 +211,7 @@ public class BucketizerTest extends AbstractTestBase {
                         .setHandleInvalid(HasHandleInvalid.KEEP_INVALID)
                         .setSplitsArray(splitsArray);
         Bucketizer loadedBucketizer =
-                StageTestUtils.saveAndReload(
-                        tEnv, bucketizer, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, bucketizer, 
tempFolder.newFolder().getAbsolutePath());
         Table output = loadedBucketizer.transform(inputTable)[0];
         verifyOutputResult(output, loadedBucketizer.getOutputCols(), 
expectedKeepResult);
     }
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/MinMaxScalerTest.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/MinMaxScalerTest.java
index b26f042..1a0cfc4 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/MinMaxScalerTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/MinMaxScalerTest.java
@@ -24,9 +24,10 @@ import org.apache.flink.configuration.Configuration;
 import org.apache.flink.ml.feature.minmaxscaler.MinMaxScaler;
 import org.apache.flink.ml.feature.minmaxscaler.MinMaxScalerModel;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -46,6 +47,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 /** Tests {@link MinMaxScaler} and {@link MinMaxScalerModel}. */
@@ -170,15 +172,31 @@ public class MinMaxScalerTest {
         verifyPredictionResult(output, minMaxScaler.getOutputCol(), 
EXPECTED_DATA);
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        trainDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
trainDataTable);
+        predictDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
predictDataTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class}, 
TestUtils.getColumnDataTypes(trainDataTable));
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class},
+                TestUtils.getColumnDataTypes(predictDataTable));
+
+        MinMaxScaler minMaxScaler = new MinMaxScaler();
+        MinMaxScalerModel minMaxScalerModel = minMaxScaler.fit(trainDataTable);
+        Table output = minMaxScalerModel.transform(predictDataTable)[0];
+        verifyPredictionResult(output, minMaxScaler.getOutputCol(), 
EXPECTED_DATA);
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         MinMaxScaler minMaxScaler = new MinMaxScaler();
         MinMaxScaler loadedMinMaxScaler =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
                         tEnv, minMaxScaler, 
tempFolder.newFolder().getAbsolutePath());
         MinMaxScalerModel model = loadedMinMaxScaler.fit(trainDataTable);
         MinMaxScalerModel loadedModel =
-                StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         assertEquals(
                 Arrays.asList("minVector", "maxVector"),
                 model.getModelData()[0].getResolvedSchema().getColumnNames());
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/OneHotEncoderTest.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/OneHotEncoderTest.java
index b7a0758..8021648 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/OneHotEncoderTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/OneHotEncoderTest.java
@@ -28,7 +28,7 @@ import 
org.apache.flink.ml.feature.onehotencoder.OneHotEncoderModelData;
 import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -155,6 +155,21 @@ public class OneHotEncoderTest {
         assertArrayEquals(expectedOutput, actualOutput);
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        trainTable = TestUtils.convertDataTypesToSparseInt(tEnv, trainTable);
+        predictTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
predictTable);
+        assertArrayEquals(new Class<?>[] {Integer.class}, 
TestUtils.getColumnDataTypes(trainTable));
+        assertArrayEquals(
+                new Class<?>[] {Integer.class}, 
TestUtils.getColumnDataTypes(predictTable));
+
+        OneHotEncoderModel model = estimator.fit(trainTable);
+        Table outputTable = model.transform(predictTable)[0];
+        Map<Double, Vector>[] actualOutput =
+                executeAndCollect(outputTable, model.getInputCols(), 
model.getOutputCols());
+        assertArrayEquals(expectedOutput, actualOutput);
+    }
+
     @Test
     public void testDropLast() {
         estimator.setDropLast(false);
@@ -255,10 +270,9 @@ public class OneHotEncoderTest {
     @Test
     public void testSaveLoad() throws Exception {
         estimator =
-                StageTestUtils.saveAndReload(
-                        tEnv, estimator, 
tempFolder.newFolder().getAbsolutePath());
+                TestUtils.saveAndReload(tEnv, estimator, 
tempFolder.newFolder().getAbsolutePath());
         OneHotEncoderModel model = estimator.fit(trainTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         Table outputTable = model.transform(predictTable)[0];
         Map<Double, Vector>[] actualOutput =
                 executeAndCollect(outputTable, model.getInputCols(), 
model.getOutputCols());
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/StandardScalerTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/StandardScalerTest.java
index 5337973..48a2664 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/StandardScalerTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/StandardScalerTest.java
@@ -24,10 +24,11 @@ import 
org.apache.flink.ml.feature.standardscaler.StandardScaler;
 import org.apache.flink.ml.feature.standardscaler.StandardScalerModel;
 import org.apache.flink.ml.feature.standardscaler.StandardScalerModelData;
 import org.apache.flink.ml.linalg.DenseVector;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -182,15 +183,26 @@ public class StandardScalerTest extends AbstractTestBase {
         verifyPredictionResult(expectedResWithMeanAndStd, output, 
standardScaler.getOutputCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        denseTable = TestUtils.convertDataTypesToSparseInt(tEnv, denseTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class}, 
TestUtils.getColumnDataTypes(denseTable));
+
+        StandardScaler standardScaler = new StandardScaler().setWithMean(true);
+        Table output = standardScaler.fit(denseTable).transform(denseTable)[0];
+        verifyPredictionResult(expectedResWithMeanAndStd, output, 
standardScaler.getOutputCol());
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         StandardScaler standardScaler = new StandardScaler();
         standardScaler =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
                         tEnv, standardScaler, 
tempFolder.newFolder().getAbsolutePath());
 
         StandardScalerModel model = standardScaler.fit(denseTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
 
         assertEquals(
                 Arrays.asList("mean", "std"),
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/VectorAssemblerTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/VectorAssemblerTest.java
index 15fd5d9..420844b 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/VectorAssemblerTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/VectorAssemblerTest.java
@@ -25,7 +25,7 @@ import 
org.apache.flink.ml.feature.vectorassembler.VectorAssembler;
 import org.apache.flink.ml.linalg.DenseVector;
 import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -170,7 +170,28 @@ public class VectorAssemblerTest extends AbstractTestBase {
                         .setOutputCol("assembledVec")
                         .setHandleInvalid(HasHandleInvalid.SKIP_INVALID);
         VectorAssembler loadedVectorAssembler =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
+                        tEnv, vectorAssembler, 
TEMPORARY_FOLDER.newFolder().getAbsolutePath());
+        Table output = loadedVectorAssembler.transform(inputDataTable)[0];
+        verifyOutputResult(output, loadedVectorAssembler.getOutputCol(), 2);
+    }
+
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        inputDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
inputDataTable);
+        assertArrayEquals(
+                new Class<?>[] {
+                    Integer.class, SparseVector.class, Integer.class, 
SparseVector.class
+                },
+                TestUtils.getColumnDataTypes(inputDataTable));
+
+        VectorAssembler vectorAssembler =
+                new VectorAssembler()
+                        .setInputCols("vec", "num", "sparseVec")
+                        .setOutputCol("assembledVec")
+                        .setHandleInvalid(HasHandleInvalid.SKIP_INVALID);
+        VectorAssembler loadedVectorAssembler =
+                TestUtils.saveAndReload(
                         tEnv, vectorAssembler, 
TEMPORARY_FOLDER.newFolder().getAbsolutePath());
         Table output = loadedVectorAssembler.transform(inputDataTable)[0];
         verifyOutputResult(output, loadedVectorAssembler.getOutputCol(), 2);
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/IndexToStringModelTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/IndexToStringModelTest.java
index bc482a1..937b829 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/IndexToStringModelTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/IndexToStringModelTest.java
@@ -20,7 +20,7 @@ package org.apache.flink.ml.feature.stringindexer;
 
 import org.apache.flink.api.common.restartstrategy.RestartStrategies;
 import org.apache.flink.configuration.Configuration;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -137,7 +137,7 @@ public class IndexToStringModelTest extends 
AbstractTestBase {
                         .setInputCols("inputCol1", "inputCol2")
                         .setOutputCols("outputCol1", "outputCol2")
                         .setModelData(modelTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
 
         assertEquals(
                 Collections.singletonList("stringArrays"),
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/StringIndexerTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/StringIndexerTest.java
index c8af00e..08b36a1 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/StringIndexerTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/feature/stringindexer/StringIndexerTest.java
@@ -22,7 +22,7 @@ import 
org.apache.flink.api.common.restartstrategy.RestartStrategies;
 import org.apache.flink.configuration.Configuration;
 import org.apache.flink.ml.common.param.HasHandleInvalid;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -59,13 +59,25 @@ public class StringIndexerTest extends AbstractTestBase {
     private final String[][] expectedAlphabeticAscModelData =
             new String[][] {{"a", "b", "c", "d"}, {"-1.0", "0.0", "1.0", 
"2.0"}};
     private final List<Row> expectedAlphabeticAscPredictData =
-            Arrays.asList(Row.of("a", 2.0, 0, 3), Row.of("b", 1.0, 1, 2), 
Row.of("e", 2.0, 4, 3));
+            Arrays.asList(
+                    Row.of("a", 2.0, 0.0, 3.0),
+                    Row.of("b", 1.0, 1.0, 2.0),
+                    Row.of("e", 2.0, 4.0, 3.0));
     private final List<Row> expectedAlphabeticDescPredictData =
-            Arrays.asList(Row.of("a", 2.0, 3, 0), Row.of("b", 1.0, 2, 1), 
Row.of("e", 2.0, 4, 0));
+            Arrays.asList(
+                    Row.of("a", 2.0, 3.0, 0.0),
+                    Row.of("b", 1.0, 2.0, 1.0),
+                    Row.of("e", 2.0, 4.0, 0.0));
     private final List<Row> expectedFreqAscPredictData =
-            Arrays.asList(Row.of("a", 2.0, 2, 3), Row.of("b", 1.0, 3, 1), 
Row.of("e", 2.0, 4, 3));
+            Arrays.asList(
+                    Row.of("a", 2.0, 2.0, 3.0),
+                    Row.of("b", 1.0, 3.0, 1.0),
+                    Row.of("e", 2.0, 4.0, 3.0));
     private final List<Row> expectedFreqDescPredictData =
-            Arrays.asList(Row.of("a", 2.0, 1, 0), Row.of("b", 1.0, 0, 2), 
Row.of("e", 2.0, 4, 0));
+            Arrays.asList(
+                    Row.of("a", 2.0, 1.0, 0.0),
+                    Row.of("b", 1.0, 0.0, 2.0),
+                    Row.of("e", 2.0, 4.0, 0.0));
 
     @Before
     public void before() {
@@ -170,14 +182,14 @@ public class StringIndexerTest extends AbstractTestBase {
         output = stringIndexer.fit(trainTable).transform(predictTable)[0];
         predictedResult = 
IteratorUtils.toList(tEnv.toDataStream(output).executeAndCollect());
 
-        Set<Integer> distinctStringsCol1 = new HashSet<>();
-        Set<Integer> distinctStringsCol2 = new HashSet<>();
-        int index;
+        Set<Double> distinctStringsCol1 = new HashSet<>();
+        Set<Double> distinctStringsCol2 = new HashSet<>();
+        double index;
         for (Row r : predictedResult) {
-            index = (Integer) r.getField(2);
+            index = (Double) r.getField(2);
             distinctStringsCol1.add(index);
             assertTrue(index >= 0 && index <= 4);
-            index = (Integer) r.getField(3);
+            index = (Double) r.getField(3);
             assertTrue(index >= 0 && index <= 3);
             distinctStringsCol2.add(index);
         }
@@ -209,7 +221,7 @@ public class StringIndexerTest extends AbstractTestBase {
         stringIndexer.setHandleInvalid(StringIndexerParams.SKIP_INVALID);
         output = stringIndexer.fit(trainTable).transform(predictTable)[0];
         predictedResult = 
IteratorUtils.toList(tEnv.toDataStream(output).executeAndCollect());
-        expectedResult = Arrays.asList(Row.of("a", 2.0, 0, 3), Row.of("b", 
1.0, 1, 2));
+        expectedResult = Arrays.asList(Row.of("a", 2.0, 0.0, 3.0), Row.of("b", 
1.0, 1.0, 2.0));
         verifyPredictionResult(expectedResult, predictedResult);
 
         // Throws an exception on invalid data.
@@ -254,11 +266,11 @@ public class StringIndexerTest extends AbstractTestBase {
                         
.setStringOrderType(StringIndexerParams.ALPHABET_ASC_ORDER)
                         .setHandleInvalid(StringIndexerParams.KEEP_INVALID);
         stringIndexer =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
                         tEnv, stringIndexer, 
tempFolder.newFolder().getAbsolutePath());
 
         StringIndexerModel model = stringIndexer.fit(trainTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
 
         assertEquals(
                 Collections.singletonList("stringArrays"),
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/regression/LinearRegressionTest.java
 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/regression/LinearRegressionTest.java
index 3ea99d3..f10a63b 100644
--- 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/regression/LinearRegressionTest.java
+++ 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/regression/LinearRegressionTest.java
@@ -23,13 +23,14 @@ import org.apache.flink.api.common.typeinfo.TypeInformation;
 import org.apache.flink.api.common.typeinfo.Types;
 import org.apache.flink.api.java.typeutils.RowTypeInfo;
 import org.apache.flink.configuration.Configuration;
+import org.apache.flink.ml.linalg.SparseVector;
 import org.apache.flink.ml.linalg.Vectors;
 import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
 import org.apache.flink.ml.regression.linearregression.LinearRegression;
 import org.apache.flink.ml.regression.linearregression.LinearRegressionModel;
 import 
org.apache.flink.ml.regression.linearregression.LinearRegressionModelData;
 import org.apache.flink.ml.util.ReadWriteUtils;
-import org.apache.flink.ml.util.StageTestUtils;
+import org.apache.flink.ml.util.TestUtils;
 import 
org.apache.flink.streaming.api.environment.ExecutionCheckpointingOptions;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.table.api.Table;
@@ -109,7 +110,7 @@ public class LinearRegressionTest {
             throws Exception {
         List<Row> predResult = 
IteratorUtils.toList(tEnv.toDataStream(output).executeAndCollect());
         for (Row predictionRow : predResult) {
-            double label = (double) predictionRow.getField(labelCol);
+            double label = ((Number) 
predictionRow.getField(labelCol)).doubleValue();
             double prediction = (double) predictionRow.getField(predictionCol);
             assertTrue(Math.abs(prediction - label) / label < 
PREDICTION_TOLERANCE);
         }
@@ -175,14 +176,27 @@ public class LinearRegressionTest {
                 output, linearRegression.getLabelCol(), 
linearRegression.getPredictionCol());
     }
 
+    @Test
+    public void testInputTypeConversion() throws Exception {
+        trainDataTable = TestUtils.convertDataTypesToSparseInt(tEnv, 
trainDataTable);
+        assertArrayEquals(
+                new Class<?>[] {SparseVector.class, Integer.class, 
Integer.class},
+                TestUtils.getColumnDataTypes(trainDataTable));
+
+        LinearRegression linearRegression = new 
LinearRegression().setWeightCol("weight");
+        Table output = 
linearRegression.fit(trainDataTable).transform(trainDataTable)[0];
+        verifyPredictionResult(
+                output, linearRegression.getLabelCol(), 
linearRegression.getPredictionCol());
+    }
+
     @Test
     public void testSaveLoadAndPredict() throws Exception {
         LinearRegression linearRegression = new 
LinearRegression().setWeightCol("weight");
         linearRegression =
-                StageTestUtils.saveAndReload(
+                TestUtils.saveAndReload(
                         tEnv, linearRegression, 
tempFolder.newFolder().getAbsolutePath());
         LinearRegressionModel model = linearRegression.fit(trainDataTable);
-        model = StageTestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
+        model = TestUtils.saveAndReload(tEnv, model, 
tempFolder.newFolder().getAbsolutePath());
         assertEquals(
                 Collections.singletonList("coefficient"),
                 model.getModelData()[0].getResolvedSchema().getColumnNames());
diff --git 
a/flink-ml-lib/src/test/java/org/apache/flink/ml/util/StageTestUtils.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/util/StageTestUtils.java
deleted file mode 100644
index 138a6fc..0000000
--- a/flink-ml-lib/src/test/java/org/apache/flink/ml/util/StageTestUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.ml.util;
-
-import org.apache.flink.ml.api.Stage;
-import org.apache.flink.ml.common.datastream.TableUtils;
-import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
-import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
-
-import java.lang.reflect.Method;
-
-/** Utility methods for testing stages. */
-public class StageTestUtils {
-    /**
-     * Saves a stage to filesystem and reloads it by invoking the static 
load() method of the given
-     * stage.
-     */
-    public static <T extends Stage<T>> T saveAndReload(
-            StreamTableEnvironment tEnv, T stage, String path) throws 
Exception {
-        StreamExecutionEnvironment env = 
TableUtils.getExecutionEnvironment(tEnv);
-
-        stage.save(path);
-        try {
-            env.execute();
-        } catch (RuntimeException e) {
-            if (!e.getMessage()
-                    .equals("No operators defined in streaming topology. 
Cannot execute.")) {
-                throw e;
-            }
-        }
-
-        Method method =
-                stage.getClass().getMethod("load", 
StreamTableEnvironment.class, String.class);
-        return (T) method.invoke(null, tEnv, path);
-    }
-}
diff --git a/flink-ml-lib/src/test/java/org/apache/flink/ml/util/TestUtils.java 
b/flink-ml-lib/src/test/java/org/apache/flink/ml/util/TestUtils.java
new file mode 100644
index 0000000..171aa66
--- /dev/null
+++ b/flink-ml-lib/src/test/java/org/apache/flink/ml/util/TestUtils.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.ml.util;
+
+import org.apache.flink.api.common.functions.MapFunction;
+import org.apache.flink.api.common.typeinfo.TypeInformation;
+import org.apache.flink.api.common.typeinfo.Types;
+import org.apache.flink.api.java.typeutils.RowTypeInfo;
+import org.apache.flink.ml.api.Stage;
+import org.apache.flink.ml.common.datastream.TableUtils;
+import org.apache.flink.ml.linalg.Vector;
+import org.apache.flink.ml.linalg.typeinfo.DenseVectorTypeInfo;
+import org.apache.flink.ml.linalg.typeinfo.SparseVectorTypeInfo;
+import org.apache.flink.streaming.api.datastream.DataStream;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+import org.apache.flink.table.api.Table;
+import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
+import org.apache.flink.table.types.DataType;
+import org.apache.flink.types.Row;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.lang.reflect.Method;
+
+/** Utility methods for unit tests. */
+public class TestUtils {
+    /**
+     * Saves a stage to filesystem and reloads it by invoking the static 
load() method of the given
+     * stage.
+     */
+    public static <T extends Stage<T>> T saveAndReload(
+            StreamTableEnvironment tEnv, T stage, String path) throws 
Exception {
+        StreamExecutionEnvironment env = 
TableUtils.getExecutionEnvironment(tEnv);
+
+        stage.save(path);
+        try {
+            env.execute();
+        } catch (RuntimeException e) {
+            if (!e.getMessage()
+                    .equals("No operators defined in streaming topology. 
Cannot execute.")) {
+                throw e;
+            }
+        }
+
+        Method method =
+                stage.getClass().getMethod("load", 
StreamTableEnvironment.class, String.class);
+        return (T) method.invoke(null, tEnv, path);
+    }
+
+    /**
+     * Converts data types in the table to sparse types and integer types.
+     *
+     * <ul>
+     *   <li>If a column in the table is of DenseVector type, converts it to 
SparseVector.
+     *   <li>If a column in the table is of Double type, converts it to 
integer.
+     * </ul>
+     */
+    public static Table convertDataTypesToSparseInt(StreamTableEnvironment 
tEnv, Table table) {
+        RowTypeInfo inputTypeInfo = 
TableUtils.getRowTypeInfo(table.getResolvedSchema());
+        TypeInformation<?>[] fieldTypes = inputTypeInfo.getFieldTypes();
+        for (int i = 0; i < fieldTypes.length; i++) {
+            if (fieldTypes[i].equals(DenseVectorTypeInfo.INSTANCE)) {
+                fieldTypes[i] = SparseVectorTypeInfo.INSTANCE;
+            } else if (fieldTypes[i].equals(Types.DOUBLE)) {
+                fieldTypes[i] = Types.INT;
+            }
+        }
+
+        RowTypeInfo outputTypeInfo =
+                new RowTypeInfo(
+                        ArrayUtils.addAll(fieldTypes),
+                        ArrayUtils.addAll(inputTypeInfo.getFieldNames()));
+        DataStream<Row> dataStream = tEnv.toDataStream(table);
+        dataStream =
+                dataStream.map(
+                        new MapFunction<Row, Row>() {
+                            @Override
+                            public Row map(Row row) {
+                                int arity = row.getArity();
+                                for (int i = 0; i < arity; i++) {
+                                    Object obj = row.getField(i);
+                                    if (obj instanceof Vector) {
+                                        row.setField(i, ((Vector) 
obj).toSparse());
+                                    } else if (obj instanceof Number) {
+                                        row.setField(i, ((Number) 
obj).intValue());
+                                    }
+                                }
+                                return row;
+                            }
+                        },
+                        outputTypeInfo);
+        return tEnv.fromDataStream(dataStream);
+    }
+
+    /** Gets the types of data in each column of the input table. */
+    public static Class<?>[] getColumnDataTypes(Table table) {
+        return table.getResolvedSchema().getColumnDataTypes().stream()
+                .map(DataType::getConversionClass)
+                .toArray(Class<?>[]::new);
+    }
+}

Reply via email to