code: @Override
      protected void _fit(Dataframe trainingData) {
          ModelParameters modelParameters = knowledgeBase.getModelParameters();
          
          Map<Object, Double> thitas = modelParameters.getThitas();
          
          //we initialize the thitas to zero for all features
          thitas.put(Dataframe.COLUMN_NAME_CONSTANT, 0.0);
          for(Object feature : trainingData.getXDataTypes().keySet()) {
              thitas.put(feature, 0.0);
          }
          
          TrainingParameters trainingParameters = knowledgeBase.getTrainingParameters();
  
          double minError = Double.POSITIVE_INFINITY;
          
          double learningRate = trainingParameters.getLearningRate();
          int totalIterations = trainingParameters.getTotalIterations();
          StorageEngine storageEngine = knowledgeBase.getStorageEngine();
          for(int iteration=0;iteration<totalIterations;++iteration) {
              
              logger.debug("Iteration {}", iteration);
              
              Map<Object, Double> tmp_newThitas = storageEngine.getBigMap("tmp_newThitas", Object.class, Double.class, MapType.HASHMAP, StorageHint.IN_MEMORY, false, true);
              
              tmp_newThitas.putAll(thitas);
              
              batchGradientDescent(trainingData, tmp_newThitas, learningRate);
              
              double newError = calculateError(trainingData,tmp_newThitas);
              
              //bold driver
              if(newError>minError) {
                  learningRate/=2.0;
              }
              else {
                  learningRate*=1.05;
                  minError=newError;
                  
                  //keep the new thitas
                  thitas.clear();
                  thitas.putAll(tmp_newThitas);
              }
              
              //Drop the temporary Collection
              storageEngine.dropBigMap("tmp_newThitas", tmp_newThitas);
          }
      }
docs: {@inheritDoc}