Пример #1
0
    def standardize(self):
        """
        Standardize Kriging samples and create regression matrix.

        Returns:
            None
        """
        # Create regression matrix
        self.KrigInfo['idx'] = polytruncation(self.KrigInfo["TrendOrder"],
                                              self.KrigInfo["nvar"], 1)

        # Standardize X and y
        if self.standardization is True:
            if self.standtype.lower(
            ) == "default":  # If standardization type is set to 'default'
                self.KrigInfo["normtype"] = "default"

                # Create normalization bound from -1 to 1
                bound = np.vstack((-np.ones(shape=[1, self.KrigInfo["nvar"]]),
                                   np.ones(shape=[1, self.KrigInfo["nvar"]])))

                # Normalize sample to -1 and 1
                if self.normy is True:  # If normalize y
                    self.KrigInfo["X_norm"], self.KrigInfo[
                        "y_norm"] = standardize(self.KrigInfo['X'],
                                                self.KrigInfo['y'],
                                                type=self.standtype.lower(),
                                                normy=True,
                                                range=np.vstack(
                                                    (np.hstack(
                                                        (self.KrigInfo["lb"],
                                                         np.min(self.Y))),
                                                     np.hstack(
                                                         (self.KrigInfo["ub"],
                                                          np.max(self.Y))))))
                    self.KrigInfo["norm_y"] = True

                else:
                    self.KrigInfo["X_norm"] = standardize(
                        self.KrigInfo['X'],
                        self.KrigInfo['y'],
                        type=self.standtype.lower(),
                        range=np.vstack(
                            (self.KrigInfo["lb"], self.KrigInfo["ub"])))
                    self.KrigInfo["norm_y"] = False

            else:  # If standardization type is set to 'std'
                self.KrigInfo["normtype"] = "std"

                # create normalization with mean 0 and standard deviation 1
                if self.normy is True:
                    self.KrigInfo["X_norm"], self.KrigInfo["y_norm"], \
                    self.KrigInfo["X_mean"], self.KrigInfo["y_mean"], \
                    self.KrigInfo["X_std"], self.KrigInfo["y_std"] = standardize(
                        self.KrigInfo['X'], self.KrigInfo['y'], type=self.standtype.lower(), normy=True)

                    self.KrigInfo["norm_y"] = True
                else:
                    self.KrigInfo["X_norm"], self.KrigInfo["X_mean"], self.KrigInfo["X_std"] = \
                        standardize(self.KrigInfo['X'], self.KrigInfo['y'], type=self.standtype.lower())
                    self.KrigInfo["norm_y"] = False

                bound = np.vstack(
                    (np.min(self.KrigInfo["X_norm"],
                            axis=0), np.max(self.KrigInfo["X_norm"], axis=0)))

            self.KrigInfo["standardization"] = True
            self.KrigInfo["F"] = compute_regression_mat(
                self.KrigInfo["idx"], self.KrigInfo["X_norm"], bound,
                np.ones(shape=[self.KrigInfo["nvar"]]))
        else:
            self.KrigInfo["standardization"] = False
            self.KrigInfo["norm_y"] = False
            bound = np.vstack(
                (np.min(self.KrigInfo["X"],
                        axis=0), np.max(self.KrigInfo["X"], axis=0)))
            self.KrigInfo["F"] = compute_regression_mat(
                self.KrigInfo["idx"], self.KrigInfo["X"], bound,
                np.ones(shape=[self.KrigInfo["nvar"]]))
