File: plot_expert_mixture.py

package info (click to toggle)
openturns 1.26-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 67,708 kB
  • sloc: cpp: 261,605; python: 67,030; ansic: 4,378; javascript: 406; sh: 185; xml: 164; makefile: 101
file content (123 lines) | stat: -rw-r--r-- 3,098 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""
Mixture of experts
==================
"""

# %%
# In this example we are going to approximate a piece wise continuous function using an expert mixture of metamodels.
#
# The metamodels will be represented by the family of functions :math:`f_k \forall \in [1, n_c]`:
#
# .. math::
#      f(\vect{x}) = f_k(\vect{x})
#
# for any :math:`\vect{z} \in \textrm{Class}_k` where the :math:`n_c \in \Nset` classes are defined by the classifier.
#
# Using the supervised mode the classifier partitions the input and output spaces at once:
#
# .. math::
#    \vect{z} = (\vect{x}, f(\vect{x}))
#
# The classifier is :class:`~openturns.MixtureClassifier` based on a :class:`~openturns.Mixture` distribution defined as:
#
# .. math::
#    p(\vect{x}) = \sum_{i=1}^{n_c} w_i p_i(\vect{x})
#
#
# The rule to assign a point to a class is defined as follows: :math:`\vect{x}` is assigned to the class :math:`j = \operatorname{argmax}_j \log w_k p_k(\vect{z})`.
#
# The grade of :math:`\vect{x}` with respect to the class :math:`k` is :math:`\log w_k p_k(\vect{x})`.
#
#

# %%
import openturns as ot
import openturns.viewer as otv
import numpy as np


# %%
dimension = 1

# Define the piecewise model we want to rebuild


def piecewise(X):
    # if x < 0.0:
    #     f = (x+0.75)**2-0.75**2
    # else:
    #     f = 2.0-x**2
    xarray = np.asarray(X)
    return np.piecewise(
        xarray,
        [xarray < 0, xarray >= 0],
        [lambda x: x * (x + 1.5), lambda x: 2.0 - x * x],
    )


f = ot.PythonFunction(1, 1, func_sample=piecewise)

# %%
# Build a metamodel over each segment
degree = 5
samplingSize = 100
enumerateFunction = ot.LinearEnumerateFunction(dimension)
productBasis = ot.OrthogonalProductPolynomialFactory(
    [ot.LegendreFactory()] * dimension, enumerateFunction
)
adaptiveStrategy = ot.FixedStrategy(
    productBasis, enumerateFunction.getStrataCumulatedCardinal(degree)
)

# %%
# Interval 1: :math:`[-1.0; 0.0]`
d1 = ot.Uniform(-1.0, 0.0)
X1 = d1.getSample(samplingSize)
Y1 = f(X1)
fc1 = ot.FunctionalChaosAlgorithm(X1, Y1, d1, adaptiveStrategy)
fc1.run()
mm1 = fc1.getResult().getMetaModel()
graph = mm1.draw(-1.0, -1e-6)
view = otv.View(graph)

# %%
# Interval 2: :math:`[0.0, 1.0]`
d2 = ot.Uniform(0.0, 1.0)
X2 = d2.getSample(samplingSize)
Y2 = f(X2)
fc2 = ot.FunctionalChaosAlgorithm(X2, Y2, d2, adaptiveStrategy)
fc2.run()
mm2 = fc2.getResult().getMetaModel()
graph = mm2.draw(1e-6, 1.0)
view = otv.View(graph)

# %%
# Define the mixture
R = ot.CorrelationMatrix(2)
d1 = ot.Normal([-1.0, -1.0], [1.0] * 2, R)  # segment 1
d2 = ot.Normal([1.0, 1.0], [1.0] * 2, R)  # segment 2
weights = [1.0] * 2
atoms = [d1, d2]
mixture = ot.Mixture(atoms, weights)

# %%
# Create the classifier based on the mixture
classifier = ot.MixtureClassifier(mixture)

# %%
# Create local experts using the metamodels
experts = ot.Basis([mm1, mm2])

# %%
# Create a mixture of experts
evaluation = ot.ExpertMixture(experts, classifier)
moe = ot.Function(evaluation)

# %%
# Draw the mixture of experts
graph = moe.draw(-1.0, 1.0)
view = otv.View(graph)

# %%
# Display all figures
otv.View.ShowAll()