Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 50 additions & 30 deletions gwr/gwr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ class MGWR(GWR):
TODO

"""
def __init__(self, coords, y, X, bws, XB, err, family=Gaussian(), offset=None,
def __init__(self, coords, y, X, selector, family=Gaussian(), offset=None,
sigma2_v1=False, kernel='bisquare', fixed=False, constant=True,
dmat=None, sorted_dmat=None, spherical=False):
"""
Expand All @@ -1250,11 +1250,9 @@ def __init__(self, coords, y, X, bws, XB, err, family=Gaussian(), offset=None,
self.coords = coords
self.y = y
self.X = X
self.XB = XB
self.err = err
self.bws = bws
self.family = family
self.offset = offset
self.selector = selector
self.sigma2_v1 = sigma2_v1
self.kernel = kernel
self.fixed = fixed
Expand All @@ -1263,7 +1261,7 @@ def __init__(self, coords, y, X, bws, XB, err, family=Gaussian(), offset=None,
self.sorted_dmat = sorted_dmat
self.spherical = spherical
if constant:
self.X = USER.check_constant(self.X)
self.X = USER.check_constant(self.X)

def fit(self, ini_params=None, tol=1.0e-5, max_iter=20, solve='iwls'):
"""
Expand All @@ -1286,24 +1284,11 @@ def fit(self, ini_params=None, tol=1.0e-5, max_iter=20, solve='iwls'):
'iwls' = iteratively (re)weighted least squares (default)

"""
params = np.zeros_like(self.X)
err = self.err
S = []
SE = []
Ws = []
for i, bw in enumerate(self.bws):
W = self._build_W(self.fixed, self.kernel, self.coords, bw)
Ws.append(W)
X = self.X[:,i].reshape((-1,1))
y = self.XB[:,i].reshape((-1,1)) + err
model = GWR(self.coords, y, X, bw, self.family, self.offset,
self.sigma2_v1, self.kernel, self.fixed, constant=False)
results = model.fit(ini_params, tol, max_iter, solve)
S.append(results.S)
params[:,i] = results.params.flatten()
SE.append(results.bse)
err = results.resid_response.reshape((-1,1))
return MGWRResults(self, params, S, SE, Ws)
S = self.selector.S
R = self.selector.R
params = self.selector.est

return MGWRResults(self, params, S, R)

class MGWRResults(object):
"""
Expand Down Expand Up @@ -1344,7 +1329,7 @@ class MGWRResults(object):
TODO

"""
def __init__(self, model, params, S, SE, Ws):
def __init__(self, model, params, S, R):
"""
Initialize class
"""
Expand All @@ -1353,19 +1338,54 @@ def __init__(self, model, params, S, SE, Ws):
self.X = model.X
self.y = model.y
self.S = S
self.SE = SE
self.Ws = Ws
self.R = R
self.n = self.y.shape[0]
self._cache = {}

@cache_readonly
def predy(self):
return np.sum(np.multiply(self.params, self.X), axis=1).reshape((-1,1))
return np.dot(self.S,self.y)

@cache_readonly
def resid_response(self):
return (self.y - self.predy).reshape((-1,1))
return (self.y - self.predy).reshape(-1)

@cache_readonly
def resid_ss(self):
u = self.resid_response.flatten()
return np.dot(u, u.T)
return np.sum(self.resid_response**2)

@cache_readonly
def tr_S(self):
return np.trace(self.S)

@cache_readonly
def sigma2(self):
return self.resid_ss / (self.n - self.tr_S)

@cache_readonly
def aicc(self):
n = self.n
tr_S = self.tr_S
aicc = n*np.log(self.sigma2) + n*np.log(2*np.pi) + n*(n+tr_S)/(n-tr_S-2.0)
return aicc

@cache_readonly
def ENPj(self):
k = self.params.shape[1]
ENPj = np.zeros(k)
for j in range(k):
Rj = self.R[:,:,j]
ENPj[j] = np.trace(Rj)
return ENPj

@cache_readonly
def bse(self):
n = self.n
k = self.params.shape[1]
bse = np.zeros((n,k))
for j in range(k):
Rj = self.R[:,:,j]
Cj = Rj/self.X[:,j].reshape(-1,1)
bse[:,j] = np.sqrt(np.diag(np.dot(Cj, Cj.T)*self.sigma2))

return bse
65 changes: 25 additions & 40 deletions gwr/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,9 @@ def equal_interval(l_bound, u_bound, interval, function, int_score=False):

return opt_val, opt_score, output

MGWR_BW_Result = namedtuple('MGWR_BW_RESULT', ['bws_','bw_trace', 'kernel_values', 'scores',
'partial_predictions','model_residuals_',
'partial_residuals_',
'objective_functions',
'hat_matrix'])
MGWR_BW_Result = namedtuple('MGWR_BW_RESULT', ['bws_','bw_trace', 'scores',
'parameter_estimates','model_residuals',
'hat_matrix','covariate_specific_hat_matrices'])

def multi_bw(init, y, X, n, k, family, tol, max_iter, rss_score,
gwr_func, bw_func, sel_func):
Expand All @@ -170,18 +168,15 @@ def multi_bw(init, y, X, n, k, family, tol, max_iter, rss_score,
model = GLM(y, X, family=family, constant=False).fit()
err = model.resid_response.reshape((-1,1))
est = np.repeat(model.params.T, n, axis=0)

R = np.zeros((n,n,k))
hat_matrix = optim_model.S
for i in range(k):
temp_vec = np.zeros((1,k))
temp_vec[:,i] = 1.0
for j in range(n):
Wj = np.diag(optim_model.W[j])
XtW = np.dot(X.T, Wj)
XtWX_inv = np.linalg.inv(np.dot(XtW, X))
P = np.dot(XtWX_inv, XtW)
R[j,:,i] = np.dot((X[j,i] * temp_vec), P)

for j in range(k):
for i in range(n):
wi = optim_model.W[i].reshape(-1,1)
xT = (X * wi).T
P = np.dot(np.linalg.inv(np.dot(xT, X)), xT)
R[i,:,j] = X[i,j]*P[j]

XB = np.multiply(est, X)
if rss_score:
Expand All @@ -192,7 +187,6 @@ def multi_bw(init, y, X, n, k, family, tol, max_iter, rss_score,
BWs = []
VALs = []
FUNCs = []
Aj = np.zeros((n,n))

try:
from tqdm import tqdm #if they have it, let users have a progress bar
Expand All @@ -208,45 +202,36 @@ def tqdm(x): #otherwise, just passthrough the range
ests = np.zeros_like(X)
f_XB = XB.copy()
f_err = err.copy()
for i in range(k):
temp_y = XB[:,i].reshape((-1,1))

for j in range(k):
temp_y = XB[:,j].reshape((-1,1))
temp_y = temp_y + err
temp_X = X[:,i].reshape((-1,1))
temp_X = X[:,j].reshape((-1,1))
bw_class = bw_func(temp_y, temp_X)
funcs.append(bw_class._functions)
bw = sel_func(bw_class)
optim_model = gwr_func(temp_y, temp_X, bw)

for j in range(n):
Wj = np.diag(optim_model.W[j])
XtW = np.dot(temp_X.T, Wj)
XtWX_inv = np.linalg.inv(np.dot(XtW, temp_X))
P = np.dot(XtWX_inv, XtW)
Aj[j,:] = temp_X[j,:] * P

new_R = R.copy()
new_R[:,:,i] = Aj - np.dot(Aj, S) + np.dot(Aj, R[:,:,i])
new_S = S - R[:,:,i] + new_R[:,:,i]

R = new_R.copy()
S = new_S.copy()
Aj = optim_model.S
new_Rj = Aj - np.dot(Aj, S) + np.dot(Aj, R[:,:,j])
S = S - R[:,:,j] + new_Rj
R[:,:,j] = new_Rj

err = optim_model.resid_response.reshape((-1,1))
est = optim_model.params.reshape((-1,))

new_XB[:,i] = np.multiply(est, temp_X.reshape((-1,)))
new_XB[:,j] = optim_model.predy.reshape(-1)
bws.append(copy.deepcopy(bw))
ests[:,i] = est
ests[:,j] = est
vals.append(bw_class.bw[1])
current_partial_residuals.append(err.copy())

predy = np.sum(np.multiply(ests, X), axis=1).reshape((-1,1))
num = np.sum((new_XB - XB)**2)/n
den = np.sum(np.sum(new_XB, axis=1)**2)
score = (num/den)**0.5
XB = new_XB

if rss_score:
predy = np.sum(np.multiply(ests, X), axis=1).reshape((-1,1))
new_rss = np.sum((y - predy)**2)
score = np.abs((new_rss - rss)/new_rss)
rss = new_rss
Expand All @@ -259,6 +244,6 @@ def tqdm(x): #otherwise, just passthrough the range
break

opt_bws = BWs[-1]
return MGWR_BW_Result(opt_bws, np.array(BWs), np.array(VALs),
np.array(scores), f_XB, f_err,
current_partial_residuals, FUNCs, S)
return MGWR_BW_Result(opt_bws, np.array(BWs),
np.array(scores), ests,
err, S, R)
7 changes: 4 additions & 3 deletions gwr/sel_bw.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,10 @@ def search(self, search_method='golden_section', criterion='AICc',

if self.multi:
self._mbw()
self.XB = self.bw[4]
self.err = self.bw[5]
self.S = self.bw[-1]
self.est = self.bw[3] #params
self.err = self.bw[4] #residual
self.S = self.bw[-2] #(n,n)
self.R = self.bw[-1] #(n,n,k)
else:
self._bw()

Expand Down
5 changes: 3 additions & 2 deletions gwr/tests/test_gwr.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ def test_GS_NN(self):
np.testing.assert_allclose(cooksD, rslt.cooksD, rtol=1e-00)

def test_MGWR(self):
model = MGWR(self.coords, self.y, self.X, [157.0, 65.0, 52.0],
XB=self.XB, err=self.err, constant=False)
selector = Sel_BW(self.coords, self.y, self.X,multi=True)

model = MGWR(self.coords, self.y, self.X, selector=selector, constant=False)
rslt = model.fit()

np.testing.assert_allclose(rslt.predy, self.MGWR['predy'], atol=1e-07)
Expand Down
4 changes: 2 additions & 2 deletions gwr/tests/test_sel_bw.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def setUp(self):
black = np.array(data.by_col('PctBlack')).reshape((-1,1))
self.X = np.hstack([rural, pov, black])
XB_path = os.path.join(os.path.dirname(__file__),'XB.p')
self.XB = pk.load(open(XB_path, 'r'))
self.XB = pk.load(open(XB_path,'rb'))
err_path = os.path.join(os.path.dirname(__file__),'err.p')
self.err = pk.load(open(err_path, 'r'))
self.err = pk.load(open(err_path,'rb'))

def test_golden_fixed_AICc(self):
bw1 = 211020.83
Expand Down