diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f0de6bfcd81f02792a9521b220cd7a30a5695ac2..290f211737b44a302e5f2a2c703c7c26da2375ac 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,7 +24,7 @@ before_script:
   # Provision efficiently the local LFS cache before checkout
   - git lfs fetch origin $CI_COMMIT_SHA
   # Checkout the expected branch
-  - git checkout $CI_COMMIT_REF_NAME
+  - git checkout -f -q $CI_COMMIT_SHA
 
 after_script:
   - python3 CI/cdash_handler.py $CI_COMMIT_SHA $CI_PROJECT_ID $CI_PROJECT_DIR $K8S_SECRET_CDASH
diff --git a/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.1.txt b/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..20e589ba2a9407e406e8511baf12a44bc63c2a43
--- /dev/null
+++ b/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.1.txt
@@ -0,0 +1 @@
+io.mse: 0.003289417131
diff --git a/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.txt b/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.txt
new file mode 100644
index 0000000000000000000000000000000000000000..aec10cefd80236745402a3c392cbc9590a666de6
--- /dev/null
+++ b/Data/Baseline/OTB-Applications/Files/apTvClTrainVectorRegressionModel.txt
@@ -0,0 +1 @@
+io.mse: 0.001359587419
diff --git a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
index 8cd9ab8ed70e204d915e32c25ebb4944f52b4a9b..77d197f07a7f759cdd194eedd8713a9e884e1c67 100755
--- a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
+++ b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
@@ -356,10 +356,17 @@ def make_links(text, allapps):
     rep = {appname: ":ref:`{}`".format(appname) for appname in allapps}
     return multireplace(text, rep)
 
+def render_deprecation_string(app):
+    if app.IsDeprecated():
+        return "This application is deprecated and will be removed in a future release."
+    else:
+        return ""
+
 def render_application(appname, allapps):
     "Render app to rst"
 
-    app = otbApplication.Registry.CreateApplication(appname)
+    # Create the application without logger to avoid the deprecation warning log
+    app = otbApplication.Registry.CreateApplicationWithoutLogger(appname)
 
     # TODO: remove this when bug 440 is fixed
     app.Init()
