Bir 2D fonksiyonunu uyarlamalı olarak örneklemek için hangi basit yöntemler vardır?


22

Değerlerini örneklemek istediğim iki boyutlu bir işleve sahibim. İşlev, hesaplanması çok pahalıdır ve karmaşık bir şekle sahiptir, bu nedenle en az sayıda örnek noktası kullanarak şekli hakkında en fazla bilgiyi edinmenin bir yolunu bulmalıyım.f(x,y)

Bunu yapmak için hangi iyi yöntemler var?

Şimdiye kadar sahip olduklarım

  • İşlev değerini önceden hesapladığım mevcut bir nokta kümesinden başlıyorum (bu, noktaların kare bir kafesi veya başka bir şey olabilir).

  • Sonra bu noktaların bir Delaunay üçgenini hesapladım.

  • Delaunay üçgenlemesinde iki komşu nokta yeterince uzaksa ( ) ve işlev değeri bunlarda yeterince farklıysa ( ), o zaman bunların arasına yeni bir nokta eklerim. Bunu her komşu nokta çifti için yapıyorum.>ΔX>Δf

Bu yöntemin nesi var?

Oldukça iyi çalışıyor, ama buna benzer fonksiyonlarda ideal değil çünkü numune noktaları sırtın üzerinden atlıyor, hatta orada olduğunu farketmiyorlar.

Mathematica grafikleri

Bu gibi sonuçlar üretir (eğer başlangıç ​​noktası ızgarasının çözünürlüğü yeterince kaba ise):

Mathematica grafikleri

Yukarıdaki grafik, fonksiyon değerinin hesaplandığı noktaları göstermektedir (aslında etraflarındaki Voronoi hücreleri).

Mathematica grafikleri

Yukarıdaki grafik aynı noktalardan üretilen doğrusal enterpolasyonu gösterir ve bunu Mathematica'nın yerleşik örnekleme yöntemiyle karşılaştırır (yaklaşık aynı başlangıç ​​çözünürlüğü için).

Nasıl geliştirilir?

Buradaki asıl meselem, yöntemimin gradyanı temel alarak bir ayrıntılandırma noktası ekleyip eklememeye karar vermesi olduğunu düşünüyorum.

Arıtma noktaları eklerken eğriliği veya en azından ikinci türevi hesaba katmak daha iyi olacaktır.

Soru

Noktalarımın yerleri hiç kısıtlanmadığında ikinci türevi veya eğriliği hesaba katmanın çok basit bir yolu var mı? ( Başlamak için kare bir kafes ağına sahip olmak zorunda değilim , bu ideal olarak genel olmalı.)

Veya arıtma noktalarının konumunu en iyi şekilde hesaplamak için başka hangi basit yollar var?

Bunu Mathematica'da uygulayacağım, ama bu soru temelde yöntemle ilgili. "Uygulaması kolay" bit için, Mathematica'yı kullanmaya başladım sayılır (yani, şu ana kadar yapmak kolaydı çünkü Delaunay üçgenlemesi yapmak için bir paketi var)

Bunu uygulayacağım pratik problem

Faz diyagramı hesaplıyorum. Karmaşık bir şekle sahiptir. Bir bölgede değeri 0, başka bir bölgede 0 ile 1 arasındadır. İki bölge arasında keskin bir sıçrama vardır (süreksiz). Fonksiyonun sıfırdan büyük olduğu bölgede, hem bir miktar yumuşak değişim hem de bir kaç süreksizlik vardır.

Fonksiyon değeri bir Monte Carlo simülasyonuna dayanarak hesaplanır, bu nedenle zaman zaman hatalı bir fonksiyon değeri veya gürültü beklenebilir (bu çok nadirdir, ancak çok sayıda nokta için, örneğin sabit duruma ulaşılmadığında) bazı rastgele faktör)

Bunu daha önce Mathematica.SE'de sordum ama hala özel beta sürümünde olduğu için linkleyemiyorum. Buradaki soru uygulama ile değil yöntemle ilgilidir.


@Suki Yanıtla

Bu, önerdiğiniz bölünme türü mü, yani üçgenlerin ortasına yeni bir nokta koymak mı?

Mathematica grafikleri Mathematica grafikleri Mathematica grafikleri Mathematica grafikleri

Buradaki kaygım, bölgenin kenarlarında özel işlem gerektiriyor görünmesi, aksi halde yukarıda gösterildiği gibi çok uzun ve çok ince üçgenler vermesi. Bunu düzelttin mi?

GÜNCELLEŞTİRME

Hem tarif ettiğim yöntemde hem de @ suki'nin üçgenlere dayalı alt bölme koyma ve alt bölme noktalarını üçgen içine koyma önerisiyle ortaya çıkan bir sorun, süreksizlik olduğunda (benim sorunumda olduğu gibi), bir adımdan sonra Delaunay üçgenlemesini yeniden hesaplamak olabilir. Üç köşenin değişmesine neden olabilir ve belki de üç köşede farklı işlev değerlerine sahip bazı büyük üçgenler görünebilir.

