Pas model campuran gaussian menggunakan keturunan gradien stokastik

8

Saya sedang mengerjakan model pembelajaran kategori online yang menggunakan penurunan gradien stokastik agar sesuai dengan model campuran Gauss. Model ini didasarkan pada model pembelajaran online yang digunakan dalam Toscano & McMurray (2010).

Sementara gradient descent kelihatannya bekerja cukup baik untuk memperkirakan rata-rata dan frekuensi / kemungkinan pencampuran kategori, saya mengalami masalah dengan memperkirakan kovariansi komponen campuran. Derivatif parsial yang saya gunakan untuk pembaruan gradient descent datang dari Petersen & Pedersen (2008) (hlm. 44)

Dimulai dengan

hal(x)=kρkNx(μk,Σk)

Petersen & Pedersen memberikan turunan parsial sehubungan dengan matriks kovarians Σ sebagai

δdalamhal(x)δΣj=ρjNx(μj,Σj)kρkNx(μk,Σk)12[-Σj-1+Σj-1(x-μj)(x-μj)TΣj-1]

Langkah gradient descent untuk masing-masing Σj, karena saya sudah menerapkannya di Python adalah (ini adalah penyederhanaan dan sedikit ΔΣ untuk semua komponen dihitung sebelum melakukan pembaruan):

j.sigma += learning_rate*(G(x)/M(x))*0.5*(-inv(j.sigma) + inv(j.sigma).dot((x-j.mu).dot((x-j.mu).transpose())).dot(inv(j.sigma)))

Di mana j adalah objek yang mewakili jKomponen campuran dan j.sigma dan j.mu adalah mean dan varian komponen itu. G (x) / M (x) berdiri untuk beberapa kode yang menghitungρjNx(μj,Σj)kρkNx(μk,Σk)

Jadi, saya bertanya-tanya apakah ada yang salah dengan kode saya (sangat mungkin) atau apakah ini hanya cara yang sangat buruk untuk menyesuaikan model seperti ini ketika berhadapan dengan data dengan lebih dari dua dimensi (Lihat Toscano & McMurray untuk algoritme untuk univariat dan data bivariat yang pasti berfungsi).

referensi: Toscano, JC, & McMurray, B. (2010). Integrasi isyarat dengan kategori: Menandai isyarat akustik dalam pidato menggunakan pembelajaran tanpa pengawasan dan statistik distribusi. Ilmu Kognitif, 34, 434-464.

Petersen & Pederson. Matrix Cookbook, Versi: 14 November 2008

phased_chirp
sumber

Jawaban:

3

Dengan asumsi bahwa mus[d]adalahμj, j.sigmaadalahΣj, dan G(x)/M(x)memang menghitung probabilitas posterior komponenj diberi data x,

hal(jx)=ρjNx(μj,Σj)kρkNx(μk,Σk),
gradien itu sendiri tampaknya benar bagi saya. Tetapi di sini ada beberapa hal yang saya perhatikan yang mungkin bisa membantu Anda menemukan masalah Anda:
  • Saya akan mengharapkan akses ke mean, kovarian, dan perhitungan posterior untuk semua melibatkan salah satu , jatau dvariabel mana saja yang mewakili komponen yang Anda ingin menghitung gradien dalam kode Anda. Jika Anda memberi tahu kami apa jdan dmendukung, kami mungkin bisa memberi tahu Anda lebih banyak.
  • Jika G(x)/M(x)akses j.Sigmauntuk menghitung posterior, kode Anda mungkin tidak menghitung apa yang Anda pikirkan. Mungkin lebih baik untuk pertama menghitung semua gradien dari semua parameter, dan kemudian melakukan pembaruan.
  • Stochastic gradient descent biasanya bukan pilihan pertama untuk mengoptimalkan campuran Gaussians. Paling sering, memaksimalkan harapan (EM) digunakan (lihat, misalnya, Uskup, 2007). Bahkan jika Anda tidak menggunakan EM, Anda mungkin ingin mempertimbangkan BFGS atau L-BFGS (diterapkan di scipy.optimize) sebelum menggunakan SGD. Dan bahkan jika Anda tetap pada SGD, Anda harus mempertimbangkan menggunakan beberapa titik data ("kumpulan") pada suatu waktu untuk memperkirakan gradien, atau setidaknya termasuk istilah momentum . Secara singkat melihat kertas Toscano dan McMurray, tebakan saya adalah bahwa mereka memilih untuk menggunakan SGD karena mereka tertarik dalam memodelkan akuisisi ucapan dengan cara yang lebih masuk akal secara biologis, daripada mendapatkan kecocokan terbaik, dan melakukan ini secara online (yaitu, satu data titik pada suatu waktu). Jika Anda tidak membutuhkan ini, saran saya adalah menggunakan EM.

    (Saya baru sadar bahwa Anda secara khusus meminta pembelajaran online , jadi satu-satunya pilihan yang mungkin Anda gunakan adalah menambahkan istilah momentum untuk mempercepat segalanya.)

  • Cara Anda memilih untuk menghitung gradien sangat tidak efisien, yang selanjutnya akan memperlambat pembelajaran. Anda mungkin tidak melihat hasil yang masuk akal karena butuh selamanya sebelum algoritma menyatu dengan sesuatu yang menarik. Berikut adalah cara yang sedikit lebih baik untuk menghitung gradien:

    sigmaInv = inv(j.sigma)
    dSigma = G(x)/M(x) * 0.5 * (-sigmaInv + numpy.sum(sigmaInv.dot(x - mus[d]) * x))

    Masih ada cara untuk lebih meningkatkan perhitungan gradien. Sebagai contoh, kita masih mendapatkan arah pendakian yang valid (meskipun bukan pendakian paling curam) jika kita mengalikan gradien dengan matriks pasti positif (sepertiΣj, yang akan menyederhanakan gradien sedikit). Mungkin juga bekerja lebih baik jika kita menggunakan parametrization kovarians yang berbeda, seperti faktor Cholesky , dan menghitung gradien dari mereka sebagai gantinya.

Lucas
sumber
Terima kasih atas saran @Lucas. Maaf untuk kode yang sedikit tidak jelas. Itu bagian dari fungsi yang lebih besar yang saya tulis ulang sehingga lebih masuk akal sendiri. SigmaInv hanya dihitung sekali dan semua gradien dihitung sebelum memperbarui. Ini harus menjadi model online untuk apa yang saya lakukan, jadi saya tidak bisa menggunakan EM. Saya sudah mencoba versi yang sedikit berbeda yang menggunakan faktorisasi sigma Cholesky, tetapi berperilaku agak aneh.
phased_chirp