@@ -368,6 +375,7 @@ def render_application(appname, allapps):
 
     output = template_application.format(
         label=appname,
+        deprecation_string=render_deprecation_string(app),
         heading=rst_section(app.GetName(), '='),
         description=app.GetDescription(),
         longdescription=make_links(app.GetDocLongDescription(), allapps),
@@ -381,8 +389,9 @@ def render_application(appname, allapps):
     return output
 
 def GetApplicationTags(appname):
-     app = otbApplication.Registry.CreateApplication(appname)
-     return app.GetDocTags()
+    # Create the application without logger to avoid the deprecation warning log
+    app = otbApplication.Registry.CreateApplicationWithoutLogger(appname)
+    return app.GetDocTags()
 
 def GenerateRstForApplications(rst_dir):
     "Generate .rst files for all applications"
@@ -404,9 +413,12 @@ def GenerateRstForApplications(rst_dir):
     for appName in appNames:
 
         # Get application first tag
-        tags = GetApplicationTags(appName)
+        tags = list(GetApplicationTags(appName))
+        if "Deprecated" in tags:
+            tags.remove("Deprecated")
         if not tags or len(tags) == 0:
             raise RuntimeError("No tags for application: " + appName)
+
         tag = tags[0]
         tag_ = tag.replace(" ", "_")
 
diff --git a/Documentation/Cookbook/rst/templates/application.rst b/Documentation/Cookbook/rst/templates/application.rst
index 68db4a8b3cc9c224fcdc107d8c4e3f9f21f97329..bbe15bceff737e5f165a2bdea7d4ea17771fcaab 100644
--- a/Documentation/Cookbook/rst/templates/application.rst
+++ b/Documentation/Cookbook/rst/templates/application.rst
@@ -1,6 +1,9 @@
 .. _{label}:
 
 {heading}
+
+{deprecation_string}
+
 {description}
 
 Description
diff --git a/Modules/Applications/AppClassification/app/CMakeLists.txt b/Modules/Applications/AppClassification/app/CMakeLists.txt
index 50ac00ea1619c068da99774d0010ee532a5b7fd1..6fc42a4ee2c73a284a379f9763b170fac9b50093 100644
--- a/Modules/Applications/AppClassification/app/CMakeLists.txt
+++ b/Modules/Applications/AppClassification/app/CMakeLists.txt
@@ -65,6 +65,11 @@ otb_create_application(
   SOURCES        otbTrainRegression.cxx
   LINK_LIBRARIES ${${otb-module}_LIBRARIES})
 
+otb_create_application(
+  NAME           TrainVectorRegression
+  SOURCES        otbTrainVectorRegression.cxx
+  LINK_LIBRARIES ${${otb-module}_LIBRARIES})
+
 otb_create_application(
   NAME           PredictRegression
   SOURCES        otbPredictRegression.cxx
diff --git a/Modules/Applications/AppClassification/app/otbTrainRegression.cxx b/Modules/Applications/AppClassification/app/otbTrainRegression.cxx
index c4ac059fe4bd9fcd3ab758f94c4122999b42caf2..a93c8b5439d65e670fa92e52ee889933d45f3d61 100644
--- a/Modules/Applications/AppClassification/app/otbTrainRegression.cxx
+++ b/Modules/Applications/AppClassification/app/otbTrainRegression.cxx
@@ -271,8 +271,7 @@ void ParseCSVPredictors(std::string path, ListSampleType* outputList)
       elem.Fill(0.0);
       for (unsigned int i=0 ; i<nbCols ; ++i)
         {
-        iss.str(words[i]);
-        iss >> elem[i];
+          elem[i] = std::stod(words[i]);
         }
       outputList->PushBack(elem);
       }
diff --git a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
index 5d10533448e7a08e6141963f98ccc73d15eea063..fbd04d4a4b5c0fa213d5266d3588b1f8de7202cb 100644
--- a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
+++ b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
@@ -29,11 +29,11 @@ namespace otb
 namespace Wrapper
 {
 
-class TrainVectorClassifier : public TrainVectorBase
+class TrainVectorClassifier : public TrainVectorBase<float, int>
 {
 public:
   typedef TrainVectorClassifier Self;
-  typedef TrainVectorBase Superclass;
+  typedef TrainVectorBase<float, int> Superclass;
   typedef itk::SmartPointer<Self> Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
   itkNewMacro( Self )
@@ -66,13 +66,20 @@ protected:
       "Learning (2.3.1 and later), and Shark ML The output of this application "
       "is a text model file, whose format corresponds to the ML model type "
       "chosen. There is no image nor vector data output.");
-    SetDocLimitations("");
+    SetDocLimitations("None");
     SetDocAuthors( "OTB Team" );
     SetDocSeeAlso( " " );
 
     SetOfficialDocLink();
 
     Superclass::DoInit();
+
+    // Add a new parameter to compute confusion matrix / contingency table
+    this->AddParameter(ParameterType_OutputFilename, "io.confmatout", "Output confusion matrix or contingency table");
+    this->SetParameterDescription("io.confmatout",
+                                  "Output file containing the confusion matrix or contingency table (.csv format)."
+                                  "The contingency table is output when we unsupervised algorithms is used otherwise the confusion matrix is output.");
+    this->MandatoryOff("io.confmatout");
   }
 
   void DoUpdateParameters() override
diff --git a/Modules/Applications/AppClassification/app/otbTrainVectorRegression.cxx b/Modules/Applications/AppClassification/app/otbTrainVectorRegression.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c98e69ee0c94b0b1882a4bd0ffab112e6020e53d
--- /dev/null
+++ b/Modules/Applications/AppClassification/app/otbTrainVectorRegression.cxx
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbTrainVectorBase.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+
+class TrainVectorRegression : public TrainVectorBase<float, float>
+{
+public:
+  typedef TrainVectorRegression Self;
+  typedef TrainVectorBase<float, float> Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  itkNewMacro(Self) itkTypeMacro(Self, Superclass)
+
+      typedef Superclass::SampleType SampleType;
+  typedef Superclass::ListSampleType       ListSampleType;
+  typedef Superclass::TargetListSampleType TargetListSampleType;
+
+protected:
+  TrainVectorRegression()
+  {
+    this->m_RegressionFlag = true;
+  }
+
+  void DoInit() override
+  {
+    SetName("TrainVectorRegression");
+    SetDescription(
+        "Train a regression algorithm based on geometries with "
+        "list of features to consider and a predictor.");
+
+    SetDocLongDescription(
+        "This application trains a regression algorithm based on "
+        "a predictor geometries and a list of features to consider for "
+        "regression.\nThis application is based on LibSVM, OpenCV Machine "
+        "Learning (2.3.1 and later), and Shark ML The output of this application "
+        "is a text model file, whose format corresponds to the ML model type "
+        "chosen. There is no image or vector data output.");
+
+    SetDocLimitations("None");
+    SetDocAuthors("OTB Team");
+    SetDocSeeAlso("TrainVectorClassifier");
+
+    SetOfficialDocLink();
+
+    Superclass::DoInit();
+
+    AddParameter(ParameterType_Float, "io.mse", "Mean Square Error");
+    SetParameterDescription("io.mse", "Mean square error computed with the validation predictors");
+    SetParameterRole("io.mse", Role_Output);
+    this->MandatoryOff("io.mse");
+  }
+
+  void DoUpdateParameters() override
+  {
+    Superclass::DoUpdateParameters();
+  }
+
+  double ComputeMSE(const TargetListSampleType& list1, const TargetListSampleType& list2)
+  {
+    assert(list1.Size() == list2.Size());
+    double mse = 0.;
+    for (TargetListSampleType::InstanceIdentifier i = 0; i < list1.Size(); ++i)
+    {
+      auto elem1 = list1.GetMeasurementVector(i);
+      auto elem2 = list2.GetMeasurementVector(i);
+
+      mse += (elem1[0] - elem2[0]) * (elem1[0] - elem2[0]);
+    }
+    mse /= static_cast<double>(list1.Size());
+    return mse;
+  }
+
+
+  void DoExecute() override
+  {
+    m_FeaturesInfo.SetClassFieldNames(GetChoiceNames("cfield"), GetSelectedItems("cfield"));
+
+    if (m_FeaturesInfo.m_SelectedCFieldIdx.empty() && GetClassifierCategory() == Supervised)
+    {
+      otbAppLogFATAL(<< "No field has been selected for data labelling!");
+    }
+
+    Superclass::DoExecute();
+
+    otbAppLogINFO("Computing training performances");
+
+    auto mse = ComputeMSE(*m_ClassificationSamplesWithLabel.labeledListSample, *m_PredictedList);
+
+    otbAppLogINFO("Mean Square Error = " << mse);
+    this->SetParameterFloat("io.mse", mse);
+  }
+
+private:
+};
+}
+}
+
+OTB_APPLICATION_EXPORT(otb::Wrapper::TrainVectorRegression)
diff --git a/Modules/Applications/AppClassification/include/otbTrainVectorBase.h b/Modules/Applications/AppClassification/include/otbTrainVectorBase.h
index 37869068157660e37b5063fd69303be97023df2f..bc5c716aef98324bcd14882b451fc2636dbfe9cc 100644
--- a/Modules/Applications/AppClassification/include/otbTrainVectorBase.h
+++ b/Modules/Applications/AppClassification/include/otbTrainVectorBase.h
@@ -49,21 +49,22 @@ bool IsNotAlphaNum(char c)
   return !std::isalnum( c );
 }
 
