🚀 Coba Zilliz Cloud, Milvus yang sepenuhnya terkelola, secara gratis—rasakan performa 10x lebih cepat! Coba Sekarang>>

milvus-logo
LFAI
  • Home
  • Blog
  • Sistem pencarian berdasarkan gambar generasi kedua

Sistem pencarian berdasarkan gambar generasi kedua

  • Scenarios
August 11, 2020
Rife Wang

Artikel ini adalah bagian kedua dari Perjalanan Mengoptimalkan Pencarian Gambar Berskala Miliaran oleh UPYUN. Jika Anda melewatkan bagian pertama, klik di sini.

Sistem pencarian berdasarkan gambar generasi kedua

Sistem pencarian berdasarkan gambar generasi kedua secara teknis memilih solusi CNN + Milvus. Sistem ini didasarkan pada vektor fitur dan memberikan dukungan teknis yang lebih baik.

Ekstraksi fitur

Di bidang visi komputer, penggunaan kecerdasan buatan telah menjadi arus utama. Demikian pula, ekstraksi fitur dari sistem pencarian berdasarkan gambar generasi kedua menggunakan jaringan saraf konvolusi (CNN) sebagai teknologi yang mendasarinya

Istilah CNN sulit untuk dipahami. Di sini kami fokus untuk menjawab dua pertanyaan:

  • Apa yang dapat dilakukan CNN?
  • Mengapa saya dapat menggunakan CNN untuk pencarian gambar?

1-meme.jpg 1-meme.jpg

Ada banyak kompetisi di bidang AI dan klasifikasi gambar adalah salah satu yang paling penting. Tugas klasifikasi gambar adalah menentukan apakah konten gambar tersebut tentang kucing, anjing, apel, pir, atau jenis objek lainnya.

Apa yang bisa dilakukan CNN? CNN dapat mengekstrak fitur dan mengenali objek. Ia mengekstrak fitur dari berbagai dimensi dan mengukur seberapa dekat fitur gambar dengan fitur kucing atau anjing. Kita dapat memilih yang paling dekat sebagai hasil identifikasi kita yang menunjukkan apakah konten gambar tertentu adalah tentang kucing, anjing, atau yang lainnya.

Apa hubungan antara fungsi identifikasi objek CNN dan pencarian berdasarkan gambar? Yang kita inginkan bukanlah hasil identifikasi akhir, tetapi vektor fitur yang diekstrak dari beberapa dimensi. Vektor fitur dari dua gambar dengan konten yang sama harus dekat.

Model CNN mana yang harus saya gunakan?

Jawabannya adalah VGG16. Mengapa memilihnya? Pertama, VGG16 memiliki kemampuan generalisasi yang baik, yaitu sangat fleksibel. Kedua, vektor fitur yang diekstrak oleh VGG16 memiliki 512 dimensi. Jika hanya ada sedikit dimensi, keakuratannya bisa terpengaruh. Jika ada terlalu banyak dimensi, biaya penyimpanan dan penghitungan vektor fitur ini relatif tinggi.

Menggunakan CNN untuk mengekstrak fitur gambar adalah solusi utama. Kita dapat menggunakan VGG16 sebagai model dan Keras + TensorFlow untuk implementasi teknis. Berikut adalah contoh resmi dari Keras:

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np
model = VGG16(weights=’imagenet’, include_top=False)
img_path = ‘elephant.jpg’
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
features = model.predict(x)

Fitur yang diekstrak di sini adalah vektor fitur.

1. Normalisasi

Untuk memudahkan operasi selanjutnya, kita sering melakukan normalisasi fitur:

Apa yang digunakan selanjutnya juga adalah norm_feat yang dinormalisasi.

2. Deskripsi gambar

Gambar dimuat menggunakan metode image.load_img dari keras.preprocessing:

from keras.preprocessing import image
img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))

Sebenarnya, ini adalah metode TensorFlow yang dipanggil oleh Keras. Untuk detailnya, lihat dokumentasi TensorFlow. Objek gambar akhir sebenarnya adalah sebuah contoh gambar PIL (PIL yang digunakan oleh TensorFlow).

3. Konversi byte

Secara praktis, konten gambar sering kali ditransmisikan melalui jaringan. Oleh karena itu, alih-alih memuat gambar dari path, kami lebih memilih untuk mengubah data byte langsung menjadi objek gambar, yaitu PIL Images:

import io
from PIL import Image

# img_bytes: 图片内容 bytes
img = Image.open(io.BytesIO(img_bytes))
img = img.convert('RGB')

img = img.resize((224, 224), Image.NEAREST)

Img di atas sama dengan hasil yang diperoleh dengan metode image.load_img. Ada dua hal yang perlu diperhatikan:

  • Anda harus melakukan konversi RGB.
  • Anda harus mengubah ukuran (mengubah ukuran adalah parameter kedua dari load_img method).

4. Pemrosesan batas hitam

Gambar, seperti tangkapan layar, kadang-kadang mungkin memiliki beberapa batas hitam. Batas hitam ini tidak memiliki nilai praktis dan menyebabkan banyak gangguan. Karena alasan ini, menghilangkan batas hitam juga merupakan praktik yang umum dilakukan.

