示例#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 kpcaopt(self, w, KPCAkernel, orig_X, out='default'):
        # Calculate PLS coeff
        if KPCAkernel != "gaussian" and KPCAkernel != "precomputed":
            if KPCAkernel.lower() == 'poly' or KPCAkernel.lower(
            ) == 'polynomial':
                _drm = drm(self.n_princomp,
                           kernel='poly',
                           gamma=10**w[0],
                           coef0=10**w[1],
                           degree=np.round(w[2]))
            elif KPCAkernel.lower() == 'sigmoid':
                _drm = drm(self.n_princomp,
                           kernel='sigmoid',
                           gamma=10**w[0],
                           coef0=10**w[1])
            elif KPCAkernel.lower() == 'rbf':
                _drm = drm(self.n_princomp, kernel='rbf', gamma=10**w[0])
            elif KPCAkernel.lower() == 'linear' or KPCAkernel.lower(
            ) == 'cosine':
                _drm = drm(self.n_princomp)

            self.KrigInfo["nvar"] = self.n_princomp
            if self.standardization is True:
                self.KrigInfo["X_norm"] = deepcopy(orig_X)
                _drm.fit(self.KrigInfo["X_norm"].copy())
                transformed = _drm.transform(self.KrigInfo["X_norm"].copy())
                self.KrigInfo["lb2"] = (
                    np.min(transformed,
                           axis=0))  # Create lowerbound for transformed X
                self.KrigInfo["ub2"] = (
                    np.max(transformed,
                           axis=0))  # Create upperbound for transformed X
                self.KrigInfo["X_norm"] = standardize(
                    transformed,
                    self.KrigInfo['y'],
                    type=self.standtype.lower(),
                    range=np.vstack(
                        (self.KrigInfo["lb2"], self.KrigInfo["ub2"])))
                self.KrigInfo['idx'] = polytruncation(
                    self.KrigInfo["TrendOrder"], self.KrigInfo["nvar"], 1)
            else:
                self.KrigInfo["X"] = deepcopy(orig_X)
                _drm.fit(self.KrigInfo["X"].copy())
                transformed = _drm.transform(self.KrigInfo["X"].copy())
                self.KrigInfo["X"] = transformed
                self.KrigInfo['idx'] = polytruncation(
                    self.KrigInfo["TrendOrder"], self.KrigInfo["nvar"], 1)

        else:
            n_features = np.size(orig_X, 1)
            self.KrigInfo["nvar"] = self.n_princomp
            _drm = drm(self.n_princomp, kernel='precomputed')
            k_mat = customkernel(orig_X,
                                 orig_X,
                                 w,
                                 n_features,
                                 type='gaussian')
            if self.standardization is True:
                self.KrigInfo["X_norm"] = deepcopy(orig_X)
                transformed = _drm.fit_transform(k_mat)
                self.KrigInfo["lb2"] = (
                    np.min(transformed,
                           axis=0))  # Create lowerbound for transformed X
                self.KrigInfo["ub2"] = (
                    np.max(transformed,
                           axis=0))  # Create upperbound for transformed X
                self.KrigInfo["X_norm"] = standardize(
                    transformed,
                    self.KrigInfo['y'],
                    type=self.standtype.lower(),
                    range=np.vstack(
                        (self.KrigInfo["lb2"], self.KrigInfo["ub2"])))
                self.KrigInfo['idx'] = polytruncation(
                    self.KrigInfo["TrendOrder"], self.KrigInfo["nvar"], 1)
            else:
                pass

        if out == 'default':
            self.KrigInfo["kernel"] = ["iso_gaussian"]
            Kriging.train(self, disp=False)
        else:
            self.KrigInfo["kernel"] = ["gaussian"]
            Kriging.train(self, disp=False, pre_theta=self.KrigInfo['Theta'])

        loocverr, _ = Kriging.loocvcalc(self, drm=_drm)

        if out == 'default':
            return loocverr
        elif out == 'all':
            return _drm, loocverr
示例#3
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