Menguji Water Melon menggunakan Neural Networks: Full Dev. Siklus dari prototyping ke App. di google play

Awal


Semuanya berawal ketika saya menemukan sebuah aplikasi. di pasar Apple, yang konon mampu menentukan kematangan air mellon. Suatu program ... aneh. Pikirkan saja: alih-alih mengetuk menggunakan buku-buku jari Anda, Anda seharusnya memukul mellon air dengan iPhone Anda! Namun demikian, saya telah memutuskan untuk mengulangi fungsionalitas itu pada platform Andtoid.

Alat seleksi


Ada beberapa cara untuk memecahkan masalah yang kita miliki, dan saya harus menerapkan upaya tertentu untuk menghindari yang mudah. Yaitu, transformasi Fourier, wavelet dan editor sinyal. Saya ingin belajar jaringan saraf.

Saya memilih Keras sebagai perpustakaan NN, alat luar biasa dari Google, pembungkus di sekitar TensorFlow dan Theano. Jika Anda seorang pemula, ini jelas merupakan alat terbaik. Di satu sisi, Keras adalah alat yang ampuh, dioptimalkan oleh kecepatan, memori dan perangkat keras (dan ya, ia bekerja dengan GPU). Di sisi lain - itu menyembunyikan semua staf yang membosankan dari pengguna, memungkinkan untuk fokus pada tugas itu sendiri. Sangat nyaman.

Keras, dan jaringan saraf pada umumnya, biasanya terikat dengan Python, bahasa yang seperti ular raksasa ... tidak apa-apa. Bagaimanapun, orang perlu tahu Python untuk bekerja di bidang Pembelajaran Jauh. Untungnya, ini adalah bahasa yang mudah yang dapat dipelajari dengan sangat cepat.

Selain Python, Anda akan memerlukan beberapa perpustakaan tambahan, tetapi menguasainya mudah - bahkan dibandingkan dengan Python sendiri. Anda akan membutuhkan pengalaman (dangkal) dengan NumPy, PyPlot dan mungkin beberapa perpustakaan lainnya.

Akhirnya perlu disebutkan bahwa kita tidak akan membutuhkan GPU claster: masalah kita dapat diselesaikan pada satu CPU, lambat, tetapi tidak terlalu lambat.

Rencana kerja


Pertama-tama, kita perlu membuat jaringan saraf, menggunakan Python dan Keras, di lingkungan Ubuntu. Seseorang dapat melakukannya di Windows, tetapi waktu yang Anda habiskan untuk mengkonfigurasi berbagai hal seharusnya sudah cukup untuk mempelajari Ubuntu.

Langkah selanjutnya adalah menulis program. Saya berencana melakukannya di Java untuk Android. Ini akan menjadi prototipe, yang berarti bahwa ia akan memiliki UI, tetapi belum NN - belum.

Mengapa kita harus menulis program boneka? Inilah triknya: setiap pembelajaran mendalam membutuhkan data untuk, yah, belajar. Berapa banyak semangka air yang harus saya uji (dalam kedua arti kata ini) untuk memberikan NN data yang cukup> Seratus? Lebih?

Di sini kita akan menggunakan program dummy: Saya akan meletakkannya di Google Play, memberikannya (ok, paksa semua teman saya untuk menginstalnya) dan mengumpulkan data dari itu ... Di mana?

Langkah selanjutnya adalah menulis program sisi server, yang menerima data dari klien Android kami. Ini adalah tugas yang sangat sederhana, saya butuh sekitar dua puluh menit untuk menulis, tetapi masih, ini merupakan langkah terpisah.

Akhirnya, ketika kami memiliki cukup data, kami dapat mengajar NN.

Maka kita perlu port NN yang dihasilkan ke Jawa dan untuk merilis versi baru dari program kami, untuk menggantikan yang "dummy".

Untung Tidak, tunggu Program ini gratis. Hanya pengalaman.

Menciptakan nn


Bekerja dengan sinyal audio, yang benar-benar mengetuk mellon air, berarti jaringan saraf berulang atau yang disebut CNN satu dimensi. Karena CNN lebih mudah digunakan dan - untuk sinyal pendek - lebih baik, kita akan menggunakannya. Gagasan tentang konvolusional NN adalah dalam "menggeser" sebuah "jendela sensor" pada array data kami (yang merupakan sinyal audio). Sebagai hasilnya, alih-alih menganalisis semua data secara bersamaan, kami mencari sub-pola lokal. Setiap lapisan NN berikut bekerja dengan pola yang diperoleh oleh yang sebelumnya, mencari pola tingkat yang lebih tinggi.

