🌡️ ინტერპოლაცია: IDW და Kriging¶
გვაქვს გაზომვები ცალკეულ წერტილებში (ტემპერატურა მეტეოსადგურებზე, სიმაღლე GPS-წერტილებზე, დაბინძურება სინჯის აღების ადგილებზე), მაგრამ გვჭირდება მნიშვნელობა ნებისმიერ სხვა წერტილში ან მთელი რასტრი. ამას ინტერპოლაცია წყვეტს. მისი ყველა მეთოდი ერთ ვარაუდს ეფუძნება: ახლო წერტილები უფრო ჰგვანან ერთმანეთს, ვიდრე შორი (ტობლერის პირველი კანონი). მეთოდები იმით განსხვავდება, რამდენად და როგორ ითვალისწინებენ ამას.
| მეთოდი | იდეა | ძლიერი მხარე | სუსტი მხარე |
|---|---|---|---|
| უახლოესი მეზობელი | მნიშვნელობა = უახლოესი ნიმუშის (Voronoi) | უმარტივესი, მონაცემს არ ცვლის | საფეხურებრივი ზედაპირი |
| IDW | ყველა ნიმუშის შეწონილი საშუალო, წონა მანძილით მცირდება | მარტივი, სწრაფი | ზედაპირი ნიმუშებს შორის ვერ გასცდება მათ დიაპაზონს, ირგვლივ „ხარის თვალები" ჩნდება |
| Kriging | წონებს მონაცემთა სივრცული კორელაცია (ვარიოგრამა) განსაზღვრავს | იძლევა ცდომილების შეფასებასაც | უფრო რთულია, ვარიოგრამის არჩევა სჭირდება |
🎮 სცადეთ თქვენც¶
დააჭირეთ რუკას ნიმუშის დასამატებლად. ფარულ „ნამდვილ" ზედაპირზე ყოველი მეთოდის ცდომილება ქვემოთ ცხრილშია. გადართეთ მეთოდები და ცადეთ სლაიდერები.
დაკვირვება
- IDW-ის ხარისხი
p: დიდიp-ზე ზედაპირი უახლოესი მეზობლისკენ მიიწევს (საფეხურები), მცირეზე ძალიან გასწორებულია.p = 2ტრადიციული საწყისი მნიშვნელობაა. - Kriging-ის დისპერსია (ყვითელი რუკა): ნიმუშთან ახლოს ღია (დაბალი), ნიმუშებისგან შორს მუქი (მაღალი). IDW ამას არ გვეუბნება: ის ყველგან თანაბრად თავდაჯერებულია.
- ცოტა ნიმუშით და მცირე რადიუსით Kriging შეიძლება IDW-ზე ცუდიც იყოს. ვარიოგრამა მონაცემებს უნდა ერგებოდეს.
⚙️ IDW: მანძილით შეწონილი საშუალო¶
შესაფასებელ წერტილ P-სთვის ყოველ ნიმუშს i ვაძლევთ წონას wᵢ = 1 / dᵢᵖ, სადაც dᵢ არის მანძილი P-დან i-მდე:
- ზუსტად ნიმუშის წერტილზე
d = 0, ამიტომ პირდაპირ ნიმუშის მნიშვნელობას ვაბრუნებთ. - წონების ჯამი ნორმირებულია, ამიტომ შედეგი ყოველთვის ნიმუშების მინიმუმსა და მაქსიმუმს შორისაა: IDW ვერ ივარაუდებს მწვერვალს, რომლის ნიმუშიც არ გვაქვს.
⚙️ Kriging: წონები მონაცემთა სტრუქტურიდან¶
IDW-ში წონა მხოლოდ მანძილზეა დამოკიდებული. Kriging ორ რამეს ითვალისწინებს:
- რამდენად განსხვავდება მნიშვნელობები მანძილის ზრდასთან ერთად: ამას აღწერს ვარიოგრამა
γ(h). ის იზრდებაh-თან ერთად და რადიუსზეa(range) გადადის პლატოზე: ამაზე შორ წერტილებს ერთმანეთზე გავლენა აღარ აქვთ. - ნიმუშები ერთმანეთს როგორ ფარავს: ერთმანეთთან ახლოს მყოფი ორი ნიმუში ერთსა და იმავეს გვეუბნება, ამიტომ თითოეულს ნაკლები წონა ეძლევა (დაჯგუფების ეფექტის გასწორება, როგორც Thiessen-ის საშუალოში).
Ordinary kriging-ში წონები წრფივი სისტემიდან მოდის:
ბოლო მწკრივი ამბობს Σ w = 1, μ არის ლაგრანჟის მამრავლი. შედეგი: z(P) = Σ wᵢ zᵢ და დისპერსია σ²(P) = Σ wᵢ γ(xᵢ,P) + μ.
ჩვენი დემო იყენებს ექსპონენციალურ ვარიოგრამას γ(h) = 1 − e^(−3h/a) ნაგეტის გარეშე. ასეთ შემთხვევაში ზღურბლის (sill) სიდიდე წონებზე გავლენას არ ახდენს, ამიტომ მხოლოდ a რჩება პარამეტრად. რეალურ მონაცემებზე ვარიოგრამას ემპირიული მონაცემებიდან ირჩევენ: ითვლიან γ-ს წერტილთა წყვილებისთვის მანძილის ინტერვალებით და მასზე მოდელს ადებენ (spherical, exponential, gaussian).
სირთულე
ერთ წერტილში Kriging-ს n+1 განტოლებათა სისტემის ამოხსნა სჭირდება, O(n³). მატრიცის ინვერსიას ერთხელ ვთვლით და ყოველი უჯრისთვის მხოლოდ ვექტორზე ვამრავლებთ, O(n²). ამიტომ რასტრის დიდი ზომისთვის ხშირად მხოლოდ უახლოეს k ნიმუშს იღებენ ("moving neighborhood"), რისთვისაც k-d tree გამოიყენება.
🐍 რეალიზაცია სუფთა Python-ით¶
გამოყენება¶
import math
import random
from interp import *
random.seed(5)
def truth(x, y):
return 20 + 16 * math.sin(x / 17) * math.cos(y / 11) + 10 * math.sin((x + y) / 26)
samples = [(x, y, truth(x, y)) for x, y in ((random.uniform(0, 100), random.uniform(0, 50)) for _ in range(25))]
q = (40, 20)
print('ნამდვილი: ', round(truth(*q), 2))
print('უახლოესი: ', round(nearest_value(samples, *q), 2))
print('IDW p=2: ', round(idw(samples, *q, power=2), 2))
z, var = ordinary_kriging(samples, *q, rng=30)
print('Kriging: ', round(z, 2), f'(დისპერსია {var:.2f})')
შემოწმება
ჩვენი Kriging-ის წონები იგივეა, რაც numpy.linalg.solve-ით იგივე სისტემის ამოხსნით მიიღება (განსხვავება ~10⁻¹⁵), წონების ჯამი 1-ია და ნიმუშის წერტილზე შედეგი ზუსტად ნიმუშის მნიშვნელობაა. JavaScript-ის ვერსია, რომელიც დემოშია, იგივე რიცხვებს იძლევა.
📚 იგივე ბიბლიოთეკით¶
import numpy as np
from scipy.interpolate import griddata
xy = np.array([(s[0], s[1]) for s in samples])
v = np.array([s[2] for s in samples])
nearest = griddata(xy, v, [(40, 20)], method='nearest')
linear = griddata(xy, v, [(40, 20)], method='linear') # TIN + ბარიცენტრული
method='nearest' ჩვენი nearest_value-ის იდენტურია (შემოწმებულია). 'linear' ააგებს Delaunay-ს და სამკუთხედებში ბარიცენტრულად აინტერპოლირებს, თუმცა ამოზნექილი გარსის გარეთ აბრუნებს nan-ს.
რა არის შემოწმებული
SciPy-ს nearest და linear მეთოდებით მუშაობა გავუშვი. PyKrige-ისა და QGIS-ის ფრაგმენტები არ გამიშვია ამ გარემოში, ამიტომ პარამეტრების სახელები დოკუმენტაციასთან შეამოწმეთ.
✍️ დავალებები¶
დავალება 1: ვინ არის უკეთესი?
გამოიყენეთ leave-one-out შემოწმება (cross-validation): თითოეული ნიმუში გამოაკელით, შეაფასეთ იგი დანარჩენებით და დათვალეთ საშუალო კვადრატული ცდომილება (RMSE). შეადარეთ უახლოესი მეზობელი, IDW (p = 1…4) და Kriging (a = 10, 20, 40, 80).
ამოხსნა
def loo(fn):
err = []
for i, s in enumerate(samples):
rest = samples[:i] + samples[i + 1:]
err.append(fn(rest, s[0], s[1]) - s[2])
return math.sqrt(sum(e * e for e in err) / len(err))
print('უახლოესი', round(loo(nearest_value), 2))
for p in (1, 2, 3, 4):
print('IDW p =', p, round(loo(lambda T, x, y: idw(T, x, y, p)), 2))
for a in (10, 20, 40, 80):
print('Kriging a =', a, round(loo(lambda T, x, y: ordinary_kriging(T, x, y, a)[0]), 2))
უახლოესი 4.46
IDW p = 1 7.41
IDW p = 2 5.16
IDW p = 3 4.15
IDW p = 4 3.75
Kriging a = 10 8.77
Kriging a = 20 6.59
Kriging a = 40 4.83
Kriging a = 80 4.27
a = 80) პატარაზე გაცილებით უკეთესია, ხოლო IDW p = 4-ზე აქ Kriging-საც კი სჯობს. ვარიოგრამის რადიუსი ზედაპირის ბუნებას უნდა ერგებოდეს: a = 10 ძალიან ცუდია, რადგან ნიმუშებს ერთმანეთზე გავლენას თითქმის არ აძლევს. ამიტომ რეალურ მონაცემებზე a-ს ემპირიული ვარიოგრამიდან ირჩევენ და არა გამოცნობით.
დავალება 2: ექსტრაპოლაცია
რას აბრუნებს თითოეული მეთოდი ნიმუშებიდან ძალიან შორს, წერტილში (300, 300)? შეადარეთ ნიმუშების საშუალოს.
ამოხსნა
(საშუალო, უახლოესი, IDW, Kriging.) IDW და Kriging შორს მნიშვნელობას ერთგვარ „საშუალოსკენ" წევენ, უახლოესი კი უბრალოდ ყველაზე ახლო ნიმუშს იმეორებს. Kriging-ის შედეგი დაჯგუფების გასწორებული საშუალოა, ამიტომ უბრალო საშუალოს ზუსტად არ ემთხვევა. მთავარი ის არის, რომ ნიმუშებისგან შორს ნებისმიერი მეთოდი მონაცემზე კი არა, დაშვებაზე დგას, ამიტომ ასეთი წერტილების ნდობა არ შეიძლება. შემდეგი დავალება სწორედ ამას აჩვენებს.დავალება 3: დისპერსია როგორც ნდობა
გამოთვალეთ Kriging-ის დისპერსია: (ა) ნიმუშიდან ძალიან ახლოს, (ბ) რუკის შუაგულში (50, 25), (გ) შორს (300, 300).
ამოხსნა
დისპერსია ნიმუშთან ახლოს მცირეა, ნიმუშებს შორის საშუალო, შორს კი ზღურბლს (≈1) უახლოვდება: აქ ნიმუშებისგან ინფორმაცია აღარ გვრჩება. ამ რუკის გამოყენებით შეიძლება გადაწყვეტა, სად ღირს დამატებითი გაზომვა.დავალება 4: SciPy-ს linear და ჩვენი მეთოდები
ბადეზე x = 0, 4, …, 100, y = 0, 4, …, 50 გამოიყენეთ griddata(method='linear') და შეამოწმეთ, რამდენ წერტილში აბრუნებს nan-ს. რატომ?