İşte iki örnek:

ex1 ex2

Birincisi, düz bir süreksizlik etrafında örnekleme yaparken nihai sonucu gösterir. İkincisi, benzer bir durum için örnekleme noktası dağılımını gösterir.

Bundan kaçınmanın basit yolları nelerdir? Şu anda sadece bir yeniden yapılandırma işleminden sonra kaybolan egdeleri alt bölümlere ayırıyorum, ancak bunun bir hack gibi hissettirdiği ve simetrik kafeslerde olduğu gibi dikkatli bir şekilde yapılması gereken (kare bir ızgara gibi) birkaç geçerli Delaunay üçgenlemesi olduğu için kenarlar değişebilir. retriangulation sonra rastgele.


Bu konuda yeni gelişmeler var mı?
Andrei

Yanıtlar:


10

Bir süre önce buna benzer bir problem üzerinde çalıştım.

Uygulamalarımız arasındaki temel farkın, kenarlara değil, üçgenlere dayanarak puan ekleyeceğimi seçmem olduğunu düşünüyorum. Ayrıca üçgenler içinde kenarlar yerine yeni noktalar seçiyorum.

Üçgenlerin içine nokta eklemenin, eski noktalardan yenisine olan ortalama uzaklıktaki küçük bir artışı vererek daha verimli hale getireceğini hissediyorum.

Her neyse, kenarlar yerine üçgenleri kullanmakla ilgili bir başka güzel şey, bu belirli kenar boyunca eğim yerine gradyan vektörünün bir tahminini vermesidir.

Matlab kodumda, birkaç soyut yöntemle makinelerin çoğuna bakmak için bir temel sınıf kullandım:

  • weight(self) Hangi üçgenlerin daha sonra bölüneceği önceliğine karar vermek.
  • choosePoints(self,npoints = "auto") Her üçgenin ağırlığına göre değerlendirilecek yeni noktalara karar vermek.

Bu kurulumu çok esnek buldum:

  • bir alt sınıfın weight()fonksiyonunu üçgenin alanına ayarlamak sabit bir ağ yoğunluğu oluşturur.
  • weight()Ortalama fonksiyon değerinin çarpım zamanını hesaplamak için ayar , üçgenin alanı bir çeşit yarı-rassal olasılık örneklemesi verir.
  • kullanarak var(triangle.zs)yapabileceğini, ikili çıkışı fonksiyonlar için, ne hissettiğimi 1'den fazla boyuta bisection aramasının bir genellemedir.
  • kullanarak area + var(triangle.zs)her yerde sabit yoğunluğu koyarak oldukça etkili olduğunu ve herhangi bir yamaç boyunca artan bir yoğunluk (neredeyse artık ne).

Z değerlerinin varyansını birinci dereceden etkilerin (eğim) önemini tahmin etmek için kullandım, çünkü varyans asla eğim kabı gibi sonsuza kadar gitmeyecek.

Son örnek için, arka plan yoğunluğu iyiydi çünkü düşük değerli bir alanda yüksek değerli süreksiz bloblar arıyordum. Böylece tüm ağ gözünü yavaşça doldurur ve bir kabarcık bulduğu zaman, meyhaneye koyduğum yüksek ağırlık nedeniyle (ve sadece üst nüçgenlere doldurduğum yüksek ağırlık nedeniyle) bloğun kenarını takip etmeye konsantre olur. her yinelemede). Sonunda, elde edilen arka plan ağ yoğunluğundan daha büyük bir büyüklükte (makul şekilde şekillendirilmiş) lekeler (veya lekelerimdeki delikler) olmadığını biliyordum.

Sizin gibi sonuçlarımda bazı kötü puanlar aldım, onlar benim için bir sorun değildi, çünkü hata, eğer yakındaki puanları tekrarladıysanız muhtemelen doğru cevabı vereceklerdi. Sadece kötü noktalarımın etrafında artan mesh yoğunluğuna sahip uçlarla bitirdim.

Ne yaparsanız yapın, her zaman üçgen büyüklüğüyle ilgili ağırlıkları ayarlamanızı öneririm, böylece her şey eşit olduğunda, büyük üçgenler önce bozulur.

Belki sizin için bir çözüm yaklaşımımı bir adım daha ileriye götürmek ve o üçgen hücrenin içeriğine dayalı üçgenleri değerlendirmek yerine, bu üç ve üç komşu üçgene dayanarak değerlendirmek.

