Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 13184)
@@ -82,6 +82,6 @@
       get { return (FixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
     }
-    public IConstrainedValueParameter<StringValue> LossFunctionParameter {
-      get { return (IConstrainedValueParameter<StringValue>)Parameters[LossFunctionParameterName]; }
+    public IConstrainedValueParameter<ILossFunction> LossFunctionParameter {
+      get { return (IConstrainedValueParameter<ILossFunction>)Parameters[LossFunctionParameterName]; }
     }
     public IFixedValueParameter<IntValue> UpdateIntervalParameter {
@@ -164,9 +164,32 @@
       Parameters[CreateSolutionParameterName].Hidden = true;
 
-      var lossFunctionNames = ApplicationManager.Manager.GetInstances<ILossFunction>().Select(l => new StringValue(l.ToString()).AsReadOnly());
-      Parameters.Add(new ConstrainedValueParameter<StringValue>(LossFunctionParameterName, "The loss function", new ItemSet<StringValue>(lossFunctionNames)));
-      LossFunctionParameter.ActualValue = LossFunctionParameter.ValidValues.First(l => l.Value.Contains("Squared")); // squared error loss is the default
-    }
-
+      var lossFunctions = ApplicationManager.Manager.GetInstances<ILossFunction>();
+      Parameters.Add(new ConstrainedValueParameter<ILossFunction>(LossFunctionParameterName, "The loss function", new ItemSet<ILossFunction>(lossFunctions)));
+      LossFunctionParameter.Value = LossFunctionParameter.ValidValues.First(f => f.ToString().Contains("Squared")); // squared error loss is the default
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.4
+      #region Backwards compatible code, remove with 3.5
+      // parameter type has been changed
+      var lossFunctionParam = Parameters[LossFunctionParameterName] as ConstrainedValueParameter<StringValue>;
+      if (lossFunctionParam != null) {
+        Parameters.Remove(LossFunctionParameterName);
+        var selectedValue = lossFunctionParam.Value; // to be restored below
+
+        var lossFunctions = ApplicationManager.Manager.GetInstances<ILossFunction>();
+        Parameters.Add(new ConstrainedValueParameter<ILossFunction>(LossFunctionParameterName, "The loss function", new ItemSet<ILossFunction>(lossFunctions)));
+        // try to restore selected value
+        var selectedLossFunction =
+          LossFunctionParameter.ValidValues.FirstOrDefault(f => f.ToString() == selectedValue.Value);
+        if (selectedLossFunction != null) {
+          LossFunctionParameter.Value = selectedLossFunction;
+        } else {
+          LossFunctionParameter.Value = LossFunctionParameter.ValidValues.First(f => f.ToString().Contains("Squared")); // default: SE
+        }
+      }
+      #endregion
+    }
 
     protected override void Run(CancellationToken cancellationToken) {
@@ -187,6 +210,5 @@
       // init
       var problemData = (IRegressionProblemData)Problem.ProblemData.Clone();
-      var lossFunction = ApplicationManager.Manager.GetInstances<ILossFunction>()
-        .Single(l => l.ToString() == LossFunctionParameter.Value.Value);
+      var lossFunction = LossFunctionParameter.Value;
       var state = GradientBoostedTreesAlgorithmStatic.CreateGbmState(problemData, lossFunction, (uint)Seed, MaxSize, R, M, Nu);
 
@@ -233,17 +255,19 @@
       // produce solution 
       if (CreateSolution) {
+        var model = state.GetModel();
+
         // for logistic regression we produce a classification solution
         if (lossFunction is LogisticRegressionLoss) {
-          var model = new DiscriminantFunctionClassificationModel(state.GetModel(),
+          var classificationModel = new DiscriminantFunctionClassificationModel(model,
             new AccuracyMaximizationThresholdCalculator());
           var classificationProblemData = new ClassificationProblemData(problemData.Dataset,
             problemData.AllowedInputVariables, problemData.TargetVariable, problemData.Transformations);
-          model.RecalculateModelParameters(classificationProblemData, classificationProblemData.TrainingIndices);
-
-          var classificationSolution = new DiscriminantFunctionClassificationSolution(model, classificationProblemData);
+          classificationModel.RecalculateModelParameters(classificationProblemData, classificationProblemData.TrainingIndices);
+
+          var classificationSolution = new DiscriminantFunctionClassificationSolution(classificationModel, classificationProblemData);
           Results.Add(new Result("Solution", classificationSolution));
         } else {
           // otherwise we produce a regression solution
-          Results.Add(new Result("Solution", new RegressionSolution(state.GetModel(), problemData)));
+          Results.Add(new Result("Solution", new RegressionSolution(model, problemData)));
         }
       }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs	(revision 13184)
@@ -52,4 +52,5 @@
       internal RegressionTreeBuilder treeBuilder { get; private set; }
 
+      private readonly uint randSeed;
       private MersenneTwister random { get; set; }
 
@@ -71,4 +72,5 @@
         this.m = m;
 
+        this.randSeed = randSeed;
         random = new MersenneTwister(randSeed);
         this.problemData = problemData;
@@ -99,5 +101,11 @@
 
       public IRegressionModel GetModel() {
-        return new GradientBoostedTreesModel(models, weights);
+#pragma warning disable 618
+        var model = new GradientBoostedTreesModel(models, weights);
+#pragma warning restore 618
+        // we don't know the number of iterations here but the number of weights is equal 
+        // to the number of iterations + 1 (for the constant model)
+        // wrap the actual model in a surrogate that enables persistence and lazy recalculation of the model if necessary
+        return new GradientBoostedTreesModelSurrogate(problemData, randSeed, lossFunction, weights.Count - 1, maxSize, r, m, nu, model);
       }
       public IEnumerable<KeyValuePair<string, double>> GetVariableRelevance() {
@@ -122,5 +130,5 @@
 
     // simple interface
-    public static IRegressionSolution TrainGbm(IRegressionProblemData problemData, ILossFunction lossFunction, int maxSize, double nu, double r, double m, int maxIterations, uint randSeed = 31415) {
+    public static GradientBoostedTreesSolution TrainGbm(IRegressionProblemData problemData, ILossFunction lossFunction, int maxSize, double nu, double r, double m, int maxIterations, uint randSeed = 31415) {
       Contract.Assert(r > 0);
       Contract.Assert(r <= 1.0);
@@ -135,5 +143,5 @@
 
       var model = state.GetModel();
-      return new RegressionSolution(model, (IRegressionProblemData)problemData.Clone());
+      return new GradientBoostedTreesSolution(model, (IRegressionProblemData)problemData.Clone());
     }
 
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModel.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModel.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModel.cs	(revision 13184)
@@ -33,20 +33,48 @@
   [Item("Gradient boosted tree model", "")]
   // this is essentially a collection of weighted regression models
-  public sealed class GradientBoostedTreesModel : NamedItem, IRegressionModel {
-    [Storable]
+  public sealed class GradientBoostedTreesModel : NamedItem, IGradientBoostedTreesModel {
+    // BackwardsCompatibility3.4 for allowing deserialization & serialization of old models
+    #region Backwards compatible code, remove with 3.5
+    private bool isCompatibilityLoaded = false; // only set to true if the model is deserialized from the old format, needed to make sure that information is serialized again if it was loaded from the old format
+
+    [Storable(Name = "models")]
+    private IList<IRegressionModel> __persistedModels {
+      set {
+        this.isCompatibilityLoaded = true;
+        this.models.Clear();
+        foreach (var m in value) this.models.Add(m);
+      }
+      get { if (this.isCompatibilityLoaded) return models; else return null; }
+    }
+    [Storable(Name = "weights")]
+    private IList<double> __persistedWeights {
+      set {
+        this.isCompatibilityLoaded = true;
+        this.weights.Clear();
+        foreach (var w in value) this.weights.Add(w);
+      }
+      get { if (this.isCompatibilityLoaded) return weights; else return null; }
+    }
+    #endregion
+
     private readonly IList<IRegressionModel> models;
     public IEnumerable<IRegressionModel> Models { get { return models; } }
 
-    [Storable]
     private readonly IList<double> weights;
     public IEnumerable<double> Weights { get { return weights; } }
 
     [StorableConstructor]
-    private GradientBoostedTreesModel(bool deserializing) : base(deserializing) { }
+    private GradientBoostedTreesModel(bool deserializing)
+      : base(deserializing) {
+      models = new List<IRegressionModel>();
+      weights = new List<double>();
+    }
     private GradientBoostedTreesModel(GradientBoostedTreesModel original, Cloner cloner)
       : base(original, cloner) {
       this.weights = new List<double>(original.weights);
       this.models = new List<IRegressionModel>(original.models.Select(m => cloner.Clone(m)));
+      this.isCompatibilityLoaded = original.isCompatibilityLoaded;
     }
+    [Obsolete("The constructor of GBTModel should not be used directly anymore (use GBTModelSurrogate instead)")]
     public GradientBoostedTreesModel(IEnumerable<IRegressionModel> models, IEnumerable<double> weights)
       : base("Gradient boosted tree model", string.Empty) {
@@ -64,5 +92,5 @@
       // allocate target array go over all models and add up weighted estimation for each row
       if (!rows.Any()) return Enumerable.Empty<double>(); // return immediately if rows is empty. This prevents multiple iteration over lazy rows enumerable.
-                                                          // (which essentially looks up indexes in a dictionary)
+      // (which essentially looks up indexes in a dictionary)
       var res = new double[rows.Count()];
       for (int i = 0; i < models.Count; i++) {
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 13184)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 13184)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * and the BEACON Center for the Study of Evolution in Action.
+ * 
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  // this class is used as a surrogate for persistence of an actual GBT model 
+  // since the actual GBT model would be very large when persisted we only store all necessary information to
+  // recalculate the actual GBT model on demand
+  [Item("Gradient boosted tree model", "")]
+  public sealed class GradientBoostedTreesModelSurrogate : NamedItem, IGradientBoostedTreesModel {
+    // don't store the actual model!
+    private IGradientBoostedTreesModel actualModel; // the actual model is only recalculated when necessary
+
+    [Storable]
+    private readonly IRegressionProblemData trainingProblemData;
+    [Storable]
+    private readonly uint seed;
+    [Storable]
+    private ILossFunction lossFunction;
+    [Storable]
+    private double r;
+    [Storable]
+    private double m;
+    [Storable]
+    private double nu;
+    [Storable]
+    private int iterations;
+    [Storable]
+    private int maxSize;
+
+
+    [StorableConstructor]
+    private GradientBoostedTreesModelSurrogate(bool deserializing) : base(deserializing) { }
+
+    private GradientBoostedTreesModelSurrogate(GradientBoostedTreesModelSurrogate original, Cloner cloner)
+      : base(original, cloner) {
+      if (original.actualModel != null) this.actualModel = cloner.Clone(original.actualModel);
+
+      this.trainingProblemData = cloner.Clone(original.trainingProblemData);
+      this.lossFunction = cloner.Clone(original.lossFunction);
+      this.seed = original.seed;
+      this.iterations = original.iterations;
+      this.maxSize = original.maxSize;
+      this.r = original.r;
+      this.m = original.m;
+      this.nu = original.nu;
+    }
+
+    // create only the surrogate model without an actual model
+    public GradientBoostedTreesModelSurrogate(IRegressionProblemData trainingProblemData, uint seed, ILossFunction lossFunction, int iterations, int maxSize, double r, double m, double nu)
+      : base("Gradient boosted tree model", string.Empty) {
+      this.trainingProblemData = trainingProblemData;
+      this.seed = seed;
+      this.lossFunction = lossFunction;
+      this.iterations = iterations;
+      this.maxSize = maxSize;
+      this.r = r;
+      this.m = m;
+      this.nu = nu;
+    }
+
+    // wrap an actual model in a surrograte
+    public GradientBoostedTreesModelSurrogate(IRegressionProblemData trainingProblemData, uint seed, ILossFunction lossFunction, int iterations, int maxSize, double r, double m, double nu, IGradientBoostedTreesModel model)
+      : this(trainingProblemData, seed, lossFunction, iterations, maxSize, r, m, nu) {
+      this.actualModel = model;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GradientBoostedTreesModelSurrogate(this, cloner);
+    }
+
+    // forward message to actual model (recalculate model first if necessary)
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      if (actualModel == null) actualModel = RecalculateModel();
+      return actualModel.GetEstimatedValues(dataset, rows);
+    }
+
+    public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, (IRegressionProblemData)problemData.Clone());
+    }
+
+
+    private IGradientBoostedTreesModel RecalculateModel() {
+      return GradientBoostedTreesAlgorithmStatic.TrainGbm(trainingProblemData, lossFunction, maxSize, nu, r, m, iterations, seed).Model;
+    }
+
+    public IEnumerable<IRegressionModel> Models {
+      get {
+        if (actualModel == null) actualModel = RecalculateModel();
+        return actualModel.Models;
+      }
+    }
+
+    public IEnumerable<double> Weights {
+      get {
+        if (actualModel == null) actualModel = RecalculateModel();
+        return actualModel.Weights;
+      }
+    }
+  }
+}
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesSolution.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesSolution.cs	(revision 13184)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesSolution.cs	(revision 13184)
@@ -0,0 +1,51 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  public sealed class GradientBoostedTreesSolution : RegressionSolution {
+    public new IGradientBoostedTreesModel Model {
+      get { return (IGradientBoostedTreesModel)base.Model; }
+    }
+
+
+    [StorableConstructor]
+    private GradientBoostedTreesSolution(bool deserializing)
+      : base(deserializing) {
+    }
+    private GradientBoostedTreesSolution(GradientBoostedTreesSolution original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public GradientBoostedTreesSolution(IRegressionModel model, IRegressionProblemData problemData)
+      : base(model, problemData) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GradientBoostedTreesSolution(this, cloner);
+    }
+  }
+}
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/IGradientBoostedTreesModel.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/IGradientBoostedTreesModel.cs	(revision 13184)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/IGradientBoostedTreesModel.cs	(revision 13184)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * and the BEACON Center for the Study of Evolution in Action.
+ * 
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  public interface IGradientBoostedTreesModel : IRegressionModel {
+    IEnumerable<IRegressionModel> Models { get; }
+    IEnumerable<double> Weights { get; }
+  }
+}
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs	(revision 13184)
@@ -23,11 +23,15 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
   // loss function for the weighted absolute error
-  public class AbsoluteErrorLoss : ILossFunction {
+  [StorableClass]
+  [Item("Absolute error loss", "")]
+  public sealed class AbsoluteErrorLoss : Item, ILossFunction {
+    public AbsoluteErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -77,7 +81,14 @@
     }
 
-    public override string ToString() {
-      return "Absolute error loss";
+    #region item implementation
+    [StorableConstructor]
+    private AbsoluteErrorLoss(bool deserializing) : base(deserializing) { }
+
+    private AbsoluteErrorLoss(AbsoluteErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AbsoluteErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs	(revision 13184)
@@ -22,4 +22,5 @@
 
 using System.Collections.Generic;
+using HeuristicLab.Core;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
@@ -27,5 +28,5 @@
   // target represents the target vector  (original targets from the problem data, never changed)
   // pred   represents the current vector of predictions (a weighted combination of models learned so far, this vector is updated after each step)
-  public interface ILossFunction {
+  public interface ILossFunction : IItem {
     // returns the loss of the current prediction vector 
     double GetLoss(IEnumerable<double> target, IEnumerable<double> pred);
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs	(revision 13184)
@@ -26,8 +26,14 @@
 using System.Linq;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
   // Greedy Function Approximation: A Gradient Boosting Machine (page 9) 
-  public class LogisticRegressionLoss : ILossFunction {
+  [StorableClass]
+  [Item("Logistic regression loss", "")]
+  public sealed class LogisticRegressionLoss : Item, ILossFunction {
+    public LogisticRegressionLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -83,7 +89,15 @@
     }
 
-    public override string ToString() {
-      return "Logistic regression loss";
+    #region item implementation
+    [StorableConstructor]
+    private LogisticRegressionLoss(bool deserializing) : base(deserializing) { }
+
+    private LogisticRegressionLoss(LogisticRegressionLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LogisticRegressionLoss(this, cloner);
     }
+    #endregion
+
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs	(revision 13184)
@@ -26,8 +26,14 @@
 using System.Linq;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
   // relative error loss is a special case of weighted absolute error loss with weights = (1/target)
-  public class RelativeErrorLoss : ILossFunction {
+  [StorableClass]
+  [Item("Relative error loss", "")]
+  public sealed class RelativeErrorLoss : Item, ILossFunction {
+    public RelativeErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -105,7 +111,14 @@
     }
 
-    public override string ToString() {
-      return "Relative error loss";
+    #region item implementation
+    [StorableConstructor]
+    private RelativeErrorLoss(bool deserializing) : base(deserializing) { }
+
+    private RelativeErrorLoss(RelativeErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RelativeErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs	(revision 13184)
@@ -24,7 +24,14 @@
 using System.Collections.Generic;
 using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
-  public class SquaredErrorLoss : ILossFunction {
+  [StorableClass]
+  [Item("Squared error loss", "")]
+  public sealed class SquaredErrorLoss : Item, ILossFunction {
+    public SquaredErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -70,7 +77,14 @@
     }
 
-    public override string ToString() {
-      return "Squared error loss";
+    #region item implementation
+    [StorableConstructor]
+    private SquaredErrorLoss(bool deserializing) : base(deserializing) { }
+
+    private SquaredErrorLoss(SquaredErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SquaredErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs	(revision 13184)
@@ -119,23 +119,4 @@
     }
 
-    // simple API produces a single regression tree optimizing sum of squared errors
-    // this can be used if only a simple regression tree should be produced
-    // for a set of trees use the method CreateRegressionTreeForGradientBoosting below
-    //
-    // r and m work in the same way as for alglib random forest
-    // r is fraction of rows to use for training
-    // m is fraction of variables to use for training
-    public IRegressionModel CreateRegressionTree(int maxSize, double r = 0.5, double m = 0.5) {
-      // subtract mean of y first
-      var yAvg = y.Average();
-      for (int i = 0; i < y.Length; i++) y[i] -= yAvg;
-
-      var seLoss = new SquaredErrorLoss();
-
-      var model = CreateRegressionTreeForGradientBoosting(y, curPred, maxSize, problemData.TrainingIndices.ToArray(), seLoss, r, m);
-
-      return new GradientBoostedTreesModel(new[] { new ConstantRegressionModel(yAvg), model }, new[] { 1.0, 1.0 });
-    }
-
     // specific interface that allows to specify the target labels and the training rows which is necessary when for gradient boosted trees
     public IRegressionModel CreateRegressionTreeForGradientBoosting(double[] y, double[] curPred, int maxSize, int[] idx, ILossFunction lossFunction, double r = 0.5, double m = 0.5) {
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 13184)
@@ -82,4 +82,5 @@
     [Storable]
     // to prevent storing the references to data caches in nodes
+    // seemingly it is bad (performance-wise) to persist tuples (tuples are used as keys in a dictionary) TODO
     private Tuple<string, double, int, int>[] SerializedTree {
       get { return tree.Select(t => Tuple.Create(t.VarName, t.Val, t.LeftIdx, t.RightIdx)).ToArray(); }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 13156)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 13184)
@@ -200,4 +200,6 @@
     <Compile Include="GaussianProcess\GaussianProcessRegressionSolution.cs" />
     <Compile Include="GaussianProcess\ICovarianceFunction.cs" />
+    <Compile Include="GradientBoostedTrees\IGradientBoostedTreesModel.cs" />
+    <Compile Include="GradientBoostedTrees\GradientBoostedTreesModelSurrogate.cs" />
     <Compile Include="GradientBoostedTrees\GradientBoostedTreesAlgorithm.cs" />
     <Compile Include="GradientBoostedTrees\GradientBoostedTreesAlgorithmStatic.cs" />
@@ -209,4 +211,5 @@
     <Compile Include="GradientBoostedTrees\LossFunctions\RelativeErrorLoss.cs" />
     <Compile Include="GradientBoostedTrees\LossFunctions\SquaredErrorLoss.cs" />
+    <Compile Include="GradientBoostedTrees\GradientBoostedTreesSolution.cs" />
     <Compile Include="GradientBoostedTrees\RegressionTreeBuilder.cs" />
     <Compile Include="GradientBoostedTrees\RegressionTreeModel.cs" />
