<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Diagnostics
Step1:  Summary Statistics Selection
One of the most difficult aspects in likelihood-free inference is finding a good way to compare simulated and observed data. This is typically accomplished via a set of summary statistics, but they tend to be very problem-specific. ELFI includes tools to aid this selection in the form of the Two Stage Procedure proposed by Nunes & Balding (2010), which determines a well-performing summary statistics combination. The procedure can be summarised as follows
Step2:  Let's see if it would be beneficial try other summary statistics as well, for example the mean and the variance. To use the Two-Stage Selection process, we have to define the ElfiModel up until the node for which the summary statistics will be applied, which is typically the simulator node (here, named MA2). Because the MA2 example defines a complete ElfiModel, we have to remove the summary statistics (and anything after them, in this case the distance) from it
Step3:  Next we need to define a list of candidate summary statistics
Step4:  ELFI will generate all possible combinations of these candidates, and build an ElfiModel for each combination by generating child nodes to the user-given node (here, the simulator node MA2). A distance node between the summary statistics can be given as a function or string as with elfi.Distance or elfi.Discrepancy (here, 'euclidean')
Step5:  Sometimes the generated list of combinations may be very long. If you are able to make an educated guess about which combinations are the most promising, you can save computational time by providing these combinations to ELFI. This can be done by replacing the list_ss keyword argument with for example
<ASSISTANT_TASK:>
Python Code:
from functools import partial
import numpy as np
import scipy.stats as ss
import elfi
import logging
logging.basicConfig(level=logging.INFO)
from elfi.methods import diagnostics
Explanation: Diagnostics
End of explanation
from elfi.examples import ma2
m = ma2.get_model()
elfi.draw(m)
Explanation: Summary Statistics Selection
One of the most difficult aspects in likelihood-free inference is finding a good way to compare simulated and observed data. This is typically accomplished via a set of summary statistics, but they tend to be very problem-specific. ELFI includes tools to aid this selection in the form of the Two Stage Procedure proposed by Nunes & Balding (2010), which determines a well-performing summary statistics combination. The procedure can be summarised as follows:
First, all possible combinations of the candidate summary statistics are generated (can also be user-given)
Stage 1:
Each summary statistics combination is evaluated using the Minimum Entropy algorithm
The minimum entropy combination is selected, and the 'closest' datasets are identified
Stage 2:
For each summary statistics combination, the mean root sum of squared errors (MRSSE) is calculated over all 'closest' datasets
The minimum MRSSE combination is chosen as the one with the optimal performance.
Example: Summary statistics selection for the MA2 model
We will again use the MA2 example introduced in the tutorial, where we used the first two autocovariances as the summary statistics: one with lag=1, another with lag=2.
End of explanation
m.remove_node('S1')
m.remove_node('S2')
m.remove_node('d')
elfi.draw(m)
Explanation: Let's see if it would be beneficial try other summary statistics as well, for example the mean and the variance. To use the Two-Stage Selection process, we have to define the ElfiModel up until the node for which the summary statistics will be applied, which is typically the simulator node (here, named MA2). Because the MA2 example defines a complete ElfiModel, we have to remove the summary statistics (and anything after them, in this case the distance) from it:
End of explanation
autocov1 = ma2.autocov
autocov2 = partial(ma2.autocov, lag=2)
autocov2.__name__ = 'autocov2'  # Note: the name must be given separately if using partial
def mean(y):
    return np.mean(y, axis=1)
def var(y):
    return np.var(y, axis=1)
# Initialising the list of assessed summary statistics.
list_ss = [autocov1, autocov2, mean, var]
Explanation: Next we need to define a list of candidate summary statistics:
End of explanation
selection = diagnostics.TwoStageSelection(m['MA2'], 'euclidean', list_ss=list_ss)
Explanation: ELFI will generate all possible combinations of these candidates, and build an ElfiModel for each combination by generating child nodes to the user-given node (here, the simulator node MA2). A distance node between the summary statistics can be given as a function or string as with elfi.Distance or elfi.Discrepancy (here, 'euclidean'):
End of explanation
ss = selection.run(n_sim=100000, batch_size=10000)
ss
Explanation: Sometimes the generated list of combinations may be very long. If you are able to make an educated guess about which combinations are the most promising, you can save computational time by providing these combinations to ELFI. This can be done by replacing the list_ss keyword argument with for example: 
prepared_ss=[[autocov1], [autocov1, autocov2], [mean, var]] 
and then ELFI will only consider these combinations.
After these preparations, we can execute the selection process as follows:
End of explanation
<END_TASK>