예제 #1
0
def bip_s_resid(x, beta_hat,p,q):
    phi_hat = np.array(beta_hat[:p])
    theta_hat = np.array(beta_hat[p:])
    
    N = len(x)
    r = max(p,q)
    a_bip = np.zeros(N)
    x_sc = rsp.m_scale(x)
    kap2 = 0.8724286
    
    xArr = lambda ii: x[ii-1::-1] if ii-p-1 < 0 else x[ii-1:ii-p-1:-1]
    aqArr = lambda ii: a_bip[ii-1::-1] if ii-q-1 < 0 else a_bip[ii-1:ii-q-1:-1]
    apArr = lambda ii: a_bip[ii-1::-1] if ii-p-1 < 0 else a_bip[ii-1:ii-p-1:-1]
    
    if np.sum(np.abs(np.roots(-1*np.array([-1, *phi_hat])))>1) \
        or np.sum(np.abs(np.roots(-1*np.array([-1, *theta_hat])))>1):
        
        sigma_hat = x_sc
    else:
        # MA infinity approximation to compute scale used in eta function
        lamb = rsp.ma_infinity(phi_hat, -theta_hat, 100)
        
        # Scale used in eta function
        sigma_hat = np.sqrt(x_sc**2 /(1+kap2*np.sum(lamb**2)))
        
    if r == 0:
        a_sc_bip = x_sc
        a_bip = np.array(x)
        return a_bip
    else:
        if np.sum(np.abs(np.roots(-1*np.array([-1, *phi_hat])))>1) \
        or np.sum(np.abs(np.roots(-1*np.array([-1, *theta_hat])))>1):
            a_bip_sc = 10**10
        else:    
            if p>=1 and q>=1:
                # ARMA model
                for ii in range(r,N):
                    # BIP-ARMA residuals
                    a_bip[ii] = x[ii] -phi_hat@(xArr(ii)-apArr(ii)+sigma_hat*rsp.eta(apArr(ii)/sigma_hat))\
                    +theta_hat@(sigma_hat*rsp.eta(aqArr(ii)/sigma_hat))
            elif p==0 and q>=1:
                # MA model
                for ii in range(r,N):
                    # BIP-MA residuals
                    a_bip[ii] = x[ii]+theta_hat@(sigma_hat*rsp.eta(aqArr(ii)/sigma_hat))
            elif p>=1 and q==0:
                # AR model
                for ii in range(r,N):
                    # BIP-AR residuals
                    a_bip[ii] = x[ii] - phi_hat@(xArr(ii)-apArr(ii)+sigma_hat*rsp.eta(apArr(ii)/sigma_hat))

        a_bip_sc = rsp.m_scale(a_bip[p:])

        # cleaned signal
        x_filt = np.array(x)
        
        for ii in range(p,N):
            x_filt[ii] = x[ii]-a_bip[ii]+sigma_hat*rsp.eta(a_bip[ii]/sigma_hat)
            
        return a_bip, x_filt
def arma_est_bip_s(x, p, q, meth='SLSQP'):
    if p == 0 and q == 0:
        inno_scale = rsp.m_scale(x)
        print('at least p or q has to be non-zero')
    if len(x) <= p + q:
        raise ValueError(
            'There are too many parameters to estimate for chosen data size. Reduce model order or use a larger data set.'
        )

    # Robust starting point by BIP AR-S approximation
    beta_initial = rsp.robust_starting_point(x, p, q)[0]
    '''
    if len(beta_initial) != 1:
        # optimize on residuals
        F = lambda beta: rsp.arma_s_resid_sc(x, beta, p, q)[1] 
        
        F_bip = lambda beta: rsp.bip_s_resid_sc(x, beta, p, q)[2]
    else:
        # optimize directly on scale
        F = lambda beta: rsp.arma_s_resid_sc(x, beta, p, q)[0] 

        F_bip = lambda beta: rsp.bip_s_resid_sc(x, beta, p, q)[0] 
    
    beta_arma = lsq(F, beta_initial,xtol=5*1e-7,ftol=5*1e-7,method='lm')['x']
    # different from matlab print('beta_arma: ', beta_arma)
    # but has lower residuals than matlab print('F(beta_arma): ',rsp.arma_s_resid_sc(x,beta_arma,p,q))
    beta_bip = lsq(F_bip, beta_initial,xtol=5*1e-7,ftol=5*1e-7,method='lm')['x']
    '''
    F = lambda beta: rsp.arma_s_resid_sc(x, beta, p, q)

    F_bip = lambda beta: rsp.bip_s_resid_sc(x, beta, p, q)[0]

    beta_arma = minimize(F, beta_initial, method=meth)['x']

    beta_bip = minimize(F_bip, beta_initial, method=meth)['x']

    a_sc = rsp.arma_s_resid_sc(x, beta_arma, p,
                               q)  # innovations m-scale for ARMA model

    a_bip_sc, x_filt, _ = rsp.bip_s_resid_sc(
        x, beta_bip, p, q)  # innovations m-scale for BIP-ARMA model

    # final parameter estimate uses the model that provides smaller
    # m-scale
    beta_hat = beta_arma if a_sc < a_bip_sc else beta_bip

    # final m-scale
    a_m_sc = min(a_sc, a_bip_sc)

    results = {
        'ar_coeffs': -1 * beta_hat[:p],
        'ma_coeffs': -1 * beta_hat[p:],
        'inno_scale': a_m_sc,
        'cleaned_signal': x_filt,
        'ar_coeffs_init': -1 * beta_initial[:p],
        'ma_coeffs_init': -1 * beta_initial[p:]
    }

    return results