Пример #2
0
def prediction(x, KrigInfo, predtypes, num=None, drm=None, **kwargs):
    """Predict response using a given Kriging model.

    Calculates expected improvement (for optimization), SSqr, Kriging
    prediction, and prediction from regression function

    Information: This function is a modification from "Forrester, A.,
    Sobester, A., & Keane, A. (2008). Engineering design via surrogate
    modelling:  a practical guide. John Wiley & Sons."

    Variables used from Kriging model dictionary KrigInfo:
        Xnorm - (nsamp x nvar) matrix of normalized experimental design.
        Y - (nsamp x 1) vector of responses.
        PHI - (nsamp x nind) matrix of regression function.
        idx - (nind x nvar) matrix consisting of polynomial index for
            regression function.
        kernel - Type of kernel function.
        wgkf - (1 x nkrnl) vector of weights for kernel functions.
        U - Choleski factorisation of correlation matrix.
        xparam - Hyperparameters of the Kriging model.
        BE - Coefficients of regression function
        SigmaSqr - SigmaSqr (Kriging variance) of the Kriging model

    N.B. Output will be a list if several predtypes are specified.

    Author: Pramudita Satria Palar([email protected], [email protected])

    Args:
        x (list/np.array): Prediction site (will be normalized to [-1,1])
        KrigInfo (dict): A structure containing necessary information of
            a constructed Kriging model.
        predtypes (str/[str]): Requested outputs at prediction site x.
            Valid predtypes are:
            'pred' - for Kriging prediction.
            'SSqr' - for Kriging prediction error.
            'fpc' - Kriging trend function.
            'lcb' -
            'ebe' -
            'EI' - for expected improvement.
            'poi' -
            'pof' -
        num (int, optional): Objective Function number. Defaults to None.

    Returns:
        If only one output specified through predtypes, a single value
        or array is returned. Else a list of each output is returned.

    Raises:
        ValueError:
        KeyError:
    """
    nvar = KrigInfo["nvar"]
    if KrigInfo["n_princomp"] is not False:
        nvar = KrigInfo["n_princomp"]
    kernel = KrigInfo["kernel"]
    nkernel = KrigInfo["nkernel"]
    # p = 2  # from reference  # Apparently unused?

    # If vector, turn into 1D array
    if x.ndim == 1:
        x = x.reshape(1, -1)

    # # Is this extra check necessary?
    # if KrigInfo['multiobj'] is True and 'num' in KrigInfo:
    #     wgkf = KrigInfo['wgkf'][num]
    #     idx = KrigInfo['idx'][num]

    if KrigInfo["standardization"] is False:
        X = KrigInfo["X"]
        y = get_val(KrigInfo, "y", num)
    else:
        X = KrigInfo["X_norm"]
        if "y_norm" in KrigInfo:
            y = get_val(KrigInfo, "y_norm", num)
        else:
            y = get_val(KrigInfo, "y", num)

    theta = 10**get_val(KrigInfo, "Theta", num)
    U = get_val(KrigInfo, "U", num)
    PHI = get_val(KrigInfo, "F", num)
    BE = get_val(KrigInfo, "BE", num)
    wgkf = get_val(KrigInfo, "wgkf", num)
    idx = get_val(KrigInfo, "idx", num)
    SigmaSqr = get_val(KrigInfo, "SigmaSqr", num)

    if KrigInfo["type"].lower() == "kpls":
        plscoeff = get_val(KrigInfo, "plscoeff", num)

    if KrigInfo["standardization"] is True:
        if KrigInfo["normtype"] == "default":
            x = standardize(x,
                            0,
                            type="default",
                            range=np.vstack((KrigInfo["lb"], KrigInfo["ub"])))
        elif KrigInfo["normtype"] == "std":
            x = (x - KrigInfo["X_mean"]) / KrigInfo["X_std"]
        else:
            msg = (f"Kriging model dictionary 'normtype' value: "
                   f"'{KrigInfo['normtype']}' is not recognised.")
            raise ValueError(msg)

    if drm is not None:
        if drm.kernel != "precomputed":
            x = drm.transform(x.copy())
            if KrigInfo["standardization"] is True:
                x = standardize(
                    x,
                    0,
                    type="default",
                    range=np.vstack((KrigInfo["lb2"], KrigInfo["ub2"])),
                )
        else:
            feat = np.size(x, 1)
            k_mat = customkernel(x,
                                 KrigInfo["orig_X"],
                                 KrigInfo["kpcaw"],
                                 feat,
                                 type="gaussian")
            x = drm.transform(k_mat)
            if KrigInfo["standardization"] is True:
                x = standardize(
                    x,
                    0,
                    type="default",
                    range=np.vstack((KrigInfo["lb2"], KrigInfo["ub2"])),
                )

    # Calculate number of sample points
    n = np.ma.size(X, axis=0)
    npred = np.size(x, axis=0)

    # Construct regression matrix for prediction
    bound = np.vstack((-np.ones(shape=[1, KrigInfo["nvar"]]),
                       np.ones(shape=[1, KrigInfo["nvar"]])))
    PC = compute_regression_mat(idx, x, bound,
                                np.ones(shape=[KrigInfo["nvar"]]))
    fpc = np.dot(PC, BE)

    PsiComp = np.zeros(shape=[n, npred, nkernel])

    # Fill psi vector
    if KrigInfo["type"].lower() == "kriging":
        for ii in range(0, nkernel):
            psi_i = calckernel(X, x, theta, nvar, type=kernel[ii])
            PsiComp[:, :, ii] = wgkf[ii] * psi_i
        psi = np.sum(PsiComp, 2)

    elif KrigInfo["type"].lower() == "kpls":
        for ii in range(0, nkernel):
            psi_i = calckernel(X,
                               x,
                               theta,
                               KrigInfo["nvar"],
                               type=kernel[ii],
                               plscoeff=plscoeff)
            PsiComp[:, :, ii] = wgkf[ii] * psi_i
        psi = np.sum(PsiComp, 2)

    else:
        msg = (f"Kriging model dictionary 'type' value: '{KrigInfo['type']}'"
               f"is not recognised.")
        raise ValueError(msg)

    # Calculate prediction
    f = fpc + np.dot(
        np.transpose(psi),
        mldivide(U, mldivide(np.transpose(U), (y - np.dot(PHI, BE)))))

    if num == None:
        if KrigInfo["norm_y"] == True:
            f = stdtoreal(f, KrigInfo)
    else:
        if KrigInfo["norm_y"] == True:
            f = stdtoreal(f, KrigInfo, num=num)

    # Compute sigma-squared error
    dummy1 = mldivide(U, mldivide(np.transpose(U), psi))
    dummy2 = mldivide(U, mldivide(np.transpose(U), PHI))
    term1 = 1 - np.sum(np.transpose(psi) * np.transpose(dummy1), 1)
    ux = (np.dot(np.transpose(PHI), dummy1)) - np.transpose(PC)
    term2 = ux * (mldivide(np.dot(np.transpose(PHI), dummy2), ux))
    SSqr = np.dot(SigmaSqr, (term1 + term2))
    s = abs(SSqr)**0.5

    # Switch prediction type
    if isinstance(predtypes, str):
        predtypes = [predtypes]

    outputs = []  # Collect requested outputs into a list
    for pred in predtypes:
        if pred.lower() == "pred":
            output = f
        elif pred.lower() == "ssqr":
            output = SSqr.T
        elif pred.lower() == "s":
            output = s.T
        elif pred.lower() == "fpc":
            output = fpc
        elif pred.lower() == "lcb":
            output = f - np.dot(KrigInfo["sigmalcb"], SSqr)
        elif pred.lower() == "ebe":
            output = -SSqr
        elif pred.lower() == "ei":
            yBest = np.min(y)
            if SSqr.all() == 0:
                ExpImp = 0
            else:
                EITermOne = (yBest - f) * (0.5 + 0.5 * erf(
                    (1 / np.sqrt(2)) * (yBest - f) / np.transpose(s)))
                EITermTwo = (np.transpose(s) / np.sqrt(2 * np.pi) *
                             np.exp(-0.5 *
                                    (yBest - f)**2 / np.transpose(SSqr)))

                # Give penalty for CMA-ES optimizer, if both term produce 0.
                # Else in certain conditions, it may leads to error in CMA-ES.
                realmin = np.finfo(float).tiny
                if not EITermOne.any() and not EITermTwo.any():
                    tiny_number = np.random.uniform(realmin, realmin * 100)
                    ExpImp = np.array([[tiny_number]])
                else:
                    ExpImp = EITermOne + EITermTwo + realmin
            output = -ExpImp
        elif pred.lower() == "poi":
            ProbImp = 0.5 + 0.5 * erf(1 / np.sqrt(2) *
                                      (np.min(y) - f) / np.transpose(s))
            output = -ProbImp
        elif pred.lower() == "pof":
            if KrigInfo["limittype"] == ">" or KrigInfo["limittype"] == ">=":
                ProbFeas = 0.5 + 0.5 * erf(1 / np.sqrt(2) * (
                    (f - KrigInfo["limit"]) / np.transpose(s)))
            elif KrigInfo["limittype"] == "<" or KrigInfo["limittype"] == "<=":
                ProbFeas = 0.5 + 0.5 * erf(1 / np.sqrt(2) * (
                    (KrigInfo["limit"] - f) / np.transpose(s)))
            else:
                raise ValueError("Limit Type is not available yet!")
            output = ProbFeas
        else:
            msg = f"Specified prediction type: '{pred}' is not recognised."
            raise NotImplementedError(msg)
        outputs.append(output)

    # If only one output specified, try to return as single value or array.
    if len(outputs) == 1:
        try:
            return outputs[0].item()
        except ValueError:
            return outputs[0]
    else:
        return outputs
