コード例 #1
0
ファイル: scipy.py プロジェクト: taoyyt/modest-py
    def plot_parameter_evo(self, file=None):
        par_df = self.summary.drop([SCIPY.METHOD], axis=1)
        par_df = par_df.rename(columns={
            x: 'error' if x == SCIPY.ERR else x for x in par_df.columns
            })

        # Get axes
        axes = par_df.plot(subplots=True)
        fig = figures.get_figure(axes)
        # x label
        axes[-1].set_xlabel('Iteration')
        # ylim for error
        axes[-1].set_ylim(0, None)

        if file:
            fig.set_size_inches(SCIPY.FIG_SIZE)
            fig.savefig(file, dpi=SCIPY.FIG_DPI)
        return axes
コード例 #2
0
ファイル: estimation.py プロジェクト: sdu-cfei/modest-py
    def validate(self, vp=None):
        """
        Performs a simulation with estimated parameters
        for the previously selected validation period. Other period
        can be chosen with the `vp` argument. User chosen `vp` in this method
        does not override the validation period chosen during instantiation
        of this class.

        Parameters
        ----------
        vp: tuple or None
            Validation period given as a tuple of start and stop time in
            seconds.

        Returns
        -------
        dict
            Validation error, keys: 'tot', '<var1>', '<var2>', ...
        pandas.DataFrame
            Simulation result
        """
        # Get estimates
        est = self.final
        est.index = [0]  # Reset index (needed by model.set_param())

        self.logger.info("Validation of parameters: {}".format(
            str(est.iloc[0].to_dict())))

        # Slice data
        if vp is None:
            start, stop = self.vp[0], self.vp[1]
        else:
            start, stop = vp[0], vp[1]
        inp_slice = self.inp.loc[start:stop]
        ideal_slice = self.ideal.loc[start:stop]

        # Initialize IC parameters and add to known
        if self.ic_param:
            for par in self.ic_param:
                ic = ideal_slice[self.ic_param[par]].iloc[0]
                self.known[par] = ic

        # Initialize model
        model = Model(self.fmu_path)
        model.set_input(inp_slice)
        model.set_param(est)
        model.set_param(self.known)
        model.set_outputs(list(self.ideal.columns))

        # Simulate and get error
        try:
            result = model.simulate()
        except Exception as e:
            msg = "Problem found inside FMU. Did you set all parameters?"
            self.logger.error(str(e))
            self.logger.error(msg)
            raise e

        err = modestpy.estim.error.calc_err(result, ideal_slice)

        # Create validation plot
        ax = plot_comparison(result, ideal_slice, f=None)
        fig = figures.get_figure(ax)
        fig.set_size_inches(Estimation.FIG_SIZE)
        fig.savefig(os.path.join(self.workdir, "validation.png"),
                    dpi=Estimation.FIG_DPI)

        # Remove temp dirs
        self._clean()

        # Return
        return err, result