예제 #3
0
def arma_s_resid(x, beta_hat, p, q):
    phi_hat = np.array(beta_hat[:p])
    theta_hat = np.array(beta_hat[p:])

    N = len(x)
    r = max(p, q)
    a = np.zeros(N)
    x_sc = rsp.m_scale(x)

    if r == 0:
        a = np.array(x)
        return a, x_sc
    elif np.sum(np.abs(np.roots(-1*np.array([-1, *phi_hat])))>1) \
        or np.sum(np.abs(np.roots(-1*np.array([-1, *theta_hat])))>1):

        a_sc = 10**10
        return a, rsp.m_scale(a[p:])
    elif p >= 1 and q >= 1:
        # ARMA residuals
        xArr = lambda ii: x[ii - 1::-1] if ii - p - 1 < 0 else x[ii - 1:ii - p
                                                                 - 1:-1]
        aArr = lambda ii: a[ii - 1::-1] if ii - q - 1 < 0 else a[ii - 1:ii - q
                                                                 - 1:-1]

        for ii in range(r, N):
            a[ii] = x[ii] - phi_hat @ xArr(ii) + theta_hat @ aArr(ii)

        return a, rsp.m_scale(a[p:])
    elif p == 0 and q >= 0:
        # MA residuals
        aArr = lambda ii: a[ii - 1::-1] if ii - q - 1 < 0 else a[ii - 1:ii - q
                                                                 - 1:-1]

        for ii in range(r, N):
            a[ii] = x[ii] + theta_hat @ aArr(ii)
    elif q == 0 and p >= 0:
        # AR residuals
        xArr = lambda ii: x[ii - 1::-1] if ii - p - 1 < 0 else x[ii - 1:ii - p
                                                                 - 1:-1]

        for ii in range(r, N):
            a[ii] = x[ii] - phi_hat @ xArr(ii)

    return a, rsp.m_scale(a[p:])
예제 #4
0
def arma_s_resid_sc(x, beta_hat, p, q):

    phi_hat = beta_hat[:p]
    theta_hat = beta_hat[p:]

    N = len(x)
    r = max(p, q)
    a = np.zeros(N)  # will contain residuals
    x_sc = rsp.m_scale(x)

    poles = lambda xc: np.sum(np.abs(np.roots(-1 * np.array([-1, *xc]))) > 1)

    if r == 0:
        a_sc = np.array(x_sc)
        a = np.array(x)
    else:
        if poles(phi_hat) or poles(theta_hat):
            return 10**10
        else:
            xArr = lambda ii: x[ii - 1::-1] if ii - p - 1 < 0 else x[
                ii - 1:ii - p - 1:-1]
            aArr = lambda ii: a[ii - 1::-1] if ii - q - 1 < 0 else a[
                ii - 1:ii - q - 1:-1]

            if p >= 1 and q >= 1:
                # ARMA Models
                for ii in range(r, N):
                    # ARMA residuals
                    a[ii] = x[ii] - np.sum(
                        phi_hat * xArr(ii)) + theta_hat @ aArr(ii)
            elif p == 0 and q >= 1:
                # MA model
                for ii in range(r, N):
                    a[ii] = x[ii] + theta_hat @ aArr(ii)
            elif p >= 1 and q == 0:
                # AR model
                for ii in range(r, N):
                    a[ii] = x[ii] - phi_hat @ xArr(ii)  # AR residuals
    return rsp.m_scale(a[p:])
