Jika Anda tidak memiliki Python, tetapi ada model Keras dan Java

Halo semuanya! Dalam membangun ML-model, Python saat ini menempati posisi terdepan dan sangat populer di kalangan komunitas spesialis Ilmu Data [ 1 ].

Seperti kebanyakan pengembang, Python menarik kita dengan kesederhanaan dan sintaksis yang ringkas. Kami menggunakannya untuk memecahkan masalah pembelajaran mesin menggunakan jaringan saraf tiruan. Namun, dalam praktiknya, bahasa pengembangan produk tidak selalu Python, dan ini mengharuskan kami untuk menyelesaikan masalah integrasi tambahan.

Dalam artikel ini saya akan berbicara tentang solusi yang kami dapatkan ketika kami perlu mengaitkan model Keras Python dengan Java.

Apa yang kami perhatikan:

  • Fitur bundel model Keras dan Java;
  • Bersiap untuk bekerja dengan kerangka kerja DeepLearning4j (singkatnya DL4J);
  • Mengimpor model Keras ke DL4J (hati-hati, bagian ini berisi banyak wawasan) - cara mendaftarkan lapisan, batasan apa yang dimiliki modul impor, cara memeriksa hasil pekerjaannya.

Kenapa membaca?

  • Untuk menghemat waktu di awal, jika Anda akan menghadapi tugas integrasi serupa;
  • Untuk mengetahui apakah solusi kami tepat untuk Anda dan jika Anda dapat menggunakan kembali pengalaman kami.

alt gambar

Karakteristik integral tentang pentingnya kerangka pembelajaran yang mendalam [ 2 ].

Ringkasan kerangka pembelajaran mendalam yang paling populer dapat ditemukan di sini [ 3 ] dan di sini [ 4 ].

Seperti yang Anda lihat, sebagian besar kerangka kerja ini didasarkan pada Python dan C ++: mereka menggunakan C ++ sebagai kernel untuk mempercepat operasi dasar dan sangat dimuat, dan Python sebagai antarmuka interaksi untuk mempercepat pengembangan.

Faktanya, banyak bahasa pembangunan jauh lebih luas. Java adalah pemimpin dalam pengembangan produk untuk perusahaan dan organisasi besar. Beberapa kerangka kerja populer untuk jaringan saraf memiliki port untuk Jawa dalam bentuk pengikat JNI / JNA, tetapi dalam kasus ini ada kebutuhan untuk membangun proyek untuk setiap arsitektur dan keuntungan Jawa dalam masalah pengaburan lintas-platform. Nuansa ini bisa sangat penting dalam solusi yang direplikasi.

Pendekatan alternatif lain adalah dengan menggunakan Jython untuk mengkompilasi ke dalam bytecode Java; tetapi ada kelemahan di sini - hanya mendukung versi 2 Python, serta kemampuan terbatas untuk menggunakan pustaka Python pihak ketiga.

Untuk menyederhanakan pengembangan solusi jaringan saraf di Jawa, kerangka kerja DeepLearning4j (singkatnya DL4J) sedang dikembangkan. DL4 selain Java API menawarkan satu set model pra-terlatih [ 5 ]. Secara umum, alat pengembangan ini sulit untuk bersaing dengan TensorFlow. TensorFlow mengungguli DL4J dengan dokumentasi yang lebih rinci dan sejumlah contoh, kemampuan teknis, ukuran komunitas, dan pengembangan cepat. Namun demikian, tren yang dipatuhi Skymind cukup menjanjikan. Pesaing signifikan di Jawa untuk alat ini belum terlihat.

Pustaka DL4J adalah salah satu dari sedikit (jika bukan satu-satunya) yang memungkinkan untuk mengimpor model-Keras, ia memperluas fungsionalitas dengan lapisan-lapisan yang dikenal dengan Keras [ 6 ]. Pustaka DL4J berisi direktori dengan contoh-contoh implementasi ML-model jaringan saraf (contoh dl4j). Dalam kasus kami, kehalusan penerapan model-model ini di Jawa tidak begitu menarik. Perhatian yang lebih rinci akan diberikan untuk mengimpor model Keras / TF yang terlatih ke Jawa menggunakan metode DL4J.

Memulai


