.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/surrogate/plot_surrogate_scenario.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_surrogate_plot_surrogate_scenario.py: Plug a surrogate discipline in a Scenario ========================================= In this section we describe the usage of surrogate model in |g|, which is implemented in the :class:`.SurrogateDiscipline` class. A :class:`.SurrogateDiscipline` can be used to substitute a :class:`.MDODiscipline` within a :class:`.Scenario`. This :class:`.SurrogateDiscipline` is an evaluation of the :class:`.MDODiscipline` and is faster to compute than the original discipline. It relies on a :class:`.MLRegressionAlgo`. This comes at the price of computing a :term:`DOE` on the original :class:`.MDODiscipline`, and validating the approximation. The computations from which the approximation is built can be available, or can be built using |g|' :term:`DOE` capabilities. See :ref:`sobieski_doe` and :ref:`sellar_mdo`. In |g|'s, the data used to build the surrogate model is taken from a :class:`.Dataset` containing both inputs and outputs of the :term:`DOE`. This :class:`.Dataset` may have been generated by |g| from a cache, using the :meth:`.AbstractFullCache.export_to_dataset` method, or, from a numpy array or a text file using the :meth:`.Dataset.set_from_array` and :meth:`.Dataset.set_from_file`. Then, the surrogate discipline can be used as any other discipline in a :class:`.MDOScenario`, a :class:`.DOEScenario`, or a :class:`.MDA`. .. GENERATED FROM PYTHON SOURCE LINES 50-66 .. code-block:: default from __future__ import division, unicode_literals from numpy import array, hstack, vstack from gemseo.api import ( configure_logger, create_discipline, create_scenario, create_surrogate, ) from gemseo.core.dataset import Dataset from gemseo.problems.sobieski.core import SobieskiProblem configure_logger() .. rst-class:: sphx-glr-script-out Out: .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 67-79 Create a surrogate discipline ----------------------------- Create the learning dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you already have available data from a :term:`DOE` produced externally, it is possible to create a :class:`.Dataset` and Step 1 ends here. For example, let us consider a synthetic dataset, with :math:`x` as input and :math:`y` as output, described as a numpy array. Then, we store these data in a :class:`.Dataset`: .. GENERATED FROM PYTHON SOURCE LINES 79-91 .. code-block:: default variables = ["x", "y"] sizes = {"x": 1, "y": 1} groups = {"x": "inputs", "y": "outputs"} data = vstack( ( hstack((array([1.0]), array([1.0]))), hstack((array([2.0]), array([2.0]))), ) ) synthetic_dataset = Dataset() synthetic_dataset.set_from_array(data, variables, sizes, groups) .. GENERATED FROM PYTHON SOURCE LINES 92-112 If you do not have available data,the following paragraphs of Step 1 concern you. Here, we illustrate the generation of the training data using a :class:`.DOEScenario`, similarly to :ref:`sobieski_doe`, where more details are given. In this basic example, an :class:`.MDODiscipline` computing the mission performance (range) in the :ref:`SSBJ test case ` is sampled with a :class:`.DOEScenario`. Then, the generated database is used to build a :class:`.SurrogateDiscipline`. But more complex scenarios can be used in the same way: complete optimization processes or MDAs can be replaced by their surrogate counterparts. The right :term:`HDF` cache shall then be used to build the :class:`.SurrogateDiscipline`, but the main logic won't differ from this example. Firstly, we create the :class:`.MDODiscipline` by means of the API function :meth:`~gemseo.api.create_discipline` and cache the evaluations in memory, using the :meth:`.MDODiscipline.set_cache_policy` method: .. GENERATED FROM PYTHON SOURCE LINES 112-116 .. code-block:: default discipline = create_discipline("SobieskiMission") discipline.set_cache_policy(cache_type=discipline.MEMORY_FULL_CACHE) .. GENERATED FROM PYTHON SOURCE LINES 117-124 .. _surrogates_design_space: Then, we read the :class:`.DesignSpace` of the :ref:`Sobieski problem ` and keep only the inputs of the Sobieski Mission "x_shared", "y_24", "y_34" as inputs of the DOE: .. GENERATED FROM PYTHON SOURCE LINES 125-128 .. code-block:: default design_space = SobieskiProblem().read_design_space() design_space = design_space.filter(["x_shared", "y_24", "y_34"]) .. GENERATED FROM PYTHON SOURCE LINES 129-133 From this :class:`.MDODiscipline` and this :class:`.DesignSpace`, we build a :class:`.DOEScenario` by means of the API function :meth:`~gemseo.api.create_scenario`: .. GENERATED FROM PYTHON SOURCE LINES 134-142 .. code-block:: default scenario = create_scenario( [discipline], "DisciplinaryOpt", objective_name="y_4", design_space=design_space, scenario_type="DOE", ) .. GENERATED FROM PYTHON SOURCE LINES 143-144 Lastly, we execute the process with the :term:`LHS` algorithm and 30 samples. .. GENERATED FROM PYTHON SOURCE LINES 144-149 .. code-block:: default scenario.execute({"n_samples": 30, "algo": "lhs"}) mission_dataset = discipline.cache.export_to_dataset( inputs_names=["x_shared", "y_24", "y_34"] ) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none INFO - 21:50:42: INFO - 21:50:42: *** Start DOE Scenario execution *** INFO - 21:50:42: DOEScenario INFO - 21:50:42: Disciplines: SobieskiMission INFO - 21:50:42: MDOFormulation: DisciplinaryOpt INFO - 21:50:42: Algorithm: lhs INFO - 21:50:42: Optimization problem: INFO - 21:50:42: Minimize: y_4(x_shared, y_24, y_34) INFO - 21:50:42: With respect to: x_shared, y_24, y_34 INFO - 21:50:42: DOE sampling: 0%| | 0/30 [00:00`_, however, several other designs are available, based on the package or `OpenTURNS `_. Some examples of these designs are plotted in :ref:`doe_algos`. To list the available :term:`DOE` algorithms in the current |g| configuration, use :meth:`gemseo.api.get_available_doe_algorithms`. .. GENERATED FROM PYTHON SOURCE LINES 161-175 Create the :class:`.SurrogateDiscipline` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From this :class:`.Dataset`, we can build a :class:`.SurrogateDiscipline` of the :class:`.MDODiscipline`. Indeed, by means of the API function :class:`~gemseo.api.create_surrogate`, we create the :class:`.SurrogateDiscipline` from the cache file, which can be executed as any other :term:`discipline`. Precisely, by means of the API function :meth:`~gemseo.api.create_surrogate`, we create a :class:`.SurrogateDiscipline` relying on a :class:`.LinearRegression` and inheriting from :class:`.MDODiscipline`: .. GENERATED FROM PYTHON SOURCE LINES 175-178 .. code-block:: default synthetic_surrogate = create_surrogate("LinearRegression", synthetic_dataset) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/gemseo/conda/3.2.0/lib/python3.8/site-packages/sklearn/linear_model/_base.py:148: FutureWarning: 'normalize' was deprecated in version 1.0 and will be removed in 1.2. Please leave the normalize parameter to its default value to silence this warning. The default behavior of this estimator is to not do any normalization. If normalization is needed please use sklearn.preprocessing.StandardScaler instead. warnings.warn( INFO - 21:50:42: Build the surrogate discipline: LinReg_Dataset INFO - 21:50:42: Dataset name: Dataset INFO - 21:50:42: Dataset size: 2 INFO - 21:50:42: Surrogate model: LinearRegression INFO - 21:50:42: Use the surrogate discipline: LinReg_Dataset INFO - 21:50:42: Inputs: x INFO - 21:50:42: Outputs: y INFO - 21:50:42: Jacobian: use surrogate model jacobian .. GENERATED FROM PYTHON SOURCE LINES 179-186 .. seealso:: Note that a subset of the inputs and outputs to be used to build the :class:`.SurrogateDiscipline` may be specified by the user if needed, mainly to avoid unnecessary computations. Then, we execute it as any :class:`.MDODiscipline`: .. GENERATED FROM PYTHON SOURCE LINES 186-190 .. code-block:: default input_data = {"x": array([2.0])} out = synthetic_surrogate.execute(input_data) print(out["y"]) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [2.] .. GENERATED FROM PYTHON SOURCE LINES 191-194 In our study case, from the :term:`DOE` built at Step 1, we build a :class:`.RBFRegression` of :math:`y_4` representing the range in function of L/D: .. GENERATED FROM PYTHON SOURCE LINES 194-196 .. code-block:: default range_surrogate = create_surrogate("RBFRegression", mission_dataset) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none INFO - 21:50:42: Build the surrogate discipline: RBF_SobieskiMission INFO - 21:50:42: Dataset name: SobieskiMission INFO - 21:50:42: Dataset size: 30 INFO - 21:50:42: Surrogate model: RBFRegression INFO - 21:50:42: Use the surrogate discipline: RBF_SobieskiMission INFO - 21:50:42: Inputs: x_shared, y_24, y_34 INFO - 21:50:42: Outputs: y_4 INFO - 21:50:42: Jacobian: use surrogate model jacobian .. GENERATED FROM PYTHON SOURCE LINES 197-204 Use the :class:`.SurrogateDiscipline` in MDO -------------------------------------------- The obtained :class:`.SurrogateDiscipline` can be used in any :class:`.Scenario`, such as a :class:`.DOEScenario` or :class:`.MDOScenario`. We see here that the :meth:`.MDODiscipline.execute` method can be used as in any other discipline to compute the outputs for given inputs: .. GENERATED FROM PYTHON SOURCE LINES 204-210 .. code-block:: default for i in range(5): lod = i * 2.0 y_4_pred = range_surrogate.execute({"y_24": array([lod])})["y_4"] print("Surrogate range (L/D = {}) = {}".format(lod, y_4_pred)) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none Surrogate range (L/D = 0.0) = [-97.86844673] Surrogate range (L/D = 2.0) = [184.60105962] Surrogate range (L/D = 4.0) = [505.37518268] Surrogate range (L/D = 6.0) = [840.33241658] Surrogate range (L/D = 8.0) = [1161.49215263] .. GENERATED FROM PYTHON SOURCE LINES 211-216 And we can build and execute an optimization scenario from it. The design variables are "y_24". The Jacobian matrix is computed by finite differences by default for surrogates, except for the :class:`.SurrogateDiscipline` relying on :class:`.LinearRegression` which has an analytical (and constant) Jacobian. .. GENERATED FROM PYTHON SOURCE LINES 216-227 .. code-block:: default design_space = design_space.filter(["y_24"]) scenario = create_scenario( range_surrogate, formulation="DisciplinaryOpt", objective_name="y_4", design_space=design_space, scenario_type="MDO", maximize_objective=True, ) scenario.execute({"max_iter": 30, "algo": "L-BFGS-B"}) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none INFO - 21:50:42: INFO - 21:50:42: *** Start MDO Scenario execution *** INFO - 21:50:42: MDOScenario INFO - 21:50:42: Disciplines: Surrogate discipline: RBF_SobieskiMission INFO - 21:50:42: Dataset name: SobieskiMission INFO - 21:50:42: Dataset size: 30 INFO - 21:50:42: Surrogate model: RBFRegression INFO - 21:50:42: Inputs: x_shared, y_24, y_34 INFO - 21:50:42: Outputs: y_4 INFO - 21:50:42: MDOFormulation: DisciplinaryOpt INFO - 21:50:42: Algorithm: L-BFGS-B INFO - 21:50:42: Optimization problem: INFO - 21:50:42: Minimize: -y_4(y_24) INFO - 21:50:42: With respect to: y_24 INFO - 21:50:42: Design space: INFO - 21:50:42: +------+-------------+--------------------+-------------+-------+ INFO - 21:50:42: | name | lower_bound | value | upper_bound | type | INFO - 21:50:42: +------+-------------+--------------------+-------------+-------+ INFO - 21:50:42: | y_24 | 0.44 | 0.8060924457095278 | 11.13 | float | INFO - 21:50:42: +------+-------------+--------------------+-------------+-------+ INFO - 21:50:42: Optimization: 0%| | 0/30 [00:00`_ library, for that use the :class:`.LinearRegression` class. - Polynomial regression, based on the `Scikit-learn `_ library, for that use the :class:`.PolynomialRegression` class, - Gaussian processes (also known as Kriging), based on the `Scikit-learn `_ library, for that use the :class:`.GaussianProcessRegression` class, - Mixture of experts, for that use the :class:`.MixtureOfExperts` class, - Random forest models, based on the `Scikit-learn # `_ library, for that use the :class:`.RandomForestRegressor` class. - RBF models (Radial Basis Functions), using the `SciPy `_ library, for that use the :class:`.RBFRegression` class. - PCE models (Polynomial Chaos Expansion), based on the `OpenTURNS `_ library, for that use the :class:`.PCERegression` class. To understand the detailed behavior of the models, please go to the documentation of the used packages. Extending surrogate models -------------------------- All surrogate models work the same way: the :class:`.MLRegressionAlgo` base class shall be extended. See :ref:`extending-gemseo` to learn how to run |g| with external Python modules. Then, the :class:`.RegressionModelFactory` can build the new :class:`.MLRegressionAlgo` automatically from its regression algorithm name and options. This factory is called by the constructor of :class:`.SurrogateDiscipline`. .. seealso:: More generally, |g| provides extension mechanisms to integrate external :DOE and optimization algorithms, disciplines, MDAs and surrogate models. .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 0.163 seconds) .. _sphx_glr_download_examples_surrogate_plot_surrogate_scenario.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_surrogate_scenario.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_surrogate_scenario.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_