예제 #5
0
def arma_est_bip_mm(x,p,q):
    bip_s_est = rsp.arma_est_bip_s(x,p,q)
    
    beta_hat_s = np.array([*bip_s_est['ar_coeffs'], *bip_s_est['ma_coeffs']])

    N = len(x)
    
    F_mm = lambda beta: 1/(N-p)*rsp.muler_rho2(rsp.arma_s_resid(x,beta,p,q)[0])
    
    F_bip_mm = lambda beta: 1/(N-p)*rsp.muler_rho2(rsp.bip_s_resid(x,beta,p,q)[0])
    
    beta_arma_mm = lsq(F_mm, -beta_hat_s,xtol=5*1e-7,ftol=5*1e-7,method='lm')['x']
    
    beta_bip_mm = lsq(F_bip_mm, -beta_hat_s,xtol=5*1e-7,ftol=5*1e-7,method='lm')['x']

    a = rsp.arma_s_resid(x, beta_arma_mm, p, q)[0]
    
    a_sc = rsp.m_scale(a) # innovations m-scale for ARMA model
    
    a_bip = rsp.bip_s_resid(x, beta_bip_mm, p, q)[0]
    
    a_bip_sc = rsp.m_scale(a_bip) # innovations m-scale for BIP-ARMA model

    # final parameter estimate uses the model that provides smallest m_scale
    beta_hat = beta_arma_mm if a_sc<a_bip_sc else beta_bip_mm
    
    # final m-scale
    a_m_sc = min(a_sc, a_bip_sc)
    
    # Output the results
    
    results = {'ar_coeffs': -beta_hat[:p],
               'ma_coeffs': -beta_hat[p:],
               'inno_scale': a_m_sc,
               'cleaned_signal': bip_s_est['cleaned_signal'],
               'ar_coeffs_init': bip_s_est['ar_coeffs'],
               'ma_coeffs_init': bip_s_est['ma_coeffs']}
    
    return results
예제 #6
0
def bip_resid(xx, beta_hatx, p, q):
    x = np.array(xx)
    beta_hat = np.array(beta_hatx)

    phi_hat = beta_hat[:p] if p > 0 else []
    theta_hat = beta_hat[p:] if q > 0 else []

    N = len(x)
    r = max(p, q)
    a_bip = np.zeros(N)
    x_sc = rsp.m_scale(x)
    kap2 = 0.8724286

    if np.sum(np.abs(np.roots(np.array([1, *phi_hat*-1])))>1)\
    or np.sum(np.abs(np.roots(np.array([1, *theta_hat])))>1):
        sigma_hat = x_sc
        a_bip = np.array(x)
    else:
        lamb = rsp.ma_infinity(phi_hat, -theta_hat, 100)
        sigma_hat = np.sqrt(x_sc**2 / (1 + kap2 * np.sum(lamb**2)))

        if r == 0:
            a_bip = np.array(x)
        else:
            if p >= 1 and q >= 1:
                # ARMA Models
                for ii in range(r, N):
                    # BIP-ARMA residuals
                    xArr = x[ii - 1::-1] if ii - p - 1 < 0 else x[ii - 1:ii -
                                                                  p - 1:-1]
                    abArr = a_bip[ii -
                                  1::-1] if ii - p - 1 < 0 else a_bip[ii -
                                                                      1:ii -
                                                                      p - 1:-1]
                    aqArr = a_bip[ii -
                                  1::-1] if ii - q - 1 < 0 else a_bip[ii -
                                                                      1:ii -
                                                                      q - 1:-1]
                    a_bip[ii] = x[ii] - phi_hat @ (
                        xArr - abArr + sigma_hat * rsp.eta(abArr / sigma_hat)
                    ) + sigma_hat * theta_hat @ rsp.eta(aqArr / sigma_hat)
                    r += 1
            elif p == 0 and q >= 1:
                # MA models
                for ii in range(r, N):
                    # BIP-MA residuals
                    aArr = a_bip[ii -
                                 1::-1] if ii - q - 1 < 0 else a_bip[ii -
                                                                     1:ii - q -
                                                                     1:-1]
                    a_bip[ii] = x[ii] + theta_init * sigma_hat * rsp.eta(
                        aArr / sigma_hat)
            elif p >= 1 and q == 0:
                # AR models
                for ii in range(r, N):
                    # BIP-AR residuals
                    xArr = x[ii - 1::-1] if ii - p - 1 < 0 else x[ii - 1:ii -
                                                                  p - 1:-1]
                    aArr = a_bip[ii -
                                 1::-1] if ii - p - 1 < 0 else a_bip[ii -
                                                                     1:ii - p -
                                                                     1:-1]
                    a_bip[ii] = x[ii] + phi_hat @ (
                        xArr - aArr) + sigma_hat * rsp.eta(aArr / sigma_hat)

    return a_bip[p:]