Sebelum Anda mulai, Anda perlu menginstal program yang diperlukan:

  1. Java versi 1.7 (versi 64-bit) dan lebih tinggi.
  2. Sistem Pembuatan Proyek Apache Maven.
  3. IDE untuk dipilih: Intellij IDEA, Eclipse, Netbeans. Pengembang merekomendasikan opsi pertama, dan di samping itu, contoh pelatihan yang tersedia dibahas tentang hal itu.
  4. Git (untuk kloning proyek ke PC Anda).

Deskripsi terperinci dengan contoh peluncuran dapat ditemukan di sini [ 7 ] atau dalam video [ 8 ].

Untuk mengimpor model, pengembang DL4J menyarankan menggunakan modul impor KerasModelImport (muncul pada Oktober 2016). Fungsional modul ini mendukung kedua arsitektur model dari Keras - itu Sequential (analog dalam Java kelas MultiLayerNetwork) dan Fungsional (analog dalam ComputationGraph dalam kelas java). Model ini diimpor baik secara keseluruhan dalam format HDF5, atau 2 file terpisah - berat model dengan ekstensi h5 dan file json yang berisi arsitektur jaringan saraf.

Untuk memulai dengan cepat, pengembang DL4J menyiapkan analisis langkah-demi-langkah dari contoh sederhana pada dataset iris Fisher untuk model tipe Sequential [ 9 ]. Contoh pelatihan lain dipertimbangkan dari perspektif mengimpor model dalam dua cara (1: dalam format HDF5 penuh; 2: dalam file terpisah - bobot model (ekstensi h5) dan arsitektur (ekstensi json)), diikuti oleh perbandingan hasil model Python dan Java [ 10 ]. Ini menyimpulkan diskusi tentang kemampuan praktis modul impor.

Ada juga TF di Jawa, tetapi dalam kondisi eksperimental dan pengembang tidak memberikan jaminan operasi yang stabil [ 11 ]. Ada masalah dengan versi, dan TF di Java memiliki API yang tidak lengkap - itulah sebabnya opsi ini tidak akan dipertimbangkan di sini.

Fitur dari model Keras / TF asli:


Mengimpor jaringan saraf sangat mudah. Secara lebih rinci dalam kode kita akan menganalisis contoh integrasi jaringan saraf dengan arsitektur yang lebih rumit.

Anda tidak boleh masuk ke aspek praktis dari model ini, ini merupakan indikasi dari sudut pandang akuntansi untuk lapisan (khususnya, pendaftaran lapisan Lambda), beberapa seluk-beluk dan keterbatasan modul impor, serta DL4J secara keseluruhan. Dalam praktiknya, nuansa yang dicatat mungkin memerlukan penyesuaian arsitektur jaringan, atau sepenuhnya meninggalkan pendekatan peluncuran model melalui DL4J.

Fitur Model:

1. Jenis model - Fungsional (jaringan dengan percabangan);

2. Parameter pelatihan (ukuran bets, jumlah era) dipilih kecil: ukuran bets - 100, jumlah era - 10, langkah per era - 10;

3. 13 lapisan, ringkasan lapisan ditunjukkan pada gambar:

alt gambar

Deskripsi lapisan pendek
  1. input_1 - lapisan input, menerima tensor 2 dimensi (diwakili oleh matriks);
  2. lambda_1 - lapisan pengguna, dalam kasus kami, membuat pengisi dalam TF dari tensor nilai numerik yang sama;
  3. embedding_1 - builds Embedding (representasi vektor) untuk urutan input data teks (mengkonversi tensor 2-D menjadi 3-D);
  4. conv1d_1 - lapisan konvolusional 1-D;
  5. lstm_2 - lapisan LSTM (setelah lapisan embedding_1 (No. 3));
  6. lstm_1 - lapisan LSTM (berjalan setelah lapisan conv1d (No. 4));
  7. lambda_2 adalah lapisan pengguna di mana tensor dipotong setelah lapisan lstm_2 (No. 5) (operasi yang berlawanan dengan padding pada lapisan lambda_1 (No. 2));
  8. lambda_3 adalah lapisan pengguna di mana tensor dipotong setelah lstm_1 (No. 6) dan lapisan conv1d_1 (No. 4) (operasi yang berseberangan dengan lapisan pada lapisan lambda_1 (No. 2));
  9. concatenate_1 - ikatan lapisan terpotong (No. 7) dan (No. 8);
  10. dense_1 - lapisan 8 neuron yang terhubung penuh dan fungsi aktivasi linier eksponensial "elu";
  11. batch_normalization_1 - lapisan normalisasi;
  12. dense_2 - sepenuhnya terhubung lapisan 1 neuron dan fungsi aktivasi sigmoid "sigmoid";
  13. lambda_4 - lapisan pengguna di mana kompresi lapisan sebelumnya (memeras dalam TF) dilakukan.

