
Jaringan saraf siam adalah salah satu algoritma pembelajaran tunggal paling sederhana dan paling populer. Metode di mana untuk setiap kelas diambil hanya satu studi kasus. Dengan demikian, jaringan Siam biasanya digunakan dalam aplikasi di mana tidak ada banyak unit data di setiap kelas.
Misalkan kita perlu membuat model pengenalan wajah untuk organisasi yang mempekerjakan sekitar 500 orang. Jika kita membuat model seperti itu dari awal berdasarkan convolutional neural network (CNN), maka untuk melatih model dan mencapai akurasi pengenalan yang baik, kita akan memerlukan banyak gambar dari masing-masing 500 orang ini. Tetapi jelas bahwa kami tidak dapat mengumpulkan dataset tersebut, jadi Anda tidak boleh membuat model berdasarkan CNN atau algoritma
pembelajaran mendalam lainnya jika kami tidak memiliki cukup data. Dalam kasus seperti itu, Anda dapat menggunakan algoritma pembelajaran satu kali yang kompleks, seperti jaringan Siam, yang dapat dilatih dengan lebih sedikit data.
Bahkan, jaringan Siam terdiri dari dua jaringan saraf simetris, dengan bobot dan arsitektur yang sama, yang pada akhirnya menggabungkan dan menggunakan fungsi energi - E.
Mari kita lihat jaringan siam, menciptakan model pengenalan wajah berdasarkan itu. Kami akan mengajarinya untuk menentukan kapan dua wajah adalah sama dan kapan tidak. Dan sebagai permulaan, kita akan menggunakan dataset AT&T Database of Faces, yang dapat diunduh dari situs web
lab komputer Universitas Cambridge .
Unduh, buka paket dan lihat folder dari s1 ke s40:

Setiap folder berisi 10 foto berbeda dari satu orang yang diambil dari sudut yang berbeda. Berikut ini isi folder s1:

Dan inilah yang ada di folder s13:

Jaringan Siam perlu memasukkan nilai berpasangan dengan tanda, jadi mari kita buat set seperti itu. Ambil dua foto acak dari folder yang sama dan tandai sebagai pasangan "asli". Lalu kami mengambil dua foto dari folder yang berbeda dan menandainya sebagai pasangan "salah" (mustahil):

Setelah membagikan semua foto menjadi pasangan yang ditandai, kami akan mempelajari jaringan. Dari setiap pasangan, kami akan mentransfer satu foto ke jaringan A, dan yang kedua ke jaringan B. Kedua jaringan hanya mengekstrak vektor properti. Untuk melakukan ini, kami menggunakan dua lapisan konvolusional dengan aktivasi rectified linear unit (ReLU). Setelah mempelajari sifat-sifat, kami mentransfer vektor yang dihasilkan oleh kedua jaringan ke fungsi energi yang memperkirakan kesamaan. Kami menggunakan jarak Euclidean sebagai fungsi.
Sekarang pertimbangkan semua langkah ini secara lebih rinci.
Pertama, impor perpustakaan yang diperlukan:
import re import numpy as np from PIL import Image from sklearn.model_selection import train_test_split from keras import backend as K from keras.layers import Activation from keras.layers import Input, Lambda, Dense, Dropout, Convolution2D, MaxPooling2D, Flatten from keras.models import Sequential, Model from keras.optimizers import RMSprop
Sekarang kita mendefinisikan fungsi untuk membaca gambar input. Fungsi
read_image
mengambil gambar dan mengembalikan array NumPy:
def read_image(filename, byteorder='>'):
Misalnya, buka foto ini:
Image.open("data/orl_faces/s1/1.pgm")