예제 #7
0
def ar_est_bip_s(xxx, P):
    '''
    Inputs:
    x   : 1darray, dtype=float. data
    P   : scalar. Autoregressive order
    '''
    x = np.array(xxx)
    N = len(x)
    kap2 = 0.8724286
    phi_grid = np.arange(-.99,.991,.05) # coarse grid search
    fine_grid= np.arange(-.99,.991,.001) # finer grid via polynomial interpolation
    a_bip_sc = np.zeros([len(phi_grid)]) # residual scale for BIP-AR on finer grid 
    a_sc = np.zeros(len(phi_grid)) # residual scale for AR on finer grid

    # The following was introduced so as not to predict based
    # on highly contaminated data in the
    # first few samples.

    x_tran = x[:min(10,int(np.floor(N/2)))]
    sig_x_tran = np.median(np.abs(x-np.median(x)))

    x_tran[np.abs(x_tran)>3*sig_x_tran] = 3*sig_x_tran*np.sign(x_tran[np.abs(x_tran)>3*sig_x_tran])
    x[1:min(10,int(np.floor(N/2)))] = x_tran[1:min(10,int(np.floor(N/2)))]
    
    if P==0:
        # AR order = 0
        phi_hat = [] # return empty AR-parameter vector
        a_scale_final = rsp.m_scale(x)
        return phi_hat, a_scale_final
    elif P==1:
        x_filt, phi_hat, a_scale_final = rsp.bip_ar1_s(x,N,phi_grid,fine_grid,kap2)
    elif P>1:
        phi_hat = np.zeros((P,P))
        x_filt, phi_hat[0,0], a_scale_final = rsp.bip_ar1_s(x,N,phi_grid,fine_grid,kap2)

        npa = lambda x: np.array(x)

        for p in range(1,P):
            for mm in range(len(phi_grid)):
                for pp in range(p):
                    phi_hat[p,pp] =\
                    phi_hat[p-1,pp]-phi_grid[mm]*phi_hat[p-1,p-pp-1]
                predictor_coeffs =\
                np.array([*phi_hat[p,:p], phi_grid[mm]])

                M = len(predictor_coeffs)

                if np.mean(np.abs(np.roots([1, *predictor_coeffs]))<1)==1:
                    lambd = rsp.ma_infinity(predictor_coeffs, 0, 100)
                    sigma_hat = a_scale_final[0]/np.sqrt(1+kap2*np.sum(lambd**2))
                else:
                    sigma_hat = 1.483*np.median(np.abs(x-np.median(x)))
                a = np.zeros(len(x))
                a2= np.zeros(len(x))

                for ii in range(p+1,N):
                    xArr = x[ii-1::-1] if ii-M-1 <0 else x[ii-1:ii-M-1:-1]
                    aArr = a[ii-1::-1] if ii-M-1 <0 else a[ii-1:ii-M-1:-1]

                    a[ii] = compA(x[ii],predictor_coeffs,xArr,aArr,sigma_hat)

                    a2[ii] = x[ii] - predictor_coeffs@xArr
                a_bip_sc[mm] = rsp.m_scale(a[p:]) # residual scale for BIP-AR
                a_sc[mm] = rsp.m_scale(a2[p:]) # residual scale for AR
            # tau-estimate under the BIP-AR(p) and AR(p)
            phi, phi2, temp, temp2, ind_max, ind_max2 = tauEstim(phi_grid, a_bip_sc, fine_grid, a_sc)

            # final estimate minimizes the residual scale of the two
            if temp2<temp:
                ind_max=ind_max2
                temp=temp2
            for pp in range(p):
                phi_hat[p,pp] = phi_hat[p-1,pp]-fine_grid[ind_max]*phi_hat[p-1,p-pp-1]
            phi_hat[p,p] = fine_grid[ind_max]

            # final AR(p) tau-scale-estimate depending on phi_hat(p,p)
            if np.mean(np.abs(np.roots([1,*phi_hat[p,:]]))<1) == 1:
                lambd = rsp.ma_infinity(phi_hat[p,:], 0, 100)
                #sigma used for bip-model
                sigma_hat = a_scale_final[0]/np.sqrt(1+kap2*np.sum(lambd**2))
            else:
                sigma_hat = 1.483*np.median(np.abs(x-np.median(x)))

            x_filt = np.zeros(len(x))

            for ii in range(p+1,N):
                xArr = x[ii-1::-1] if ii-M-1 <0 else x[ii-1:ii-M-1:-1]
                aArr = a[ii-1::-1] if ii-M-1 <0 else a[ii-1:ii-M-1:-1]

                a[ii] = x[ii]-phi_hat[p,:p+1]@(xArr-aArr\
                +sigma_hat*rsp.eta(aArr/sigma_hat))

                a2[ii]=x[ii]-phi_hat[p,:p+1]@xArr

            if temp2>temp:
                a_scale_final.append(rsp.m_scale(a[p:]))
            else:
                a_scale_final.append(rsp.m_scale(a2[p:]))

        phi_hat = phi_hat[p,:] # BIP-AR(P) tau-estimate        

        for ii in range(p,N):
            x_filt[ii] = x[ii] - a[ii] + sigma_hat*rsp.eta(a[ii]/sigma_hat)

    return phi_hat, x_filt, a_scale_final