Пример #3
0
    def simultpredehvi(self, disp=False):
        """
        Perform multi updates on EHVI MOBO using Kriging believer method.

        Returns:
             xalltemp (nparray) : Array of design variables updates.
             yalltemp (nparray) : Array of objectives value updates.
             metricall (nparray) : Array of metric of the updates.
        """

        krigtemp = [0] * len(self.kriglist)
        for index, obj in enumerate(self.kriglist):
            krigtemp[index] = deepcopy(obj)
        yprednext = np.zeros(shape=[len(krigtemp)])
        sprednext = np.zeros(shape=[len(krigtemp)])
        ypartemp = self.ypar
        yall = self.yall

        for ii in range(self.multiupdate):
            t1 = time.time()
            if disp:
                print(f"update number {ii+1}")
            else:
                pass

            xnext, metrictemp = run_multi_opt(krigtemp, self.moboInfo,
                                              ypartemp, self.krigconstlist,
                                              self.cheapconstlist)
            bound = np.vstack(
                (-np.ones(shape=[1, krigtemp[0].KrigInfo["nvar"]]),
                 np.ones(shape=[1, krigtemp[0].KrigInfo["nvar"]])))

            for jj in range(len(krigtemp)):
                yprednext[jj], sprednext[jj] = krigtemp[jj].predict(
                    xnext, ['pred', 's'])
                krigtemp[jj].KrigInfo['X'] = np.vstack(
                    (krigtemp[jj].KrigInfo['X'], xnext))
                krigtemp[jj].KrigInfo['y'] = np.vstack(
                    (krigtemp[jj].KrigInfo['y'], yprednext[jj]))
                krigtemp[jj].standardize()
                krigtemp[jj].KrigInfo["F"] = compute_regression_mat(
                    krigtemp[jj].KrigInfo["idx"],
                    krigtemp[jj].KrigInfo["X_norm"], bound,
                    np.ones(shape=[krigtemp[jj].KrigInfo["nvar"]]))
                krigtemp[jj].KrigInfo = likelihood(
                    krigtemp[jj].KrigInfo['Theta'],
                    krigtemp[jj].KrigInfo,
                    mode='all',
                    trainvar=krigtemp[jj].trainvar)

            if ii == 0:
                xalltemp = deepcopy(xnext)
                yalltemp = deepcopy(yprednext)
                salltemp = deepcopy(sprednext)
                metricall = deepcopy(metrictemp)
            else:
                xalltemp = np.vstack((xalltemp, xnext))
                yalltemp = np.vstack((yalltemp, yprednext))
                salltemp = np.vstack((salltemp, sprednext))
                metricall = np.vstack((metricall, metrictemp))

            yall = np.vstack((yall, yprednext))
            ypartemp, _ = searchpareto.paretopoint(yall)

            if disp:
                print("time: ", time.time() - t1, " s")

        return [xalltemp, yalltemp, salltemp, metricall]
