Apa metode sederhana yang ada untuk pengambilan sampel fungsi 2D secara adaptif?

22

Saya memiliki fungsi dua dimensi yang nilainya ingin saya sampel. Fungsi ini sangat mahal untuk dikomputasi dan memiliki bentuk yang kompleks, jadi saya perlu mencari cara untuk mendapatkan informasi paling banyak tentang bentuknya menggunakan jumlah titik sampel yang paling sedikit.f(x,y)

Metode apa yang bagus untuk melakukan ini?

Apa yang saya miliki sejauh ini

  • Saya mulai dari set poin yang ada di mana saya sudah menghitung nilai fungsi (ini bisa berupa kisi persegi poin atau yang lainnya).

  • Lalu saya menghitung triangulasi Delaunay dari poin-poin ini.

  • Jika dua titik tetangga dalam triangulasi Delaunay cukup jauh ( ) dan nilai fungsi cukup berbeda di dalamnya ( > Δ f ), maka saya memasukkan titik baru di tengah-tengah di antara mereka. Saya melakukan ini untuk setiap pasangan titik tetangga.>ΔX>Δf

Apa yang salah dengan metode ini?

Yah, itu bekerja relatif baik, tetapi pada fungsi yang mirip dengan ini tidak ideal karena titik sampel cenderung "melompati" punggungan dan bahkan tidak menyadari itu ada di sana.

Grafik Mathematica

Ini menghasilkan hasil seperti ini (jika resolusi grid titik awal cukup kasar):

Grafik Mathematica

Plot di atas menunjukkan titik di mana nilai fungsi dihitung (sebenarnya sel Voronoi di sekitarnya).

Grafik Mathematica

Plot di atas menunjukkan interpolasi linier yang dihasilkan dari titik yang sama, dan membandingkannya dengan metode pengambilan sampel bawaan Mathematica (untuk resolusi awal yang hampir sama).

Bagaimana cara memperbaikinya?

Saya pikir masalah utama di sini adalah bahwa metode saya memutuskan apakah akan menambahkan titik perbaikan atau tidak berdasarkan gradien.

Akan lebih baik untuk memperhitungkan kelengkungan atau setidaknya turunan kedua saat menambahkan poin perbaikan.

Pertanyaan

Apa cara yang sangat sederhana untuk menerapkan cara memperhitungkan turunan atau kelengkungan kedua ketika lokasi poin saya tidak dibatasi sama sekali? (Saya tidak harus memiliki kisi kuadrat dari titik awal, ini idealnya bersifat umum.)

Atau cara sederhana apa yang ada untuk menghitung posisi titik perbaikan secara optimal?

Saya akan menerapkan ini dalam Mathematica, tetapi pertanyaan ini terutama tentang metode ini. Untuk bit "mudah diimplementasikan" tidak dihitung bahwa saya menggunakan Mathematica (yaitu ini mudah dilakukan sejauh ini karena memiliki paket untuk melakukan triangulasi Delaunay)

Masalah praktis apa yang saya terapkan ini

Saya menghitung diagram fase. Ini memiliki bentuk yang rumit. Di satu wilayah nilainya 0, di wilayah lain itu antara 0 dan 1. Ada lompatan tajam antara kedua wilayah (itu terputus-putus). Di wilayah di mana fungsi lebih besar dari nol ada beberapa variasi halus dan beberapa diskontinuitas.

Nilai fungsi dihitung berdasarkan simulasi Monte Carlo, sehingga kadang-kadang nilai fungsi atau noise yang salah diharapkan (ini sangat jarang terjadi, tetapi untuk sejumlah besar titik itu terjadi, misalnya ketika kondisi mapan tidak tercapai karena beberapa faktor acak)

Saya sudah menanyakan ini di Mathematica.SE tetapi saya tidak dapat menautkannya karena masih dalam versi beta pribadi. Pertanyaan ini di sini adalah tentang metode, bukan implementasinya.


Balas ke @suki

Apakah ini jenis pembagian yang Anda sarankan, yaitu menempatkan titik baru di tengah segitiga?

Grafik Mathematica Grafik Mathematica Grafik Mathematica Grafik Mathematica

Perhatian saya di sini adalah bahwa tampaknya memerlukan penanganan khusus di tepi wilayah, jika tidak akan memberikan segitiga yang sangat panjang dan sangat tipis, seperti yang ditunjukkan di atas. Apakah Anda benar untuk ini?

MEMPERBARUI

Masalah yang muncul baik dengan metode yang saya jelaskan dan dengan saran @ suki untuk menempatkan pembagian berdasarkan segitiga dan menempatkan titik pembagian di dalam segitiga adalah bahwa ketika ada diskontinuitas (seperti dalam masalah saya), mengkompilasi ulang triangulasi Delaunay setelah langkah mungkin menyebabkan segitiga berubah dan mungkin beberapa segitiga besar muncul yang memiliki nilai fungsi yang berbeda dalam tiga simpul.