Bu, tam Hessian matrisinin bir tahminini almak için yeterli bilgiyi içerecektir. İlgili z = c1*x + C2*y c11*x^2+c12*x*y+c22*y^2üçgenlerde tüm tepe noktalarına uyacak en küçük kareler yaparak elde edebilirsiniz (ilk önce koordinat sistemini ortalayın).

Gradyanı veya Hessian'ı (bu sabitleri) doğrudan kullanmam çünkü süreksizlikte sonsuzluğa gidecekler.

Belki de z değerlerinin toplam puan hatası, bu noktaların düzlemsel bir yaklaşımına göreceli olarak, ikinci dereceden etkilerin ne kadar ilginç olduğuna dair yararlı bir ölçü olabilir.


Güncellenmiş:

Bu bana mantıklı geliyor.

Asla özel kasa kenarlarına dolaşmadım. Bu beni biraz rahatsız etti, ama yaptığım şey için, kenarlarda birçok noktayla başlamak yeterliydi.

daha zarif, iki yaklaşımı birleştirerek, kenarları ve üçgenleri ağırlıklandırmak olacaktır. Öyleyse bir kenar çok uzunsa, ikiye bölün. Konseptin daha yüksek boyutlara yayılma şeklini seviyorum (ancak sayılar hızlı büyüyor) ...

Ancak ağın ana gövdesinin yüksek en boy oranlı üçgenlere sahip olmasını beklemiyorsanız, sınır bulmak için Matlab'ın serbest sınır işlevi gibi bir işlev kullanabilirsiniz , ardından aynı algoritmayı sınır üzerinde daha az bir boyutta çalıştırın. Doğru yapılırsa, örneğin bir küpte, kenarlarda, yüzlerde ve küpün içinde aynı ağ yoğunluğunu elde edebilirsiniz. İlginç.

Asla iyi bir çözüm bulamadığım bir şey, versiyonumun başlangıç ​​noktası setinin dışbükey gövdesi dışında asla keşif yapamamasıydı.


Ayrıca önce üçgenleri kullanmayı düşündüm, ama önce bazı teknik problemlerim oldu (o zamandan beri çözdüm), ve sonra yine de üçgenleri kullanmanın daha iyi olmayacağını düşündüm. Soru: Yeni noktaları nereye koydunuz? Üçgenlerin ortasında mı? Bunu yapmadım çünkü çok uzun ve ince üçgenler yaratmasını bekliyordum. Mesajımı kısa bir süre sonra anladığımı anlatacağım şekilde güncelleyeceğim, böylece doğru anladığımı doğrulayabilirsin :-) teşekkürler!
Szabolcs

Lütfen düzenlememi görüp netleştirebilir misiniz?
Szabolcs

Ne tür bir alt bölüm şeması kullandığımdan bağımsız olarak, kenarların muhafaza edilmesinin kaçınılmaz olduğu ortaya çıktı. Benim durumumda, kenara dik olarak yüksek bir degrade var, ancak buna paralel değil, kenarları özel bir şekilde yapmazsam işleri verimsiz yapıyordum.
Szabolcs

Bulduğum bir başka problem ise, yeniden üçgenleşmenin , tepe noktalarının farklı işlev değerlerine sahip olduğu durumlarda zaman zaman büyük üçgenlerin ortaya çıkmasıydı. Bunun gibi şeylerle bitirdim : i.stack.imgur.com/nRPwi.png doğrusal enterpolasyonlu yoğunluk grafiğidir ve i.stack.imgur.com/208bP.png örnekleme noktalarıdır (aynı değildir). Bu sadece düz bir kenar boyunca bir süreksizliktir. Bu soruna çarptın mı? Evet ise, nasıl çözdünüz? Her alt bölüm adımından sonra tamamen yeniden düzenleme yaptınız mı?
Szabolcs

Nirengi gerçekten burada bir şey ifade ettiğinden emin değilim. Değerlendirdiğiniz her nokta, bir noktadaki fonksiyonun değeridir, öyleyse neden kafessiz yöntemlerde kullandıkları gibi bir şey yapmıyorsunuz? en.wikipedia.org/wiki/Smoothed-particle_hydrodynamics Türevlerini de bu şekilde tahmin edebilirsiniz ...
meawoppl

0

Sezgilerinizdeki asıl sorunun, gradyanı yalnızca bir boyutta düşündüğünüz ve dolayısıyla dfdx'in küçük, ancak dfdy'nin büyük olduğu bölgelerde (örneğin ortasındaki gibi), bakarken noktaları kaçıracağını düşünüyorum. "yanlış" boyutta.

Hızlı bir düzeltme, dört noktadan oluşan kümeleri dikkate almak, ağırlık merkezlerini almak ve yaklaşma | dfdx | + | dfdy | bu dört noktayı kullanarak. Diğer bir alternatif, üç puan (yani bir üçgen) almak ve üstlerindeki yüzeyin maksimum eğimini almaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.