Пример #4
0
    def simultpredehvi(self, disp=False, pool=None):
        """
        Perform multi updates on EHVI MOBO using Kriging believer method.

        Args:
            disp (bool, optional): Print progress. Defaults to True.
            pool (int, optional): A multiprocessing.Pool instance.
                Will be passed to functions for use, if specified.
                Defaults to None.

        Returns:
            xalltemp (np.ndarray): [n_kb, n_dv] array of update design
                variable values.
            yalltemp (np.ndarray): [n_kb, n_obj] array of update
                objective values.
            salltemp (np.ndarray): [n_kb, n_obj] array of update
                objective uncertainty values.
            metricall (np.ndarray): [n_kb, 1] array of update metric
                values.
        """
        n_krig = len(self.kriglist)
        n_dv = self.kriglist[0].KrigInfo["nvar"]

        krigtemp = [deepcopy(obj) for obj in self.kriglist]
        yprednext = np.zeros([n_krig])
        sprednext = np.zeros([n_krig])

        xalltemp = np.empty([self.multiupdate, n_dv])
        yalltemp = np.empty([self.multiupdate, n_krig])
        salltemp = np.empty([self.multiupdate, n_krig])
        metricall = np.empty([self.multiupdate, 1])

        ypartemp = self.ypar
        yall = self.yall

        for ii in range(self.multiupdate):
            t1 = time.time()
            if disp:
                print(f"update number {ii+1}")

            xnext, metrictemp = run_multi_opt(
                krigtemp,
                self.moboInfo,
                ypartemp,
                krigconstlist=self.krigconstlist,
                cheapconstlist=self.cheapconstlist,
                pool=pool)

            bound = np.vstack((-np.ones([1, n_dv]), np.ones([1, n_dv])))

            for jj, krig in enumerate(krigtemp):
                yprednext[jj], sprednext[jj] = krig.predict(
                    xnext, ['pred', 's'])
                krig.KrigInfo['X'] = np.vstack((krig.KrigInfo['X'], xnext))
                krig.KrigInfo['y'] = np.vstack(
                    (krig.KrigInfo['y'], yprednext[jj]))
                krig.standardize()
                krig.KrigInfo["F"] = compute_regression_mat(
                    krig.KrigInfo["idx"], krig.KrigInfo["X_norm"], bound,
                    np.ones([n_dv]))
                krig.KrigInfo = likelihood(krig.KrigInfo['Theta'],
                                           krig.KrigInfo,
                                           mode='all',
                                           trainvar=krig.trainvar)

            xalltemp[ii, :] = xnext[:]
            yalltemp[ii, :] = yprednext[:]
            salltemp[ii, :] = sprednext[:]
            metricall[ii, :] = metrictemp

            yall = np.vstack((yall, yprednext))
            ypartemp, _ = searchpareto.paretopoint(yall)

            if disp:
                print(f"time: {time.time() - t1:.2f} s")

        return xalltemp, yalltemp, salltemp, metricall