INPUT MODULE: INFERENCE OF MARGINALS AND COPULA¶
This example showcases how to infer both the marginal distributions and the copula from a given multivariate data.
Since INPUT MODULE: INFERENCE OF MARGINALS
example have thoroughly showcased many inference options for the marginals, this example emphasizes on the inference options for the copula (although both are inferred).
Package imports¶
from uqpylab import sessions
import numpy as np
import matplotlib.pyplot as plt
Start a remote UQCloud session¶
# Start the session
mySession = sessions.cloud()
# (Optional) Get a convenient handle to the command line interface
uq = mySession.cli
# Reset the session
mySession.reset()
Processing .
.
done! uqpylab.sessions :: INFO :: This is UQ[py]Lab, version 1.00, running on https://uqcloud.ethz.ch. UQ[py]Lab is free software, published under the open source BSD 3-clause license. To request special permissions, please contact: - Stefano Marelli (marelli@ibk.baug.ethz.ch). A new session (607400a311464fde91ea48d765ee7a42) started.
uqpylab.sessions :: INFO :: Reset successful.
Set the random seed for reproducibility¶
uq.rng(100, 'twister');
Data generation¶
A hypothetical data set used for the inference is first generated using a reference (true) probabilistic input model. The input models inferred from this data set can later on be compared with the true one.
The true probabilistic input model consists of three random variables:
- $X_1 \sim \mathcal{N}(0, 1)$
- $X_2 \sim \textrm{Exp}(1)$
- $X_3 \sim \mathcal{U}([0,1])$
Specify the marginals of these random variables:
iOptsTrue = {
'Marginals': [
{
'Type': 'Gaussian',
'Parameters': [-1,1]
},
{
'Type': 'Exponential',
'Parameters': [1]
},
{
'Type': 'Uniform',
'Parameters': [-1,3]
}
]
}
The three random variables are coupled by a canonical vine (C-vine) copula with the specifications as follows:
iOptsTrue['Copula'] = {
'Type': 'CVine',
'Structure': [[3,1,2]],
# fix the pair copula families and rotations
'Families': ['Gaussian', 'Gumbel', 't'],
'Rotations': [0,90,0],
'Parameters': [.4, 2, [-.2, 2]]
}
Create an INPUT object based on the specified marginals and copulas:
iOptsTrue['Name'] = 'True Input'
myInputTrue = uq.createInput(iOptsTrue)
Visualize the input model:
uq.display(myInputTrue);
uq.print(myInputTrue)
============================================================== Input object name: True Input Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -1.000e+00, 1.000e+00 | -1.000e+00, 1.000e+00 2 | X2 | Exponential | 1.000e+00 | 1.000e+00, 1.000e+00 3 | X3 | Uniform | -1.000e+00, 3.000e+00 | 1.000e+00, 1.155e+00 Copula: Type: CVine Dimension: 3 Variables coupled: [1 2 3] Structure: [3 1 2] Truncation: 3 (none) Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_3,1 | Gaussian | 0 | 4.0000e-01 2 | C_3,2 | Gumbel | 90 | 2.0000e+00 3 | C_1,2|3 | t | 0 | - 22..00000000ee-+0010 ==============================================================
Sample from the input model:
X = uq.getSample(myInputTrue,200)
The pseudo-observations corresponding to the first sample can also be calculated. These are the cumulative densities of each observation according to its marginal distribution. When known, they can be used for copula inference instead of the original observations.
U = uq.all_cdf(X,myInputTrue['Marginals'])
Inference of marginals and copula¶
Marginals and copula inference¶
In this example, a fully data driven inference is performed:
- no information is known except the given data
- both the marginals and the copula are inferred among the supported types
- before copula inference, a test of statistical independence is performed to split the random variables into independent subsets, if any
iOpts = {
'Inference': [
{
'Data': X.tolist()
}
],
'Name': 'InputHat 1'
}
InputHat1 = uq.createInput(iOpts)
Processing .
.
. done!
Print out a report on the inferred input model:
uq.print(InputHat1)
============================================================== Input object name: InputHat 1 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -9.244e-01, 9.881e-01 | -9.244e-01, 9.881e-01 2 | X2 | Exponential | 9.685e-01 | 1.032e+00, 1.032e+00 3 | X3 | Uniform | -1.013e+00, 3.015e+00 | 1.001e+00, 1.163e+00 Copula: Type: DVine Dimension: 3 Variables coupled: [1 2 3] Structure: [3 2 1] Truncation: 2 Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_3,2 | Gumbel | 90 | 1.7840e+00 2 | C_2,1 | t | 0 | -5.2992e-01 7.1571e+00 3 | C_3,1|2 | Clayton | 180 | 3.0628e-01 ==============================================================
Different selection criteria for marginals and copula inference¶
In the example below, the default inference criterion for copula (AIC) is changed to the Bayesian inference criterion (BIC). This criterion has a stronger penalization for copula models having more parameters.
iOpts['Inference'][0]['Criterion'] = 'BIC'
iOpts['Name'] = 'InputHat 2'
InputHat2 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat2)
============================================================== Input object name: InputHat 2 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -9.244e-01, 9.881e-01 | -9.244e-01, 9.881e-01 2 | X2 | Exponential | 9.685e-01 | 1.032e+00, 1.032e+00 3 | X3 | Uniform | -1.013e+00, 3.015e+00 | 1.001e+00, 1.163e+00 Copula: Type: DVine Dimension: 3 Variables coupled: [1 2 3] Structure: [3 2 1] Truncation: 2 Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_3,2 | Gumbel | 90 | 1.7840e+00 2 | C_2,1 | t | 0 | -5.2992e-01 7.1571e+00 3 | C_3,1|2 | Clayton | 180 | 3.0628e-01 ==============================================================
Copula inference with fixed copula type¶
A copula type can be fixed prior to inference and therefore only parameter fitting takes place.
Below, the copula is fixed to be a Gaussian copula:
iOpts['Copula'] = {
'Type': 'Gaussian'
}
iOpts['Name'] = 'InputHat 3'
InputHat3 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat3)
============================================================== Input object name: InputHat 3 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -9.244e-01, 9.881e-01 | -9.244e-01, 9.881e-01 2 | X2 | Exponential | 9.685e-01 | 1.032e+00, 1.032e+00 3 | X3 | Uniform | -1.013e+00, 3.015e+00 | 1.001e+00, 1.163e+00 Copula: Type: Gaussian Dimension: 3 Variables coupled: [1 2 3] Parameters: [+1.0000 -0.5190 +0.4427 ; -0.5190 +1.0000 -0.6241 ; +0.4427 -0.6241 +1.0000 ] ==============================================================
Marginals inference with fully specified copula¶
The copula type as well as its parameters can be fully specified at the outset. This specification limits the inference only to the marginals.
In the example below, the parameter of a Gaussian copula is specified:
iOpts['Copula']['Parameters'] = [[1, -.4, .3], [-.4, 1, -.6], [.3, -.6, 1]]
iOpts['Name'] = 'InputHat 4'
InputHat4 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat4)
============================================================== Input object name: InputHat 4 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -9.244e-01, 9.881e-01 | -9.244e-01, 9.881e-01 2 | X2 | Exponential | 9.685e-01 | 1.032e+00, 1.032e+00 3 | X3 | Uniform | -1.013e+00, 3.015e+00 | 1.001e+00, 1.163e+00 Copula: Type: Gaussian Dimension: 3 Variables coupled: [1 2 3] Parameters: [+1.0000 -0.4000 +0.3000 ; -0.4000 +1.0000 -0.6000 ; +0.3000 -0.6000 +1.0000 ] ==============================================================
Copula inference with fixed marginals¶
Contrary to the previous case, the marginals can be fully specified at the outset and thus limits the inference only to the copula:
del iOpts
iOpts = {
'Marginals': [
{
'Type': 'Gaussian',
'Parameters': [-1,1]
},
{
'Type': 'Exponential',
'Parameters': [1]
},
{
'Type': 'Uniform',
'Parameters': [-1,3]
}
],
'Inference': [
{
'Data': X.tolist()
}
]
}
iOpts['Name'] = 'InputHat 5'
InputHat5 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat5)
============================================================== Input object name: InputHat 5 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -1.000e+00, 1.000e+00 | -1.000e+00, 1.000e+00 2 | X2 | Exponential | 1.000e+00 | 1.000e+00, 1.000e+00 3 | X3 | Uniform | -1.000e+00, 3.000e+00 | 1.000e+00, 1.155e+00 Copula: Type: DVine Dimension: 3 Variables coupled: [1 2 3] Structure: [3 2 1] Truncation: 2 Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_3,2 | Clayton | 270 | 1.3257e+00 2 | C_2,1 | t | 0 | -5.2995e-01 5.7536e+00 3 | C_3,1|2 | Clayton | 180 | 2.8652e-01 ==============================================================
Copula inference using different data¶
Sometimes, the same amount of observation is not available to infer the marginals and the copula. For instance, joint observations from the full random vector may be fewer than observations from the individual variables.
In the example below, the copula is inferred on a smaller data set, taking every second observation.
iOpts['Copula'] = {
'Type': 'auto',
'Inference': {
'Data': X[::2].tolist()
}
}
iOpts['Name'] = 'InputHat 6'
InputHat6 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat6)
============================================================== Input object name: InputHat 6 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -1.000e+00, 1.000e+00 | -1.000e+00, 1.000e+00 2 | X2 | Exponential | 1.000e+00 | 1.000e+00, 1.000e+00 3 | X3 | Uniform | -1.000e+00, 3.000e+00 | 1.000e+00, 1.155e+00 Copula: Type: CVine Dimension: 3 Variables coupled: [1 2 3] Structure: [2 3 1] Truncation: 2 Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_2,3 | Frank | 270 | 5.1734e+00 2 | C_2,1 | t | 0 | -5.2701e-01 3.8734e+00 3 | C_3,1|2 | Independent | 0 | ==============================================================
Copula inference on pseudo-observations in the unit hypercube¶
Finally, in the example below, the copula is inferred based on the pseudo-observations in the unit hypercube:
del iOpts
iOpts = {
'Marginals': [
{
'Type': 'Gaussian',
'Parameters': [-1, 1]
},
{
'Type': 'Exponential',
'Parameters': [1]
},
{
'Type': 'Uniform',
'Parameters': [-1, 3]
}
],
'Copula': {
'Type': 'auto',
'Inference': {
'DataU': U.tolist()
}
}
}
iOpts['Name'] = 'InputHat 7'
InputHat7 = uq.createInput(iOpts)
Print out a report on the inferred input model:
uq.print(InputHat7)
============================================================== Input object name: InputHat 7 Dimension(M): 3 Marginals: Index | Name | Type | Parameters | Moments ----------------------------------------------------------------------------- 1 | X1 | Gaussian | -1.000e+00, 1.000e+00 | -1.000e+00, 1.000e+00 2 | X2 | Exponential | 1.000e+00 | 1.000e+00, 1.000e+00 3 | X3 | Uniform | -1.000e+00, 3.000e+00 | 1.000e+00, 1.155e+00 Copula: Type: CVine Dimension: 3 Variables coupled: [1 2 3] Structure: [2 3 1] Truncation: 2 Pair copulas: Index | Pair Copula | Family | Rot | Parameters 1 | C_2,3 | Clayton | 90 | 1.3257e+00 2 | C_2,1 | t | 0 | -5.2995e-01 5.7536e+00 3 | C_3,1|2 | Clayton | 180 | 2.8652e-01 ==============================================================
Terminate the remote UQCloud session¶
mySession.quit()
uqpylab.sessions :: INFO :: Session 607400a311464fde91ea48d765ee7a42 terminated.
True