-class TrainVectorBase : public LearningApplicationBase<float, int>
+template <class TInputValue, class TOutputValue>
+class TrainVectorBase : public LearningApplicationBase<TInputValue, TOutputValue>
 {
 public:
   /** Standard class typedefs. */
   typedef TrainVectorBase Self;
-  typedef LearningApplicationBase<float, int> Superclass;
+  typedef LearningApplicationBase<TInputValue, TOutputValue> Superclass;
   typedef itk::SmartPointer <Self> Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
   /** Standard macro */
   itkTypeMacro(Self, Superclass);
 
-  typedef Superclass::SampleType SampleType;
-  typedef Superclass::ListSampleType ListSampleType;
-  typedef Superclass::TargetListSampleType TargetListSampleType;
+  typedef typename Superclass::SampleType           SampleType;
+  typedef typename Superclass::ListSampleType       ListSampleType;
+  typedef typename Superclass::TargetListSampleType TargetListSampleType;
 
   typedef double ValueType;
   typedef itk::VariableLengthVector <ValueType> MeasurementType;
@@ -86,8 +87,8 @@ protected:
   class SamplesWithLabel
   {
   public:
-    ListSampleType::Pointer listSample;
-    TargetListSampleType::Pointer labeledListSample;
+    typename ListSampleType::Pointer       listSample;
+    typename TargetListSampleType::Pointer labeledListSample;
     SamplesWithLabel()
     {
       listSample = ListSampleType::New();
@@ -178,13 +179,18 @@ protected:
 
   SamplesWithLabel m_TrainingSamplesWithLabel;
   SamplesWithLabel m_ClassificationSamplesWithLabel;
-  TargetListSampleType::Pointer m_PredictedList;
+  typename TargetListSampleType::Pointer m_PredictedList;
   FeaturesInfo m_FeaturesInfo;
 
   void DoInit() override;
   void DoUpdateParameters() override;
   void DoExecute() override;
 
+private:
+  /**
+   * Get the field of the input feature corresponding to the input field
+   */
+  inline TOutputValue GetFeatureField(const ogr::Feature& feature, int field);
 };
 
 }
diff --git a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
index fb5e582dae4dc6073b77a5a2f1f2659831e1b3e9..c1e4f88f1cf9f428a038da63d99161e26daa9f66 100644
--- a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
+++ b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
@@ -27,100 +27,98 @@ namespace otb
 namespace Wrapper
 {
 
-void TrainVectorBase::DoInit()
+template <class TInputValue, class TOutputValue>
+void
+TrainVectorBase<TInputValue, TOutputValue>
+::DoInit()
 {
   // Common Parameters for all Learning Application
-  AddParameter( ParameterType_Group, "io", "Input and output data" );
-  SetParameterDescription( "io", 
+  this->AddParameter( ParameterType_Group, "io", "Input and output data" );
+  this->SetParameterDescription( "io", 
     "This group of parameters allows setting input and output data." );
 
-  AddParameter( ParameterType_InputVectorDataList, "io.vd", "Input Vector Data" );
-  SetParameterDescription( "io.vd",
+  this->AddParameter( ParameterType_InputVectorDataList, "io.vd", "Input Vector Data" );
+  this->SetParameterDescription( "io.vd",
     "Input geometries used for training (note: all geometries from the layer will be used)" );
 
-  AddParameter( ParameterType_InputFilename, "io.stats", "Input XML image statistics file" );
-  MandatoryOff( "io.stats" );
-  SetParameterDescription( "io.stats", 
+  this->AddParameter( ParameterType_InputFilename, "io.stats", "Input XML image statistics file" );
+  this->MandatoryOff( "io.stats" );
+  this->SetParameterDescription( "io.stats", 
     "XML file containing mean and variance of each feature." );
 
-  AddParameter( ParameterType_OutputFilename, "io.out", "Output model" );
-  SetParameterDescription( "io.out", 
+  this->AddParameter( ParameterType_OutputFilename, "io.out", "Output model" );
+  this->SetParameterDescription( "io.out", 
     "Output file containing the model estimated (.txt format)." );
 
-  AddParameter( ParameterType_Int, "layer", "Layer Index" );
-  SetParameterDescription( "layer", 
+  this->AddParameter( ParameterType_Int, "layer", "Layer Index" );
+  this->SetParameterDescription( "layer", 
     "Index of the layer to use in the input vector file." );
-  MandatoryOff( "layer" );
-  SetDefaultParameterInt( "layer", 0 );
+  this->MandatoryOff( "layer" );
+  this->SetDefaultParameterInt( "layer", 0 );
 
-  AddParameter(ParameterType_ListView,  "feat", "Field names for training features");
-  SetParameterDescription("feat",
+  this->AddParameter(ParameterType_ListView,  "feat", "Field names for training features");
+  this->SetParameterDescription("feat",
     "List of field names in the input vector data to be used as features for training.");
 
   // Add validation data used to compute confusion matrix or contingency table
-  AddParameter( ParameterType_Group, "valid", "Validation data" );
-  SetParameterDescription( "valid", 
+  this->AddParameter( ParameterType_Group, "valid", "Validation data" );
+  this->SetParameterDescription( "valid", 
     "This group of parameters defines validation data." );
 
-  AddParameter( ParameterType_InputVectorDataList, "valid.vd", 
+  this->AddParameter( ParameterType_InputVectorDataList, "valid.vd", 
     "Validation Vector Data" );
-  SetParameterDescription( "valid.vd", "Geometries used for validation "
+  this->SetParameterDescription( "valid.vd", "Geometries used for validation "
           "(must contain the same fields used for training, all geometries from the layer will be used)" );
-  MandatoryOff( "valid.vd" );
+  this->MandatoryOff( "valid.vd" );
 
-  AddParameter( ParameterType_Int, "valid.layer", "Layer Index" );
-  SetParameterDescription( "valid.layer", 
+  this->AddParameter( ParameterType_Int, "valid.layer", "Layer Index" );
+  this->SetParameterDescription( "valid.layer", 
     "Index of the layer to use in the validation vector file." );
-  MandatoryOff( "valid.layer" );
-  SetDefaultParameterInt( "valid.layer", 0 );
+  this->MandatoryOff( "valid.layer" );
+  this->SetDefaultParameterInt( "valid.layer", 0 );
 
   // Add class field if we used validation
-  AddParameter( ParameterType_ListView, "cfield",
+  this->AddParameter( ParameterType_ListView, "cfield",
     "Field containing the class integer label for supervision" );
-  SetParameterDescription( "cfield", 
+  this->SetParameterDescription( "cfield", 
     "Field containing the class id for supervision. "
     "The values in this field shall be cast into integers. "
     "Only geometries with this field available will be taken into account." );
-  SetListViewSingleSelectionMode( "cfield", true );
+  this->SetListViewSingleSelectionMode( "cfield", true );
 
-  // Add a new parameter to compute confusion matrix / contingency table
-  AddParameter( ParameterType_OutputFilename, "io.confmatout", 
-    "Output confusion matrix or contingency table" );
-  SetParameterDescription( "io.confmatout", 
-    "Output file containing the confusion matrix or contingency table (.csv format)."
-    "The contingency table is output when we unsupervised algorithms is used otherwise the confusion matrix is output." );
-  MandatoryOff( "io.confmatout" );
-
-  AddParameter(ParameterType_Bool, "v", "Verbose mode");
-  SetParameterDescription("v", "Verbose mode, display the contingency table result.");
-  SetParameterInt("v", 1);
+  this->AddParameter(ParameterType_Bool, "v", "Verbose mode");
+  this->SetParameterDescription("v", "Verbose mode, display the contingency table result.");
+  this->SetParameterInt("v", 1);
 
   // Doc example parameter settings
-  SetDocExampleParameterValue( "io.vd", "vectorData.shp" );
-  SetDocExampleParameterValue( "io.stats", "meanVar.xml" );
-  SetDocExampleParameterValue( "io.out", "svmModel.svm" );
-  SetDocExampleParameterValue( "feat", "perimeter  area  width" );
-  SetDocExampleParameterValue( "cfield", "predicted" );
+  this->SetDocExampleParameterValue( "io.vd", "vectorData.shp" );
+  this->SetDocExampleParameterValue( "io.stats", "meanVar.xml" );
+  this->SetDocExampleParameterValue( "io.out", "svmModel.svm" );
+  this->SetDocExampleParameterValue( "feat", "perimeter  area  width" );
+  this->SetDocExampleParameterValue( "cfield", "predicted" );
 
 
   // Add parameters for the classifier choice
   Superclass::DoInit();
 
-  AddRANDParameter();
+  this->AddRANDParameter();
 }
 
-void TrainVectorBase::DoUpdateParameters()
+template <class TInputValue, class TOutputValue>
+void 
+TrainVectorBase<TInputValue, TOutputValue>
+::DoUpdateParameters()
 {
   // if vector data is present and updated then reload fields
-  if( HasValue( "io.vd" ) )
+  if( this->HasValue( "io.vd" ) )
     {
-    std::vector<std::string> vectorFileList = GetParameterStringList( "io.vd" );
+    std::vector<std::string> vectorFileList = this->GetParameterStringList( "io.vd" );
     ogr::DataSource::Pointer ogrDS = ogr::DataSource::New( vectorFileList[0], ogr::DataSource::Modes::Read );
     ogr::Layer layer = ogrDS->GetLayer( static_cast<size_t>( this->GetParameterInt( "layer" ) ) );
     ogr::Feature feature = layer.ogr().GetNextFeature();
 
-    ClearChoices( "feat" );
-    ClearChoices( "cfield" );
+    this->ClearChoices( "feat" );
+    this->ClearChoices( "cfield" );
 
     for( int iField = 0; iField < feature.ogr().GetFieldCount(); iField++ )
       {
@@ -134,20 +132,23 @@ void TrainVectorBase::DoUpdateParameters()
       if( fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal )
         {
         std::string tmpKey = "feat." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) );
-        AddChoice( tmpKey, item );
+        this->AddChoice( tmpKey, item );
         }
-      if( fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64 )
+      if( fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal )
         {
         std::string tmpKey = "cfield." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) );
-        AddChoice( tmpKey, item );
+        this->AddChoice( tmpKey, item );
         }
       }
     }
 }
 
-void TrainVectorBase::DoExecute()
+template <class TInputValue, class TOutputValue>
+void
+TrainVectorBase<TInputValue, TOutputValue>
+::DoExecute()
 {
-  m_FeaturesInfo.SetFieldNames( GetChoiceNames( "feat" ), GetSelectedItems( "feat" ));
+  m_FeaturesInfo.SetFieldNames( this->GetChoiceNames( "feat" ), this->GetSelectedItems( "feat" ));
 
   // Check input parameters
   if( m_FeaturesInfo.m_SelectedIdx.empty() )
@@ -158,29 +159,35 @@ void TrainVectorBase::DoExecute()
   ShiftScaleParameters measurement = GetStatistics( m_FeaturesInfo.m_NbFeatures );
   ExtractAllSamples( measurement );
 
-  this->Train( m_TrainingSamplesWithLabel.listSample, m_TrainingSamplesWithLabel.labeledListSample, GetParameterString( "io.out" ) );
+  this->Train( m_TrainingSamplesWithLabel.listSample, m_TrainingSamplesWithLabel.labeledListSample, this->GetParameterString( "io.out" ) );
 
   m_PredictedList =
-    this->Classify( m_ClassificationSamplesWithLabel.listSample, GetParameterString( "io.out" ) );
+    this->Classify( m_ClassificationSamplesWithLabel.listSample, this->GetParameterString( "io.out" ) );
 }
 
-
-void TrainVectorBase::ExtractAllSamples(const ShiftScaleParameters &measurement)
+template <class TInputValue, class TOutputValue>
+void
+TrainVectorBase<TInputValue, TOutputValue>
+::ExtractAllSamples(const ShiftScaleParameters &measurement)
 {
   m_TrainingSamplesWithLabel = ExtractTrainingSamplesWithLabel(measurement);
   m_ClassificationSamplesWithLabel = ExtractClassificationSamplesWithLabel(measurement);
 }
 
-TrainVectorBase::SamplesWithLabel
-TrainVectorBase::ExtractTrainingSamplesWithLabel(const ShiftScaleParameters &measurement)
+template <class TInputValue, class TOutputValue>
+typename TrainVectorBase<TInputValue, TOutputValue>::SamplesWithLabel
+TrainVectorBase<TInputValue, TOutputValue>
+::ExtractTrainingSamplesWithLabel(const ShiftScaleParameters &measurement)
 {
   return ExtractSamplesWithLabel( "io.vd", "layer", measurement);
 }
 
-TrainVectorBase::SamplesWithLabel
-TrainVectorBase::ExtractClassificationSamplesWithLabel(const ShiftScaleParameters &measurement)
+template <class TInputValue, class TOutputValue>
+typename TrainVectorBase<TInputValue, TOutputValue>::SamplesWithLabel
+TrainVectorBase<TInputValue, TOutputValue>
+::ExtractClassificationSamplesWithLabel(const ShiftScaleParameters &measurement)
 {
-  if(GetClassifierCategory() == Supervised)
+  if(this->GetClassifierCategory() == Superclass::Supervised)
     {
     SamplesWithLabel tmpSamplesWithLabel;
     SamplesWithLabel validationSamplesWithLabel = ExtractSamplesWithLabel( "valid.vd", "valid.layer", measurement );
@@ -206,15 +213,16 @@ TrainVectorBase::ExtractClassificationSamplesWithLabel(const ShiftScaleParameter
     }
 }
 
-
-TrainVectorBase::ShiftScaleParameters
-TrainVectorBase::GetStatistics(unsigned int nbFeatures)
+template <class TInputValue, class TOutputValue>
+typename TrainVectorBase<TInputValue, TOutputValue>::ShiftScaleParameters
+TrainVectorBase<TInputValue, TOutputValue>
+::GetStatistics(unsigned int nbFeatures)
 {
   ShiftScaleParameters measurement = ShiftScaleParameters();
-  if( HasValue( "io.stats" ) && IsParameterEnabled( "io.stats" ) )
+  if( this->HasValue( "io.stats" ) && this->IsParameterEnabled( "io.stats" ) )
     {
-    StatisticsReader::Pointer statisticsReader = StatisticsReader::New();
-    std::string XMLfile = GetParameterString( "io.stats" );
+    typename StatisticsReader::Pointer statisticsReader = StatisticsReader::New();
+    std::string XMLfile = this->GetParameterString( "io.stats" );
     statisticsReader->SetFileName( XMLfile );
     measurement.meanMeasurementVector = statisticsReader->GetStatisticVectorByName( "mean" );
     measurement.stddevMeasurementVector = statisticsReader->GetStatisticVectorByName( "stddev" );
@@ -229,16 +237,34 @@ TrainVectorBase::GetStatistics(unsigned int nbFeatures)
   return measurement;
 }
 
+// Template specialization for the integer case (i.e.classification), to avoid a cast from double to integer
+template <>
+inline int
+TrainVectorBase<float, int>
+::GetFeatureField(const ogr::Feature & feature, int fieldIndex)
+{
+  return(feature[fieldIndex].GetValue<int>());
+}
+
+template <class TInputValue, class TOutputValue>
+inline TOutputValue
+TrainVectorBase<TInputValue, TOutputValue>
+::GetFeatureField(const ogr::Feature & feature, int fieldIndex)
+{
+  return(feature[fieldIndex].GetValue<double>());
+}
 
-TrainVectorBase::SamplesWithLabel
-TrainVectorBase::ExtractSamplesWithLabel(std::string parameterName, std::string parameterLayer,
+template <class TInputValue, class TOutputValue>
+typename TrainVectorBase<TInputValue, TOutputValue>::SamplesWithLabel
+TrainVectorBase<TInputValue, TOutputValue>
+::ExtractSamplesWithLabel(std::string parameterName, std::string parameterLayer,
                                     const ShiftScaleParameters &measurement)
 {
   SamplesWithLabel samplesWithLabel;
-  if( HasValue( parameterName ) && IsParameterEnabled( parameterName ) )
+  if( this->HasValue( parameterName ) && this->IsParameterEnabled( parameterName ) )
     {
-    ListSampleType::Pointer input = ListSampleType::New();
-    TargetListSampleType::Pointer target = TargetListSampleType::New();
+    typename ListSampleType::Pointer input = ListSampleType::New();
+    typename TargetListSampleType::Pointer target = TargetListSampleType::New();
     input->SetMeasurementVectorSize( m_FeaturesInfo.m_NbFeatures );
 
     std::vector<std::string> fileList = this->GetParameterStringList( parameterName );
@@ -251,7 +277,7 @@ TrainVectorBase::ExtractSamplesWithLabel(std::string parameterName, std::string
       bool goesOn = feature.addr() != 0;
       if( !goesOn )
         {
-        otbAppLogWARNING( "The layer " << GetParameterInt( parameterLayer ) << " of " << fileList[k]
+        otbAppLogWARNING( "The layer " << this->GetParameterInt( parameterLayer ) << " of " << fileList[k]
                                        << " is empty, input is skipped." );
         continue;
         }
@@ -284,14 +310,14 @@ TrainVectorBase::ExtractSamplesWithLabel(std::string parameterName, std::string
         MeasurementType mv;
         mv.SetSize( m_FeaturesInfo.m_NbFeatures );
         for( unsigned int idx = 0; idx < m_FeaturesInfo.m_NbFeatures; ++idx )
-          mv[idx] = feature.ogr().GetFieldAsDouble( featureFieldIndex[idx] );
+          mv[idx] = feature[featureFieldIndex[idx]].GetValue<double>();
 
         input->PushBack( mv );
 
         if(cFieldIndex>=0 && ogr::Field(feature,cFieldIndex).HasBeenSet())
-          target->PushBack( feature.ogr().GetFieldAsInteger( cFieldIndex ) );
+          target->PushBack(GetFeatureField(feature,cFieldIndex));
         else
-          target->PushBack( 0 );
+          target->PushBack( 0. );
 
         feature = layer.ogr().GetNextFeature();
         goesOn = feature.addr() != 0;
@@ -300,7 +326,7 @@ TrainVectorBase::ExtractSamplesWithLabel(std::string parameterName, std::string
 
 
 
-    ShiftScaleFilterType::Pointer shiftScaleFilter = ShiftScaleFilterType::New();
+    typename ShiftScaleFilterType::Pointer shiftScaleFilter = ShiftScaleFilterType::New();
     shiftScaleFilter->SetInput( input );
     shiftScaleFilter->SetShifts( measurement.meanMeasurementVector );
     shiftScaleFilter->SetScales( measurement.stddevMeasurementVector );
diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt
index 2379deb501c3c6233fb1a1a6b34e8fe99a78c6e0..15286ce99c373666820979ebc1f73d7c848169f6 100644
--- a/Modules/Applications/AppClassification/test/CMakeLists.txt
+++ b/Modules/Applications/AppClassification/test/CMakeLists.txt
@@ -837,6 +837,22 @@ if(OTB_USE_OPENCV)
     ${TEMP}/apTvClTrainVectorClassifierModel.rf)
 endif()
 
+#----------- TrainVectorRegression TESTS ----------------
+if(OTB_USE_OPENCV)
+  otb_test_application(NAME apTvClTrainVectorRegression
+    APP  TrainVectorRegression
+    OPTIONS -io.vd ${INPUTDATA}/Classification/apTvClSampleExtractionOut.sqlite
+    -feat value_0 value_1 value_2 value_3
+    -cfield class
+    -classifier rf
+    -io.out ${TEMP}/apTvClTrainVectorRegressionModel.rf
+    -io.mse ${TEMP}/apTvClTrainVectorRegressionModel.txt
+    TESTENVOPTIONS ${TEMP}/apTvClTrainVectorRegressionModel.txt
+    VALID   ${ascii_comparison}
+    ${OTBAPP_BASELINE_FILES}/apTvClTrainVectorRegressionModel.txt
+    ${TEMP}/apTvClTrainVectorRegressionModel.txt)
+endif()
+
 #----------- TrainVectorClassifier unsupervised TESTS ----------------
 if(OTB_USE_SHARK)
   otb_test_application(NAME apTvClTrainVectorUnsupervised
diff --git a/Modules/Applications/AppImageUtils/app/otbRescale.cxx b/Modules/Applications/AppImageUtils/app/otbRescale.cxx
index 703215872f1ad4ba111438a819108497b338fba3..0a50d18e46ceffab913d0e97a0930c0d3a1ed6b4 100644
--- a/Modules/Applications/AppImageUtils/app/otbRescale.cxx
+++ b/Modules/Applications/AppImageUtils/app/otbRescale.cxx
@@ -59,7 +59,7 @@ private:
                                   "Input minimum and maximum values is automatically computed for all image bands.");
     SetDocLimitations("None");
     SetDocAuthors("OTB-Team");
-    SetDocSeeAlso(" ");
+    SetDocSeeAlso("DynamicConvert");
 
     AddDocTag(Tags::Deprecated);
     AddDocTag(Tags::Manip);
diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
index 29c8d8c6aed5d2d92c36a44344da5f4b3a970dd0..6f8f839953e039d408f676a8f7c70231db5ec3ba 100644
--- a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
@@ -96,12 +96,14 @@ private:
                       " application is not compatible with in-memory connection since it does"
                       " its own internal streaming.");
     SetDocAuthors("David Youssefi");
-    SetDocSeeAlso( "[1] Michel, J., Youssefi, D., & Grizonnet, M. (2015). Stable"
-                   " mean-shift algorithm and its application to the segmentation of"
-                   " arbitrarily large remote sensing images. IEEE Transactions on"
-                   " Geoscience and Remote Sensing, 53(2), 952-964.\n"
-                   "[2] LSMSegmentation\n"
-                   "[3] LSMSVectorization");
+    SetDocSeeAlso(
+        "Alternative: SmallRegionsMerging\n"
+        "[1] Michel, J., Youssefi, D., & Grizonnet, M. (2015). Stable"
+        " mean-shift algorithm and its application to the segmentation of"
+        " arbitrarily large remote sensing images. IEEE Transactions on"
+        " Geoscience and Remote Sensing, 53(2), 952-964.\n"
+        "[2] LSMSSegmentation\n"
+        "[3] LSMSVectorization");
     AddDocTag(Tags::Segmentation);
     AddDocTag(Tags::Deprecated);
     AddDocTag("LSMS");
diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h
index 3e087664964ec72fda368b33c054875825afd4c8..4da58cf694656ef7fa65856fc0af418f8da2ff3d 100644
--- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h
+++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h
@@ -669,6 +669,9 @@ public:
 
   void AddDocTag(const std::string&);
 
+  /** return wether the application has the "deprecated tag or not */
+  bool IsDeprecated();
+
   DocExampleStructure::Pointer GetDocExample();
   unsigned int GetNumberOfExamples();
   std::string GetExampleComment(unsigned int id);
diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
index 3657c6a54a6d9fb0450623ab54b432ccbc597fc2..085ae8c098cdb74b0130e5659091c75960921b42 100644
--- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
+++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
@@ -256,6 +256,11 @@ void Application::AddDocTag(const std::string & tag)
     }
 }
 
+bool Application::IsDeprecated()
+{
+  return std::find(m_DocTags.begin(), m_DocTags.end(), Tags::Deprecated) != m_DocTags.end();
+}
+
 DocExampleStructure::Pointer Application::GetDocExample()
 {
   if (!IsInitialized())
diff --git a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
index 9e097a67cfafd11f96efc38867ea37e4b643d62b..e6a26418b2af0f7664a3eb338cd1fa45744c1da9 100644
--- a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
+++ b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
@@ -112,9 +112,6 @@ public:
   /** Create and display the help of the application */
   void DisplayHelp(bool longHelp=false);
 
-   /** Create and display the long help of the application */
-  void DisplayLongHelp();
-
   /** Performs specific action for testing environment */
   void LoadTestEnv();
 
diff --git a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
index 4cdb8ee984d82b12abc715c8beadfa4e22d9f3bb..2e31ce8356f15ab9db6a59cd87038f937165cbe9 100644
--- a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
+++ b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
@@ -282,7 +282,12 @@ bool CommandLineLauncher::BeforeExecute()
     return false;
     }
 
-  return true;
+    if (m_Application->IsDeprecated())
+    {
+      m_Application->GetLogger()->Warning("This application is deprecated and will be removed in a future OTB release.\n");
+    }
+
+    return true;
 }
 
 bool CommandLineLauncher::LoadPath()
@@ -584,6 +589,12 @@ void CommandLineLauncher::DisplayHelp(bool longHelp)
   std::cerr<<std::endl;
   std::cerr << "This is the " << m_Application->GetName() << " application, version " << OTB_VERSION_STRING << std::endl << std::endl;
 
+  if (m_Application->IsDeprecated())
+  {
+    std::cerr << "WARNING: This application is deprecated, it will be removed in a future OTB release." << std::endl;
+    std::cerr << std::endl;
+  }
+
   std::cerr << m_Application->GetDescription() << std::endl;
 
   if(longHelp)
diff --git a/Modules/Wrappers/QtWidget/src/appmainwindow.ui b/Modules/Wrappers/QtWidget/src/appmainwindow.ui
index c376f1984f3cec0518739bf1dd22fe3b6fb4f4be..88eb9a25bdf45af1a55696859d6a5f87c1177356 100644
--- a/Modules/Wrappers/QtWidget/src/appmainwindow.ui
+++ b/Modules/Wrappers/QtWidget/src/appmainwindow.ui
@@ -117,6 +117,13 @@
       </widget>
      </widget>
     </item>
+    <item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
+     <widget class="QLabel" name="deprecation">
+      <property name="text">
+       <string>Deprecation status</string>
+      </property>
+     </widget>
+    </item>
     <item>
      <widget class="QLabel" name="message">
       <property name="text">
diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetMainWindow.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetMainWindow.cxx
index 93c3f459e2e43b49d43e879a84e3f83ccfa30345..282c710ec25cc52408d97e2808a0726f5cb9c14d 100644
--- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetMainWindow.cxx
+++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetMainWindow.cxx
@@ -70,6 +70,18 @@ QtMainWindow::QtMainWindow(Application::Pointer app, QtWidgetView* gui, QWidget*
   // Setup the progress bar to observe the model
   ui->progressBar->SetModel(gui->GetModel());
 
+  // Fill and display the deprecation status label if needed, or hide it.
+  if (app->IsDeprecated())
+  {
+    ui->deprecation->setVisible(true);
+    ui->deprecation->setText("<font color='#E65100'>This application is deprecated and will be removed in a future release.</font>");
+  }
+  else
+  {
+    ui->deprecation->setVisible(false);
+    ui->deprecation->setText("");
+  }
+
   // Connect application progress text to the QLabel
   connect(ui->progressBar, &QtWidgetSimpleProgressReport::SetText, ui->message, &QLabel::setText);
 
diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i
index a3b9590f34b84880213124c43438a4728612bed0..d03ad7b1e9551e17289aaa586f797fa5f51917ea 100644
--- a/Modules/Wrappers/SWIG/src/otbApplication.i
+++ b/Modules/Wrappers/SWIG/src/otbApplication.i
@@ -225,6 +225,7 @@ public:
   unsigned long itk::Object::AddObserver(const EventObject & event, 
                                           Command * command);
 
+  bool IsDeprecated();
 
 #if SWIGPYTHON
   %extend 
@@ -901,6 +902,8 @@ public:
         application = _otbApplication.Registry_CreateApplicationWithoutLogger(name)
         if application is not None:
             application.SetupLogger()
+            if application.IsDeprecated():
+                application.GetLogger().Warning("This application is deprecated and will be removed in a future OTB release")
         return application
   }
   #else
diff --git a/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i
index 4bd7852b2ee7540e8cacb172ecbca7ba2d376ffa..748c8bfef4820b6bd9a04c6d19d8c57f61ca7a84 100644
--- a/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i
+++ b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i
@@ -72,6 +72,15 @@ public:
   virtual void AddLogOutput(itkLogOutput *output);
   static Logger * Instance();
   void ResetOutputs();
+
+  // Wrap message methods so we can print stuff from Python
+  void Debug(std::string const & message);
+  void Info(std::string const & message);
+  void Warning(std::string const & message);
+  void Critical(std::string const & message);
+  void Error(std::string const & message);
+  void Fatal(std::string const & message);
+
 protected:
   Logger();
   virtual ~Logger();