Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 12873)
@@ -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,5 +255,5 @@
       // produce solution 
       if (CreateSolution) {
-        var surrogateModel = new GradientBoostedTreesModelSurrogate(problemData, (uint)Seed, lossFunction.ToString(),
+        var surrogateModel = new GradientBoostedTreesModelSurrogate(problemData, (uint)Seed, lossFunction,
           Iterations, MaxSize, R, M, Nu, state.GetModel());
 
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 12873)
@@ -45,5 +45,5 @@
     private readonly uint seed;
     [Storable]
-    private string lossFunctionName;
+    private ILossFunction lossFunction;
     [Storable]
     private double r;
@@ -66,6 +66,6 @@
 
       this.trainingProblemData = cloner.Clone(original.trainingProblemData);
+      this.lossFunction = cloner.Clone(original.lossFunction);
       this.seed = original.seed;
-      this.lossFunctionName = original.lossFunctionName;
       this.iterations = original.iterations;
       this.maxSize = original.maxSize;
@@ -76,9 +76,9 @@
 
     // create only the surrogate model without an actual model
-    public GradientBoostedTreesModelSurrogate(IRegressionProblemData trainingProblemData, uint seed, string lossFunctionName, int iterations, int maxSize, double r, double m, double nu)
+    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.lossFunctionName = lossFunctionName;
+      this.lossFunction = lossFunction;
       this.iterations = iterations;
       this.maxSize = maxSize;
@@ -89,6 +89,6 @@
 
     // wrap an actual model in a surrograte
-    public GradientBoostedTreesModelSurrogate(IRegressionProblemData trainingProblemData, uint seed, string lossFunctionName, int iterations, int maxSize, double r, double m, double nu, IRegressionModel model)
-      : this(trainingProblemData, seed, lossFunctionName, iterations, maxSize, r, m, nu) {
+    public GradientBoostedTreesModelSurrogate(IRegressionProblemData trainingProblemData, uint seed, ILossFunction lossFunction, int iterations, int maxSize, double r, double m, double nu, IRegressionModel model)
+      : this(trainingProblemData, seed, lossFunction, iterations, maxSize, r, m, nu) {
       this.actualModel = model;
     }
@@ -110,5 +110,4 @@
 
     private IRegressionModel RecalculateModel() {
-      var lossFunction = ApplicationManager.Manager.GetInstances<ILossFunction>().Single(l => l.ToString() == lossFunctionName);
       return GradientBoostedTreesAlgorithmStatic.TrainGbm(trainingProblemData, lossFunction, maxSize, nu, r, m, iterations, seed).Model;
     }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/AbsoluteErrorLoss.cs	(revision 12873)
@@ -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 class AbsoluteErrorLoss : Item, ILossFunction {
+    public AbsoluteErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -77,7 +81,11 @@
     }
 
-    public override string ToString() {
-      return "Absolute error loss";
+    #region item implementation
+    private AbsoluteErrorLoss(AbsoluteErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AbsoluteErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/ILossFunction.cs	(revision 12873)
@@ -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: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/LogisticRegressionLoss.cs	(revision 12873)
@@ -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 class LogisticRegressionLoss : Item, ILossFunction {
+    public LogisticRegressionLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -83,7 +89,12 @@
     }
 
-    public override string ToString() {
-      return "Logistic regression loss";
+    #region item implementation
+    private LogisticRegressionLoss(LogisticRegressionLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LogisticRegressionLoss(this, cloner);
     }
+    #endregion
+
   }
 }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/RelativeErrorLoss.cs	(revision 12873)
@@ -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 class RelativeErrorLoss : Item, ILossFunction {
+    public RelativeErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -105,7 +111,11 @@
     }
 
-    public override string ToString() {
-      return "Relative error loss";
+    #region item implementation
+    private RelativeErrorLoss(RelativeErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RelativeErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs	(revision 12872)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/LossFunctions/SquaredErrorLoss.cs	(revision 12873)
@@ -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 class SquaredErrorLoss : Item, ILossFunction {
+    public SquaredErrorLoss() { }
+
     public double GetLoss(IEnumerable<double> target, IEnumerable<double> pred) {
       var targetEnum = target.GetEnumerator();
@@ -70,7 +77,11 @@
     }
 
-    public override string ToString() {
-      return "Squared error loss";
+    #region item implementation
+    private SquaredErrorLoss(SquaredErrorLoss original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SquaredErrorLoss(this, cloner);
     }
+    #endregion
   }
 }