コード例 #3
0
ファイル: estimation.py プロジェクト: sdu-cfei/modest-py
    def estimate(self, get="best"):
        """
        Estimates parameters.

        Returns average or best estimates depending on `get`.
        Average parameters are calculated as arithmetic average
        from all learning periods. Best parameters are those which
        resulted in the lowest error during respective learning period.
        It is advised to use 'best' parameters.

        The chosen estimates ('avg' or 'best') are saved
        in a csv file `final.csv` in the working directory.
        In addition estimates and errors from all learning periods
        are saved in `best_per_run.csv`.

        Parameters
        ----------
        get: str, default 'best'
            Type of returned estimates: 'avg' or 'best'

        Returns
        -------
        dict(str: float)
        """
        # (0) Sanity checks
        allowed_types = ["best", "avg"]
        assert get in allowed_types, "get={} is not allowed".format(get)

        # (1) Initialize local variables
        # Tuple with method names
        # e.g. ('MODESTGA', 'PS'), ('MODESTGA', 'SCIPY') or ('MODESTGA', )
        methods = self.methods

        # List of plots to be saved
        plots = list()

        cols = ["_method_", "_error_"] + [par_name for par_name in self.est]

        # Estimates and errors from all iterations from all methods
        summary = pd.DataFrame(columns=cols)
        summary.index.name = "_iter_"

        # List of DataFrames with summaries from all runs
        summary_list = list()

        # (2) Double step estimation
        n = 1  # Learning period counter

        for period in self.lp:
            # (2.1) Copy initial parameters
            est = copy.copy(self.est)

            # (2.2) Slice data
            start, stop = period[0], period[1]
            inp_slice = self.inp.loc[start:stop]
            ideal_slice = self.ideal.loc[start:stop]

            # (2.3) Get data for IC parameters and add to known parameters
            if self.ic_param:
                for par in self.ic_param:
                    ic = ideal_slice[self.ic_param[par]].iloc[0]
                    self.known[par] = ic

            # (2.4) Iterate over estimation methods (append results from all)
            m = 0  # Method counter
            for m_name in methods:
                # (2.4.1) Instantiate method class
                m_class = self.method_dict[m_name][0]
                m_opts = self.method_dict[m_name][1]

                m_inst = m_class(self.fmu_path, inp_slice, self.known, est,
                                 ideal_slice, **m_opts)

                # (2.4.2) Estimate
                m_estimates = m_inst.estimate()

                # (2.4.3) Update current estimates
                # (stored in self.est dictionary)
                for key in est:
                    new_value = m_estimates[key].iloc[0]
                    est[key] = (new_value, est[key][1], est[key][2])

                # (2.4.4) Append summary
                full_traj = m_inst.get_full_solution_trajectory()
                if m > 0:
                    # Add iterations from previous methods
                    full_traj.index += summary.index[-1]
                summary = summary.append(full_traj, verify_integrity=True)
                summary.index.rename("_iter_", inplace=True)

                # (2.4.5) Save method's plots
                plots = m_inst.get_plots()
                for p in plots:
                    fig = figures.get_figure(p["axes"])
                    fig_file = os.path.join(self.workdir,
                                            "{}_{}.png".format(p["name"], n))
                    fig.set_size_inches(Estimation.FIG_SIZE)
                    fig.savefig(fig_file, dpi=Estimation.FIG_DPI)
                plt.close("all")

                # (2.4.6) Increase method counter
                m += 1

            # (2.5) Add summary from this run to the list of all summaries
            summary_list.append(summary)
            summary = pd.DataFrame(columns=cols)  # Reset

            # (2.6) Increase learning period counter
            n += 1

        # (3) Get and save best estimates per run and final estimates
        best_per_run = self._get_finals(summary_list)
        best_per_run.to_csv(os.path.join(self.workdir, "best_per_run.csv"))

        if get == "best":
            cond = best_per_run["_error_"] == best_per_run["_error_"].min()
            # Take only one if more than one present
            final = best_per_run.loc[cond].iloc[0:1]
            final = final.drop("_error_", axis=1)
        elif get == "avg":
            final = best_per_run.drop("_error_", axis=1).mean().to_frame().T
        else:
            # This shouldn't happen, because the type is checked at (0)
            raise RuntimeError("Unknown type of estimates: {}".format(get))

        final_file = os.path.join(self.workdir, "final.csv")
        final.to_csv(final_file, index=False)

        # (4) Save summaries from all learning periods
        for s, n in zip(summary_list, range(1, len(summary_list) + 1)):
            sfile = os.path.join(self.workdir, "summary_{}.csv".format(n))
            s.to_csv(sfile)

        # (5) Save error plot including all learning periods
        ax = self._plot_error_per_run(summary_list, err_type=self.ftype)
        fig = figures.get_figure(ax)
        fig.savefig(os.path.join(self.workdir, "errors.png"))

        # (6) Assign results to instance attributes
        self.best_per_run = best_per_run
        self.final = final

        # (7) Estimates to dict
        final = final.to_dict("records")[0]

        # (8) Delete temp dirs
        self._clean()

        # (9) Return final estimates
        return final