Untuk membuatnya lebih mudah, bayangkan kita harus menemukan burung camar di foto samudera. Kami geser "jendela" kecil di gambar, mencari pola "tanda centang" putih. Sekarang, itu adalah jaringan saraf konvolusional 2D, yang merupakan sinyal satu dimensi, 1D CNN adalah pilihan logis.

NN memiliki struktur sebagai berikut:

model = Sequential() model.add(Conv1D(filters=32, kernel_size=512, strides=3, padding='valid', use_bias=False, input_shape=(nSampleSize, 1), name='c1d', activation='relu')) model.add(Activation('relu', input_shape=(nSampleSize, 1))) model.add(MaxPooling1D(pool_size=(2))) model.add(Conv1D(32, (3))) model.add(Activation('relu')) model.add(MaxPooling1D(pool_size=(2))) model.add(Conv1D(64, (3))) model.add(Activation('relu')) model.add(MaxPooling1D(pool_size=(2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(nNumOfOutputs)) #1)) model.add(Activation('sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) 

NN ini memiliki dua output (ia memprediksi dua nilai: manis dan matang. Manisnya bisa 0 (tidak manis), 1 (normal) dan 2 (luar biasa). Sedangkan untuk kematangan, bisa 0 (terlalu kaku), 1 (bagus) ) dan 2 - terlalu lembut, seperti kapas dengan pasir.

Untuk membuat label (keluaran) itu, kita perlu data yang disiapkan oleh manusia, cara itu dilakukan dibahas nanti, dalam bab tentang program Android. Tujuan NN kami adalah untuk memprediksi, menggunakan sampel audio, perkiraan yang akan dilakukan manusia.

Menulis program


Seperti yang saya sebutkan, akan ada dua versi program: "dummy" dan "final". Dummy yang melakukan prediksi acak (dan pengguna akan diperingatkan tentang hal itu). Saat melakukannya, ia merekam sampel audio dan mengirimkannya ke server kami bersama dengan perkiraan pengguna kualitas nyata dari mellon air. Dengan kata lain, program hanya mengumpulkan data.

Ini adalah halaman versi terakhir dari sebuah program, ini gratis.

Apa fungsinya:

1. Ketika tombol "mikrofon" ditekan, rekaman dimulai. Pengguna memiliki lima detik untuk mengetuk mellon air tiga kali, sangat mirip dengan mengetuk pintu. Kemudian Anda dapat menekan tombol "melon air" untuk mendapatkan "prediksi".

gambar

2. Rekaman yang kami buat disimpan sebagai file sementara. Maksud saya sementara, itu akan ditimpa oleh rekaman berikutnya. Anda dapat mengulang ketukan jika seseorang berbicara di dalam ruangan (Anda tidak akan percaya betapa sulitnya membuat orang terdiam selama lima detik!), Atau air mengalir, atau ada suara lain yang muncul.

Oke, katakan saja melon air dibeli dan Anda telah membawanya pulang. Anda telah membuat rekaman, dan kemudian Anda memotongnya. Sekarang Anda siap untuk memperkirakan rasanya.

Pilih tab "Simpan".

Pada tab ini kami memiliki dua kotak kombo: manis dan matang. Pilih nilai, dan klik Simpan.

Penting! Anda hanya dapat menekan Simpan sekali! Hal ini dilakukan untuk mencegah pengguna mengirim beberapa estimasi untuk mellon air yang sama. Ini juga berarti bahwa Anda harus memilih nilai dengan hati-hati, dan hanya kemudian mengklik Simpan. Setelah Anda menyimpan hasilnya, file audio diganti namanya, dan itu tidak akan dihapus lain kali Anda merekam.

gambar

3. Akhirnya, setelah Anda membuat estimasi (meand dimakan) dosen melon air, Anda telah kembali dari desa di mana Anda memiliki akses tak terbatas ke melon air, tetapi tidak ada internet. Sekarang Anda online. Buka tab Kirim dan tekan tombol. Paket yang berisi info untuk semua semangka yang belum Anda kirim, akan dikirim ke server kami.

gambar

Menulis program sisi server


Ini sangat mudah, jadi saya lebih baik menerbitkan kode sumber. Program "menangkap" file, menetapkan nama unik dan menempatkannya ke folder yang hanya dapat diakses oleh pemilik situs.

 <?php if (is_uploaded_file($_FILES['file']['tmp_name'])) { $uploads_dir = './melonaire/'; $tmp_name = $_FILES['file']['tmp_name']; $pic_name = $_FILES['file']['name']; $filename = md5(date('Ymd H:i:s:u')); move_uploaded_file($tmp_name, $uploads_dir.$filename); } else { echo "File not uploaded successfully."; } ?> 

Melatih nn


Kami membagi data menjadi pelatihan (70%) dan pengujian (30%). Neural Net bertemu dengan baik, tidak ada kejutan di sini. Catatan untuk pemula: jangan lupa untuk menormalkan data input, itu akan menghemat banyak waktu dan saraf. Sesuatu seperti ini:

 for file_name in os.listdir(path): nSweetness, nRipeness, arr_loaded = loadData(file_name) arr_data.append(arr_loaded / max(abs(arr_loaded))) # 2 stands for num. of inputs of a combo box - 1 arr_labels.append([nSweetness / 2.0, nRipeness / 2.0]) 

Porting ke java


Ada beberapa cara untuk port NN dari Python ke Java. Akhir-akhir ini, Google membuat proses ini sangat nyaman, jadi jika Anda memutuskan untuk mempelajari buku teks, pastikan itu tidak usang. Inilah cara saya melakukannya:

 from keras.models import Model from keras.models import load_model from keras.layers import * import os import sys import tensorflow as tf # ------------------- def print_graph_nodes(filename): g = tf.GraphDef() g.ParseFromString(open(filename, 'rb').read()) print() print(filename) print("=======================INPUT=========================") print([n for n in g.node if n.name.find('input') != -1]) print("=======================OUTPUT========================") print([n for n in g.node if n.name.find('output') != -1]) print("===================KERAS_LEARNING=====================") print([n for n in g.node if n.name.find('keras_learning_phase') != -1]) print("======================================================") print() # ------------------- def get_script_path(): return os.path.dirname(os.path.realpath(sys.argv[0])) # ------------------- def keras_to_tensorflow(keras_model, output_dir, model_name,out_prefix="output_", log_tensorboard=True): if os.path.exists(output_dir) == False: os.mkdir(output_dir) out_nodes = [] for i in range(len(keras_model.outputs)): out_nodes.append(out_prefix + str(i + 1)) tf.identity(keras_model.output[i], out_prefix + str(i + 1)) sess = K.get_session() from tensorflow.python.framework import graph_util, graph_io init_graph = sess.graph.as_graph_def() main_graph = graph_util.convert_variables_to_constants(sess, init_graph, out_nodes) graph_io.write_graph(main_graph, output_dir, name=model_name, as_text=False) if log_tensorboard: from tensorflow.python.tools import import_pb_to_tensorboard import_pb_to_tensorboard.import_to_tensorboard( os.path.join(output_dir, model_name), output_dir) model = load_model(get_script_path() + "/models/model.h5") #keras_to_tensorflow(model, output_dir=get_script_path() + "/models/model.h5", # model_name=get_script_path() + "/models/converted.pb") print_graph_nodes(get_script_path() + "/models/converted.pb") 

Perhatikan baris terakhir: dalam kode Java, Anda akan memerlukan nama lapisan input dan output NN. Pernyataan "cetak" menampilkannya untuk kita.

Selanjutnya, kami menempatkan file yang diekspor ke folder "aset" proyek Android Studio (nama file adalah coordted.pb, jangan tanya), tambahkan pustaka (di sini , di sini atau lebih baik, di sini tensorflowinferenceinterface, dan ... itu saja.

Itu dia. Ketika saya melakukannya untuk pertama kalinya, saya mengharapkan masalah, tapi ... semuanya berjalan baik.

Ini adalah panggilan ke NN kami dari kode Java:

  protected Void doInBackground(Void... params) { try { //Pass input into the tensorflow tf.feed(INPUT_NAME, m_arrInput, 1, // batch ? m_arrInput.length, 1); // channels ? //compute predictions tf.run(new String[]{OUTPUT_NAME}); //copy the output into the PREDICTIONS array tf.fetch(OUTPUT_NAME, m_arrPrediction); } catch (Exception e) { e.getMessage(); } return null; } 

Di sini "m_arrInput" - array yang berisi dua elemen, dengan prediksi kami (manisnya, kematangan), dalam rentang 0 hingga 1.

Kesimpulan


Saya percaya saya harus berterima kasih kepada audiens saya atas perhatian dan untuk mengungkapkan harapan bahwa itu menarik. Sebagai gantinya, saya berharap Anda lebih banyak melon air manis, dan saya harap Anda akan mengirim saya sampel audio baru, saat Anda memakannya (mellons, bukan sampel, ya!)

Program ini gratis, tentu saja.

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


All Articles