Panduan untuk Deeplearning4j

1. Perkenalan

Dalam artikel ini, kita akan membuat jaringan neural sederhana dengan pustaka deeplearning4j (dl4j) - alat modern dan canggih untuk pembelajaran mesin.

Sebelum kita mulai, bukan berarti panduan ini tidak memerlukan pengetahuan mendalam tentang aljabar linier, statistik, teori pembelajaran mesin, dan banyak topik lain yang diperlukan untuk insinyur ML yang berpengalaman.

2. Apa Itu Pembelajaran Mendalam?

Jaringan saraf adalah model komputasi yang terdiri dari lapisan node yang saling berhubungan.

Node adalah prosesor data numerik seperti neuron. Mereka mengambil data dari masukan mereka, menerapkan beberapa bobot dan fungsi ke data ini dan mengirimkan hasilnya ke keluaran. Jaringan seperti itu dapat dilatih dengan beberapa contoh data sumber.

Pelatihan pada dasarnya adalah menyimpan beberapa status numerik (bobot) di node yang nantinya memengaruhi komputasi. Contoh pelatihan mungkin berisi item data dengan fitur dan kelas tertentu yang diketahui dari item ini (misalnya, "set 16 × 16 piksel ini berisi huruf tulisan tangan" a ").

Setelah pelatihan selesai, jaringan neural dapat memperoleh informasi dari data baru, meskipun belum pernah melihat item data tertentu ini sebelumnya . Jaringan yang dimodelkan dengan baik dan terlatih dapat mengenali gambar, surat tulisan tangan, ucapan, memproses data statistik untuk menghasilkan hasil untuk kecerdasan bisnis, dan banyak lagi.

Jaringan saraf dalam menjadi mungkin dalam beberapa tahun terakhir, dengan kemajuan kinerja tinggi dan komputasi paralel. Jaringan semacam itu berbeda dari jaringan neural sederhana karena terdiri dari beberapa lapisan perantara (atau tersembunyi) . Struktur ini memungkinkan jaringan untuk memproses data dengan cara yang jauh lebih rumit (dengan cara rekursif, berulang, konvolusional, dll.), Dan mengekstrak lebih banyak informasi darinya.

3. Menyiapkan Proyek

Untuk menggunakan perpustakaan, kita membutuhkan setidaknya Java 7. Selain itu, karena beberapa komponen asli, ini hanya bekerja dengan versi JVM 64-bit.

Sebelum memulai dengan panduan ini, mari kita periksa apakah persyaratannya terpenuhi:

$ java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

Pertama, mari tambahkan pustaka yang diperlukan ke file pom.xml Maven kita . Kami akan mengekstrak versi perpustakaan ke entri properti (untuk versi terbaru perpustakaan, lihat repositori Pusat Maven):

 0.9.1    org.nd4j nd4j-native-platform ${dl4j.version}   org.deeplearning4j deeplearning4j-core ${dl4j.version}  

Perhatikan bahwa dependensi nd4j-native-platform adalah salah satu dari beberapa implementasi yang tersedia.

Ini bergantung pada pustaka asli yang tersedia untuk banyak platform berbeda (macOS, Windows, Linux, Android, dll.). Kami juga dapat mengalihkan backend ke platform nd4j-cuda-8.0 , jika kami ingin menjalankan komputasi pada kartu grafis yang mendukung model pemrograman CUDA.

4. Menyiapkan Data

4.1. Mempersiapkan File DataSet

Kami akan menulis "Hello World" dari pembelajaran mesin - klasifikasi kumpulan data bunga iris. Ini adalah kumpulan data yang dikumpulkan dari bunga dari spesies yang berbeda ( Iris setosa , Iris versicolor , dan Iris virginica ).

Spesies ini berbeda dalam panjang dan lebar kelopak dan sepal. Akan sulit untuk menulis algoritma yang tepat yang mengklasifikasikan item data masukan (yaitu, menentukan spesies apa yang dimiliki bunga tertentu). Tetapi jaringan saraf yang terlatih dapat mengklasifikasikannya dengan cepat dan dengan sedikit kesalahan.

Kita akan menggunakan versi CSV dari data ini, di mana kolom 0..3 berisi fitur yang berbeda dari spesies dan kolom 4 berisi kelas catatan, atau spesies, dikodekan dengan nilai 0, 1 atau 2:

5.1,3.5,1.4,0.2,0 4.9,3.0,1.4,0.2,0 4.7,3.2,1.3,0.2,0 … 7.0,3.2,4.7,1.4,1 6.4,3.2,4.5,1.5,1 6.9,3.1,4.9,1.5,1 …

4.2. Membuat vektor dan Membaca Data

Kami mengenkode kelas dengan angka karena jaringan saraf bekerja dengan angka. Mengubah item data dunia nyata menjadi serangkaian angka (vektor) disebut vektorisasi - deeplearning4j menggunakan pustaka datavec untuk melakukan ini.

Pertama, mari gunakan pustaka ini untuk memasukkan file dengan data vektorisasi. Saat membuat CSVRecordReader , kita dapat menentukan jumlah baris yang akan dilewati (misalnya, jika file memiliki baris header) dan simbol pemisah (dalam kasus kita koma):

try (RecordReader recordReader = new CSVRecordReader(0, ',')) { recordReader.initialize(new FileSplit( new ClassPathResource("iris.txt").getFile())); // … }

Untuk mengulangi rekaman, kita dapat menggunakan salah satu dari beberapa implementasi antarmuka DataSetIterator . Dataset bisa sangat besar, dan kemampuan untuk halaman atau cache nilai bisa berguna.

Tapi dataset kecil kita hanya berisi 150 record, jadi mari kita membaca semua data ke dalam memori sekaligus dengan panggilan iterator.next () .

Kami juga menentukan indeks kolom kelas yang dalam kasus kami sama dengan jumlah fitur (4) dan jumlah total kelas (3).

Juga, perhatikan bahwa kita perlu mengocok dataset untuk menghilangkan pengurutan kelas di file asli.

Kami menetapkan seed acak konstan (42) dan bukan panggilan System.currentTimeMillis () default sehingga hasil pengacakan akan selalu sama. Ini memungkinkan kami untuk mendapatkan hasil yang stabil setiap kali kami menjalankan program:

DataSetIterator iterator = new RecordReaderDataSetIterator( recordReader, 150, FEATURES_COUNT, CLASSES_COUNT); DataSet allData = iterator.next(); allData.shuffle(42);

4.3. Normalisasi dan Pemisahan

Hal lain yang harus kita lakukan dengan data sebelum pelatihan adalah menormalkannya. Normalisasi adalah proses dua fase:

  • pengumpulan beberapa statistik tentang data (fit)
  • mengubah (mentransformasikan) data dengan cara tertentu agar seragam

Normalisasi mungkin berbeda untuk jenis data yang berbeda.

Misalnya, jika kita ingin memproses gambar dengan berbagai ukuran, pertama-tama kita harus mengumpulkan statistik ukuran dan kemudian menskalakan gambar ke ukuran yang seragam.

Tetapi untuk bilangan, normalisasi biasanya berarti mengubahnya menjadi apa yang disebut distribusi normal. Kelas NormalizerStandardize dapat membantu kita dengan itu:

DataNormalization normalizer = new NormalizerStandardize(); normalizer.fit(allData); normalizer.transform(allData);

Sekarang data sudah siap, kita perlu membagi set menjadi dua bagian.

Bagian pertama akan digunakan dalam sesi pelatihan. Kami akan menggunakan bagian kedua dari data (yang tidak akan dilihat jaringan sama sekali) untuk menguji jaringan yang dilatih.

This would allow us to verify that the classification works correctly. We will take 65% of the data (0.65) for the training and leave the rest 35% for the testing:

SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.65); DataSet trainingData = testAndTrain.getTrain(); DataSet testData = testAndTrain.getTest();

5. Preparing the Network Configuration

5.1. Fluent Configuration Builder

Now we can build a configuration of our network with a fancy fluent builder:

MultiLayerConfiguration configuration = new NeuralNetConfiguration.Builder() .iterations(1000) .activation(Activation.TANH) .weightInit(WeightInit.XAVIER) .learningRate(0.1) .regularization(true).l2(0.0001) .list() .layer(0, new DenseLayer.Builder().nIn(FEATURES_COUNT).nOut(3).build()) .layer(1, new DenseLayer.Builder().nIn(3).nOut(3).build()) .layer(2, new OutputLayer.Builder( LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .activation(Activation.SOFTMAX) .nIn(3).nOut(CLASSES_COUNT).build()) .backprop(true).pretrain(false) .build();

Even with this simplified fluent way of building a network model, there’s a lot to digest and a lot of parameters to tweak. Let’s break this model down.

5.2. Setting Network Parameters

The iterations() builder method specifies the number of optimization iterations.

The iterative optimization means performing multiple passes on the training set until the network converges to a good result.

Usually, when training on real and large datasets, we use multiple epochs (complete passes of data through the network) and one iteration for each epoch. But since our initial dataset is minimal, we'll use one epoch and multiple iterations.

The activation() is a function that runs inside a node to determine its output.

The simplest activation function would be linear f(x) = x. But it turns out that only non-linear functions allow networks to solve complex tasks by using a few nodes.

There are lots of different activation functions available which we can look up in the org.nd4j.linalg.activations.Activation enum. We could also write our activation function if needed. But we'll use the provided hyperbolic tangent (tanh) function.

The weightInit() method specifies one of the many ways to set up the initial weights for the network. Correct initial weights can profoundly affect the results of the training. Without going too much into the math, let’s set it to a form of Gaussian distribution (WeightInit.XAVIER), as this is usually a good choice for a start.

All other weight initialization methods can be looked up in the org.deeplearning4j.nn.weights.WeightInit enum.

Learning rate is a crucial parameter that profoundly affects the ability of the network to learn.

We could spend a lot of time tweaking this parameter in a more complex case. But for our simple task, we'll use a pretty significant value of 0.1 and set it up with the learningRate() builder method.

One of the problems with training neural networks is a case of overfitting when a network “memorizes” the training data.

This happens when the network sets excessively high weights for the training data and produces bad results on any other data.

To solve this issue, we’re going to set up l2 regularization with the line .regularization(true).l2(0.0001). Regularization “penalizes” the network for too large weights and prevents overfitting.

5.3. Building Network Layers

Next, we create a network of dense (also known as fully connect) layers.

The first layer should contain the same amount of nodes as the columns in the training data (4).

The second dense layer will contain three nodes. This is the value we can variate, but the number of outputs in the previous layer has to be the same.

The final output layer should contain the number of nodes matching the number of classes (3). The structure of the network is shown in the picture:

After successful training, we'll have a network that receives four values via its inputs and sends a signal to one of its three outputs. This is a simple classifier.

Finally, to finish building the network, we set up back propagation (one of the most effective training methods) and disable pre-training with the line .backprop(true).pretrain(false).

6. Creating and Training a Network

Sekarang mari buat jaringan neural dari konfigurasi, inisialisasi, dan jalankan:

MultiLayerNetwork model = new MultiLayerNetwork(configuration); model.init(); model.fit(trainingData);

Sekarang kita dapat menguji model yang dilatih dengan menggunakan sisa kumpulan data dan memverifikasi hasilnya dengan metrik evaluasi untuk tiga kelas:

INDArray output = model.output(testData.getFeatureMatrix()); Evaluation eval = new Evaluation(3); eval.eval(testData.getLabels(), output);

Jika sekarang kita mencetak eval.stats () , kita akan melihat bahwa jaringan kita cukup bagus dalam mengklasifikasikan bunga iris, meskipun ia melakukan kesalahan kelas 1 untuk kelas 2 sebanyak tiga kali.

Examples labeled as 0 classified by model as 0: 19 times Examples labeled as 1 classified by model as 1: 16 times Examples labeled as 1 classified by model as 2: 3 times Examples labeled as 2 classified by model as 2: 15 times ==========================Scores======================================== # of classes: 3 Accuracy: 0.9434 Precision: 0.9444 Recall: 0.9474 F1 Score: 0.9411 Precision, recall & F1: macro-averaged (equally weighted avg. of 3 classes) ========================================================================

Pembangun konfigurasi yang lancar memungkinkan kita menambah atau mengubah lapisan jaringan dengan cepat, atau mengubah beberapa parameter lain untuk melihat apakah model kita dapat ditingkatkan.

7. Kesimpulan

Dalam artikel ini, kami telah membangun jaringan neural yang sederhana namun kuat dengan menggunakan pustaka deeplearning4j.

Seperti biasa, kode sumber artikel tersedia di GitHub.