docs: public static void reduceDimension(final List<Tuple> trainingData) {
          // FeatName - <feat possible vals, count of instances that has this val>
          // Do NOT store index for featname, index might not be same among tuples for the same featname.
          Map<String, Map<Double, Integer>> featNameValues = new HashMap<>();
          for (Tuple t : trainingData) {
              double[] featValues = t.vector.getVector();
              String[] name;
              if (t.vector instanceof FeatNamedVector) {
                  name = ((FeatNamedVector) t.vector).featsName;
              } else {
                  name = IntStream.range(0, t.vector.getVector().length).mapToObj(String::valueOf).toArray(String[]::new);
              }
  
              for (int i = 0; i < featValues.length; i++) {
                  if (!featNameValues.containsKey(name[i])) {
                      featNameValues.put(name[i], new HashMap<>());
                  }
  
                  Map<Double, Integer> valMap = featNameValues.get(name[i]);
                  int newCount = 0;
                  if (valMap.containsKey(featValues[i])) {
                      newCount = valMap.get(featValues[i]);
                  }
  
                  newCount++;
                  valMap.put(featValues[i], newCount);
              }
          }
  
          Set<String> singleValFeats = getSingleValFeat(featNameValues, trainingData.size());
          LOG.debug("Single value feats: ");
          LOG.debug(singleValFeats.toString().replaceAll(", ", System.lineSeparator()));
  
          for (Tuple t : trainingData) {
              List<Double> featVal = new ArrayList<>();
              double[] originalVectorVal = t.vector.getVector();
  
              Set<Integer> indicesToBeRemoved;
              if (t.vector instanceof FeatNamedVector) {
                  indicesToBeRemoved = new HashSet<>();
                  String[] featName = ((FeatNamedVector) t.vector).featsName;
  
                  for (int i = 0; i < featName.length; i++) {
                      if (singleValFeats.contains(featName[i])) {
                          indicesToBeRemoved.add(i);
                      }
                  }
              } else {
                  indicesToBeRemoved = singleValFeats.stream().map(Integer::parseInt).collect(Collectors.toSet());
              }
  
  
              for (int i = 0; i < originalVectorVal.length; i++) {
                  if (!indicesToBeRemoved.contains(i)) {
                      featVal.add(originalVectorVal[i]);
                  }
              }
  
              t.vector.setVector(featVal.stream().mapToDouble(x -> x).toArray());
  
              // Set feat name if needed
              if (t.vector instanceof FeatNamedVector) {
                  List<String> featName = new ArrayList<>();
                  String[] originalFeatName = ((FeatNamedVector) t.vector).featsName;
  
                  for (int i = 0; i < originalVectorVal.length; i++) {
                      if (!indicesToBeRemoved.contains(i)) {
                          featName.add(originalFeatName[i]);
                      }
                  }
  
                  ((FeatNamedVector) t.vector).featsName = featName.stream().toArray(String[]::new);
              }
  
  
          }
  
      }