Kami meneruskannya ke fungsi
read_image
dan mendapatkan array NumPy:
img = read_image('data/orl_faces/s1/1.pgm') img.shape (112, 92)
Sekarang kita mendefinisikan fungsi
get_data
yang akan menghasilkan data. Izinkan saya mengingatkan Anda bahwa jaringan Siam perlu mengirimkan pasangan data (asli dan tidak penting) dengan tanda biner.
Pertama, baca gambar (
img1
,
img2
) dari satu direktori, simpan di dalam array
x_genuine_pair,
atur
y_genuine
ke
1
. Kemudian kita membaca gambar (
img1
,
img2
) dari direktori yang berbeda, menyimpannya di pasangan
x_imposite,
dan mengatur
y_imposite
ke
0
.
x_genuine_pair
dan
x_imposite
di
X
, dan
y_genuine
dan
y_imposite
di
Y
:
size = 2 total_sample_size = 10000 def get_data(size, total_sample_size):
Sekarang kita akan menghasilkan data dan memeriksa ukurannya. Kami memiliki 20.000 foto, yang dikumpulkan dari 10.000 pasangan asli dan 10.000 pasangan palsu:
X, Y = get_data(size, total_sample_size) X.shape (20000, 2, 1, 56, 46) Y.shape (20000, 1)
Kami akan membagikan seluruh rangkaian informasi: 75% pasangan akan mengikuti pelatihan, dan 25% - untuk menguji:
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=.25)
Sekarang buat jaringan siam. Pertama kita mendefinisikan jaringan inti - itu akan menjadi jaringan saraf convolutional untuk mengekstraksi properti. Buat dua lapisan konvolusional menggunakan aktivasi ReLU dan lapisan dengan penyatuan maksimum setelah lapisan datar:
def build_base_network(input_shape): seq = Sequential() nb_filter = [6, 12] kernel_size = 3
Kemudian kami akan mentransfer sepasang gambar dari jaringan inti, yang akan mengembalikan representasi vektor, mis. Vektor properti:
input_dim = x_train.shape[2:] img_a = Input(shape=input_dim) img_b = Input(shape=input_dim) base_network = build_base_network(input_dim) feat_vecs_a = base_network(img_a) feat_vecs_b = base_network(img_b)
feat_vecs_a
dan
feat_vecs_b
adalah vektor properti dari sepasang gambar. Mari kita lewati fungsi energi mereka untuk menghitung jarak di antara mereka. Dan sebagai fungsi energi, kami menggunakan jarak Euclidean:
def euclidean_distance(vects): x, y = vects return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True)) def eucl_dist_output_shape(shapes): shape1, shape2 = shapes return (shape1[0], 1) distance = Lambda(euclidean_distance, output_shape=eucl_dist_output_shape)([feat_vecs_a, feat_vecs_b])
Kami menetapkan jumlah zaman ke 13, menerapkan properti RMS untuk optimisasi dan mendeklarasikan model:
epochs = 13 rms = RMSprop() model = Model(input=[input_a, input_b], output=distance)
Sekarang kita mendefinisikan fungsi function
contrastive_loss
kerugian dan mengkompilasi model:
def contrastive_loss(y_true, y_pred): margin = 1 return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0))) model.compile(loss=contrastive_loss, optimizer=rms)
Mari kita pelajari modelnya:
img_1 = x_train[:, 0] img_2 = x_train[:, 1] model.fit([img_1, img_2], y_train, validation_split=.25, batch_size=128, verbose=2, nb_epoch=epochs)
Anda melihat bagaimana penurunan kerugian seiring berlalunya waktu:
Train on 11250 samples, validate on 3750 samples Epoch 1/13 - 60s - loss: 0.2179 - val_loss: 0.2156 Epoch 2/13 - 53s - loss: 0.1520 - val_loss: 0.2102 Epoch 3/13 - 53s - loss: 0.1190 - val_loss: 0.1545 Epoch 4/13 - 55s - loss: 0.0959 - val_loss: 0.1705 Epoch 5/13 - 52s - loss: 0.0801 - val_loss: 0.1181 Epoch 6/13 - 52s - loss: 0.0684 - val_loss: 0.0821 Epoch 7/13 - 52s - loss: 0.0591 - val_loss: 0.0762 Epoch 8/13 - 52s - loss: 0.0526 - val_loss: 0.0655 Epoch 9/13 - 52s - loss: 0.0475 - val_loss: 0.0662 Epoch 10/13 - 52s - loss: 0.0444 - val_loss: 0.0469 Epoch 11/13 - 52s - loss: 0.0408 - val_loss: 0.0478 Epoch 12/13 - 52s - loss: 0.0381 - val_loss: 0.0498 Epoch 13/13 - 54s - loss: 0.0356 - val_loss: 0.0363
Dan sekarang mari kita uji model pada data uji:
pred = model.predict([x_test[:, 0], x_test[:, 1]])
Tentukan fungsi untuk menghitung akurasi:
def compute_accuracy(predictions, labels): return labels[predictions.ravel()
Kami menghitung akurasinya:
compute_accuracy(pred, y_test) 0.9779092702169625
Kesimpulan
Dalam panduan ini, kami belajar cara membuat model pengenalan wajah berdasarkan jaringan Siam. Arsitektur jaringan tersebut terdiri dari dua jaringan saraf identik yang memiliki berat dan struktur yang sama, dan hasil pekerjaan mereka ditransfer ke fungsi energi tunggal - ini menentukan identitas data input. Untuk informasi lebih lanjut tentang meta-learning menggunakan
Python, lihat
Hands-On Meta-Learning with Python.Komentar saya
Pengetahuan tentang jaringan Siam saat ini diperlukan saat bekerja dengan gambar. Ada banyak pendekatan untuk melatih jaringan dalam sampel kecil, pembuatan data baru, metode augmentasi. Metode ini memungkinkan relatif "murah" untuk mencapai hasil yang baik, berikut adalah contoh yang lebih klasik dari jaringan Siam di "Hello world" untuk jaringan saraf - dataset MNIST
keras.io/examples/mnist_siamese