4. Kehilangan fungsi - binary_crossentropy

loss=βˆ’ frac1N sum1N(ytrue loglog(ypred)+(1βˆ’ytrue) loglog(1βˆ’ypred))



5. Metrik kualitas model - rata-rata harmonik (F-ukur)

F=2 fracPrecision timesRecallPrecision+Recall


Dalam kasus kami, masalah metrik kualitas tidak sepenting kebenaran impor. Kebenaran impor ditentukan oleh kebetulan hasil dalam model Python dan Java NN yang bekerja dalam mode Inference.

Impor model Keras di DL4J:


Versi yang digunakan: Tensorflow 1.5.0 dan Keras 2.2.5. Dalam kasus kami, model dari Python diunggah secara keseluruhan oleh file HDF5.

# saving model model1.save('model1_functional.h5') 

Saat mengimpor model ke DL4J, modul impor tidak menyediakan metode API untuk melewatkan parameter tambahan: nama modul tensorflow (dari mana fungsi diimpor saat membangun model).

Secara umum, DL4J hanya bekerja dengan fungsi Keras, daftar lengkap diberikan di bagian Keras Impor [ 6 ], jadi jika model dibuat pada Keras menggunakan metode dari TF (seperti dalam kasus kami), modul impor tidak akan dapat mengidentifikasi mereka.

Pedoman umum untuk mengimpor model


Jelas, bekerja dengan model Keras menyiratkan pelatihan berulangnya. Untuk tujuan ini, untuk menghemat waktu, parameter pelatihan ditetapkan (1 zaman) dan 1 langkah per zaman (steps_per_epoch).

Saat Anda pertama kali mengimpor model, khususnya dengan lapisan khusus dan kombinasi lapisan langka, keberhasilan tidak mungkin. Oleh karena itu, disarankan untuk melakukan proses impor secara iteratif: kurangi jumlah lapisan model Keras hingga Anda dapat mengimpor dan menjalankan model di Jawa tanpa kesalahan. Selanjutnya, tambahkan satu lapis pada satu waktu ke model Keras dan impor model yang dihasilkan ke Jawa, menyelesaikan kesalahan yang terjadi.

Menggunakan Fungsi Kehilangan TF


Untuk membuktikan bahwa, ketika mengimpor ke Jawa, fungsi kerugian dari model yang dilatih harus dari Keras, kami menggunakan log_loss dari tensorflow (sebagai yang paling mirip dengan fungsi custom_loss). Kami mendapatkan kesalahan berikut di konsol:

 Exception in thread "main" org.deeplearning4j.nn.modelimport.keras.exceptions.UnsupportedKerasConfigurationException: Unknown Keras loss function log_loss. 

Mengganti Metode TF dengan Keras


Dalam kasus kami, fungsi-fungsi dari modul TF digunakan 2 kali dan dalam semua kasus mereka hanya ditemukan di lapisan lambda.

Lapisan Lambda adalah lapisan khusus yang digunakan untuk menambahkan fungsi sewenang-wenang.

Model kami hanya memiliki 4 lapisan lambda. Faktanya adalah bahwa di Jawa perlu mendaftarkan lapisan lambda ini secara manual melalui KerasLayer.registerLambdaLayer (jika tidak kita akan mendapatkan kesalahan [ 12 ]). Dalam hal ini, fungsi yang didefinisikan di dalam lapisan lambda harus merupakan fungsi dari pustaka Java yang sesuai. Di Jawa tidak ada contoh mendaftar lapisan ini, serta dokumentasi yang komprehensif untuk ini; contohnya ada di sini [ 13 ]. Pertimbangan umum dipinjam dari contoh [ 14 , 15 ].

