Skip to content

Commit

Permalink
Implement FunctionalChaosValidation and LinearModelValidation
Browse files Browse the repository at this point in the history
  • Loading branch information
mbaudin47 committed Apr 30, 2024
1 parent bd6881b commit 0843759
Show file tree
Hide file tree
Showing 34 changed files with 2,026 additions and 10 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* CovarianceModel nuggetFactor can be optimized by KrigingAlgorithm

==== New classes ====
* FunctionalChaosValidation (openturns.experimental)
* SmoothedUniformFactory (openturns.experimental)
* GeneralizedParetoValidation (openturns.experimental)
* SamplePartition (openturns.experimental)
Expand Down
10 changes: 9 additions & 1 deletion lib/etc/openturns.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -863,18 +863,26 @@
<FunctionalChaosSobolIndices-MaximumNumberOfOutput value_int="1000" />
<FunctionalChaosSobolIndices-PrintColumnWidth value_int="15" />

<!-- OT::FunctionalChaosValidation parameters -->
<FunctionalChaosValidation-DefaultKFoldParameter value_int="10" />
<FunctionalChaosValidation-ModelSelection value_bool="false" />

<!-- OT::LeastSquaresExpansion parameters -->
<LeastSquaresExpansion-DecompositionMethod value_str="QR" />

<!-- OT::LinearModelAlgorithm parameters -->
<LinearModelAlgorithm-DecompositionMethod value_str="QR" />
<LinearModelAlgorithm-DecompositionMethod value_str="QR" />

<!-- OT::LinearModelAnalysis parameters -->
<LinearModelAnalysis-Identifiers value_int="3" />
<LinearModelAnalysis-PrintEllipsisThreshold value_int="20" />
<LinearModelAnalysis-SmallPValueFormat value_str="{:.4e}" />
<LinearModelAnalysis-LargePValueFormat value_int="{:.4f}" />

<!-- OT::LinearModelValidation parameters -->
<LinearModelValidation-DefaultKFoldParameter value_int="10" />
<LinearModelValidation-ModelSelection value_bool="false" />

<!-- OT::LinearModelStepwiseAlgorithm parameters -->
<LinearModelStepwiseAlgorithm-Penalty value_float="2.0" />
<LinearModelStepwiseAlgorithm-MaximumIterationNumber value_int="1000" />
Expand Down
10 changes: 9 additions & 1 deletion lib/src/Base/Common/ResourceMap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1498,15 +1498,23 @@ void ResourceMap::loadDefaultConfiguration()
addAsUnsignedInteger("FunctionalChaosSobolIndices-MaximumNumberOfOutput", 1000);
addAsUnsignedInteger("FunctionalChaosSobolIndices-PrintColumnWidth", 15);

// FunctionalChaosValidation parameters //
addAsUnsignedInteger("FunctionalChaosValidation-DefaultKFoldParameter", 10);
addAsBool("FunctionalChaosValidation-ModelSelection", false);

// LinearModelAlgorithm parameters //
addAsString("LinearModelAlgorithm-DecompositionMethod", "QR");

// LinearModelAnalysis parameters //
addAsUnsignedInteger("LinearModelAnalysis-Identifiers", 3);
addAsUnsignedInteger("LinearModelAnalysis-PrintEllipsisThreshold", 20);
addAsString("LinearModelAnalysis-SmallPValueFormat", "{:.4e}");
addAsString("LinearModelAnalysis-LargePValueFormat", "{:.4f}");

// LinearModelValidation parameters //
addAsUnsignedInteger("LinearModelValidation-DefaultKFoldParameter", 10);
addAsBool("LinearModelValidation-ModelSelection", false);