Berikut ini dua contoh:

ex1 ex2

Yang pertama menunjukkan hasil akhir saat pengambilan sampel di sekitar diskontinuitas lurus. Yang kedua menunjukkan distribusi titik sampling untuk kasus serupa.

Apa cara sederhana yang ada untuk menghindari ini? Saat ini saya hanya membagi lagi egdes yang hilang setelah retriangulation, tapi ini terasa seperti retasan dan perlu dilakukan dengan hati-hati seperti dalam kasus jerat simetris (seperti kotak persegi) ada beberapa triangulasi Delaunay yang valid, maka ujung-ujungnya mungkin berubah secara acak setelah retriangulasi.

Szabolcs
sumber
apakah ada perkembangan baru dalam masalah ini?
Andrei

Jawaban:

10

Saya bekerja pada masalah yang mirip dengan ini beberapa waktu lalu.

Saya pikir perbedaan utama antara implementasi kami adalah bahwa saya memilih tempat untuk menambahkan poin berdasarkan segitiga, bukan tepi. Saya juga memilih titik-titik baru di dalam segitiga daripada di tepi.

Saya merasa bahwa menambahkan titik di dalam segitiga akan membuatnya lebih efisien dengan memberikan sedikit peningkatan jarak rata-rata dari titik lama ke yang baru.

Pokoknya hal baik lainnya tentang menggunakan segitiga bukan tepi adalah memberikan perkiraan vektor gradien, bukan kemiringan di sepanjang tepi khusus ini.

Dalam kode matlab saya, saya menggunakan kelas dasar untuk mengurus sebagian besar mesin, dengan beberapa metode abstrak:

  • weight(self) untuk memutuskan prioritas segitiga mana yang akan dibagi berikutnya.
  • choosePoints(self,npoints = "auto") untuk memutuskan poin-poin baru untuk dievaluasi berdasarkan bobot masing-masing segitiga.

Saya menemukan pengaturan ini sangat fleksibel:

  • pengaturan fungsi sub-kelas weight()ke area segitiga menghasilkan kepadatan jala yang konstan.
  • pengaturan weight()untuk menghitung nilai fungsi rata-rata kali luas segitiga memberikan semacam sampling probabilitas kuasi-acak.
  • menggunakan var(triangle.zs)bisa lakukan, untuk fungsi yang memiliki keluaran biner, apa yang saya rasakan adalah generalisasi dari pencarian pembelahan ke lebih dari 1 dimensi.
  • Penggunaannya area + var(triangle.zs)cukup efektif untuk menempatkan kepadatan konstan di mana-mana, dan peningkatan kepadatan di sepanjang lereng apa pun (hampir seperti yang Anda miliki sekarang).

Saya menggunakan varians dari nilai z, untuk memperkirakan pentingnya efek urutan pertama (kemiringan) karena varians tidak akan pernah pergi hingga tak terbatas seperti kemiringan yang bisa.

Sebagai contoh terakhir, kepadatan latar belakangnya bagus karena saya sedang mencari gumpalan diskontinyu bernilai tinggi di ruang bernilai rendah. Jadi perlahan-lahan akan mengisi seluruh jala dan ketika akan menemukan gumpalan itu akan berkonsentrasi mengikuti tepi gumpalan sepanjang jalan di sekitar karena berat tinggi saya memakai gradien (dan itu hanya mengisi nsegitiga atas) pada setiap iterasi). Pada akhirnya saya bisa tahu bahwa tidak ada gumpalan (berbentuk cukup) (atau lubang di gumpalan saya) dengan ukuran lebih besar dari kepadatan latar belakang mesh yang dihasilkan.

Seperti Anda, saya memang mendapatkan beberapa poin buruk dalam hasil saya, mereka tidak masalah bagi saya karena kesalahannya adalah bahwa jika Anda menjalankan kembali poin terdekat, mereka mungkin akan memberikan jawaban yang benar. Saya baru saja berakhir dengan blip peningkatan kepadatan mesh di sekitar poin buruk saya.

Apa pun yang Anda lakukan, saya selalu menyarankan untuk membuat bobot yang terkait dengan ukuran segitiga sehingga, semua yang sama, segitiga besar dipecah terlebih dahulu.

Mungkin solusi bagi Anda adalah mengambil pendekatan saya satu langkah lebih jauh dan alih-alih mengevaluasi segitiga berdasarkan isi sel segitiga itu, evaluasi berdasarkan pada satu dan ketiga segitiga yang berdekatan.

Itu akan berisi informasi yang cukup untuk mendapatkan perkiraan matriks Goni lengkap. Anda bisa mendapatkannya dengan melakukan paling tidak kuadrat dari z = c1*x + C2*y c11*x^2+c12*x*y+c22*y^2semua verteks dalam segitiga bunga (pusatkan sistem koordinat pada segitiga terlebih dahulu).