Secara berurutan pertimbangkan untuk mendaftarkan semua lapisan lambda dari model di Jawa:

1) Lapisan Lambda untuk menambahkan konstanta ke tensor (matriks) beberapa kali sepanjang arah yang diberikan (dalam kasus kami, kiri dan kanan):

Input dari lapisan ini terhubung ke input model.

1.1) Lapisan Python:

 padding = keras.layers.Lambda(lambda x: tf.pad(x, paddings=[[0, 0], [10, 10]], constant_values=1))(embedding) 

Untuk kejelasan, fungsi lapisan ini berfungsi, kami secara eksplisit mengganti nilai numerik dalam lapisan python.

Tabel dengan contoh tensor 2x2 yang berubah-ubah
Itu 2x2Sudah menjadi 2x22
[[ 1 , 2 ],
[ 3 , 4 ]]
[[37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 1 , 2 , 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37],
[37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3 , 4 , 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37]]


1.2) Lapisan Java:

 KerasLayer.registerLambdaLayer("lambda_1", new SameDiffLambdaLayer() { @Override public SDVariable defineLayer(SameDiff sameDiff, SDVariable sdVariable) { return sameDiff.nn().pad(sdVariable, new int[][]{ { 0, 0 }, { 10, 10 }}, 1); } @Override public InputType getOutputType(int layerIndex, InputType inputType) { return InputType.feedForward(20); } }); 

Di semua lapisan lambda terdaftar di Jawa, 2 fungsi didefinisikan ulang:
Fungsi pertama "definelayer" bertanggung jawab untuk metode yang digunakan (sama sekali bukan fakta yang jelas: metode ini hanya dapat digunakan dari bawah nn () backend); getOutputType bertanggung jawab atas output dari layer terdaftar, argumennya adalah parameter numerik (di sini 20, tetapi secara umum setiap nilai integer diizinkan). Ini terlihat tidak konsisten, tetapi berfungsi seperti ini.

2) Lapisan Lambda untuk memotong tensor (matriks) sepanjang arah yang diberikan (dalam kasus kami, kiri dan kanan):

Dalam hal ini, lapisan LSTM memasukkan input dari lapisan lambda.

2.1) Lapisan Python:

 slicing_lstm = keras.layers.Lambda(lambda x: x[:, 10:-10])(lstm) 

Tabel dengan contoh tensor 2x22x5 sewenang-wenang
Itu 2x22x5Sudah menjadi 2x2x5
[[1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1 , 2,3,4,5], [1,2,3,4,5], [ 1 , 2 , 3 , 4 , 5 ], [ 1 , 2 , 3 , 4 , 5 ], [1,2 , 3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3 , 4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4] , 5], [1,2,3,4,5]],

[[1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [ 1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1, 2,3,4,5], [1,2,3,4,5], [ 1 , 2 , 3 , 4 , 5 ], [ 1 , 2 , 3 , 4 , 5 ], [1,2, 3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3, 4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [1,2,3,4, 5], [1,2,3,4,5]]]
[[[ 1 , 2 , 3 , 4 , 5 ], [ 1 , 2 , 3 , 4 , 5 ]],
[[ 1 , 2 , 3 , 4 , 5 ], [ 1 , 2 , 3 , 4 , 5 ]]]]


2.2) layer Java:

 KerasLayer.registerLambdaLayer("lambda_2", new SameDiffLambdaLayer() { @Override public SDVariable defineLayer(SameDiff sameDiff, SDVariable sdVariable) { return sameDiff.stridedSlice(sdVariable, new int[]{ 0, 0, 10 }, new int[]{ (int)sdVariable.getShape()[0], (int)sdVariable.getShape()[1], (int)sdVariable.getShape()[2]-10}, new int[]{ 1, 1, 1 }); } @Override public InputType getOutputType(int layerIndex, InputType inputType) { return InputType.recurrent(60); } }); 

Dalam hal lapisan ini, parameter InputType berubah dari feedforward (20) menjadi berulang (60). Dalam argumen berulang, jumlahnya bisa berupa bilangan bulat apa saja (bukan nol), tetapi jumlahnya dengan argumen berulang dari lapisan lambda berikutnya harus memberikan 160 (mis., Pada lapisan berikutnya, argumen harus 100). Angka 160 disebabkan oleh fakta bahwa tensor dengan dimensi (Tidak, Tidak, 160) harus diterima pada input concatenate_1 dari layer.