예제 #8
0
def bip_s_resid_sc(x, beta_hat, p, q):

    phi_hat = np.array(beta_hat[:p])  # [] if p=0, MA case

    theta_hat = np.array(beta_hat[p:])  # [] if p=length(beta_hat), AR case

    #x = np.array(x)
    N = len(x)
    r = max(p, q)

    a_bip = np.zeros(N)

    x_sc = rsp.m_scale(x)

    kap2 = 0.8724286

    poles = lambda x: np.sum(np.abs(np.roots(-1 * np.array([-1, *x]))) > 1)

    if poles(phi_hat) or poles(theta_hat):
        sigma_hat = x_sc
    else:
        lamb = rsp.ma_infinity(
            phi_hat, -1 * theta_hat, 100
        )  # MA infinity approximation to compute scale used in eta function
        sigma_hat = np.sqrt(x_sc**2 /
                            (1 + kap2 * np.sum(lamb**2)))  # scale used in eta

    if r == 0:
        a_sc_bip = x_sc
        a_bip = np.array(x)
    else:
        if poles(phi_hat) or poles(theta_hat):
            return 10**10, a_bip, x[p:]
        else:
            xArr = lambda ii: x[ii - 1::-1] if ii - p - 1 < 0 else x[
                ii - 1:ii - p - 1:-1]
            aArr = lambda ii: a_bip[ii-1::-1] if ii-q-1 < 0 \
            else a_bip[ii-1:ii-q-1:-1]
            apArr = lambda ii: a_bip[ii-1::-1] if ii-p-1 < 0 \
            else a_bip[ii-1:ii-p-1:-1]
            if p >= 1 and q >= 1:
                # ARMA model
                for ii in range(r, N):
                    # BIP-ARMA residuals
                    a_bip[ii] = x[ii]\
                    -phi_hat@\
                    (xArr(ii)-apArr(ii)+sigma_hat*rsp.eta(apArr(ii)/sigma_hat))+sigma_hat*([email protected](aArr(ii)/sigma_hat))
            elif p == 0 and q >= 1:
                # MA residuals
                for ii in range(r, N):
                    # BIP-MA residuals
                    a_bip[ii] = x[ii] + theta_hat @ (
                        sigma_hat * rsp.eta(aArr(ii) / sigma_hat))
            elif p >= 1 and q == 0:
                # AR Model
                for ii in range(r, N):
                    a_bip[ii] = x[ii]-phi_hat@(xArr(ii)-apArr(ii)\
                    +sigma_hat*rsp.eta(apArr(ii)/sigma_hat))
            a_bip_sc = rsp.m_scale(a_bip[p:])
            x_filt = np.array(x)

            for ii in range(p, N):
                x_filt[ii] = x[ii] - a_bip[ii] + sigma_hat * rsp.eta(
                    a_bip[ii] / sigma_hat)

    return a_bip_sc, x_filt, a_bip[p:]