Batas hitam pada dasarnya adalah baris atau kolom piksel di mana semua pikselnya adalah (0, 0, 0) (gambar RGB). Untuk menghilangkan batas hitam adalah menemukan baris atau kolom ini dan menghapusnya. Ini sebenarnya adalah perkalian matriks 3-D di NumPy.

Contoh menghapus batas hitam horizontal:

# -*- coding: utf-8 -*-
import numpy as np
from keras.preprocessing import image
def RemoveBlackEdge(img):
Args:
       img: PIL image instance
Returns:
       PIL image instance
"""
   width = img.width
   img = image.img_to_array(img)
   img_without_black = img[~np.all(img == np.zeros((1, width, 3), np.uint8), axis=(1, 2))]
   img = image.array_to_img(img_without_black)
return img

Ini adalah hal yang ingin saya bicarakan tentang penggunaan CNN untuk mengekstrak fitur gambar dan mengimplementasikan pemrosesan gambar lainnya. Sekarang mari kita lihat mesin pencari vektor.

Mesin pencari vektor

Masalah mengekstraksi vektor fitur dari gambar sudah terpecahkan. Kemudian masalah yang tersisa adalah:

  • Bagaimana cara menyimpan vektor fitur?
  • Bagaimana cara menghitung kemiripan vektor fitur, yaitu, bagaimana cara mencari? Mesin pencari vektor sumber terbuka Milvus dapat menyelesaikan kedua masalah ini. Sejauh ini, Milvus telah berjalan dengan baik di lingkungan produksi kami.

3-milvus-logo.png 3-milvus-logo.png

Milvus, mesin pencari vektor

Mengekstrak vektor fitur dari sebuah gambar masih jauh dari cukup. Kita juga perlu mengelola vektor fitur ini secara dinamis (penambahan, penghapusan, dan pembaruan), menghitung kemiripan vektor, dan mengembalikan data vektor dalam rentang tetangga terdekat. Mesin pencari vektor sumber terbuka Milvus melakukan tugas-tugas ini dengan cukup baik.

Bagian selanjutnya dari artikel ini akan menjelaskan praktik-praktik spesifik dan hal-hal yang perlu diperhatikan.

1. Persyaratan untuk CPU

Untuk menggunakan Milvus, CPU Anda harus mendukung set instruksi avx2. Untuk sistem Linux, gunakan perintah berikut untuk memeriksa set instruksi mana yang didukung oleh CPU Anda:

cat /proc/cpuinfo | grep flags

Maka Anda akan mendapatkan sesuatu seperti:

flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb         rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2     ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti intel_ppin tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc dtherm ida arat pln pts

Apa yang ditunjukkan oleh flag berikut adalah set instruksi yang didukung oleh CPU Anda. Tentu saja, ini lebih dari yang saya butuhkan. Saya hanya ingin melihat apakah set instruksi tertentu, seperti avx2, didukung. Cukup tambahkan grep untuk menyaringnya:

cat /proc/cpuinfo | grep flags | grep avx2

Jika tidak ada hasil yang dikembalikan, itu berarti set instruksi tertentu tidak didukung. Anda perlu mengganti mesin Anda.

2. Perencanaan kapasitas

Perencanaan kapasitas adalah pertimbangan pertama kita ketika kita mendesain sebuah sistem. Berapa banyak data yang perlu kita simpan? Berapa banyak memori dan ruang disk yang dibutuhkan oleh data tersebut?

Mari kita hitung dengan cepat. Setiap dimensi dari sebuah vektor adalah float32. Tipe float32 membutuhkan 4 Byte. Maka sebuah vektor dengan 512 dimensi membutuhkan 2 KB penyimpanan. Dengan cara yang sama:

  • Seribu vektor 512 dimensi membutuhkan penyimpanan 2 MB.
  • Satu juta vektor 512 dimensi membutuhkan penyimpanan 2 GB.
  • 10 juta vektor 512 dimensi membutuhkan penyimpanan 20 GB.
  • 100 juta vektor 512 dimensi membutuhkan penyimpanan 200 GB.
  • Satu miliar vektor 512 dimensi membutuhkan penyimpanan 2 TB.

Jika kita ingin menyimpan semua data dalam memori, maka sistem membutuhkan setidaknya kapasitas memori yang sesuai.

Anda disarankan untuk menggunakan alat penghitung ukuran resmi: Alat pengukur ukuran Milvus.

Sebenarnya memori kita mungkin tidak sebesar itu. (Tidak masalah jika Anda tidak memiliki cukup memori. Milvus secara otomatis memasukkan data ke dalam disk). Selain data vektor asli, kita juga perlu mempertimbangkan penyimpanan data lain seperti log.

3. Konfigurasi sistem

Untuk informasi lebih lanjut tentang konfigurasi sistem, lihat dokumentasi Milvus:

  • Konfigurasi server Milvus: https://milvus.io/docs/v0.10.1/milvus_config.md

4. Desain basis data

Koleksi & Partisi

  • Koleksi juga dikenal sebagai tabel.
  • Partisi mengacu pada partisi-partisi di dalam koleksi.

Implementasi yang mendasari partisi sebenarnya sama dengan koleksi, kecuali bahwa partisi berada di bawah koleksi. Tetapi dengan partisi, pengaturan data menjadi lebih fleksibel. Kita juga dapat melakukan query pada partisi tertentu di dalam koleksi untuk mendapatkan hasil query yang lebih baik.

Berapa banyak koleksi dan partisi yang dapat kita miliki? Informasi dasar mengenai koleksi dan partisi ada di Metadata. Milvus menggunakan SQLite (integrasi internal Milvus) atau MySQL (membutuhkan koneksi eksternal) untuk manajemen metadata internal. Jika Anda menggunakan SQLite secara default untuk mengelola Metadata, Anda akan mengalami penurunan kinerja yang parah ketika jumlah koleksi dan partisi terlalu besar. Oleh karena itu, jumlah total koleksi dan partisi tidak boleh melebihi 50.000 (Milvus 0.8.0 akan membatasi jumlah ini menjadi 4.096). Jika Anda ingin mengatur jumlah yang lebih besar, Anda disarankan untuk menggunakan MySQL melalui koneksi eksternal.

Struktur data yang didukung oleh koleksi dan partisi Milvus sangat sederhana, yaitu ID + vector. Dengan kata lain, hanya ada dua kolom dalam tabel: ID dan data vektor.

Catatan:

  • ID harus berupa bilangan bulat.
  • Kita perlu memastikan bahwa ID adalah unik di dalam koleksi, bukan di dalam partisi.

Pemfilteran bersyarat

Ketika kita menggunakan basis data tradisional, kita dapat menentukan nilai field sebagai kondisi penyaringan. Meskipun Milvus tidak melakukan penyaringan dengan cara yang persis sama, kita dapat mengimplementasikan penyaringan bersyarat sederhana dengan menggunakan koleksi dan partisi. Sebagai contoh, kita memiliki sejumlah besar data gambar dan data tersebut dimiliki oleh pengguna tertentu. Kemudian kita dapat membagi data ke dalam partisi berdasarkan pengguna. Oleh karena itu, menggunakan pengguna sebagai kondisi filter sebenarnya menentukan partisi.

Data terstruktur dan pemetaan vektor

Milvus hanya mendukung struktur data ID + vektor. Namun dalam skenario bisnis, yang kita butuhkan adalah data terstruktur yang mengandung makna bisnis. Dengan kata lain, kita perlu menemukan data terstruktur melalui vektor. Oleh karena itu, kita perlu mempertahankan hubungan pemetaan antara data terstruktur dan vektor melalui ID.

structured data ID <--> mapping table <--> Milvus ID

Memilih indeks

Anda dapat merujuk ke artikel berikut:

  • Jenis-jenis indeks: https://www.milvus.io/docs/v0.10.1/index.md
  • Cara memilih indeks: https://medium.com/@milvusio/cara-memilih-indeks-di-milvus-4f3d15259212

5. Memproses hasil pencarian

Hasil pencarian Milvus adalah kumpulan ID + jarak:

  • ID: ID dalam sebuah koleksi.
  • Jarak: nilai jarak 0 ~ 1 menunjukkan tingkat kemiripan; semakin kecil nilainya, semakin mirip kedua vektor.

Memfilter data yang ID-nya -1

Ketika jumlah koleksi terlalu sedikit, hasil pencarian mungkin berisi data yang ID-nya -1. Kita perlu menyaringnya sendiri.

Penomoran halaman

Pencarian untuk vektor sangat berbeda. Hasil kueri diurutkan berdasarkan urutan kemiripan, dan hasil yang paling mirip (topK) dipilih (topK ditentukan oleh pengguna pada saat kueri).

Milvus tidak mendukung pagination. Kita perlu mengimplementasikan fungsi pagination sendiri jika kita membutuhkannya untuk bisnis. Sebagai contoh, jika kita memiliki sepuluh hasil di setiap halaman dan hanya ingin menampilkan halaman ketiga, kita perlu menentukan bahwa topK = 30 dan hanya mengembalikan sepuluh hasil terakhir.

Ambang batas kemiripan untuk bisnis

Jarak antara vektor dua gambar adalah antara 0 dan 1. Jika kita ingin memutuskan apakah dua gambar mirip dalam skenario bisnis tertentu, kita perlu menentukan ambang batas dalam kisaran ini. Dua gambar serupa jika jaraknya lebih kecil dari ambang batas, atau sangat berbeda satu sama lain jika jaraknya lebih besar dari ambang batas. Anda perlu menyesuaikan ambang batas untuk memenuhi kebutuhan bisnis Anda.

Artikel ini ditulis oleh rifewang, pengguna Milvus dan insinyur perangkat lunak UPYUN. Jika Anda menyukai artikel ini, selamat datang untuk menyapa di https://github.com/rifewang.

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

Terus Baca