Hi Flore,
Following our meeting here are the extended versions of the otmixmod test adapted to a multivariate input/output model and using different algorithms for the local experts:
With kriging, Q2= [0.998673,0.999992]:
import openturns as ot
import openturns.viewer as otv
import otmixmod
ot.Log.Show(ot.Log.NONE)
size = 200
kmax = 100
if size >= 1000:
symbol = 'dot'
else:
symbol = 'bullet'
model = ot.SymbolicFunction(
["x", "y", "z"], ["(1.0 + sign(x)) * cos(y) - (sign(x) - 1) * sin(2*x)", "exp(-sign(z)+x+z)"])
inDim = model.getInputDimension()
outDim = model.getOutputDimension()
# To extract the input part of the mixture
inputIndices = ot.Indices(inDim)
inputIndices.fill(0)
# To extract the output part of the mixture
outputIndices = ot.Indices(outDim)
outputIndices.fill(inDim)
dist = ot.ComposedDistribution([ot.Uniform()]*inDim)
dataX = dist.getSample(size)
dataY = model(dataX)
# For validation
sizeValid = size // 5
dataXValid = dist.getSample(sizeValid)
dataYValid = model(dataXValid)
# Stack the input and output data bases
data = ot.Sample(dataX)
data.stack(dataY)
gpairs = ot.VisualTest.DrawPairs(data)
for i in range(gpairs.getNbRows()+1):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
gpairs.setGraph(i-1, j, g)
except:
pass
view = otv.View(gpairs, (800, 800))
view.save("Pairs.png")
view.close()
bestExpert = 0
bestCluster = 0
bestError = ot.SpecFunc.MaxScalar
bestMixture = 0
k = 2
stop = False
covModel = 'Gaussian_pk_Lk_Ck'
if size >= 1000:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "HMAT")
else:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "LAPACK")
while not stop:
print("Try with", k, "cluster(s)")
try:
# Classify data
mixture, labels, logLike = otmixmod.MixtureFactory(k, covModel).buildAsMixture(data)
classifier = ot.MixtureClassifier(mixture)
# Build the clusters
print("Build the clusters")
clusters = otmixmod.MixtureFactory.BuildClusters(data, labels, k)
# Build the local meta-models
print("Build the local experts")
metaModels = ot.Basis()
cov = ot.MaternModel([1.0], 3.5)
for i in range(k):
print("Expert ", i)
# Here we learn the kriging model output by output
outMeta = list()
for n in range(outDim):
algo = ot.KrigingAlgorithm(clusters[i].getMarginal(inputIndices),
clusters[i].getMarginal(outputIndices[n]),
cov, ot.Basis())
base = ot.NLopt("LN_COBYLA")
algo.setOptimizationAlgorithm(base)
algo.setOptimizationBounds(ot.Interval([0.01]*inDim, [100.0]*inDim))
algo.run()
cov = algo.getResult().getCovarianceModel()
outMeta.append(algo.getResult().getMetaModel())
metaModels.add(ot.AggregatedFunction(outMeta))
print("Build the expert mixture")
expert = ot.Function(ot.ExpertMixture(metaModels, classifier))
# Validation error
dataYMeta = expert(dataXValid)
error = (dataYValid - dataYMeta).computeRawMoment(2)
var = dataYValid.computeCenteredMoment(2)
for i in range(outDim):
error[i] /= var[i]
print("k=", k, "error=", error)
if (error.norm() < bestError):
bestExpert = expert
bestCluster = k
bestError = error.norm()
bestMixture = mixture
except:
pass
stop = (k == kmax)
print(k, "cluster(s) done, best=", bestCluster, "error=%.4e" % bestError)
k += 1
algo = ot.MetaModelValidation(dataXValid, dataYValid, bestExpert)
q2 = algo.computePredictivityFactor()
print("#"*50)
print("Q2=", q2)
print("#"*50)
residual = algo.getResidualDistribution()
g = algo.drawValidation()
view = otv.View(g, square_axes = True)
view.save("Validation.png")
view.close()
g = residual.drawPDF()
g.setLegendPosition("")
view = otv.View(g)
view.save("Residual.png")
view.close()
xMin = data.getMin()
xMax = data.getMax()
for i in range(1+gpairs.getNbRows()):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
g.add(bestMixture.getMarginal([j,i]).drawPDF([xMin[j], xMin[i]], [xMax[j], xMax[i]]))
g.setLegendPosition("")
gpairs.setGraph(i-1, j, g)
except:
print("failed for i=", i, "j=", j)
pass
view = otv.View(gpairs)
view.save("PairsMixture.png")
view.close()
With basic PCE, Q2= [0.97927,0.989968]:
import openturns as ot
import openturns.viewer as otv
import otmixmod
ot.Log.Show(ot.Log.NONE)
size = 200
kmax = 100
if size >= 1000:
symbol = 'dot'
else:
symbol = 'bullet'
model = ot.SymbolicFunction(
["x", "y", "z"], ["(1.0 + sign(x)) * cos(y) - (sign(x) - 1) * sin(2*x)", "exp(-sign(z)+x+z)"])
inDim = model.getInputDimension()
outDim = model.getOutputDimension()
# To extract the input part of the mixture
inputIndices = ot.Indices(inDim)
inputIndices.fill(0)
# To extract the output part of the mixture
outputIndices = ot.Indices(outDim)
outputIndices.fill(inDim)
dist = ot.ComposedDistribution([ot.Uniform()]*inDim)
dataX = dist.getSample(size)
dataY = model(dataX)
# For validation
sizeValid = size // 5
dataXValid = dist.getSample(sizeValid)
dataYValid = model(dataXValid)
# Stack the input and output data bases
data = ot.Sample(dataX)
data.stack(dataY)
gpairs = ot.VisualTest.DrawPairs(data)
for i in range(gpairs.getNbRows()+1):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
gpairs.setGraph(i-1, j, g)
except:
pass
view = otv.View(gpairs, (800, 800))
view.save("Pairs.png")
view.close()
bestExpert = 0
bestCluster = 0
bestError = ot.SpecFunc.MaxScalar
bestMixture = 0
k = 2
stop = False
covModel = 'Gaussian_pk_Lk_Ck'
if size >= 1000:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "HMAT")
else:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "LAPACK")
while not stop:
print("Try with", k, "cluster(s)")
try:
# Classify data
mixture, labels, logLike = otmixmod.MixtureFactory(k, covModel).buildAsMixture(data)
classifier = ot.MixtureClassifier(mixture)
# Build the clusters
print("Build the clusters")
clusters = otmixmod.MixtureFactory.BuildClusters(data, labels, k)
# Build the local meta-models
print("Build the local experts")
metaModels = ot.Basis()
for i in range(k):
print("Expert ", i)
algo = ot.FunctionalChaosAlgorithm(clusters[i].getMarginal(inputIndices), clusters[i].getMarginal(outputIndices))
algo.run()
metaModels.add(algo.getResult().getMetaModel())
print("distribution=", algo.getResult().getDistribution())
print("Build the expert mixture")
expert = ot.Function(ot.ExpertMixture(metaModels, classifier))
# Validation error
dataYMeta = expert(dataXValid)
error = (dataYValid - dataYMeta).computeRawMoment(2)
var = dataYValid.computeCenteredMoment(2)
for i in range(outDim):
error[i] /= var[i]
print("k=", k, "error=", error)
if (error.norm() < bestError):
bestExpert = expert
bestCluster = k
bestError = error.norm()
bestMixture = mixture
except:
pass
stop = (k == kmax)
print(k, "cluster(s) done, best=", bestCluster, "error=%.4e" % bestError)
k += 1
algo = ot.MetaModelValidation(dataXValid, dataYValid, bestExpert)
q2 = algo.computePredictivityFactor()
print("#"*50)
print("Q2=", q2)
print("#"*50)
residual = algo.getResidualDistribution()
g = algo.drawValidation()
view = otv.View(g, square_axes = True)
view.save("Validation.png")
view.close()
g = residual.drawPDF()
g.setLegendPosition("")
view = otv.View(g)
view.save("Residual.png")
view.close()
xMin = data.getMin()
xMax = data.getMax()
for i in range(1+gpairs.getNbRows()):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
g.add(bestMixture.getMarginal([j,i]).drawPDF([xMin[j], xMin[i]], [xMax[j], xMax[i]]))
g.setLegendPosition("")
gpairs.setGraph(i-1, j, g)
except:
print("failed for i=", i, "j=", j)
pass
view = otv.View(gpairs)
view.save("PairsMixture.png")
view.close()
With improved PCE, Q2= [0.997574,0.990906]:
import openturns as ot
import openturns.viewer as otv
import otmixmod
size = 200
kmax = 100
if size >= 1000:
symbol = 'dot'
else:
symbol = 'bullet'
model = ot.SymbolicFunction(
["x", "y", "z"], ["(1.0 + sign(x)) * cos(y) - (sign(x) - 1) * sin(2*x)", "exp(-sign(z)+x+z)"])
inDim = model.getInputDimension()
outDim = model.getOutputDimension()
# To extract the input part of the mixture
inputIndices = ot.Indices(inDim)
inputIndices.fill(0)
# To extract the output part of the mixture
outputIndices = ot.Indices(outDim)
outputIndices.fill(inDim)
dist = ot.ComposedDistribution([ot.Uniform()]*inDim)
dataX = dist.getSample(size)
dataY = model(dataX)
# For validation
sizeValid = size // 5
dataXValid = dist.getSample(sizeValid)
dataYValid = model(dataXValid)
# Stack the input and output data bases
data = ot.Sample(dataX)
data.stack(dataY)
gpairs = ot.VisualTest.DrawPairs(data)
for i in range(gpairs.getNbRows()+1):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
gpairs.setGraph(i-1, j, g)
except:
pass
view = otv.View(gpairs, (800, 800))
view.save("Pairs.png")
view.ShowAll()
view.close()
bestExpert = 0
bestCluster = 0
bestError = ot.SpecFunc.MaxScalar
bestMixture = 0
k = 2
stop = False
covModel = 'Gaussian_pk_Lk_Ck'
if size >= 1000:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "HMAT")
else:
ot.ResourceMap.SetAsString("KrigingAlgorithm-LinearAlgebra", "LAPACK")
while not stop:
print("Try with", k, "cluster(s)")
try:
# Classify data
mixture, labels, logLike = otmixmod.MixtureFactory(k, covModel).buildAsMixture(data)
classifier = ot.MixtureClassifier(mixture)
# Build the clusters
print("Build the clusters")
clusters = otmixmod.MixtureFactory.BuildClusters(data, labels, k)
# Build the local meta-models
print("Build the local experts")
metaModels = ot.Basis()
for i in range(k):
print("Expert ", i)
# Extract the distribution of the current cluster
distribution = mixture.getDistributionCollection()[
i].getMarginal(inputIndices)
# Build the local meta model using PCE
# We use a projection strategy
projection = ot.LeastSquaresStrategy(ot.LeastSquaresMetaModelSelectionFactory(ot.LARS(), ot.CorrectedLeaveOneOut()))
# We use an Hermite chaos expansion
basis = ot.OrthogonalProductPolynomialFactory(
ot.PolynomialFamilyCollection(inDim, ot.OrthogonalUniVariatePolynomialFamily(ot.HermiteFactory())))
# FixedStrategy
degree = 8
adaptive = ot.AdaptiveStrategy(
ot.OrthogonalBasis(basis), ot.EnumerateFunction().getStrataCumulatedCardinal(degree))
algo = ot.FunctionalChaosAlgorithm(clusters[i].getMarginal(inputIndices), clusters[
i].getMarginal(outputIndices), distribution, adaptive, projection)
algo.run()
metaModels.add(algo.getResult().getMetaModel())
print("Build the expert mixture")
expert = ot.Function(ot.ExpertMixture(metaModels, classifier))
# Validation error
dataYMeta = expert(dataXValid)
error = (dataYValid - dataYMeta).computeRawMoment(2)
var = dataYValid.computeCenteredMoment(2)
for i in range(outDim):
error[i] /= var[i]
print("k=", k, "error=", error)
if (error.norm() < bestError):
bestExpert = expert
bestCluster = k
bestError = error.norm()
bestMixture = mixture
except:
pass
stop = (k == kmax)
print(k, "cluster(s) done, best=", bestCluster, "error=%.4e" % bestError)
k += 1
algo = ot.MetaModelValidation(dataXValid, dataYValid, bestExpert)
q2 = algo.computePredictivityFactor()
print("#"*50)
print("Q2=", q2)
print("#"*50)
residual = algo.getResidualDistribution()
g = algo.drawValidation()
view = otv.View(g, square_axes = True)
view.save("Validation.png")
view.ShowAll()
view.close()
g = residual.drawPDF()
g.setLegendPosition("")
view = otv.View(g)
view.save("Residual.png")
view.ShowAll()
view.close()
xMin = data.getMin()
xMax = data.getMax()
for i in range(1+gpairs.getNbRows()):
for j in range(i):
try:
g = gpairs.getGraph(i-1, j)
d = g.getDrawable(0)
d.setPointStyle(symbol)
g.setDrawable(d, 0)
g.add(bestMixture.getMarginal([j,i]).drawPDF([xMin[j], xMin[i]], [xMax[j], xMax[i]]))
g.setLegendPosition("")
gpairs.setGraph(i-1, j, g)
except:
print("failed for i=", i, "j=", j)
pass
view = otv.View(gpairs)
view.save("PairsMixture.png")
view.ShowAll()
view.close()