Bagaimana seseorang dapat menyederhanakan dan mempercepat perhitungan jaringan saraf propagasi langsung?

Halo pembaca yang budiman. Banyak yang telah ditulis dan dikatakan tentang jaringan saraf, terutama tentang bagaimana dan mengapa mereka dapat diterapkan. Selain itu, entah bagaimana tidak banyak perhatian diberikan pada dua masalah penting: a) bagaimana menyederhanakan dan cepat menghitung jaringan saraf (satu perhitungan eksponen diwujudkan oleh fungsi perpustakaan bahasa pemrograman, biasanya tidak kurang dari 15-20 instruksi prosesor), b) apa, setidaknya sebagian, logika jaringan yang dibangun - pada kenyataannya, matriks besar nilai bobot dan perpindahan yang diperoleh setelah pelatihan jaringan entah bagaimana tidak benar-benar membantu untuk memahami pola-pola yang ditemukan jaringan ini (mereka tetap tersembunyi dan tugas menentukannya adalah tugas willow) tion - kadang-kadang sangat penting). Saya akan berbicara tentang salah satu pendekatan saya untuk memecahkan masalah ini untuk jaringan saraf distribusi langsung biasa, sementara saya mencoba bertahan dengan minimal matematika.

Sedikit teori


Jaringan distribusi langsung, dari sudut pandang matematika, adalah fungsi yang sangat besar, yang mencakup nilai-nilai input jaringan, koefisien pembobotan dan perpindahan neuron. Dalam setiap neuron lapisan, nilai input dari lapisan (vektor X) dikalikan dengan berat neuron (vektor Wi), tambahkan dengan offset Bi

si=WiX+Bi


dan masukkan fungsi aktivasi A(si)membentuk output dari neuron lapisan.

Fungsi aktivasi mungkin tidak terlalu sederhana untuk dihitung, misalnya, mereka sering mengandung eksponensial (sigmoid eksponensial, tangen hiperbolik). Jika Anda melihat kode assembler yang mengimplementasikan eksponen, Anda dapat menemukan, pertama, banyak pemeriksaan berbeda yang tidak selalu diperlukan, dan kedua, penghitungan eksponen itu sendiri biasanya dilakukan dalam setidaknya dua operasi:

exp(v)=2vβˆ—log2(e)


Oleh karena itu, jika kita ingin mempercepat perhitungan jaringan, maka tugas pertama adalah menyederhanakan perhitungan fungsi aktivasi. Anda dapat mencoba mengorbankan sedikit kualitas karena peningkatan kecepatan, kira-kira mengganti perhitungan fungsi aktivasi klasik dengan perhitungan fungsi yang lebih sederhana, yang (pada data input yang tersedia) memberikan hasil yang kurang lebih sama. Secara umum, ini adalah masalah interpolasi klasik: kami memiliki satu set nilai yang dihitung oleh fungsi asli A (s), dan kami memilih fungsi yang lebih sederhana yang memberikan nilai yang sangat mirip. Fungsi sederhana seperti itu dapat berupa polinomial biasa, atau polinomial dengan kekuatan negatif, atau sesuatu seperti itu. Saya menggunakan empat jenis fungsi tersebut:

a(s)=b0+b1βˆ—s+b2βˆ—s2+...+bnβˆ—sn;
a(s)=b0+b1/s+b2/s2+...+bn/sn;
a(s)=b0+b1βˆ—s0,5+b2βˆ—s1+b3βˆ—s1,5+...+bnβˆ—s0,5n;
a(s)=b0+b1/s0,5+b2/s1+b3/s1,5+...+bn/s0,5n;

Misalkan untuk setiap neuron kami berhasil mengganti fungsi aktivasi dengan yang sedikit lebih sederhana - ini dapat dilakukan, misalnya, dengan menerapkan metode kuadrat terkecil. Substitusi semacam itu sendiri mungkin tidak akan memberikan keuntungan yang sangat besar. Tetapi di sini Anda dapat mencoba trik lain:

  1. Menulis fungsi analitik besar NET (X) yang dihitung oleh jaringan secara keseluruhan;
  2. Ganti fungsi asli A dalam NET (X) dengan fungsi pengganti yang diperoleh untuk fungsi tersebut;
  3. Sederhanakan NET (X) yang diperoleh secara aljabar (atau lebih tepatnya, gunakan beberapa kode yang sudah jadi untuk penyederhanaan ekspresi simbolik). Ini sudah dimungkinkan (setidaknya, jauh lebih mudah daripada kami mencoba menyederhanakan jaringan dengan fungsi aslinya, misalnya, dengan eksponen).

