protected GLM refitGaussianRegressor(int p, int[][] groups, boolean[] selected, int[][][] indices, double[][][] values, double[] y, double[][] w, int maxNumIters) {
		List<int[]> iList = new ArrayList<>();
		List<double[]> vList = new ArrayList<>();
		for (int g = 0; g < selected.length; g++) {
			if (selected[g]) {
				int[][] iBlock = indices[g];
				double[][] vBlock = values[g];
				for (int j = 0; j < vBlock.length; j++) {
					iList.add(iBlock[j]);
					vList.add(vBlock[j]);
				}
			}
		}

		if (vList.size() == 0) {
			if (fitIntercept) {
				double intercept = StatUtils.mean(y);
				GLM glm = new GLM();
				glm.intercept[0] = intercept;
				return glm;
			} else {
				return new GLM();
			}
		}

		int[][] idxNew = new int[iList.size()][];
		for (int i = 0; i < idxNew.length; i++) {
			idxNew[i] = iList.get(i);
		}
		double[][] valNew = new double[vList.size()][];
		for (int i = 0; i < valNew.length; i++) {
			valNew[i] = vList.get(i);
		}

		int[] attrs = new int[valNew.length];
		for (int i = 0; i < attrs.length; i++) {
			attrs[i] = i;
		}

		RidgeLearner ridgeLearner = new RidgeLearner();
		ridgeLearner.setVerbose(verbose);
		ridgeLearner.setEpsilon(epsilon);
		ridgeLearner.fitIntercept(fitIntercept);
		// A ridge regression with very small regularization parameter
		// This often improves stability a lot
		GLM glm = ridgeLearner.buildGaussianRegressor(attrs, idxNew, valNew, y, maxNumIters, 1e-8);
		return getGLM(p, groups, selected, glm.coefficients(0), glm.intercept(0), LinkFunction.IDENTITY);
	}