MinMaxScalerPreprocessor implements Preprocessor<K, V>, DeployableObject { @Override public LabeledVector apply(K k, V v) { LabeledVector res = basePreprocessor.apply(k, v); assert res.size() == min.length; assert res.size() == max.length; for (int i = 0; i < res.size(); i++) { double num = res.get(i) - min[i]; double denom = max[i] - min[i]; double scaled = num / denom; if (Double.isNaN(scaled)) res.set(i, num); else res.set(i, scaled); } return res; } MinMaxScalerPreprocessor(double[] min, double[] max, Preprocessor<K, V> basePreprocessor); @Override LabeledVector apply(K k, V v); double[] getMin(); double[] getMax(); @Override List<Object> getDependencies();  }
@Test public void testApply() { double[][] data = new double[][]{ {2., 4., 1.}, {1., 8., 22.}, {4., 10., 100.}, {0., 22., 300.} }; Vectorizer<Integer, double[], Integer, Double> vectorizer = new DoubleArrayVectorizer<>(0, 1, 2); MinMaxScalerPreprocessor<Integer, double[]> preprocessor = new MinMaxScalerPreprocessor<>( new double[] {0, 4, 1}, new double[] {4, 22, 300}, vectorizer ); double[][] standardData = new double[][]{ {2. / 4, (4. - 4.) / 18., 0.}, {1. / 4, (8. - 4.) / 18., (22. - 1.) / 299.}, {1., (10. - 4.) / 18., (100. - 1.) / 299.}, {0., (22. - 4.) / 18., (300. - 1.) / 299.} }; for (int i = 0; i < data.length; i++) assertArrayEquals(standardData[i], preprocessor.apply(i, data[i]).features().asArray(), 1e-8); }
@Test public void testApplyDivisionByZero() { double[][] data = new double[][]{{1.}, {1.}, {1.}, {1.}}; MinMaxScalerPreprocessor<Integer, double[]> preprocessor = new MinMaxScalerPreprocessor<>( new double[] {1.}, new double[] {1.}, new DoubleArrayVectorizer<>(0) ); double[][] standardData = new double[][]{{0.}, {0.}, {0.}, {0.}}; for (int i = 0; i < data.length; i++) assertArrayEquals(standardData[i], preprocessor.apply(i, data[i]).features().asArray(), 1e-8); }