Image captioning, kemampuan untuk secara otomatis menghasilkan deskripsi tekstual dari sebuah gambar, merupakan salah satu bidang paling menarik di persimpangan Computer Vision dan Natural Language Processing (NLP). Teknologi ini memiliki potensi aplikasi yang luas, mulai dari meningkatkan aksesibilitas web bagi penyandang tunanetra hingga memungkinkan pengindeksan dan pencarian gambar yang lebih cerdas. Dalam tutorial ini, kita akan membahas langkah demi langkah cara membangun model image captioning sederhana menggunakan arsitektur encoder-decoder yang populer, menggabungkan Convolutional Neural Network (CNN) untuk memahami gambar dan Long Short-Term Memory (LSTM) untuk menghasilkan teks, dengan implementasi menggunakan Keras/TensorFlow.
Memahami Dasar-Dasar Image Captioning
Apa Itu Image Captioning dan Mengapa Penting?
Image captioning adalah tugas menghasilkan deskripsi bahasa alami (caption) yang relevan untuk konten visual dalam sebuah gambar. Ini lebih dari sekadar klasifikasi gambar (mengenali objek utama) atau deteksi objek (menemukan lokasi objek); image captioning bertujuan untuk menangkap hubungan antar objek, atributnya, dan tindakan yang terjadi, lalu menyajikannya dalam bentuk kalimat yang koheren.
Pentingnya image captioning terletak pada kemampuannya untuk:
- Meningkatkan Aksesibilitas: Memberikan deskripsi gambar untuk pengguna tunanetra melalui pembaca layar.
- Memperkaya Pengalaman Pengguna: Menyediakan konteks tambahan untuk gambar di media sosial atau platform berita.
- Pengindeksan dan Pencarian Konten Visual: Memungkinkan pencarian gambar berdasarkan deskripsi kontennya, bukan hanya metadata.
- Interaksi Manusia-Robot: Memungkinkan robot untuk mendeskripsikan lingkungan visualnya.
Meskipun demikian, membangun model image captioning yang akurat dan relevan secara kontekstual tetap menjadi tantangan, terutama dalam menangani kompleksitas visual dan nuansa bahasa.
Mengenal Arsitektur Umum: Model Encoder-Decoder (CNN+LSTM)
Pendekatan yang paling umum digunakan untuk image captioning adalah arsitektur encoder-decoder. Arsitektur ini terdiri dari dua komponen utama:
- Encoder (Biasanya CNN): Bagian ini bertugas untuk ‘memahami’ gambar. Model Convolutional Neural Network (CNN), seringkali yang telah dilatih sebelumnya (pre-trained) pada dataset klasifikasi gambar besar seperti ImageNet (misalnya VGG16, InceptionV3, ResNet), digunakan untuk mengekstrak fitur-fitur visual penting dari gambar input. Output dari lapisan terakhir (atau salah satu lapisan sebelumnya) CNN berfungsi sebagai representasi vektor yang ringkas dari konten gambar.
- Decoder (Biasanya RNN/LSTM/GRU): Bagian ini bertugas untuk menghasilkan sequence kata (caption). Recurrent Neural Network (RNN), khususnya varian seperti Long Short-Term Memory (LSTM) atau Gated Recurrent Unit (GRU) yang lebih baik dalam menangani dependensi jangka panjang, digunakan di sini. Decoder menerima representasi gambar dari encoder (sebagai konteks awal atau input berulang) dan menghasilkan caption kata demi kata. Pada setiap langkah waktu, LSTM memprediksi kata berikutnya dalam sequence berdasarkan kata sebelumnya dan konteks gambar. Arsitektur
cnn lstm image captioning
inilah yang akan kita fokuskan dalam tutorial ini.
Secara konseptual, encoder mengubah gambar menjadi representasi numerik (vektor fitur), dan decoder mengubah representasi numerik tersebut kembali menjadi sequence bahasa alami (caption). Transisi ini memungkinkan model menjembatani pemahaman visual dengan generasi bahasa.
Persiapan Lingkungan dan Dataset untuk Tutorial
Instalasi Library Pendukung: TensorFlow, Keras, dan Lainnya
Sebelum memulai, pastikan Anda telah menginstal library Python yang diperlukan. Library utama adalah TensorFlow (yang kini menyertakan Keras). Kita juga memerlukan library lain untuk manipulasi data dan pemrosesan gambar.
Anda dapat menginstalnya menggunakan pip:
pip install tensorflow numpy pandas matplotlib Pillow nltk scikit-learn
Catatan: nltk
mungkin diperlukan untuk tokenisasi atau pembersihan teks tingkat lanjut, meskipun Keras Tokenizer seringkali sudah cukup. scikit-learn
bisa berguna untuk membagi data latih dan validasi.
Menyiapkan Lingkungan Kerja: Python dan Jupyter/Google Colab
Tutorial ini dirancang untuk dijalankan di lingkungan Python (disarankan versi 3.7 atau lebih baru). Menggunakan Jupyter Notebook atau Google Colaboratory sangat direkomendasikan karena memungkinkan eksekusi kode sel demi sel, visualisasi, dan eksperimen yang mudah, terutama saat bekerja dengan data gambar dan model deep learning.
Memilih Dataset: Menggunakan Flickr8k untuk Pembelajaran Awal
Untuk tutorial ini, kita akan menggunakan dataset Flickr8k (image captioning dataset flickr8k
), yang merupakan pilihan populer untuk pemula karena ukurannya yang relatif kecil dibandingkan dataset lain seperti COCO atau Flickr30k.
Dataset Flickr8k terdiri dari:
- 8.000 gambar.
- 5 caption referensi per gambar, yang ditulis oleh manusia.
Anda perlu mengunduh dataset ini. Biasanya terdiri dari dua bagian utama:
- Folder berisi file gambar (misalnya,
Flicker8k_Dataset
). - File teks berisi nama file gambar dan caption-nya (misalnya,
Flickr8k.token.txt
).
Anda dapat mencari “Flickr8k dataset download” untuk menemukan sumber unduhan (seringkali melalui Kaggle atau repositori universitas). Setelah mengunduh, ekstrak file-file tersebut ke direktori kerja proyek Anda.
Alternatif: Jika Flickr8k masih terasa besar atau Anda hanya ingin mencoba konsepnya dengan cepat, Anda bisa menggunakan subset yang lebih kecil dari dataset ini untuk percobaan awal.
Tahap Pra-pemrosesan Data Gambar (Input Encoder)
Langkah ini fokus pada persiapan data gambar agar siap dimasukkan ke dalam model CNN (encoder). Proses ini sering disebut sebagai pra pemrosesan data image captioning
dari sisi visual.
Memuat dan Menyesuaikan Ukuran Gambar
Model CNN pre-trained biasanya mengharapkan gambar input dengan ukuran tertentu (misalnya, 224×224 untuk VGG16, 299×299 untuk InceptionV3). Kita perlu memuat setiap gambar dari dataset dan mengubah ukurannya sesuai kebutuhan model CNN yang akan kita gunakan sebagai encoder.
import os
from tensorflow.keras.preprocessing.image import load_img, img_to_array
from tensorflow.keras.applications.inception_v3 import preprocess_input
import numpy as np
# Tentukan path ke folder gambar dan ukuran target
image_folder = 'path/to/Flicker8k_Dataset' # Ganti dengan path direktori dataset Anda
target_size = (299, 299) # Sesuaikan dengan model CNN (misal InceptionV3)
def load_and_preprocess_image(image_path, target_size):
"""Memuat, mengubah ukuran, dan melakukan pra-pemrosesan satu gambar."""
try:
img = load_img(image_path, target_size=target_size)
# Ubah gambar menjadi array numpy
img_array = img_to_array(img)
# Tambahkan dimensi batch (model Keras mengharapkan input batch)
img_array = np.expand_dims(img_array, axis=0)
# Lakukan pra-pemrosesan sesuai standar model InceptionV3
# Ini biasanya mencakup penskalaan pixel ke rentang tertentu
img_array = preprocess_input(img_array)
return img_array
except Exception as e:
print(f"Error saat memuat gambar {image_path}: {e}")
return None
# Contoh penggunaan (nantinya akan diterapkan ke semua gambar):
# # Ganti 'example.jpg' dengan nama file gambar yang valid
# sample_image_path = os.path.join(image_folder, '1000268201_693b08cb0e.jpg')
# preprocessed_img = load_and_preprocess_image(sample_image_path, target_size)
# if preprocessed_img is not None:
# print(f"Shape gambar setelah pra-pemrosesan: {preprocessed_img.shape}") # Harusnya (1, 299, 299, 3)
Normalisasi Nilai Pixel Gambar
Normalisasi nilai pixel gambar adalah langkah krusial. Model deep learning umumnya bekerja lebih baik ketika nilai input berada dalam rentang yang konsisten (misalnya, 0 hingga 1 atau -1 hingga 1). Fungsi preprocess_input
yang disediakan oleh Keras untuk model pre-trained (seperti InceptionV3 yang kita gunakan) biasanya sudah mencakup normalisasi yang sesuai untuk model tersebut.
Jika Anda tidak menggunakan preprocess_input
bawaan, metode normalisasi umum adalah membagi semua nilai pixel (yang biasanya dalam rentang 0-255) dengan 255.0 untuk mendapatkan rentang 0-1.
# Contoh normalisasi manual jika tidak pakai preprocess_input:
# img = load_img(image_path, target_size=target_size)
# img_array = img_to_array(img)
# img_array = img_array / 255.0 # Normalisasi ke rentang [0, 1]
# img_array = np.expand_dims(img_array, axis=0) # Tambah dimensi batch
Ekstraksi Fitur Gambar Menggunakan CNN Pre-trained
Melatih CNN dari awal membutuhkan dataset yang sangat besar dan waktu komputasi yang signifikan. Oleh karena itu, kita akan menggunakan teknik transfer learning. Kita memuat model CNN yang sudah dilatih (misalnya, InceptionV3) tanpa lapisan klasifikasi terakhirnya (dengan parameter include_top=False
). Kemudian, kita melewatkan setiap gambar yang sudah dipra-proses melalui model ini untuk mendapatkan vektor fitur (feature vector) yang merepresentasikan konten visual gambar tersebut.
from tensorflow.keras.applications import InceptionV3
from tensorflow.keras.models import Model
import pickle # Untuk menyimpan hasil ekstraksi fitur
# Muat model InceptionV3 pre-trained (bobot dari ImageNet) tanpa lapisan klasifikasi atas
base_model = InceptionV3(weights='imagenet')
# Buat model baru yang outputnya adalah layer sebelum fully connected layer terakhir ('avg_pool')
# Lapisan ini memberikan representasi fitur yang ringkas
cnn_model = Model(inputs=base_model.input, outputs=base_model.layers[-2].output)
# Fungsi untuk mengekstrak fitur dari semua gambar dalam folder
# Disarankan menyimpan fitur ini agar tidak perlu dihitung ulang setiap kali menjalankan kode
def extract_features(image_folder, cnn_model, target_size):
features = {}
# Dapatkan daftar semua file gambar (.jpg)
all_image_files = [f for f in os.listdir(image_folder) if f.endswith('.jpg')]
total_images = len(all_image_files)
print(f"Memulai ekstraksi fitur untuk {total_images} gambar...")
for i, image_file in enumerate(all_image_files):
image_path = os.path.join(image_folder, image_file)
# Muat dan pra-proses gambar
img_array = load_and_preprocess_image(image_path, target_size)
if img_array is not None:
# Dapatkan vektor fitur dari model CNN
feature_vector = cnn_model.predict(img_array, verbose=0) # Output shape (1, 2048) untuk InceptionV3 avg_pool
# Simpan fitur dengan nama file gambar sebagai key (tanpa ekstensi .jpg)
image_id = image_file.split('.')[0]
features[image_id] = feature_vector.flatten() # Flatten agar menjadi array 1D
# Tampilkan progress setiap 100 gambar
if (i + 1) % 100 == 0:
print(f"Selesai memproses {i + 1}/{total_images} gambar")
print(f"Ekstraksi fitur selesai.")
return features
# --- Eksekusi Ekstraksi Fitur (jalankan sekali) ---
# # Pastikan variabel image_folder, cnn_model, target_size sudah didefinisikan
# image_features = extract_features(image_folder, cnn_model, target_size)
#
# # Simpan fitur ke file menggunakan pickle untuk penggunaan nanti
# output_feature_file = 'image_features_inceptionv3.pkl'
# print(f"Menyimpan fitur ke {output_feature_file}...")
# with open(output_feature_file, 'wb') as f:
# pickle.dump(image_features, f)
# print(f"Fitur gambar berhasil disimpan.")
# --- Muat Fitur dari File (untuk penggunaan selanjutnya) ---
# feature_file = 'image_features_inceptionv3.pkl'
# try:
# with open(feature_file, 'rb') as f:
# image_features = pickle.load(f)
# print(f"Fitur gambar berhasil dimuat dari {feature_file}.")
# except FileNotFoundError:
# print(f"Error: File fitur {feature_file} tidak ditemukan. Jalankan ekstraksi fitur terlebih dahulu.")
# image_features = None # Pastikan variabel ada meskipun kosong
Setelah langkah ini, kita memiliki kamus (dictionary) `image_features` yang berisi representasi numerik (vektor fitur) untuk setiap gambar dalam dataset, siap digunakan oleh bagian decoder.
Tahap Pra-pemrosesan Data Teks (Input Decoder)
Sekarang kita beralih ke persiapan data teks (caption). Ini adalah bagian penting kedua dari pra pemrosesan data image captioning
, yang fokus pada sisi bahasa.
Memuat dan Membersihkan Teks Caption
Pertama, kita perlu membaca file yang berisi caption (misalnya, Flickr8k.token.txt
). File ini biasanya memiliki format nama_file_gambar#nomor_caption[tab]caption_teks
. Kita perlu mem-parsing file ini, membersihkan teks caption (mengubah ke huruf kecil, menghapus tanda baca dan angka, menghapus kata pendek), dan membuat struktur data (seperti dictionary) yang memetakan setiap ID gambar ke daftar caption bersihnya.
import string
def load_captions(filename):
"""Memuat dan mem-parsing file caption dari format Flickr8k."""
captions_map = {}
try:
with open(filename, 'r') as f:
for line in f:
# Split berdasarkan tab atau spasi pertama
parts = line.split('\t')
if len(parts) != 2:
parts = line.split(' ', 1)
if len(parts) != 2:
continue # Lewati baris yang formatnya tidak sesuai
image_id_part, caption = parts
# Ambil ID gambar bersih (nama file tanpa #N dan ekstensi)
image_id = image_id_part.split('#')[0].split('.')[0]
caption = caption.strip()
# Inisialisasi list jika ID gambar baru
if image_id not in captions_map:
captions_map[image_id] = []
captions_map[image_id].append(caption)
except FileNotFoundError:
print(f"Error: File caption '{filename}' tidak ditemukan.")
return None
return captions_map
def clean_captions(captions_map):
"""Membersihkan teks caption: lowercase, hapus tanda baca, angka, kata pendek."""
# Buat tabel translasi untuk menghapus tanda baca
table = str.maketrans('', '', string.punctuation)
cleaned_captions = {}
for image_id, caption_list in captions_map.items():
cleaned_captions[image_id] = []
for caption in caption_list:
# Ubah ke huruf kecil
caption = caption.lower()
# Hapus tanda baca
caption = caption.translate(table)
# Hapus kata yang mengandung angka atau hanya satu huruf
words = caption.split()
words = [word for word in words if word.isalpha() and len(word) > 1]
# Gabungkan kembali menjadi string
cleaned_caption = ' '.join(words)
cleaned_captions[image_id].append(cleaned_caption)
return cleaned_captions
# Ganti dengan path file token Flickr8k Anda
caption_file = 'path/to/Flickr8k.token.txt'
all_captions = load_captions(caption_file)
cleaned_captions_map = None
if all_captions:
print(f"Berhasil memuat {len(all_captions)} gambar dengan caption.")
cleaned_captions_map = clean_captions(all_captions)
# Tampilkan contoh caption bersih untuk satu gambar
# first_image_id = list(cleaned_captions_map.keys())[0]
# print(f"\nContoh caption bersih untuk gambar '{first_image_id}':")
# for cap in cleaned_captions_map[first_image_id]:
# print(f"- {cap}")
else:
print("Gagal memuat caption. Pastikan path file benar.")
Membuat Vocabulary dan Melakukan Tokenisasi Teks
Model deep learning tidak bisa memproses teks mentah. Kita perlu mengubah kata-kata menjadi representasi numerik. Langkah pertama adalah membuat ‘vocabulary’, yaitu kumpulan semua kata unik yang ada di seluruh caption yang sudah dibersihkan. Kemudian, kita menggunakan `Tokenizer` dari Keras untuk memetakan setiap kata unik ke sebuah indeks numerik (token).
from tensorflow.keras.preprocessing.text import Tokenizer
def create_tokenizer(cleaned_captions_map):
"""Membuat dan melatih (fit) tokenizer Keras pada semua caption."""
# Kumpulkan semua teks caption bersih menjadi satu list besar
all_caption_texts = []
for key in cleaned_captions_map:
for caption in cleaned_captions_map[key]:
all_caption_texts.append(caption)
# Inisialisasi tokenizer Keras
tokenizer = Tokenizer()
# Fit tokenizer pada seluruh teks caption
# Ini akan membangun vocabulary (word -> index mapping)
tokenizer.fit_on_texts(all_caption_texts)
return tokenizer
# Hanya jalankan jika cleaned_captions_map berhasil dibuat
tokenizer = None
vocab_size = 0
if cleaned_captions_map:
tokenizer = create_tokenizer(cleaned_captions_map)
# Ukuran vocabulary adalah jumlah kata unik + 1 (untuk indeks 0, biasanya padding)
vocab_size = len(tokenizer.word_index) + 1
print(f"\nUkuran Vocabulary (termasuk token OOV): {vocab_size}")
# Contoh melihat mapping kata ke indeks
# print(f"Indeks untuk kata 'dog': {tokenizer.word_index.get('dog')}")
# print(f"Indeks untuk kata 'woman': {tokenizer.word_index.get('woman')}")
# print(f"Kata untuk indeks 5: {tokenizer.index_word.get(5)}")
else:
print("Tokenizer tidak dapat dibuat karena data caption tidak tersedia.")
Menambahkan Token Khusus `startseq` dan `endseq`
Dalam model sequence-to-sequence seperti image captioning, sangat penting untuk memberi sinyal kapan sebuah sequence (caption) dimulai dan kapan berakhir. Kita menambahkan token khusus, biasanya startseq
dan endseq
, ke awal dan akhir setiap caption. Ini membantu model LSTM belajar kapan harus mulai menghasilkan kata dan kapan harus berhenti.
# Modifikasi dictionary caption untuk menambahkan token start/end
def add_start_end_tokens(cleaned_captions_map):
captions_with_tokens = {}
for img_id, cap_list in cleaned_captions_map.items():
captions_with_tokens[img_id] = []
for caption in cap_list:
# Tambahkan token 'startseq' di awal dan 'endseq' di akhir
modified_caption = 'startseq ' + caption + ' endseq'
captions_with_tokens[img_id].append(modified_caption)
return captions_with_tokens
final_captions_map = None
if cleaned_captions_map:
final_captions_map = add_start_end_tokens(cleaned_captions_map)
# Penting: Pastikan tokenizer juga mengenali token 'startseq' dan 'endseq'.
# Jika tokenizer dibuat SEBELUM menambahkan token ini, vocabulary mungkin perlu diupdate.
# Cara termudah adalah membuat tokenizer SETELAH menambahkan token start/end.
# Jika tokenizer sudah dibuat, pastikan kata 'startseq' dan 'endseq' ada di tokenizer.word_index.
# Jika tokenizer dibuat setelah menambahkan token:
# tokenizer = create_tokenizer(final_captions_map)
# vocab_size = len(tokenizer.word_index) + 1
# print(f"Ukuran Vocabulary setelah token start/end: {vocab_size}")
# Periksa apakah token ada di tokenizer (jika dibuat sebelumnya)
if tokenizer and ('startseq' not in tokenizer.word_index or 'endseq' not in tokenizer.word_index):
print("Warning: Tokenizer mungkin belum mengenali 'startseq' atau 'endseq'. Pertimbangkan membuat ulang tokenizer.")
# Tampilkan contoh caption dengan token
# first_image_id = list(final_captions_map.keys())[0]
# print(f"\nContoh caption dengan token untuk '{first_image_id}':")
# print(f"- {final_captions_map[first_image_id][0]}")
Konversi Caption ke Sequence Angka dan Melakukan Padding
Setelah memiliki tokenizer yang ‘fit’, kita ubah setiap caption (yang kini memiliki token startseq
dan endseq
) menjadi urutan (sequence) indeks numerik menggunakan metode `texts_to_sequences`. Karena caption memiliki panjang yang bervariasi, sementara input model LSTM biasanya memerlukan panjang yang tetap, kita perlu melakukan padding. Kita tentukan panjang maksimum caption (`max_length`) dalam dataset dan menambahkan nilai khusus (biasanya 0) di awal (pre-padding) atau akhir (post-padding) sequence yang lebih pendek agar semua sequence memiliki panjang yang sama.
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical
import numpy as np
def get_max_length(final_captions_map):
"""Menghitung panjang caption maksimum setelah ditambah token start/end."""
all_final_texts = []
for key in final_captions_map:
for caption in final_captions_map[key]:
all_final_texts.append(caption)
return max(len(caption.split()) for caption in all_final_texts)
max_length = 0
if final_captions_map:
max_length = get_max_length(final_captions_map)
print(f"\nPanjang caption maksimum setelah token: {max_length}")
# Fungsi krusial untuk membuat data input-output untuk training LSTM
# Model akan belajar memprediksi kata berikutnya (output y) berdasarkan fitur gambar (X1) dan sequence kata sebelumnya (X2)
def create_sequences(tokenizer, max_length, captions_dict, features_dict, vocab_size):
X1, X2, y = list(), list(), list()
# Iterasi melalui semua ID gambar dalam dictionary caption
image_ids = list(captions_dict.keys())
print(f"Membuat sequence training dari {len(image_ids)} gambar...")
processed_count = 0
for img_id in image_ids:
# Pastikan fitur gambar untuk ID ini sudah diekstrak
if img_id not in features_dict:
continue # Lewati jika fitur gambar tidak ditemukan
captions = captions_dict[img_id]
# Iterasi melalui semua caption untuk gambar ini
for caption in captions:
# Ubah caption menjadi sequence angka (token)
seq = tokenizer.texts_to_sequences()[0]
# Buat pasangan input-output untuk setiap kata dalam sequence
# Model belajar memprediksi seq[i] berdasarkan seq[:i]
for i in range(1, len(seq)):
# Input sequence: kata dari awal hingga sebelum kata target
in_seq = seq[:i]
# Output: kata target (kata berikutnya)
out_seq = seq[i]
# Pad input sequence agar panjangnya sama (max_length)
in_seq_padded = pad_sequences([in_seq], maxlen=max_length, padding='pre')[0]
# Output bisa berupa index saja (jika menggunakan sparse_categorical_crossentropy)
# atau one-hot encoded (jika menggunakan categorical_crossentropy)
# out_word_index = to_categorical([out_seq], num_classes=vocab_size)[0]
out_word_index = out_seq # Simpan sebagai index
# Simpan fitur gambar (X1), sequence input (X2), dan kata output (y)
X1.append(features_dict[img_id]) # Fitur gambar
X2.append(in_seq_padded) # Sequence kata input
y.append(out_word_index) # Kata target (index)
processed_count += 1
if processed_count % 1000 == 0:
print(f"Telah memproses {processed_count}/{len(image_ids)} gambar untuk sequence.")
print(f"Pembuatan sequence selesai. Jumlah sampel: {len(X1)}")
return np.array(X1), np.array(X2), np.array(y)
# --- Membagi Data Train/Validation SEBELUM Membuat Sequence ---
# Penting untuk membagi ID gambar menjadi set training dan validasi
# agar gambar yang sama tidak muncul di kedua set.
# train_ids = ... # Daftar ID gambar untuk training
# val_ids = ... # Daftar ID gambar untuk validasi
# # Buat dictionary caption dan fitur terpisah untuk train dan val
# train_captions = {img_id: final_captions_map[img_id] for img_id in train_ids if img_id in final_captions_map}
# train_features = {img_id: image_features[img_id] for img_id in train_ids if img_id in image_features}
# val_captions = {img_id: final_captions_map[img_id] for img_id in val_ids if img_id in final_captions_map}
# val_features = {img_id: image_features[img_id] for img_id in val_ids if img_id in image_features}
# # Sekarang buat sequence untuk training dan validasi
# if tokenizer and max_length > 0 and 'image_features' in locals() and image_features:
# # Membuat data training
# X1_train, X2_train, y_train = create_sequences(tokenizer, max_length, train_captions, train_features, vocab_size)
# print(f"\nShape data training:")
# print(f" Fitur Gambar (X1_train): {X1_train.shape}")
# print(f" Sequence Input (X2_train): {X2_train.shape}")
# print(f" Target Output (y_train): {y_train.shape}")
#
# # Membuat data validasi
# X1_val, X2_val, y_val = create_sequences(tokenizer, max_length, val_captions, val_features, vocab_size)
# print(f"\nShape data validasi:")
# print(f" Fitur Gambar (X1_val): {X1_val.shape}")
# print(f" Sequence Input (X2_val): {X2_val.shape}")
# print(f" Target Output (y_val): {y_val.shape}")
# else:
# print("\nTidak dapat membuat sequence. Pastikan tokenizer, max_length, dan image_features sudah siap.")
Dengan langkah ini, kita telah menyiapkan data gambar (vektor fitur `X1`) dan data teks (sequence angka input `X2` dan target output `y`) yang siap digunakan untuk melatih model image captioning keras tensorflow
.
Membangun Model Encoder-Decoder dengan Keras
Sekarang kita akan mendefinisikan arsitektur model cnn lstm image captioning
menggunakan Keras Functional API. Model ini akan menerima dua input: fitur gambar dan sequence kata.
Definisi Input dan Lapisan Awal
Kita memerlukan dua input: satu untuk vektor fitur gambar yang diekstrak oleh CNN, dan satu lagi untuk sequence caption yang sudah di-tokenisasi dan di-padding.
from tensorflow.keras.layers import Input, Dense, LSTM, Embedding, Dropout, add
from tensorflow.keras.models import Model
# Dimensi dari vektor fitur gambar (output InceptionV3 avg_pool)
# Sesuaikan jika Anda menggunakan CNN atau lapisan output yang berbeda
feature_dim = 2048
# Dimensi embedding untuk kata-kata (bisa disesuaikan)
embedding_dim = 256
# Dimensi output LSTM (bisa disesuaikan)
lstm_units = 256
# Input 1: Vektor fitur gambar
input_img_features = Input(shape=(feature_dim,), name='image_features_input')
# Lapisan untuk memproses fitur gambar, mungkin mengurangi dimensi
# dan menambahkan non-linearitas. Dropout untuk regularisasi.
img_feature_proc = Dropout(0.5)(input_img_features)
img_feature_dense = Dense(embedding_dim, activation='relu', name='feature_projection')(img_feature_proc)
# Input 2: Sequence caption (integer yang sudah di-pad)
input_caption_seq = Input(shape=(max_length,), name='caption_sequence_input')
# Lapisan Embedding: Mengubah indeks kata menjadi vektor padat
# mask_zero=True penting untuk memberitahu LSTM agar mengabaikan padding (nilai 0)
seq_embedding = Embedding(vocab_size, embedding_dim, mask_zero=True, name='word_embedding')(input_caption_seq)
# Dropout pada embedding
seq_proc = Dropout(0.5)(seq_embedding)
Menggabungkan Fitur Gambar dan Teks dalam Decoder LSTM
Pendekatan umum adalah menggunakan fitur gambar yang telah diproses untuk menginisialisasi *state* dari LSTM. Namun, untuk implementasi yang lebih sederhana (seperti yang sering dimulai), kita bisa menggabungkan fitur gambar dengan input teks *sebelum* masuk ke LSTM, atau menggabungkan output LSTM dengan fitur gambar *setelahnya*. Di sini, kita akan coba menggabungkan fitur gambar (yang sudah di-Dense) dengan output dari lapisan Embedding kata menggunakan lapisan `add`. Ini menyiratkan bahwa informasi gambar ‘disuntikkan’ di setiap langkah waktu LSTM.
Catatan: Penggabungan ini memerlukan dimensi yang cocok. Karena `img_feature_dense` memiliki shape `(batch_size, embedding_dim)` dan `seq_proc` memiliki shape `(batch_size, max_length, embedding_dim)`, penggabungan langsung dengan `add` tidak bisa dilakukan seperti ini. Pendekatan yang lebih tepat adalah menggunakan fitur gambar sebagai initial state LSTM atau menggunakan mekanisme Attention.
Untuk tutorial ini, mari kita gunakan pendekatan yang sedikit berbeda dan lebih umum untuk model sederhana: fitur gambar akan diproses, sequence kata akan diproses oleh LSTM, dan kemudian output LSTM akan digunakan untuk prediksi akhir. Konteks gambar secara implisit diharapkan tertangkap oleh LSTM selama training karena pasangan (gambar, sequence) yang benar diberikan.
# --- Pendekatan Sederhana: LSTM memproses sequence, outputnya ke prediksi ---
# Lapisan LSTM memproses sequence embedding kata
# LSTM akan menghasilkan output di langkah waktu terakhir (jika return_sequences=False)
# atau output di setiap langkah waktu (jika return_sequences=True)
# Untuk prediksi kata berikutnya, kita butuh output di setiap langkah.
lstm_layer = LSTM(lstm_units, return_sequences=False, name='lstm_decoder')(seq_proc) # Ubah return_sequences jika perlu
# Tambahkan Dropout setelah LSTM
lstm_dropout = Dropout(0.5)(lstm_layer)
# --- Menggabungkan Konteks Gambar dan Teks (Alternatif jika dimensi cocok) ---
# Jika kita ingin menggabungkan informasi gambar *setelah* LSTM:
# Misal, jika img_feature_dense dan lstm_layer punya dimensi sama (misal 256)
# combined_context = add([img_feature_dense, lstm_layer])
# final_dropout = Dropout(0.5)(combined_context)
# output_dense = Dense(vocab_size, activation='softmax', name='output_predictor')(final_dropout)
# --- Output Layer Langsung dari LSTM (Paling Sederhana) ---
# Lapisan Dense terakhir untuk memprediksi kata berikutnya dari vocabulary
# Inputnya adalah output dari LSTM (setelah dropout)
output_dense = Dense(vocab_size, activation='softmax', name='output_word_predictor')(lstm_dropout)
# Mendefinisikan Model Keras
# Model ini menerima dua input: fitur gambar dan sequence caption
# dan menghasilkan probabilitas untuk setiap kata dalam vocabulary
model = Model(inputs=[input_img_features, input_caption_seq], outputs=output_dense, name='simple_captioning_model')
# Tampilkan ringkasan model
print(model.summary())
Model ini sekarang siap untuk dikompilasi dan dilatih. Arsitektur ini, meskipun sederhana, menangkap esensi dari model encoder-decoder untuk image captioning.
Melatih Model Image Captioning Anda dengan Python
Setelah model didefinisikan, langkah berikutnya adalah melatih model image captioning python
ini menggunakan data yang telah kita siapkan.
Menentukan Fungsi Loss dan Optimizer
Karena tugas kita adalah memprediksi kata berikutnya dari vocabulary (masalah klasifikasi multi-kelas), dan target output kita (y_train
, y_val
) adalah indeks integer (bukan vektor one-hot), kita akan menggunakan fungsi loss sparse_categorical_crossentropy
. Optimizer yang populer dan seringkali memberikan hasil baik untuk jenis tugas ini adalah Adam
.
# Kompilasi model dengan loss function dan optimizer
# Kita juga menyertakan 'accuracy' sebagai metrik untuk dipantau selama training
model.compile(loss='sparse_categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
print("\nModel berhasil dikompilasi.")
Melaksanakan Proses Training Menggunakan `model.fit`
Kita akan melatih model menggunakan data training yang sudah kita buat (X1_train
, X2_train
, y_train
). Jika dataset terlalu besar untuk dimuat ke memori sekaligus (meskipun Flickr8k mungkin masih muat), Anda perlu membuat generator data menggunakan tf.data.Dataset
atau subclass keras.utils.Sequence
.
Kita juga akan menggunakan data validasi (X1_val
, X2_val
, y_val
) untuk memantau kinerja model pada data yang tidak terlihat selama training dan mencegah overfitting.
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
import os
# Pastikan variabel data training (X1_train, X2_train, y_train)
# dan data validasi (X1_val, X2_val, y_val) sudah tersedia.
# Tentukan parameter training
epochs = 20 # Jumlah epoch (iterasi penuh pada dataset). Sesuaikan sesuai kebutuhan.
batch_size = 64 # Jumlah sampel yang diproses sebelum memperbarui bobot. Sesuaikan.
# Direktori untuk menyimpan bobot model terbaik
weights_dir = 'model_weights'
os.makedirs(weights_dir, exist_ok=True)
checkpoint_path = os.path.join(weights_dir, 'best_model_weights.weights.h5')
# Callback untuk menyimpan bobot model terbaik berdasarkan loss validasi
model_checkpoint = ModelCheckpoint(filepath=checkpoint_path,
monitor='val_loss', # Pantau loss pada data validasi
save_best_only=True, # Simpan hanya jika performa membaik
save_weights_only=True, # Hanya simpan bobot, bukan seluruh model
mode='min', # Mode 'min' karena kita memantau loss (ingin minimum)
verbose=1)
# Callback untuk menghentikan training lebih awal jika tidak ada perbaikan
early_stopping = EarlyStopping(monitor='val_loss', # Pantau loss validasi
patience=5, # Jumlah epoch tanpa perbaikan sebelum berhenti (misal 5)
mode='min',
restore_best_weights=True, # Kembalikan bobot terbaik saat berhenti
verbose=1)
# Mulai proses training
print("\nMemulai training model...")
# history = model.fit(
# [X1_train, X2_train], # Input: list berisi array fitur gambar dan array sequence caption
# y_train, # Output: array berisi indeks kata target
# epochs=epochs,
# batch_size=batch_size,
# validation_data=([X1_val, X2_val], y_val), # Data validasi untuk evaluasi per epoch
# callbacks=[model_checkpoint, early_stopping], # Gunakan callbacks yang sudah didefinisikan
# verbose=1 # Tampilkan progress bar (1) atau ringkasan per epoch (2)
# )
# print("\nTraining selesai.")
# Anda bisa menyimpan history untuk memvisualisasikan kurva learning nanti
# import matplotlib.pyplot as plt
#
# def plot_history(history):
# plt.figure(figsize=(12, 5))
# # Plot training & validation accuracy values
# plt.subplot(1, 2, 1)
# plt.plot(history.history['accuracy'])
# plt.plot(history.history['val_accuracy'])
# plt.title('Model accuracy')
# plt.ylabel('Accuracy')
# plt.xlabel('Epoch')
# plt.legend(['Train', 'Validation'], loc='upper left')
#
# # Plot training & validation loss values
# plt.subplot(1, 2, 2)
# plt.plot(history.history['loss'])
# plt.plot(history.history['val_loss'])
# plt.title('Model loss')
# plt.ylabel('Loss')
# plt.xlabel('Epoch')
# plt.legend(['Train', 'Validation'], loc='upper left')
# plt.tight_layout()
# plt.show()
#
# # plot_history(history)
Proses training ini akan menyesuaikan bobot dalam lapisan Embedding, LSTM, dan Dense untuk meminimalkan fungsi loss pada data training, sambil dipantau kinerjanya pada data validasi.
Tips Opsional: Menggunakan GPU dan Menyesuaikan Batch Size
- Pemanfaatan GPU: Melatih model deep learning, terutama dengan LSTM dan data gambar, bisa sangat lambat jika hanya menggunakan CPU. Menggunakan GPU (jika tersedia di Google Colab, Kaggle Notebook, atau komputer lokal Anda) akan mempercepat proses training secara drastis. TensorFlow biasanya akan otomatis mendeteksi dan menggunakan GPU jika driver dan library CUDA/cuDNN terkonfigurasi dengan benar.
- Ukuran Batch (Batch Size): Ukuran batch memengaruhi kecepatan training dan penggunaan memori. Batch size yang lebih besar dapat mempercepat waktu training per epoch (karena lebih banyak data diproses secara paralel) tetapi membutuhkan lebih banyak memori (GPU VRAM/RAM). Batch size yang terlalu kecil bisa membuat proses update bobot menjadi lebih ‘berisik’ (noisy gradient). Eksperimen dengan nilai seperti 32, 64, 128, atau 256 untuk menemukan keseimbangan terbaik antara kecepatan dan stabilitas training untuk setup Anda.
Evaluasi Kinerja dan Membuat Prediksi Caption
Setelah model dilatih, kita perlu mengevaluasi kinerjanya secara kuantitatif dan melihat contoh bagaimana ia menghasilkan caption untuk gambar baru.
Mengevaluasi Kualitas Caption: Metrik BLEU
Mengevaluasi kualitas caption yang dihasilkan secara otomatis adalah tugas yang subjektif dan menantang, karena satu gambar bisa memiliki banyak deskripsi yang valid. Metrik otomatis yang paling umum digunakan dalam evaluasi model image captioning
adalah BLEU score.
BLEU (Bilingual Evaluation Understudy) score bekerja dengan membandingkan n-gram (urutan kata berdekatan, misal 1-gram, 2-gram, dst.) dari caption yang dihasilkan oleh model dengan n-gram dari satu atau lebih caption referensi (yang dibuat oleh manusia). Skor ini mengukur sejauh mana kemiripan antara output model dan referensi. Semakin tinggi skor BLEU (biasanya antara 0 dan 1, atau diskalakan 0-100), semakin baik kemiripannya.
Perhitungan BLEU score biasanya dilakukan pada seluruh dataset evaluasi (test set). Anda bisa menggunakan implementasi dari library nltk.translate.bleu_score
.
# Contoh konseptual perhitungan BLEU (membutuhkan implementasi generate_caption)
# from nltk.translate.bleu_score import corpus_bleu
# def evaluate_model_bleu(model, tokenizer, features_dict, captions_dict, max_length):
# actual, predicted = list(), list()
# image_ids = list(captions_dict.keys())
# print(f"Mengevaluasi model pada {len(image_ids)} gambar...")
#
# for i, image_id in enumerate(image_ids):
# # Pastikan fitur gambar ada
# if image_id not in features_dict: continue
#
# # Ambil caption referensi asli (sudah dibersihkan tapi sebelum token start/end)
# # Asumsikan Anda punya dictionary `cleaned_captions_map`
# references = [cap.split() for cap in cleaned_captions_map.get(image_id, [])]
# if not references:
# continue
#
# # Generate caption menggunakan model
# # Perlu fungsi `generate_caption` yang akan kita buat di bagian selanjutnya
# generated_caption = generate_caption(model, tokenizer, features_dict[image_id], max_length)
# predicted_caption_tokens = generated_caption.split()
#
# actual.append(references) # List of lists of tokens
# predicted.append(predicted_caption_tokens) # List of tokens
#
# if (i + 1) % 500 == 0:
# print(f"Evaluasi selesai untuk {i + 1}/{len(image_ids)} gambar.")
#
# # Hitung skor BLEU (1 sampai 4)
# print("\nMenghitung Skor BLEU...")
# bleu1 = corpus_bleu(actual, predicted, weights=(1.0, 0, 0, 0))
# bleu2 = corpus_bleu(actual, predicted, weights=(0.5, 0.5, 0, 0))
# bleu3 = corpus_bleu(actual, predicted, weights=(0.33, 0.33, 0.33, 0))
# bleu4 = corpus_bleu(actual, predicted, weights=(0.25, 0.25, 0.25, 0.25))
#
# print(f"Skor BLEU-1: {bleu1*100:.2f}")
# print(f"Skor BLEU-2: {bleu2*100:.2f}")
# print(f"Skor BLEU-3: {bleu3*100:.2f}")
# print(f"Skor BLEU-4: {bleu4*100:.2f} (sering dilaporkan)")
# return bleu1, bleu2, bleu3, bleu4
# --- Panggil fungsi evaluasi (setelah model dilatih dan fungsi generate_caption dibuat) ---
# # Gunakan data validasi atau test set (pastikan data tidak overlap dengan training)
# # evaluate_model_bleu(model, tokenizer, val_features, val_captions, max_length)
Skor BLEU memberikan ukuran kuantitatif, tetapi penting juga untuk melihat contoh caption yang dihasilkan secara kualitatif.
Membuat Prediksi Caption untuk Gambar Baru (Inferensi)
Bagian yang paling menarik adalah menggunakan model yang telah dilatih untuk menghasilkan caption pada gambar yang belum pernah dilihatnya. Proses ini disebut inferensi dan dilakukan secara iteratif, langkah demi langkah:
- Dapatkan vektor fitur gambar untuk gambar input baru menggunakan model CNN encoder yang sama.
- Mulai sequence input untuk decoder dengan token
startseq
. - Masukkan vektor fitur gambar dan sequence kata saat ini ke dalam model yang telah dilatih.
- Model akan memprediksi probabilitas untuk setiap kata dalam vocabulary sebagai kata berikutnya.
- Pilih kata dengan probabilitas tertinggi (ini disebut Greedy Search).
- Tambahkan kata yang dipilih ke sequence input.
- Ulangi langkah 3-6 sampai model memprediksi token
endseq
atau sampai panjang maksimum caption tercapai.
Berikut adalah contoh kode image captioning keras
untuk fungsi prediksi (generasi caption):
import numpy as np
from tensorflow.keras.preprocessing.sequence import pad_sequences
# Asumsikan model sudah dilatih dan bobot terbaik sudah dimuat
# model.load_weights(checkpoint_path)
# Buat mapping terbalik: index -> kata
index_to_word = {index: word for word, index in tokenizer.word_index.items()}
def generate_caption(model, tokenizer, image_feature, max_length, index_to_word):
"""Menghasilkan caption untuk satu fitur gambar menggunakan Greedy Search."""
# Mulai sequence input dengan token 'startseq'
in_text = 'startseq'
# Konversi 'startseq' ke token
start_token = tokenizer.texts_to_sequences(['startseq'])[0]
# Iterasi untuk menghasilkan kata demi kata
for i in range(max_length):
# Ubah sequence teks saat ini menjadi sequence integer
sequence = tokenizer.texts_to_sequences([in_text])[0]
# Pad sequence agar panjangnya sesuai input model
sequence_padded = pad_sequences([sequence], maxlen=max_length, padding='pre')
# Prediksi probabilitas kata berikutnya
# Input ke model adalah fitur gambar (reshaped) dan sequence padded
image_feature_reshaped = np.reshape(image_feature, (1, image_feature.shape[0]))
yhat = model.predict([image_feature_reshaped, sequence_padded], verbose=0)
# Ambil index kata dengan probabilitas tertinggi
predicted_index = np.argmax(yhat)
# Ubah index menjadi kata
word = index_to_word.get(predicted_index)
# Jika kata tidak ditemukan (misalnya index 0 jika padding), hentikan
if word is None:
break
# Tambahkan kata yang diprediksi ke sequence input untuk langkah berikutnya
in_text += ' ' + word
# Jika model memprediksi token 'endseq', hentikan generasi
if word == 'endseq':
break
# Bersihkan hasil: hapus 'startseq' dan 'endseq'
final_caption_words = in_text.split()
final_caption = ' '.join(final_caption_words[1:-1]) # Ambil kata di antara start dan end
return final_caption
# --- Contoh Penggunaan Fungsi Generate Caption ---
# # 1. Pilih ID gambar dari set validasi/test (yang fiturnya sudah ada)
# val_image_ids = list(val_features.keys())
# random_image_id = np.random.choice(val_image_ids)
# test_feature = val_features[random_image_id]
# print(f"Membuat caption untuk gambar ID: {random_image_id}")
# # 2. Atau, proses gambar baru dari file
# new_image_path = 'path/to/your/new_image.jpg'
# print(f"Memproses gambar baru: {new_image_path}")
# try:
# preprocessed_new_img = load_and_preprocess_image(new_image_path, target_size)
# if preprocessed_new_img is not None:
# # Gunakan cnn_model (yang sudah dimuat sebelumnya) untuk ekstrak fitur
# new_feature = cnn_model.predict(preprocessed_new_img).flatten()
# test_feature = new_feature # Gunakan fitur ini untuk generate caption
# print("Fitur gambar baru berhasil diekstrak.")
# else:
# test_feature = None
# print("Gagal memproses gambar baru.")
# except FileNotFoundError:
# test_feature = None
# print(f"Error: File gambar baru tidak ditemukan di {new_image_path}")
# # 3. Generate caption jika fitur tersedia
# if test_feature is not None:
# generated = generate_caption(model, tokenizer, test_feature, max_length, index_to_word)
# print(f"\nCaption Hasil Generate: {generated}")
#
# # (Opsional) Tampilkan gambar dan caption asli/generate
# # import matplotlib.pyplot as plt
# # from tensorflow.keras.preprocessing.image import load_img
# #
# # # Dapatkan path gambar (jika menggunakan ID dari dataset)
# # if 'random_image_id' in locals():
# # image_path = os.path.join(image_folder, random_image_id + '.jpg')
# # else:
# # image_path = new_image_path
# #
# # img = load_img(image_path)
# # plt.imshow(img)
# # plt.title(f"Generated: {generated}")
# # plt.axis('off')
# # plt.show()
# #
# # # Tampilkan caption referensi (jika ada)
# # if 'random_image_id' in locals() and random_image_id in cleaned_captions_map:
# # print("\nCaption Referensi:")
# # for ref_cap in cleaned_captions_map[random_image_id]:
# # print(f"- {ref_cap}")
Fungsi generate_caption
ini mengimplementasikan proses inferensi langkah demi langkah untuk menghasilkan deskripsi otomatis dari sebuah gambar berdasarkan model yang telah dilatih.
Kesimpulan dan Langkah Selanjutnya
Rangkuman Tutorial Image Captioning Sederhana Ini
Dalam tutorial ini, kita telah menjelajahi langkah-langkah fundamental untuk membangun model image captioning sederhana python
menggunakan Keras dan TensorFlow:
- Memahami konsep dasar dan pentingnya image captioning.
- Mengenal arsitektur encoder (CNN) untuk ekstraksi fitur visual dan decoder (LSTM) untuk generasi teks.
- Melakukan pra-pemrosesan data gambar (resize, normalize, ekstraksi fitur) dan data teks (pembersihan, tokenisasi, padding, penambahan token start/end).
- Mendefinisikan model gabungan encoder-decoder menggunakan Keras Functional API.
- Menyusun data training dalam format yang sesuai (fitur gambar, sequence input, kata target).
- Melatih model menggunakan
model.fit
dengan fungsi loss dan optimizer yang tepat. - Mengevaluasi model menggunakan metrik BLEU (konsep) dan melakukan prediksi (generasi caption) untuk gambar baru menggunakan metode Greedy Search.
Ini memberikan fondasi yang solid untuk memahami bagaimana model deep learning dapat menjembatani pemahaman visual dan bahasa alami.
Potensi Pengembangan dan Peningkatan Lebih Lanjut
Model sederhana yang kita bangun adalah titik awal yang bagus. Ada banyak cara untuk meningkatkan kinerja dan kemampuannya:
- Mekanisme Attention: Ini adalah peningkatan yang sangat umum dan signifikan. Attention memungkinkan decoder untuk secara dinamis ‘fokus’ pada bagian gambar yang paling relevan saat menghasilkan setiap kata dalam caption, menghasilkan deskripsi yang lebih akurat dan kontekstual.
- Dataset Lebih Besar dan Beragam: Menggunakan dataset yang lebih besar seperti MS COCO atau Flickr30k dapat membantu model menggeneralisasi lebih baik ke berbagai jenis gambar dan konsep.
- Fine-tuning Lapisan CNN: Alih-alih hanya menggunakan fitur dari CNN pre-trained secara statis, Anda bisa melakukan ‘fine-tuning’ pada beberapa lapisan terakhir dari CNN bersamaan dengan melatih decoder. Ini memungkinkan encoder untuk belajar fitur yang lebih spesifik untuk tugas captioning.
- Arsitektur Alternatif: Mencoba unit RNN lain seperti GRU (Gated Recurrent Unit) sebagai pengganti LSTM, atau mengeksplorasi arsitektur yang lebih modern seperti Transformer, yang telah menunjukkan hasil state-of-the-art dalam banyak tugas NLP dan visi.
- Metode Sampling saat Inferensi: Menggunakan Beam Search alih-alih Greedy Search saat melakukan prediksi. Beam Search mengeksplorasi beberapa kandidat sequence kata yang paling mungkin secara bersamaan, seringkali menghasilkan caption yang lebih koheren dan berkualitas, meskipun dengan biaya komputasi yang sedikit lebih tinggi.
- Preprocessing Teks Lebih Lanjut: Menggunakan teknik seperti stemming atau lemmatization, atau menangani kata-kata langka (out-of-vocabulary) dengan lebih baik.
Penutup: Terus Belajar dan Bereksperimen!
Dunia Kecerdasan Buatan (AI), khususnya di persimpangan Computer Vision dan Natural Language Processing, berkembang dengan sangat cepat. Kami harap tutorial ini memberikan Anda pemahaman konseptual dan dasar praktis untuk memulai perjalanan belajar image captioning
. Jangan ragu untuk bereksperimen dengan kode yang disediakan, mencoba dataset yang berbeda, menyesuaikan hyperparameter model, atau mengimplementasikan teknik yang lebih canggih seperti Attention.
Menguasai teknik AI seperti image captioning membuka banyak kemungkinan, mulai dari meningkatkan aksesibilitas digital hingga menciptakan solusi otomatisasi konten yang inovatif. Bagi bisnis yang ingin melangkah lebih jauh dan mengintegrasikan solusi AI canggih—termasuk pemrosesan gambar, teks, video, dan optimasi SEO otomatis—platform dan layanan seperti yang ditawarkan oleh Kirim AI dapat menjadi mitra strategis. Dengan keahlian dalam pengembangan platform AI (website, aplikasi mobile) dan strategi digital terintegrasi, mereka membantu bisnis memanfaatkan potensi penuh AI untuk mendorong pertumbuhan. Pelajari lebih lanjut tentang bagaimana solusi AI dapat diimplementasikan untuk mendukung tujuan bisnis Anda.
Tanggapan (0 )