2 argumen pertama adalah variabel, tergantung pada ukuran string input.

3) Lapisan Lambda untuk memotong tensor (matriks) sepanjang arah yang diberikan (dalam kasus kami, kiri dan kanan):

Input dari layer ini adalah layer LSTM, sebelum layer conv1_d berada

3.1) Lapisan Python:

 slicing_convolution = keras.layers.Lambda(lambda x: x[:,10:-10])(lstm_conv) 

Operasi ini sepenuhnya identik dengan operasi dalam paragraf 2.1.

3.2) Lapisan Java:

 KerasLayer.registerLambdaLayer("lambda_3", new SameDiffLambdaLayer() { @Override public SDVariable defineLayer(SameDiff sameDiff, SDVariable sdVariable) { return sameDiff.stridedSlice(sdVariable, new int[]{ 0, 0, 10 }, new int[]{ (int)sdVariable.getShape()[0], (int)sdVariable.getShape()[1], (int)sdVariable.getShape()[2]-10}, new int[]{ 1, 1, 1 }); } @Override public InputType getOutputType(int layerIndex, InputType inputType) { return InputType.recurrent(100); } }); 

Lapisan lambda ini mengulangi lapisan lambda sebelumnya dengan pengecualian parameter berulang (100). Mengapa "100" diambil dicatat dalam deskripsi lapisan sebelumnya.

Dalam poin 2 dan 3, lapisan lambda terletak setelah lapisan LSTM, sehingga jenis berulang digunakan. Tetapi jika sebelum lambda-layer tidak ada LSTM, tetapi conv1d_1, maka Anda masih perlu mengatur berulang (terlihat tidak konsisten, tetapi berfungsi seperti itu).

4) Lapisan Lambda untuk mengompres lapisan sebelumnya:

Input dari lapisan ini adalah lapisan yang terhubung sepenuhnya.

4.1) Lapisan Python:

  squeeze = keras.layers.Lambda(lambda x: tf.squeeze( x, axis=-1))(dense) 

Tabel dengan contoh tensor 2x4x1 sewenang-wenang
Itu 2x4x1Menjadi 2x4
[[[ [1], [2], [3], [4]] ,

[ [1], [2], [3], [4] ]]
[[ 1, 2, 3, 4 ],
[ 1, 2, 3, 4 ]]


4.2) Lapisan Java:

 KerasLayer.registerLambdaLayer("lambda_4", new SameDiffLambdaLayer() { @Override public SDVariable defineLayer(SameDiff sameDiff, SDVariable sdVariable) { return sameDiff.squeeze(sdVariable, -1); } @Override public InputType getOutputType(int layerIndex, InputType inputType) { return InputType.feedForward(15); } }); 

Input dari lapisan ini menerima lapisan yang sepenuhnya terhubung, InputType untuk layer ini feedForward (15), parameter 15 tidak mempengaruhi model (nilai integer apa pun diperbolehkan).

Unduh Model Impor


Model dimuat melalui modul ComputationGraph:

 ComputationGraph model = org.deeplearning4j.nn.modelimport.keras.KerasModelImport.importKerasModelAndWeights("/home/user/Models/model1_functional.h5"); 

Mengeluarkan data ke konsol Java


Di Jawa, khususnya di DL4J, tensor ditulis sebagai array dari perpustakaan Nd4j berkinerja tinggi, yang dapat dianggap sebagai analog dari perpustakaan Numpy dengan Python.

Katakanlah string input kami terdiri dari 4 karakter. Simbol direpresentasikan sebagai bilangan bulat (sebagai indeks), misalnya, menurut beberapa penomoran. Array dimensi yang sesuai (4) dibuat untuk mereka.

Misalnya, kami memiliki 4 karakter indeks-disandikan: 1, 3, 4, 8.

Kode di Jawa:

 INDArray myArray = Nd4j.zeros(1,4); // one row 4 column array myArray.putScalar(0,0,1); myArray.putScalar(0,1,3); myArray.putScalar(0,2,4); myArray.putScalar(0,3,8); INDArray output = model.outputSingle(myArray); System.out.println(output); 