// LinearModelStepwiseAlgorithm parameters //
addAsScalar("LinearModelStepwiseAlgorithm-Penalty", 2.0);
addAsUnsignedInteger("LinearModelStepwiseAlgorithm-MaximumIterationNumber", 1000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ot_add_source_file (FixedStrategy.cxx)
ot_add_source_file (FunctionalChaosAlgorithm.cxx)
ot_add_source_file (FunctionalChaosResult.cxx)
ot_add_source_file (FunctionalChaosSobolIndices.cxx)
ot_add_source_file (FunctionalChaosValidation.cxx)
ot_add_source_file (ProjectionStrategy.cxx)
ot_add_source_file (ProjectionStrategyImplementation.cxx)
ot_add_source_file (LeastSquaresExpansion.cxx)
Expand All @@ -28,6 +29,7 @@ ot_install_header_file (LeastSquaresExpansion.hxx)
ot_install_header_file (IntegrationExpansion.hxx)
ot_install_header_file (LeastSquaresStrategy.hxx)
ot_install_header_file (FunctionalChaosAlgorithm.hxx)
ot_install_header_file (FunctionalChaosValidation.hxx)
ot_install_header_file (OTFunctionalChaos.hxx)
ot_install_header_file (AdaptiveStrategyImplementation.hxx)
ot_install_header_file (ProjectionStrategy.hxx)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// -*- C++ -*-
/**
* @brief Validation of a functional chaos expansion
*
* Copyright 2005-2023 Airbus-EDF-IMACS-ONERA-Phimeca
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <algorithm>
#include "openturns/PersistentObjectFactory.hxx"
#include "openturns/FunctionalChaosValidation.hxx"
#include "openturns/Os.hxx"
#include "openturns/OSS.hxx"
#include "openturns/DesignProxy.hxx"
#include "openturns/LeastSquaresMethod.hxx"
#include "openturns/KFoldSplitter.hxx"
#include "openturns/MetaModelValidation.hxx"

BEGIN_NAMESPACE_OPENTURNS

CLASSNAMEINIT(FunctionalChaosValidation)

static const Factory<FunctionalChaosValidation> Factory_FunctionalChaosValidation;

/* Default constructor */
FunctionalChaosValidation::FunctionalChaosValidation()
: MetaModelValidation()
{
// Nothing to do
}

/* Default constructor */

FunctionalChaosValidation::FunctionalChaosValidation(const FunctionalChaosResult & functionalChaosResult,
const CrossValidationMethod cvMethod,
const UnsignedInteger & kParameter)
: MetaModelValidation(functionalChaosResult.getOutputSample()
, ComputeMetamodelCrossValidationPredictions(functionalChaosResult, cvMethod, kParameter))
, functionalChaosResult_(functionalChaosResult)
{
if ((cvMethod != LEAVEONEOUT) && (cvMethod != KFOLD))
throw InvalidArgumentException(HERE) << "The method " << cvMethod << " is not available.";
cvMethod_ = cvMethod;
if (kParameter < 1)
throw InvalidArgumentException(HERE) << "Cannot set k parameter of K-Fold method to " << kParameter << " which is lower than 1";
const UnsignedInteger sampleSize = functionalChaosResult_.getInputSample().getSize();
if (kParameter > sampleSize)
throw InvalidArgumentException(HERE) << "Cannot set k parameter of K-Fold method to " << kParameter
<< " which is larger than the sample size =" << sampleSize;
kParameter_ = kParameter;
if (!ResourceMap::GetAsBool("FunctionalChaosValidation-ModelSelection") && \
functionalChaosResult_.involvesModelSelection())
throw InvalidArgumentException(HERE) << "Cannot perform fast cross-validation "
<< "with a polynomial chaos expansion involving model selection";
if (!functionalChaosResult.isLeastSquares())
throw InvalidArgumentException(HERE) << "Error: the polynomial chaos expansion was not computed from least squares.";
}

/* Virtual constructor */
FunctionalChaosValidation * FunctionalChaosValidation::clone() const
{
return new FunctionalChaosValidation(*this);
}

/* String converter */
String FunctionalChaosValidation::__repr__() const
{
OSS oss;
oss << "class=" << FunctionalChaosValidation::GetClassName()
<< " functional chaos result=" << functionalChaosResult_
<< " kParameter_=" << kParameter_
<< " cvMethod_=" << cvMethod_;
return oss;
}

/* Get result*/
FunctionalChaosResult FunctionalChaosValidation::getFunctionalChaosResult() const
{
return functionalChaosResult_;
}

/* Get the K parameter */
UnsignedInteger FunctionalChaosValidation::getKParameter() const
{
return kParameter_;
}

/* Get the CV Method */
UnsignedInteger FunctionalChaosValidation::getMethod() const
{
return cvMethod_;
}

/* Compute cross-validation metamodel predictions */
Sample FunctionalChaosValidation::ComputeMetamodelCrossValidationPredictions(
const FunctionalChaosResult & functionalChaosResult,
const CrossValidationMethod cvMethod,
const UnsignedInteger & kParameter)
{
const Sample residualsSample(functionalChaosResult.getSampleResiduals());
const Sample inputSample(functionalChaosResult.getInputSample());
const UnsignedInteger sampleSize = inputSample.getSize();
const FunctionCollection reducedBasis(functionalChaosResult.getReducedBasis());
const UnsignedInteger reducedBasisSize = reducedBasis.getSize();
if (reducedBasisSize > sampleSize)
throw InvalidArgumentException(HERE) << "Error: the sample size is: " << sampleSize <<
" which is lower than the basis size: " << reducedBasisSize;
const Sample outputSample(functionalChaosResult.getOutputSample());
const UnsignedInteger outputDimension = outputSample.getDimension();
const Function transformation(functionalChaosResult.getTransformation());
const Sample standardSample(transformation(inputSample));
DesignProxy designProxy(standardSample, reducedBasis);
Indices allIndices(reducedBasisSize);
allIndices.fill();
// The method name is set to the default one, given by ResourceMap
const String methodName(ResourceMap::GetAsString("LeastSquaresExpansion-DecompositionMethod"));
LeastSquaresMethod leastSquaresMethod(LeastSquaresMethod::Build(methodName, designProxy, allIndices));
leastSquaresMethod.update(Indices(0), allIndices, Indices(0));
Sample cvPredictions(sampleSize, outputDimension);
if (cvMethod == LEAVEONEOUT)
{
const Point diagonalH = leastSquaresMethod.getHDiag();
for (UnsignedInteger j = 0; j < outputDimension; ++j)
for (UnsignedInteger i = 0; i < sampleSize; ++i)
cvPredictions(i, j) = outputSample(i, j) - residualsSample(i, j) / (1.0 - diagonalH[i]);
}
else if (cvMethod == KFOLD)
{
const SymmetricMatrix projectionMatrix(leastSquaresMethod.getH());
// Compute K-Fold error
KFoldSplitter splitter(sampleSize, kParameter);
Indices indicesTest;
for (UnsignedInteger foldIndex = 0; foldIndex < kParameter; ++foldIndex)
{
splitter.generate(indicesTest);
const UnsignedInteger foldSize = indicesTest.getSize();
SymmetricMatrix projectionKFoldMatrix(foldSize);
for (UnsignedInteger i1 = 0; i1 < foldSize; ++i1)
for (UnsignedInteger i2 = 0; i2 < 1 + i1; ++i2)
projectionKFoldMatrix(i1, i2) = projectionMatrix(indicesTest[i1], indicesTest[i2]);
const IdentityMatrix identityMatrix(foldSize);
const SymmetricMatrix reducedMatrix(identityMatrix - projectionKFoldMatrix);
const Sample residualsSampleKFoldTest(residualsSample.select(indicesTest));
Matrix multipleRightHandSide(foldSize, outputDimension);
for (UnsignedInteger j = 0; j < outputDimension; ++j)
for (UnsignedInteger i = 0; i < foldSize; ++i)
multipleRightHandSide(i, j) = residualsSampleKFoldTest(i, j);
const Matrix residualsKFoldMatrix(reducedMatrix.solveLinearSystem(multipleRightHandSide));
for (UnsignedInteger j = 0; j < outputDimension; ++j)
for (UnsignedInteger i = 0; i < foldSize; ++i)
cvPredictions(indicesTest[i], j) = outputSample(indicesTest[i], j) - residualsKFoldMatrix(i, j);
} // For fold indices
}
else
throw InvalidArgumentException(HERE) << "The method " << cvMethod << " is not available.";
return cvPredictions;
}

/* Method save() stores the object through the StorageManager */
void FunctionalChaosValidation::save(Advocate & adv) const
{
PersistentObject::save(adv);
adv.saveAttribute( "functionalChaosResult_", functionalChaosResult_ );
}

/* Method load() reloads the object from the StorageManager */
void FunctionalChaosValidation::load(Advocate & adv)
{
PersistentObject::load(adv);
adv.loadAttribute( "functionalChaosResult_", functionalChaosResult_ );
}

END_NAMESPACE_OPENTURNS
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// -*- C++ -*-
/**
* @brief The validation of a chaos expansion
*
* Copyright 2005-2023 Airbus-EDF-IMACS-ONERA-Phimeca
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef OPENTURNS_FUNCTIONALCHAOSVALIDATION_HXX
#define OPENTURNS_FUNCTIONALCHAOSVALIDATION_HXX

#include "openturns/Sample.hxx"
#include "openturns/FunctionalChaosResult.hxx"
#include "openturns/MetaModelValidation.hxx"

BEGIN_NAMESPACE_OPENTURNS

/**
* @class FunctionalChaosValidation
*
* The validation of a chaos expansion
*/

class OT_API FunctionalChaosValidation
: public MetaModelValidation
{
CLASSNAME

public:
typedef Collection<Function> FunctionCollection;
enum CrossValidationMethod {LEAVEONEOUT = 0, KFOLD = 1};

/** Default constructor */
FunctionalChaosValidation();

/** Parameter constructor */
FunctionalChaosValidation(const FunctionalChaosResult & chaosResult,
const CrossValidationMethod method,
const UnsignedInteger & kParameter = ResourceMap::GetAsUnsignedInteger("FunctionalChaosValidation-DefaultKFoldParameter"));

/** Virtual constructor */
FunctionalChaosValidation * clone() const override;

/** String converter */
String __repr__() const override;

/** Result accessor */
FunctionalChaosResult getFunctionalChaosResult() const;

/** Get the K-parameter */
UnsignedInteger getKParameter() const;

/** Get the CV Method */
UnsignedInteger getMethod() const;

/** Method save() stores the object through the StorageManager */
void save(Advocate & adv) const override;

/** Method load() reloads the object from the StorageManager */
void load(Advocate & adv) override;

protected:

private:

/** The functional chaos result */
FunctionalChaosResult functionalChaosResult_;

/** K-parameter */
UnsignedInteger kParameter_;

/** Cross-validation method */
CrossValidationMethod cvMethod_;

/* Compute cross-validation metamodel predictions */
static Sample ComputeMetamodelCrossValidationPredictions(
const FunctionalChaosResult & functionalChaosResult, const CrossValidationMethod cvMethod,
const UnsignedInteger & kParameter);

} ; /* class FunctionalChaosValidation */


END_NAMESPACE_OPENTURNS

#endif /* OPENTURNS_FUNCTIONALCHAOSVALIDATION_HXX */
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "openturns/FunctionalChaosAlgorithm.hxx"
#include "openturns/FunctionalChaosResult.hxx"
#include "openturns/FunctionalChaosSobolIndices.hxx"
#include "openturns/FunctionalChaosValidation.hxx"
#include "openturns/LeastSquaresExpansion.hxx"
#include "openturns/IntegrationExpansion.hxx"
#include "openturns/LeastSquaresStrategy.hxx"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ ot_add_source_file (LinearModelResult.cxx)
ot_add_source_file (LinearModelAlgorithm.cxx)
ot_add_source_file (LinearModelStepwiseAlgorithm.cxx)
ot_add_source_file (LinearModelAnalysis.cxx)
ot_add_source_file (LinearModelValidation.cxx)

ot_install_header_file (LinearModelResult.hxx)
ot_install_header_file (LinearModelAlgorithm.hxx)
ot_install_header_file (LinearModelStepwiseAlgorithm.hxx)
ot_install_header_file (LinearModelAnalysis.hxx)
ot_install_header_file (LinearModelValidation.hxx)

ot_install_header_file (OTLinearModel.hxx)
Loading

0 comments on commit 0843759

Please sign in to comment.