public static GaussianProcessRegression<double[]> fit(double[][] x, double[] y, Properties params) {
        MercerKernel<double[]> kernel = MercerKernel.of(params.getProperty("smile.gaussian_process.kernel", "linear"));
        double noise = Double.parseDouble(params.getProperty("smile.gaussian_process.noise", "1E-10"));
        boolean normalize = Boolean.parseBoolean(params.getProperty("smile.gaussian_process.normalize", "true"));
        double tol = Double.parseDouble(params.getProperty("smile.gaussian_process.tolerance", "1E-5"));
        int maxIter = Integer.parseInt(params.getProperty("smile.gaussian_process.iterations", "0"));
        return fit(x, y, kernel, noise, normalize, tol, maxIter);
    }
@Test
    public void testHPO() {
        System.out.println("HPO longley");

        MathEx.setSeed(19650218); // to get repeatable results.

        double[][] longley = MathEx.clone(Longley.x);
        MathEx.standardize(longley);

        GaussianProcessRegression<double[]> model = GaussianProcessRegression.fit(longley, Longley.y, new GaussianKernel(8.0), 0.2, true, 1E-5, 500);
        System.out.println(model);
        assertEquals(-0.8996, model.L, 1E-4);
        assertEquals(0.0137, model.noise, 1E-4);

        MercerKernel<double[]> kernel = model.kernel;
        double noise = model.noise;

        RegressionMetrics metrics = LOOCV.regression(longley, Longley.y, (xi, yi) -> GaussianProcessRegression.fit(xi, yi, kernel, noise));

        System.out.println(metrics);
        assertEquals(1.7104, metrics.rmse, 1E-4);
    }