Saya tidak akan menggunakan gradien atau Hessian (konstanta-konstanta itu) secara langsung karena mereka akan menjadi tak terhingga pada diskontinuitas.

Mungkin kesalahan sum-kuadrat dari nilai z relatif terhadap perkiraan planar dari titik-titik tersebut akan menjadi ukuran yang berguna tentang seberapa menarik efek urutan kedua.


Diperbarui:

Itu terlihat masuk akal bagi saya.

Saya tidak pernah benar-benar sempat ke casing khusus tepi. Itu sedikit mengganggu saya, tetapi untuk apa yang saya lakukan, itu sudah cukup untuk memulai dengan banyak poin di tepinya.

lebih elegan akan menggabungkan dua pendekatan kami, tepi bobot dan segitiga. Kemudian jika suatu tepi terlalu panjang, potong menjadi dua ... Saya suka cara konsep itu digeneralisasi ke dimensi yang lebih tinggi (tetapi jumlahnya menjadi sangat cepat) ...

Tetapi karena Anda tidak mengharapkan tubuh utama mesh memiliki segitiga aspek rasio tinggi, sehingga Anda bisa menggunakan fungsi seperti fungsi freeboundary Matlab untuk menemukan batas, kemudian jalankan algoritma yang sama dalam satu dimensi kurang pada batas. Jika dilakukan dengan benar, pada kubus misalnya, Anda bisa mendapatkan kepadatan jala yang sama di tepi, di wajah, dan di dalam kubus. Menarik.

Satu hal yang saya tidak pernah menemukan solusi yang baik adalah kenyataan bahwa versi saya tidak akan pernah mengeksplorasi di luar cembung cangkang dari set poin awal.

mdaoust
sumber
Saya juga berpikir tentang menggunakan segitiga terlebih dahulu, tetapi saya memiliki beberapa masalah teknis terlebih dahulu (yang telah saya pecahkan sejak saat itu), dan kemudian saya pikir tidak akan jauh lebih baik menggunakan segitiga. Pertanyaan: di mana Anda menempatkan poin baru? Di tengah segitiga? Saya tidak melakukan ini karena saya berharap itu akan membuat beberapa segitiga yang sangat panjang dan tipis. Saya akan memperbarui posting saya segera dengan apa yang saya mengerti Anda lakukan sehingga Anda dapat memverifikasi jika saya benar :-) terima kasih!
Szabolcs
Bisakah Anda melihat edit dan klarifikasi saya?
Szabolcs
Ternyata casing khusus ujung-ujungnya tidak bisa dihindari, tidak peduli skema pembagian seperti apa yang saya gunakan. Dalam kasus saya, saya memiliki gradien tinggi tegak lurus tepi, tetapi tidak sejajar dengan itu, yang membuat hal-hal tidak efisien jika saya tidak khusus tepi kasus.
Szabolcs
Masalah lain yang saya temukan adalah triangulasi ulang menyebabkan segitiga besar muncul sesekali di mana simpul memiliki nilai fungsi yang berbeda. Saya berakhir dengan hal-hal seperti ini: i.stack.imgur.com/nRPwi.png adalah plot kepadatan interpolasi linear, dan i.stack.imgur.com/208bP.png adalah titik pengambilan sampel (tidak persis sama). Ini hanya diskontinuitas sepanjang garis lurus. Apakah Anda mendapatkan masalah ini? Jika ya, bagaimana Anda mengatasinya? Apakah Anda melakukan retriangulasi sepenuhnya setelah setiap langkah pembagian?
Szabolcs
Saya tidak yakin triangulasi benar-benar berarti di sini. Setiap titik yang Anda nilai adalah nilai fungsi pada suatu titik, jadi mengapa tidak melakukan sesuatu seperti yang mereka gunakan dalam metode bebas mesh? en.wikipedia.org/wiki/Smoothed-particle_hydrodynamics Anda juga dapat memperkirakan turunannya dengan cara ini ...
meawoppl
0

Saya pikir masalah utama dalam heuristik Anda adalah bahwa Anda mempertimbangkan gradien hanya dalam satu dimensi dan dengan demikian, di daerah di mana dfdx kecil tetapi dfdy besar (seperti yang terjadi di tengah-tengah contoh Anda), Anda akan kehilangan poin ketika melihat dalam dimensi "salah".

Salah satu perbaikan cepat adalah dengan mempertimbangkan set empat titik, mengambil pusat gravitasi mereka, dan mendekati | dfdx | + | dfdy | menggunakan empat poin itu. Alternatif lain adalah mengambil tiga titik (yaitu segitiga) dan mengambil gradien maksimum permukaan di atasnya.

Pedro
sumber