基于 Python(gma) 的 克里金(Kriging)法插值的主要过程
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                基于 Python(gma) 的 克里金(Kriging)法插值的主要过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                ??由于克里金插值的復雜性,本文不再對其原理進行介紹。詳情可自行百度。
- 本算法基于 Python 的開源克里金插值包 pykrige。
- 但本算法已對其進行改造,以使其符合 gma 的整體邏輯。
- 本算法已不包含任何 pykrige 的原始代碼。
原始代碼構建
from gma.algorithm.spmis.interpolate import *class Kriging(IPolate):'''克里金法插值'''# 繼承 gma 的標準插值類 IPolate。本處不再做詳細說明。def __init__(self, Points, Values, Boundary = None, Resolution = None, InProjection = 'WGS84', VariogramModel = 'Linear',VariogramParameters = None,**kwargs):IPolate.__init__(self, Points, Values, Boundary, Resolution, InProjection)self.eps = eps# 初始化半變異函數及參數self.VariogramModel, self.VParametersList = GetVariogramParameters(VariogramModel, VariogramParameters)self.VariogramFUN = getattr(variogram, self.VariogramModel)if self.VParametersList is None:self.VParametersList = self._INITVariogramModel(**kwargs)# 調整輸入數據if self.GType == 'PROJCS':self.Center = (self.Points.min(axis = 0) + self.Points.max(axis = 0)) * 0.5self.AnisotropyScaling = AnisotropyScalingself.AnisotropyAngle = AnisotropyAngleself.DistanceMethod = cdistelse:# 方便后期優化self.Center = np.array([0,0])self.AnisotropyScaling = 1.0self.AnisotropyAngle = 0.0self.DistanceMethod = GreatCircleDistanceself.AdjustPoints = AdjustAnisotropy(self.Points, self.Center, [self.AnisotropyScaling], [self.AnisotropyAngle])self.XYs = AdjustAnisotropy(self.XYs, self.Center,[self.AnisotropyScaling], [self.AnisotropyAngle])def _INITVariogramModel(self, **kwargs):'''初始化參數'''if 'NLags' in kwargs:NLags = kwargs['NLags']initialize.ValueType(NLags, 'pint')else:NLags = 6if 'Weight' in kwargs:Weight = ToNumericArray(kwargs['Weight']).flatten().astype(bool)[0]else:Weight = FalseLags, SEMI = INITVariogramModel(self.Points, self.Values, NLags, self.GType)# 為求解自動參數準備if self.VariogramModel == "Linear":X0 = [np.ptp(SEMI) / np.ptp(Lags), np.min(SEMI)]BNDS = ([0.0, 0.0], [np.inf, np.max(SEMI)])elif self.VariogramModel == "Power":X0 = [np.ptp(SEMI) / np.ptp(Lags), 1.1, np.min(SEMI)]BNDS = ([0.0, 0.001, 0.0], [np.inf, 1.999, np.max(SEMI)])else:X0 = [np.ptp(SEMI), 0.25 * np.max(Lags), np.min(SEMI)]BNDS = ([0.0, 0.0, 0.0], [10.0 * np.max(SEMI), np.max(Lags), np.max(SEMI)])# 最小二乘法求解默認參數def _VariogramResiduals(Params, X, Y, Weight):if Weight:Weight = 1.0 / (1.0 + np.exp(-2.1972 / (0.1 * np.ptp(X)) * (0.7 * np.ptp(X) + np.min(X) - x))) + 1 else:Weight = 1return (self.VariogramFUN(X, *Params) - Y) * WeightRES = least_squares(_VariogramResiduals, X0, bounds = BNDS, loss = "soft_l1",args = (Lags, SEMI, Weight))return RES.xdef _GetKrigingMatrix(self):"""獲取克里金矩陣"""LDs = self.DistanceMethod(self.AdjustPoints, self.AdjustPoints)A = -self.VariogramFUN(LDs, *self.VParametersList)A = np.pad(A, (0, 1), constant_values = 1)# 填充主對角線np.fill_diagonal(A, 0.0)return Adef _UKExec(self, A, LDs, SearchRadius):"""泛克里金求解"""Args = LDs.argsort(axis = 1)[:,:SearchRadius]Values = self.Values[Args.T].T# A 的逆矩陣AInv = inv(A)B = -self.VariogramFUN(LDs, *self.VParametersList)B[np.abs(LDs) <= self.eps] = 0.0B = np.pad(B, ((0,0),(0,1)), constant_values = 1)X = np.dot(B, AInv)B = B[np.ogrid[:len(B)], Args.T].TX = X[np.ogrid[:len(X)], Args.T].TX = X / X.sum(axis = 1, keepdims = True)UKResults = np.sum(X * Values, axis = 1), np.sum((X * -B), axis = 1)return UKResultsdef _OKExec(self, A, LDs, SearchRadius):"""普通克里金求解"""Args = LDs.argsort(axis = 1)[:,:SearchRadius]LDs = LDs[np.ogrid[:len(LDs)], Args.T].TB = -self.VariogramFUN(LDs, *self.VParametersList)B[np.abs(LDs) <= self.eps] = 0.0B = np.pad(B, ((0,0),(0,1)), constant_values = 1)OKResults = np.zeros([2, len(LDs)])for i, b in enumerate(B):BSelector = Args[i] ASelector = np.append(BSelector, len(self.AdjustPoints))a = A[ASelector[:, None], ASelector] x = solve(a, b)OKResults[:, i] = x[:SearchRadius].dot(self.Values[BSelector]), -x.dot(b)return OKResultsdef Execute(self, SearchRadius = 12, KMethod = 'Ordinary'):'''克里金插值'''initialize.ValueType(SearchRadius, 'pint')SearchRadius = np.min([SearchRadius, len(self.AdjustPoints)])A = self._GetKrigingMatrix()LDs = self.DistanceMethod(self.XYs, self.AdjustPoints)if KMethod not in ['Universal', 'Ordinary']:raise ValueError("Undefined Kriging method. Please select 'Universal' or 'Ordinary'!")elif KMethod == 'Universal':KResults = self._UKExec(A, LDs, SearchRadius)else:KResults = self._OKExec(A, LDs, SearchRadius)NT = namedtuple('Kriging', ['Data', 'SigmaSQ', 'Transform'])return NT(KResults[0].reshape(self.YLAT, self.XLON),KResults[1].reshape(self.YLAT, self.XLON), self.Transform)插值應用
在 gma 1.0.13.15 之后的版本可以直接引用。
import gma import pandas as pdData = pd.read_excel("Interpolate.xlsx") Points = Data.loc[:, ['經度','緯度']].values Values = Data.loc[:, ['值']].values# 普通克里金(球面函數模型)插值 KD = Kriging(Points, Values,Resolution = 0.05, VariogramModel = 'Spherical', VariogramParameters = None,InProjection = 'EPSG:4326').Execute(KMethod = 'Ordinary')# 泛克里金類似,這里不做示例gma.rasp.WriteRaster(r'.\gma_OKriging.tif',KD.Data,Projection = 'WGS84',Transform = KD.Transform, DataType = 'Float32')結果對比
?? 與 ArcGIS Ordinary Kriging 插值結果(重分類后)對比:
 ?? 與 pykrige 包 Universal Kriging 插值結果(重分類后)對比:
 
總結
以上是生活随笔為你收集整理的基于 Python(gma) 的 克里金(Kriging)法插值的主要过程的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 股指跨期套利基础学习
- 下一篇: 小白学统计|面板数据分析与Stata应用
