def deriv(self, m, v=None): alpha = self.slope sig1, sig2, c = m[0], m[1], m[2:] if self.logSigma: sig1, sig2 = np.exp(sig1), np.exp(sig2) # 2D if self.mesh.dim == 2: X = self.mesh.gridCC[self.actInd, 0] Y = self.mesh.gridCC[self.actInd, 1] if self.normal == 'X': f = polynomial.polyval(Y, c) - X V = polynomial.polyvander(Y, len(c) - 1) elif self.normal == 'Y': f = polynomial.polyval(X, c) - Y V = polynomial.polyvander(X, len(c) - 1) else: raise (Exception("Input for normal = X or Y or Z")) # 3D elif self.mesh.dim == 3: X = self.mesh.gridCC[self.actInd, 0] Y = self.mesh.gridCC[self.actInd, 1] Z = self.mesh.gridCC[self.actInd, 2] if self.normal == 'X': f = (polynomial.polyval2d( Y, Z, c.reshape( (self.order[0] + 1, self.order[1] + 1))) - X) V = polynomial.polyvander2d(Y, Z, self.order) elif self.normal == 'Y': f = (polynomial.polyval2d( X, Z, c.reshape( (self.order[0] + 1, self.order[1] + 1))) - Y) V = polynomial.polyvander2d(X, Z, self.order) elif self.normal == 'Z': f = (polynomial.polyval2d( X, Y, c.reshape( (self.order[0] + 1, self.order[1] + 1))) - Z) V = polynomial.polyvander2d(X, Y, self.order) else: raise (Exception("Input for normal = X or Y or Z")) if self.logSigma: g1 = -(np.arctan(alpha * f) / np.pi + 0.5) * sig1 + sig1 g2 = (np.arctan(alpha * f) / np.pi + 0.5) * sig2 else: g1 = -(np.arctan(alpha * f) / np.pi + 0.5) + 1.0 g2 = (np.arctan(alpha * f) / np.pi + 0.5) g3 = Utils.sdiag(alpha * (sig2 - sig1) / (1. + (alpha * f)**2) / np.pi) * V if v is not None: return sp.csr_matrix(np.c_[g1, g2, g3]) * v return sp.csr_matrix(np.c_[g1, g2, g3])
def deriv(self, m, v=None): alpha = self.slope sig1, sig2, c = m[0], m[1], m[2:] if self.logSigma: sig1, sig2 = np.exp(sig1), np.exp(sig2) # 2D if self.mesh.dim == 2: X = self.mesh.gridCC[self.actInd, 0] Y = self.mesh.gridCC[self.actInd, 1] if self.normal == 'X': f = polynomial.polyval(Y, c) - X V = polynomial.polyvander(Y, len(c)-1) elif self.normal == 'Y': f = polynomial.polyval(X, c) - Y V = polynomial.polyvander(X, len(c)-1) else: raise(Exception("Input for normal = X or Y or Z")) # 3D elif self.mesh.dim == 3: X = self.mesh.gridCC[self.actInd, 0] Y = self.mesh.gridCC[self.actInd, 1] Z = self.mesh.gridCC[self.actInd, 2] if self.normal == 'X': f = (polynomial.polyval2d(Y, Z, c.reshape((self.order[0]+1, self.order[1]+1))) - X) V = polynomial.polyvander2d(Y, Z, self.order) elif self.normal == 'Y': f = (polynomial.polyval2d(X, Z, c.reshape((self.order[0]+1, self.order[1]+1))) - Y) V = polynomial.polyvander2d(X, Z, self.order) elif self.normal == 'Z': f = (polynomial.polyval2d(X, Y, c.reshape((self.order[0]+1, self.order[1]+1))) - Z) V = polynomial.polyvander2d(X, Y, self.order) else: raise(Exception("Input for normal = X or Y or Z")) if self.logSigma: g1 = -(np.arctan(alpha*f)/np.pi + 0.5)*sig1 + sig1 g2 = (np.arctan(alpha*f)/np.pi + 0.5)*sig2 else: g1 = -(np.arctan(alpha*f)/np.pi + 0.5) + 1.0 g2 = (np.arctan(alpha*f)/np.pi + 0.5) g3 = Utils.sdiag(alpha*(sig2-sig1)/(1.+(alpha*f)**2)/np.pi)*V if v is not None: return sp.csr_matrix(np.c_[g1, g2, g3]) * v return sp.csr_matrix(np.c_[g1, g2, g3])
def test_polyvander2d(self): # also tests polyval2d for non-square coefficient array x1, x2, x3 = self.x c = np.random.random((2, 3)) van = poly.polyvander2d(x1, x2, [1, 2]) tgt = poly.polyval2d(x1, x2, c) res = np.dot(van, c.flat) assert_almost_equal(res, tgt) # check shape van = poly.polyvander2d([x1], [x2], [1, 2]) assert_(van.shape == (1, 5, 6))
def test_polyvander2d(self) : # also tests polyval2d for non-square coefficient array x1, x2, x3 = self.x c = np.random.random((2, 3)) van = poly.polyvander2d(x1, x2, [1, 2]) tgt = poly.polyval2d(x1, x2, c) res = np.dot(van, c.flat) assert_almost_equal(res, tgt) # check shape van = poly.polyvander2d([x1], [x2], [1, 2]) assert_(van.shape == (1, 5, 6))
def polyfit2d(x, y, f, deg): """ Returns polynomial coefficients given the values of a function at some point Code courtesy of 'klaus se' on stackoverflow.com/questions/7997152 args: x (numpy.ndarray) : x coordinates y (numpy.ndarray) : y coordinates f (numpy.ndarray) : funtion values deg (iterable of ints) : (max_degree_x, max_degre_y) returns: c (numpy.ndarray) : array of polynomial coefficients for use with numpy's polyval2d routine """ from numpy.polynomial import polynomial import numpy as np x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1,vander.shape[-1])) f = f.reshape((vander.shape[0],)) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg+1)
def _polyfit2d(x, y, f, deg): deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f, rcond=None)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, f, deg): """ Returns polynomial coefficients given the values of a function at some point Code courtesy of 'klaus se' on stackoverflow.com/questions/7997152 args: x (numpy.ndarray) : x coordinates y (numpy.ndarray) : y coordinates f (numpy.ndarray) : funtion values deg (iterable of ints) : (max_degree_x, max_degre_y) returns: c (numpy.ndarray) : array of polynomial coefficients for use with numpy's polyval2d routine """ from numpy.polynomial import polynomial import numpy as np x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg + 1)
def polyfit(x=None, y=None, z=None, w=None, order=None): """Two-dimensional polynomial fit. References: http://stackoverflow.com/questions/7997152/ python-3d-polynomial-surface-fit-order-dependent/7997925#7997925 x: array of coordinates y: array of coordinates (2d only) z: values of these coordinates (1d array as x and y) w: weights order: int for 1d, tuple of 2 values (x-order, y-order) for 2d Return: matrix of coefficents, for the 2d is ok to be fed into polynomial.polyval2d() """ assert z.shape == w.shape if y is None: # note that np.polynomial.polynomial.polyfit want sigmas not variances m = np.polyfit(x, z, order, w=np.sqrt(w)) else: from numpy.polynomial import polynomial x, y = np.meshgrid(np.asarray(x),np.asarray(y), indexing='ij') # TODO: unset x,y,z value if flagged z = z[(w != 0)] x = x[(w != 0)] y = y[(w != 0)] vander = polynomial.polyvander2d(x, y, order) vander = vander.reshape((-1,vander.shape[-1])) z = z.reshape((vander.shape[0],)) m = np.linalg.lstsq(vander, z)[0] order = np.asarray(order) m = m.reshape(order+1) # matrix of coefficents return m
def polyfit(x=None, y=None, z=None, w=None, order=None): """Two-dimensional polynomial fit. References: http://stackoverflow.com/questions/7997152/ python-3d-polynomial-surface-fit-order-dependent/7997925#7997925 x: array of coordinates y: array of coordinates (2d only) z: values of these coordinates (1d array as x and y) w: weights order: int for 1d, tuple of 2 values (x-order, y-order) for 2d Return: matrix of coefficents, for the 2d is ok to be fed into polynomial.polyval2d() """ assert z.shape == w.shape if y is None: # note that np.polynomial.polynomial.polyfit want sigmas not variances m = np.polyfit(x, z, order, w=np.sqrt(w)) else: from numpy.polynomial import polynomial x, y = np.meshgrid(np.asarray(x), np.asarray(y), indexing='ij') # TODO: unset x,y,z value if flagged z = z[(w != 0)] x = x[(w != 0)] y = y[(w != 0)] vander = polynomial.polyvander2d(x, y, order) vander = vander.reshape((-1, vander.shape[-1])) z = z.reshape((vander.shape[0], )) m = np.linalg.lstsq(vander, z)[0] order = np.asarray(order) m = m.reshape(order + 1) # matrix of coefficents return m
def test_polyfit2d(x, y, f, deg=3): x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1,vander.shape[-1])) f = f.reshape((vander.shape[0],)) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg+1)
def polyfit2d(x, y, z, deg): # deg : x and y maximum degrees: [x_deg, y_deg]. x = np.asarray(x) y = np.asarray(y) z = np.asarray(z) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) z = z.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, z)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, z, deg): # deg : x and y maximum degrees: [x_deg, y_deg]. x = np.asarray(x) y = np.asarray(y) z = np.asarray(z) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) z = z.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, z)[0] return c.reshape(deg+1)
def polyfit2d(x, y, f, deg): from numpy.polynomial import polynomial import numpy as np x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, f, deg, mask=None): """ Given coordinates and values, fit a polynomial and return parameters. Parameters ---------- x : 1D array of coordinates y : 1D array of coordinates f : 1D array of expression results / data deg : degree of polynomial to fit Optional Parameters ------------------- mask : 2D array of booleans to exclude factors of full polynomial Returns ------- 2D array with polynomial factors. """ from numpy.polynomial import polynomial import numpy as np x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) try: len(deg) except: deg = [deg, deg] deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) # apply mask to delete terms if desired if mask != None: mask = np.asarray(mask).flatten() vander = vander.transpose()[mask].transpose() # vander = np.delete(vander, (7,8,9), 1) # vander = vander.reshape((-1,vander.shape[-1])) # f = f.reshape((vander.shape[0],)) c = np.linalg.lstsq(vander, f)[0] # insert zeroes to deleted terms if a mask was applied to keep matrix order if mask != None: cc = np.zeros(mask.size) j = 0 for i, item in enumerate(mask): if item: cc[i] = c[j] j += 1 else: cc = c return cc.reshape(deg + 1)
def polyfit2d(x, y, f, deg): ''' Fits a 2d polynomyial of degree deg to the points f where f is the value of point [x,y] ''' x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f, rcond=None)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, f, deg): """ Fit a 2D polynomial """ x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f, rcond=None)[0] return c.reshape(deg + 1)
def __polyfit2dvander(self, order): """ Performs least square optimisation of a 2D polynomial, where a 2D Van der Monde-coefficient matrix is optimised. :param order: x and y order tuple :return: coefficient matrix of shape (x_order + 1, y_order + 1) """ deg = np.asarray([order[0], order[1]]) vander = polynomial.polyvander2d(self.x, self.y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = self.z.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f, rcond=0)[0] #self.c = c.reshape(deg + 1) return c.reshape(deg + 1)
def fit(self, X, y): # ndim = len(self.deg) orders = [n + 1 for n in self.deg] order = np.prod(orders) self._mean_X = np.mean(X, axis=0, keepdims=True) self._mean_y = np.mean(y) X_ = X - self._mean_X y_ = y - self._mean_y x0 = X_[:,0].reshape(-1, 1) x1 = X_[:,1].reshape(-1, 1) xb_all = polyvander2d(x0.ravel(), x1.ravel(), deg=self.deg).reshape(-1, order) # xb has shape (n, order) where order = (deg[0] +1 ) * (deg[1] +1) # x.reshape(-1, 1) # shape = (nx, ny) => Change into shape (n, 1) where n = nx*ny # so that xb is: # xb_all = [np.ones(n, 1), x**1 , x**2, ... , x**deg[0], x**1 * y**1, x**2 * y**1,..., x**deg[0] * y**1,... , x**deg[0]*y**deg[1]] xb = xb_all[:, 1:] # drop the constant term xtx_inv = np.linalg.pinv(xb.T.dot(xb) + self.lam * np.eye(order-1)) # beta = [beta_00, beta_10, beta_20, ..., beta_01 beta_11, beta_21, ..., beta_20, beta_21, beta_22, ...] beta = np.vstack((0., xtx_inv.dot(xb.T).dot(y_.reshape(-1, 1)))).reshape(orders) self.coefficients = beta if self.fulloutput: # beta has shape (deg[0] +1, deg[1] +1) yhat = polyval2d(x0, x1, beta) + self._mean_y # This equal to evaluating the following sum: sum beta_ij * x**i * y**j for i=0,...deg[0], j=0, ..., deg[1] mean_sqared_error = mse(y, yhat) # n = y.size sigma = n * mean_sqared_error / (n-order) # Eq. after Eq. 3.9 on pp 47 in Hastie etal. beta_covariance = xtx_inv * sigma # Eq. 3.10 on pp 47 in Hastie etal. # Is it valid for ridge?? Maybe missing a correction term when lam>0 beta_variance = np.diag(beta_covariance) # .reshape(orders) std_error = np.sqrt(beta_variance) z_score = beta / std_error # 1-alpha confidence interval for beta. Eq 3.14 in Hastie z_alpha = -ss.norm.ppf(self.alpha/2) # inverse of the gaussian cdf function (ss.norm.cdf(-z_alpha)==alpha/2), cdf = cumulative density function beta_low = beta - z_alpha * std_error beta_up = beta + z_alpha * std_error self.stats = fitstats(mse=mean_sqared_error, r2=r_squared(y, yhat), beta_variance=beta_variance, zscore=z_score, beta_low=beta_low, beta_up=beta_up) return self
def _fit_lin_surface(zz, pixelsize): from numpy.polynomial import polynomial xx, yy = wpu.grid_coord(zz, pixelsize) f = zz.flatten() deg = np.array([1, 1]) vander = polynomial.polyvander2d(xx.flatten(), yy.flatten(), deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0],)) c = np.linalg.lstsq(vander, f)[0] print(c) return polynomial.polyval2d(xx, yy, c.reshape(deg+1))
def newtForwardTransform(orders, locations, functionVals): if len(locations.shape)==1: return np.array(poly.polyfit(locations, functionVals, orders[0])) else: if locations.shape[1]==2: V=poly.polyvander2d(locations[:,0], locations[:,1], orders) elif locations.shape[1]==3: V=poly.polyvander3d(locations[:,0],locations[:,1],locations[:,2], orders) elif locations.shape[1]==4: V=newtVander4d(locations,orders) elif locations.shape[1]==5: V=newtVander5d(locations,orders) else: raise NotImplementedError # there's a bad startup joke about this being good enough for the paper. ret, _, _, _=npl.lstsq(V, functionVals, rcond=None) return np.reshape(ret, (np.array(orders)+1).flatten())
def polyfit2d(x, y, z, order=5): """Takes x and y coordinates and their resultant z value, and creates a matrix where element i,j is the coefficient of the desired order polynomial x ** i * y ** j Arguments: x {np.array} -- flat array of x coordinates y {np.array} -- flat array of y coordinates z {np.array} -- flat array of z value at the corresponding x and y value order {int} -- max order of polynomial to work out Returns: np.array -- matrix of polynomial coefficients """ deg = np.array([order, order]) vander = polynomial.polyvander2d(x, y, deg) # vander matrix is matrix where each row i deals with x=x[i] and y=y[i], and each item in the # row has value x ** m * y ** n with (m,n) = (0,0), (0,1), (0,2) ... (1,0), (1,1), (1,2) etc up to (order, order) coeff_mat, _, _, _ = np.linalg.lstsq(vander, z, rcond=None) return coeff_mat.reshape(deg + 1)
def mls3d(data: np.ndarray, p=(0, 0), support_radius=1, deg=(0, 0)): """ трехмерный moving least squares :param data: набор (x,y,z) точек для аппроксимации :param p: опорная точка :param support_radius: радиус влияния :param deg: степень полинома :return: коэффициенты полинома """ B = polyvander2d(data[:, 0], data[:, 1], deg) rj = np.sqrt(np.sum(np.power(data[:, :2] - p[:2], 2), axis=1)) / support_radius W = np.diag(np.where(rj <= 1, 1 - 6 * rj ** 2 + 8 * rj ** 3 - 3 * rj ** 4, 0)) try: c = inv(B.T @ W @ B) @ B.T @ W @ data[:, 2] except np.linalg.LinAlgError: print('f**k') return np.zeros((deg[0] + 1) * (deg[0] + 1)) return c
def polyfit2d(x, y, z, deg): ''' Least-squares fit of a 2D polynomial to data. Uses Vandermonde matrices. Return the coefficients of a polynomial of degree deg that is the least squares fit to the data values z given at points (x,y). Similar to numpy.polynomial.polynomial.polyfit but for 2D polynomials. Parameters ---------- x : array_like, shape (M,) x-coordinates of the M sample (data) points (x[i], y[i], z[i]). y : array_like, shape (M,) y-coordinates of the M sample (data) points (x[i], y[i], z[i]). z: array_like, shape (M,) z-coordinates of the sample (data) points (x[i], y[i], z[i]). deg : 1-D array_like Degree(s) of the fitting polynomials. Returns ---------- coef : ndarray, shape (deg[0] + 1, deg[1] +1) Polynomial coefficients ordered from low to high. ''' #DATA x = np.asarray(x) y = np.asarray(y) z = np.asarray(z) #Degrees of the polynomial deg = np.asarray(deg) vander = poly.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) z = z.reshape((vander.shape[0], )) c, r, rank, s = np.linalg.lstsq(vander, z, rcond=None) return c.reshape(deg + 1), r, rank, s
def polyfit2d(x, y, f, deg): """ Fits a 2D polynomial and returns the coefficients Parameters ---------- x : numpy.ndarray y : numpy.ndarray f : numpy.ndarray deg : tuple Returns ------- poly_2d_coef : numpy.ndarray """ deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0],)) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, f, deg): """ Fits a 2D polynomial and returns the coefficients Parameters ---------- x : numpy.ndarray y : numpy.ndarray f : numpy.ndarray deg : tuple Returns ------- poly_2d_coef : numpy.ndarray """ deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, z, order): """Takes x and y coordinates and their resultant z value, and creates a matrix where element i,j is the coefficient of the desired order polynomial x ** i * y ** j Arguments: x (np.array): flat array of x coordinates y (np.array): flat array of y coordinates z (np.array): flat array of z value at the corresponding x and y value order (int): max order of polynomial to work out Returns: np.array: matrix of polynomial coefficients """ logger.info('Fitting 2D surface to polynomial in x and y') deg = np.array([int(order), int(order)]) vander = polynomial.polyvander2d(x, y, deg) # vander matrix is matrix where each row i deals with x=x[i] and y=y[i], # and each item in the row has value x ** m * y ** n with (m,n) = (0,0), # (0,1), (0,2) ... (1,0), (1,1), (1,2) etc up to (order, order) coeff_mat, _, _, _ = np.linalg.lstsq(vander, z, rcond=None) return coeff_mat.reshape(deg + 1)
def polyfit2d(x, y, f, deg): """ Performs a simple 2D polynomial fit using numpy.polyvander2d Input: x, y - coordinate vectors f - function value at respective coordinate tuple deg - degrees of polynomial to be fitted, e.g. [2,2] Output: Array of polynomial coefficients History: 2017 - Written - Anders (AIP) """ x = np.asarray(x) y = np.asarray(y) f = np.asarray(f) deg = np.asarray(deg) vander = polynomial.polyvander2d(x, y, deg) vander = vander.reshape((-1, vander.shape[-1])) f = f.reshape((vander.shape[0], )) c = np.linalg.lstsq(vander, f, rcond=None)[0] return c.reshape(deg + 1)
def polyfit2d(x, y, z, deg=1, grid=True, weight=None): ''' polyfit2d(x, y, z, deg=1, grid=True): Fit a polynomial function to 2d data (x,y) with order <deg>, z is target data. Input: <x>,<y>: are 1d arrays <z>: target data value, can be 1d or 2d. If 2d, we flatten it to 1d <deg>: int, the highest polynomial order to use, default:1 <grid>: boolean, optional. Whether x, y, z is a grid format. Then we convert it to normal array format. This is useful if we fit a polynomial to a 2d surface. In this case, z.size = x.size * y.size <weight>: same size with z, weight assigned for each data point Output: <coef>: 1d array, derived coefficients. See Note note below for the order of coef <predz>: 1d array = z.size. <V>: power item design matrix. <residual>: residual of the model fitting We use numpy.polynomial.polynomial.polyvander to construct the polynomial design matrix V. However, this function construct a full array that only constrains the highest power for individual item (x, or, y). This leads to highest power in V to 2*deg, exceeding the <deg>. For example, if the input highest <deg>=2, then the item with highest order will be x2*y2 = 4. We use the numpy.tril to select appropriate item for fitting. Then polyfit2d is equivalent to solve the linear regression weight. We use scipy.linalg.lstsq to solve the equation The order of coef is correspond to the order of power items in the column of V. Thus np.dot(V,coef) should give the <predz> Note that the order is flattened version of mask. For example. If <deg>=2, x and y power should be [0, 1, 2]. The the order (x,y) should be (0,0) (0,1), (0.2), ... (2,0),(2,1),(2,2). Hence, the coef[0] is the coefficient for the constant item in the regression.Note that this is *DIFFERENT* from the output of numpy.polyfit, which the coefficient order is from high to low to their corresponding power item. x,y,z can have nan or inf value. But we do not include them when computing weight We directly return nan values in x, y, z Example: x, y = np.arange(10), np.arange(10) xx,yy = np.meshgrid z = 2* x^2 + x + 3*y^2 plt.subplot(121) plt.imshow(z) History: 20180628 RZ add <weight> input 20180616 RZ double checked the function, it works very well. 20180510 RZ created it To do: 1. implement multi linear regression ''' import numpy as np import scipy.linalg as linalg import scipy.sparse as sparse from numpy.polynomial.polynomial import polyvander2d # check input assert isinstance(x, np.ndarray) and x.ndim == 1, 'x is not 1d np.npdarray!' assert isinstance(y, np.ndarray) and y.ndim == 1, 'y is not 1d np.npdarray!' assert isinstance(z, np.ndarray), 'z must be an array' z = z.flatten() if weight is None: weight = np.ones(m.size) # convert if grid=True if grid: xsize, ysize = x.size, y.size xx, yy = np.meshgrid(x, y) x, y = xx.flatten(), yy.flatten() # deal with nan and inf values valid = np.isfinite(x) & np.isfinite(y) & np.isfinite(z) # obtain polymial order array V V = polyvander2d(x, y, deg=[deg, deg]) # we want to set the lower right triangle of V to zero since those item exceeds # the highest order ii, jj = np.meshgrid(np.arange(deg + 1), np.arange(deg + 1)) tt = ii + jj mask = tt.flatten() <= deg # remove the item that exceeds the order V = V[:, mask] # set the weight matrix if weight: W = sparse.diags(weight[valid]) # directly solve the equation coef = linalg.inv( V[valid, :].T @ W @ V[valid, :]) @ V[valid, :].T @ W * m[valid] predz = np.dot(V, coef) residual = (weight[valid] * (predm[valid] - m[valid])**2).sum() else: coef, residual, _, _ = linalg.lstsq(V[valid, :], m[valid]) predz = np.dot(V, coef) if grid: # if grid case, we output a multi array predz = predz.reshape(xsize, ysize) return coef, predz, V, residual
#%% Invert with polymap for plane # # # Create active map to go from reduce set to full #actvMap = Maps.ActiveCells(mesh, actv, -100) # ## Creat reduced identity map #idenMap = Maps.IdentityMap(nP = nC) # XYZ = mesh.gridCC order = [1,1] YZ = Utils.ndgrid(mesh.vectorCCy, mesh.vectorCCz) V = polynomial.polyvander2d(YZ[:,0], YZ[:,1], order) #f = polynomial.polyval2d(XYZ[:,1], XYZ[:,2], c.reshape((order[0]+1,order[1]+1))) - XYZ[:,0] polymap = Maps.PolyMap(mesh, order, normal='X', logSigma=False, actInd = actv) polymap.slope = 1.0 #polymap.actInd = actv #m0 = np.r_[1e-2, 0., 0.0, -0.5, 0.2, 0.] m0 = np.r_[1e-4, 0, 1., 0., 0., 0.] #Mesh.TensorMesh.writeModelUBC(mesh,home_dir+dsep+'True_m.sus',polymap*m0) #Mesh.TensorMesh.writeModelUBC(mesh,home_dir+dsep+'Starting_m.sus',actvMap*polymap*m0)
def vandermonde(self, points): """""" vander = polyvander2d(points[:, 0], points[:, 1], [self.degree, self.degree]) ulmask = CoeffPolynomial.upper_left_triangular_mask(self.degree) return vander[:, ulmask.ravel()]