Sebagai hasilnya, kami mendapatkan sesuatu yang lebih sederhana dan, mungkin, sedikit lebih jelas secara matematis - di sini Anda sudah dapat mencoba memahami jenis fungsi yang diterapkan jaringan.

Ini adalah opsi untuk menjelaskan logika jaringan yang dibangun.

Tugas yang dijelaskan, tentu saja, hanya dalam kata-kata yang terlihat sederhana. Untuk digunakan dalam program saya, saya perlu menulis kode saya sendiri untuk penyederhanaan ekspresi simbolis. Selain itu, saya memecahkan masalah yang lebih kompleks, dengan asumsi bahwa setiap neuron dengan fungsi A (s) dapat memiliki beberapa opsi untuk fungsi aktivasi alternatif ak(s)Oleh karena itu, tugas umum juga dirujuk ke enumerasi opsi untuk fungsi tersebut dan penyederhanaan simbolis jaringan untuk setiap opsi tersebut. Di sini hanya paralelisasi perhitungan yang membantu.

Hasil


Hasilnya membuatku senang. Saya mempercepat jaringan tiga lapis (dengan tiga input) dari delapan neuron (dengan bobot dan perpindahan input) dengan fungsi aktivasi "sigmoid eksponensial". Seperti yang ditunjukkan oleh pengukuran waktu, adalah mungkin untuk memperoleh keuntungan sekitar 40% dalam waktu tanpa kehilangan kualitas yang signifikan.

Saya ilustrasikan. Berikut adalah data jaringan sumber:





Dan di lapisan ketiga, output:


Jika input ditetapkan sebagai a, b dan c, maka, setelah penggantian dan penyederhanaan, fungsi jaringan NET dianggap sebagai berikut:

double a2 = a*a; double b2 = b*b; double c2 = c*c; double a3 = a2*a; double b3 = b2*b; double c3 = c2*c; double z01 = sqrt(-1.6302e-02+7.9324e-01*a+9.65149e-01*b+5.64151e-01*c); double z06 = sqrt(1.583708e+00-8.907654e-01*a-2.844379e-01*a2+1.050942e+00*a3+1.178096e+01*b-1.865618e+00*b*a-3.145465e+00*b*a2-5.777153e+00*b2+3.138123e+00*b2*a-1.043599e+00*b3+1.32778e+00*c+5.849582e-01*c*a-3.440382e+00*c*a2+1.838371e+00*c*b+6.864703e+00*c*b*a-3.42434e+00*c*b2-3.013361e-01*c2+3.754167e+00*c2*a-3.745404e+00*c2*b-1.365524e+00*c3+1.014237e-01*z01); double NET = (-1.477593e+00)/(z06)+1.370237e+00-6.303167e-02*a-1.495051e-03*a2+2.33748e-02*a3+5.558024e-02*b+1.178189e-02*b*a-6.996071e-02*b*a2+1.837937e-02*b2+6.97974e-02*b2*a-2.321149e-02*b3+7.924241e-02*c+3.392287e-03*c*a-7.652018e-02*c*a2-1.214263e-02*c*b+1.526831e-01*c*b*a-7.616337e-02*c*b2-1.915279e-03*c2+8.349931e-02*c2*a-8.33044e-02*c2*b-3.037166e-02*c3+1.949161e-02*z01; 

Menang - Saya ulangi, 40% dari waktu, tanpa banyak kerusakan pada kualitas. Saya pikir pendekatan ini dapat diterapkan dalam kasus-kasus di mana kecepatan komputasi jaringan saraf sangat penting - misalnya, jika dihitung berulang kali, dalam siklus dua atau tiga. Contoh masalah seperti itu : solusi numerik dari masalah aerodinamika pada grid, dan di setiap node, jaringan saraf menghitung beberapa perkiraan yang berguna, misalnya, untuk perhitungan viskositas turbulen yang lebih akurat. Kemudian kita memiliki siklus eksternal dalam waktu, siklus dua atau tiga dalam koordinat tertanam di dalamnya dan sudah ada, di dalam, ada perhitungan jaringan saraf. Dalam hal ini, penyederhanaan lebih dari cukup dan bermanfaat.

Source: https://habr.com/ru/post/id442478/


All Articles