Konsol akan menampilkan probabilitas untuk setiap elemen input.

Model yang Diimpor


Arsitektur jaringan saraf dan bobot asli diimpor tanpa kesalahan. Baik model jaringan saraf Keras dan Java dalam mode Inferensi menyetujui hasil.

Model python:

alt gambar

Model Java:

alt gambar

Pada kenyataannya, mengimpor model tidak sesederhana itu. Di bawah ini kami akan menyoroti secara singkat beberapa poin yang mungkin dalam beberapa kasus kritis.

1) Lapisan normalisasi tambalan tidak berfungsi setelah lapisan rekursif. Masalah telah terbuka di GitHub selama hampir setahun [ 16 ]. Misalnya, jika Anda menambahkan lapisan ini ke model (setelah lapisan kontak), kami mendapatkan kesalahan berikut:

 Exception in thread "main" java.lang.IllegalStateException: Invalid input type: Batch norm layer expected input of type CNN, CNN Flat or FF, got InputTypeRecurrent(160) for layer index -1, layer name = batch_normalization_1 

Dalam praktiknya, model menolak untuk bekerja, mengutip kesalahan yang sama ketika lapisan normalisasi ditambahkan setelah conv1d. Setelah lapisan sepenuhnya terhubung, penambahan bekerja dengan sempurna.

2) Setelah lapisan sepenuhnya terhubung, pengaturan hasil Ratakan lapisan dalam kesalahan. Kesalahan serupa disebutkan pada Stackoverflow [ 17 ]. Selama enam bulan, tidak ada umpan balik.

Jelas ini tidak semua batasan yang dapat Anda temui ketika bekerja dengan DL4J.
Waktu operasi akhir untuk model ada di sini [ 18 ].

Kesimpulan


Sebagai kesimpulan, dapat dicatat bahwa Keras-model yang diimpor tanpa kesulitan diimpor ke DL4J hanya mungkin untuk kasus-kasus sederhana (tentu saja, jika Anda tidak memiliki pengalaman seperti itu, dan memang pengetahuan yang baik tentang Jawa).

Semakin sedikit lapisan pengguna, semakin tidak menyakitkan model yang akan diimpor, tetapi jika arsitektur jaringan rumit, Anda harus menghabiskan banyak waktu untuk mentransfernya ke DL4J.

Dukungan dokumenter dari modul impor yang dikembangkan, jumlah contoh terkait, tampak agak lembab. Pada setiap tahap, muncul pertanyaan baru - bagaimana cara mendaftar lapisan Lambda, kebermaknaan parameter, dll.

Mengingat kecepatan kompleksitas arsitektur jaringan saraf dan interaksi antara lapisan, kompleksitas lapisan, DL4J belum berkembang secara aktif untuk mencapai tingkat kerangka kerja top-end untuk bekerja dengan jaringan saraf tiruan.

Bagaimanapun, para pria layak untuk menghargai pekerjaan mereka dan ingin melihat kelanjutan pengembangan arah ini.

Referensi

  1. 5 Bahasa Pemrograman terbaik untuk bidang Kecerdasan Buatan
  2. Kerangka Pembelajaran Mendalam Skor Daya 2018
  3. Perbandingan perangkat lunak pembelajaran dalam
  4. 9 Kerangka Teratas di Dunia Kecerdasan Buatan
  5. DeepLearning4j. Model yang tersedia
  6. DeepLearning4j. Impor model keras. Fitur yang didukung.
  7. Deeplearning4j. Mulai cepat
  8. Kuliah 0: Memulai dengan DeepLearning4j
  9. Deeplearing4j: Impor model keras
  10. Kuliah 7 | Impor model keras
  11. Instal TensorFlow untuk Java
  12. Menggunakan Lapisan Keras
  13. DeepLearning4j: Kelas KerasLayer
  14. DeepLearning4j: SameDiffLambdaLayer.java
  15. DeepLearning4j: KerasLambdaTest.java
  16. DeepLearning4j: BatchNorm dengan RecurrentInputType
  17. StackOverFlow: Masalah membuka model keras di java dengan deeplearning4j (https://deeplearning4j.org/)
  18. GitHub: Kode lengkap untuk model yang dimaksud
  19. Skymind: Perbandingan Kerangka AI

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


All Articles