예제 #9
0
def bip_ar1_s(x, N, phi_grid, fine_grid, kap2):

    a_scale_final = rsp.m_scale(
        x)  # AR(0): residual scale equals observation scale

    # grid search for partial autocorrelations
    a_bip_sc = np.zeros(len(phi_grid))
    a_sc = np.zeros(len(phi_grid))
    for mm in range(len(phi_grid)):
        a = np.zeros(len(x))  # residuals for BIP-AR
        a2 = np.zeros(len(x))  # residuals for AR

        lambd = rsp.ma_infinity(phi_grid[mm], 0, 100)
        sigma_hat = a_scale_final / np.sqrt(
            1 + kap2 * np.sum(lambd**2))  # sigma used for BIP-model
        for ii in range(1, N):
            a[ii] = x[ii]-phi_grid[mm]*\
            (x[ii-1]-a[ii-1]+sigma_hat*rsp.eta(a[ii-1]/sigma_hat)) # residuals for BIP-AR
            a2[ii] = x[ii] - phi_grid[mm] * x[ii - 1]  # residuals for AR

        a_bip_sc[mm] = rsp.m_scale(a[1:])  # tau-scale of residuals for BIP-AR
        a_sc[mm] = rsp.m_scale(a2[1:])  # tau-scale of residuals for AR

    poly_approx = np.polyfit(
        phi_grid, a_bip_sc, 5
    )  # polynomial approximation of tau scale objective function for BIP-AR(1) tau-estimates
    a_interp_scale = np.polyval(
        poly_approx, fine_grid
    )  # interpolation of tau scale objective function for BIP-AR(1) tau-estimates to fine grid
    poly_approx2 = np.polyfit(
        phi_grid, a_sc, 5
    )  # polynomial approximation of  tau scale objective function for AR(1) tau-estimates
    a_interp_scale2 = np.polyval(poly_approx2, fine_grid)

    temp = np.min(a_interp_scale)
    ind_max = np.argmin(a_interp_scale)
    phi = fine_grid[ind_max]  # tau-estimate unter the BIP-AR(1)
    temp2 = np.min(a_interp_scale2)
    ind_max2 = np.argmin(a_interp_scale2)
    phi2 = fine_grid[ind_max2]  # tau-estimate under the AR(1)

    # final estimate maximizes robust likelihood of the two
    if temp2 < temp:
        phi_s = phi2
        temp = temp2
    else:
        phi_s = phi

    phi_hat = phi_s  # final BIP-tau-estimate for AR(1)

    # final AR(1) tau-scale-estimate depending on phi_hat
    lambd = rsp.ma_infinity(phi_hat, 0, 100)
    sigma_hat = a_scale_final / np.sqrt(1 + kap2 * np.sum(lambd**2))
    a = np.zeros(len(x))  # residuals for BIP-AR
    a2 = np.zeros(len(x))  # residuals for AR

    x_filt = np.zeros(len(x))

    for ii in range(1, N):
        a[ii] = x[ii] - phi_hat * (x[ii - 1] - a[ii - 1] +
                                   sigma_hat * rsp.eta(a[ii - 1] / sigma_hat))
        a2[ii] = x[ii] - phi_hat * x[ii - 1]
        x_filt[ii] = x[ii] - a[ii] + sigma_hat * rsp.eta(a[ii] / sigma_hat)

    if temp2 < temp:
        a_scale_final = [a_scale_final, rsp.m_scale(a[1:])]
    else:
        a_scale_final = [a_scale_final, rsp.m_scale(a2[1:])]

    return x_filt, phi_hat, a_scale_final
예제 #10
0
def tau_scale(x):
    b = 0.398545548533895  # E(muler_rho2) under the standard normal distribution
    sigma_m = rsp.m_scale(x)
    return np.sqrt(sigma_m**2 / len(x) * 1 / b *
                   np.sum(rsp.muler_rho2(x / sigma_m)))