Solusi software AI kustom untuk bisnis Anda. Lihat Layanan →

Kirim AI

Mulai Klasifikasi Aksi Video Pakai 3D CNN Keras TensorFlow

Pelajari cara melakukan klasifikasi aksi video menggunakan Convolutional Neural Network 3D (3D CNN) dengan Keras dan TensorFlow. Tutorial ini memandu Anda langkah demi langkah, mulai dari memahami mengapa 3D CNN lebih unggul dari 2D CNN untuk video, persiapan data (ekstraksi frame, normalisasi), pemilihan dataset publik, hingga membangun arsitektur model 3D CNN sederhana. Ikuti panduan implementasi 3D CNN TensorFlow ini untuk melatih, mengevaluasi, dan melakukan prediksi pengenalan aksi video. Dapatkan dasar yang kuat dalam analisis video AI.

0
2
Mulai Klasifikasi Aksi Video Pakai 3D CNN Keras TensorFlow

Klasifikasi aksi video, sebuah cabang penting dalam computer vision dan analisis video AI, bertujuan untuk mengidentifikasi tindakan atau aktivitas manusia yang terjadi dalam klip video. Kemampuan ini memiliki aplikasi luas, mulai dari sistem pengawasan cerdas, analisis performa atlet dalam olahraga, hingga pengembangan robotika dan interaksi manusia-komputer yang lebih intuitif. Secara tradisional, analisis video seringkali dilakukan dengan memproses setiap frame secara independen menggunakan model 2D Convolutional Neural Networks (CNN). Namun, pendekatan ini umumnya gagal menangkap informasi temporal krusial yang terkandung dalam urutan frame. Di sinilah model Convolutional Neural Network 3D (3D CNN) memainkan peran penting. Berbeda dengan pendahulunya, 3D CNN mampu memproses data video secara spatiotemporal (ruang dan waktu) secara bersamaan, memungkinkannya untuk memahami dinamika gerakan yang menjadi kunci dalam pengenalan aksi video. Artikel ini akan memandu Anda langkah demi langkah dalam membangun dan melatih model 3D CNN sederhana untuk tugas klasifikasi aksi video menggunakan library Keras dan TensorFlow, sebuah topik fundamental dalam Keras TensorFlow tutorial.

Persiapan Wajib Sebelum Memulai Tutorial 3D CNN Keras

Sebelum kita melangkah lebih jauh ke implementasi kode, pastikan Anda telah memenuhi beberapa prasyarat penting berikut agar proses belajar berjalan lancar:

  • Pengetahuan Dasar:
    • Pemahaman yang cukup mengenai pemrograman Python.
    • Konsep dasar Deep Learning, terutama cara kerja Convolutional Neural Networks (CNN).
    • Familiaritas dasar dengan library manipulasi data seperti NumPy.
  • Perangkat Lunak & Library:
    • Python (versi 3.7 atau lebih baru direkomendasikan).
    • TensorFlow (versi 2.x atau lebih baru).
    • Keras (terintegrasi dalam TensorFlow 2.x).
    • OpenCV-Python (`opencv-python`): Dibutuhkan untuk pemrosesan video.
    • Scikit-learn (`scikit-learn`): Berguna untuk membagi dataset (opsional).
    • Matplotlib (opsional): Digunakan untuk visualisasi hasil.
    • GPU (Sangat direkomendasikan): Pelatihan model deep learning pada video bisa sangat intensif secara komputasi. Menggunakan GPU akan mempercepat proses secara signifikan.

Anda dapat menginstal library yang diperlukan menggunakan manajer paket `pip`:

pip install tensorflow opencv-python scikit-learn matplotlib

Langkah 1: Menyiapkan Lingkungan dan Dataset Klasifikasi Video

Langkah pertama yang fundamental adalah menyiapkan lingkungan kerja dan dataset yang akan digunakan untuk melatih model klasifikasi aksi video Anda.

Pengaturan Lingkungan Virtual (Sangat Direkomendasikan)

Untuk menghindari potensi konflik antar versi library yang berbeda dan menjaga kerapian dependensi proyek, sangat disarankan untuk menggunakan lingkungan virtual (seperti `venv` yang terintegrasi dengan Python atau `conda`).

# Contoh menggunakan venv
python -m venv cnn3d_env

# Aktivasi Lingkungan (Linux/macOS)
source cnn3d_env/bin/activate

# Aktivasi Lingkungan (Windows PowerShell)
.\cnn3d_env\Scripts\Activate.ps1

# Aktivasi Lingkungan (Windows CMD)
cnn3d_env\Scripts\activate.bat

Memilih dan Mengunduh Dataset Video Publik

Pemilihan dataset video publik yang sesuai sangat krusial untuk keberhasilan proyek klasifikasi video. Untuk tujuan tutorial ini, sebaiknya kita menggunakan dataset yang relatif sederhana agar proses pelatihan tidak memakan waktu terlalu lama. Beberapa pilihan populer yang bisa dipertimbangkan:

  • Subset dari UCF101: UCF101 adalah dataset standar yang populer dengan 101 kelas aksi. Bagi pemula, disarankan untuk menggunakan subset kecil (misalnya, 5-10 kelas aksi) untuk mempercepat proses eksperimen awal.
  • Dataset KTH: Dataset ini berisi 6 jenis aksi (berjalan, jogging, berlari, meninju, melambaikan tangan, bertepuk tangan). Ukurannya lebih kecil dibandingkan UCF101 dan sangat cocok untuk pengujian konsep dan eksperimen awal.

Setelah memilih, unduh dataset tersebut dan pastikan Anda memahami struktur direktorinya. Biasanya, video-video akan dikelompokkan ke dalam folder berdasarkan kelas aksinya masing-masing.

Preprocessing Data Video untuk Input 3D CNN

Model 3D CNN memerlukan input dalam format tensor numerik yang terstruktur. Oleh karena itu, kita perlu mengubah video mentah melalui serangkaian langkah preprocessing. Proses ini memastikan data siap untuk diolah oleh jaringan saraf.

  1. Ekstraksi Frame: Langkah ini melibatkan pembacaan file video dan mengekstrak sejumlah frame tertentu (num_frames). Jumlah frame ini akan menentukan dimensi temporal dari input model. Frame yang diekstrak harus representatif terhadap aksi yang terjadi dalam video.
  2. import cv2
    import numpy as np
    import os
    
    def extract_frames(video_path, num_frames, target_size):
        """Mengekstrak sejumlah frame dari video dan mengubah ukurannya."""
        frames = []
        cap = cv2.VideoCapture(video_path)
        if not cap.isOpened():
            print(f"Error: Tidak dapat membuka video {video_path}")
            # Kembalikan array kosong atau sesuai kebutuhan
            return np.zeros((num_frames, *target_size, 3), dtype=np.uint8) 
            
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        
        # Jika video lebih pendek dari num_frames, ambil semua frame
        if total_frames < num_frames:
            frame_indices = np.arange(total_frames)
        else:
            # Pilih frame secara merata
            frame_indices = np.linspace(0, total_frames - 1, num_frames, dtype=int)
        
        frame_idx_set = set(frame_indices)
        current_frame_idx = 0
        
        while len(frames) < len(frame_indices):
            ret, frame = cap.read()
            if not ret:
                break # Akhir video
                
            if current_frame_idx in frame_idx_set:
                frame = cv2.resize(frame, target_size) # Ubah ukuran
                # Konversi BGR ke RGB (jika model dilatih dengan RGB)
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                frames.append(frame)
            
            current_frame_idx += 1
            
        cap.release()
        
        # Duplikasi frame terakhir jika jumlah frame yang didapat kurang
        # Ini menangani kasus video yang sangat pendek atau korup di akhir
        while len(frames) < num_frames:
            if not frames: # Kasus jika tidak ada frame sama sekali
                 print(f"Warning: Tidak ada frame yang bisa diekstrak dari {video_path}. Menggunakan frame hitam.")
                 frames.append(np.zeros((*target_size, 3), dtype=np.uint8))
            else:
                 frames.append(frames[-1]) # Duplikasi frame terakhir
    
        return np.array(frames[:num_frames]) # Pastikan jumlahnya tepat
    
    # Contoh penggunaan:
    # video_file = 'path/to/your/video.avi'
    # NUM_FRAMES = 16 
    # IMG_HEIGHT = 64
    # IMG_WIDTH = 64
    # frames = extract_frames(video_file, NUM_FRAMES, (IMG_WIDTH, IMG_HEIGHT)) 
    # print(f"Shape frame hasil ekstraksi: {frames.shape}") # Output: Shape frame hasil ekstraksi: (16, 64, 64, 3)
    
  3. Resizing dan Normalisasi Frame: Setiap frame yang diekstrak kemudian diubah ukurannya menjadi dimensi yang seragam (misalnya, 64x64 piksel). Setelah itu, nilai pikselnya dinormalisasi ke rentang [0, 1] dengan membaginya dengan 255. Normalisasi ini penting untuk stabilitas proses pelatihan model deep learning.
  4. def normalize_frames(frames):
        """Normalisasi nilai piksel frame ke rentang [0, 1]."""
        # Pastikan tipe data adalah float untuk pembagian
        normalized_frames = frames.astype(np.float32) / 255.0
        return normalized_frames
    
    # Penggunaan:
    # extracted_frames = extract_frames(...)
    # normalized_frames = normalize_frames(extracted_frames)
    # print(f"Nilai Min/Max setelah normalisasi: {normalized_frames.min():.2f}/{normalized_frames.max():.2f}") # Output: Nilai Min/Max setelah normalisasi: 0.00/1.00
    
  5. Pembuatan Urutan (Sequence) Frame: Frame-frame yang telah diproses (di-resize dan dinormalisasi) kemudian digabungkan menjadi satu tensor NumPy tunggal. Tensor ini akan memiliki dimensi `(num_frames, height, width, channels)`, yang merupakan format input standar untuk layer `Conv3D` di Keras.
  6. Pemisahan Data (Training, Validasi, Test): Dataset yang sudah diproses perlu dipisahkan menjadi tiga bagian utama: set pelatihan (digunakan untuk melatih bobot model), set validasi (digunakan untuk memantau kinerja model selama pelatihan dan melakukan tuning hyperparameter), dan set pengujian (digunakan untuk evaluasi akhir model pada data yang benar-benar baru). Pembagian yang umum adalah 60-80% untuk pelatihan, 10-20% untuk validasi, dan 10-20% untuk pengujian.
  7. from sklearn.model_selection import train_test_split
    
    # Asumsikan X_processed berisi semua data video (tensor) yang sudah diproses
    # dan y_labels berisi label numerik atau one-hot encoded yang sesuai
    # Contoh: X_processed = np.array(list_of_video_tensors)
    # Contoh: y_labels = np.array(list_of_one_hot_labels)
    
    # Periksa apakah data cukup untuk dibagi
    # if len(X_processed) > 10: # Ganti angka 10 sesuai kebutuhan minimal
    #     # Pisahkan data training+validasi dan data test (misal: 80% train+val, 20% test)
    #     X_train_val, X_test, y_train_val, y_test = train_test_split(
    #         X_processed, y_labels, 
    #         test_size=0.2, 
    #         random_state=42, 
    #         stratify=y_labels # Penting untuk menjaga proporsi kelas
    #     )
    #     
    #     # Pisahkan data training dan data validasi (misal: 75% train, 25% val dari train_val_set)
    #     # Ini menghasilkan ~60% train, 20% val, 20% test dari total data
    #     X_train, X_val, y_train, y_val = train_test_split(
    #         X_train_val, y_train_val, 
    #         test_size=0.25, # 0.25 * 0.8 = 0.2
    #         random_state=42, 
    #         stratify=y_train_val # Jaga proporsi kelas lagi
    #     )
    # 
    #     print(f"Ukuran Data Training: {X_train.shape}, {y_train.shape}")
    #     print(f"Ukuran Data Validasi: {X_val.shape}, {y_val.shape}")
    #     print(f"Ukuran Data Test: {X_test.shape}, {y_test.shape}")
    # else:
    #     print("Jumlah data tidak cukup untuk dibagi menjadi train, validation, dan test set.")
    #     # Mungkin hanya gunakan train dan test, atau kumpulkan lebih banyak data
    
  8. Pembuatan Label: Label kelas aksi (biasanya berupa nama atau string, contoh: 'jogging', 'walking') perlu dikonversikan menjadi representasi numerik yang dapat dipahami oleh model. Pendekatan yang umum adalah menggunakan *one-hot encoding*, di mana setiap kelas direpresentasikan sebagai vektor biner dengan nilai 1 pada indeks yang sesuai dengan kelas tersebut dan 0 di posisi lainnya.
  9. from sklearn.preprocessing import LabelEncoder
    from tensorflow.keras.utils import to_categorical
    
    # Asumsikan 'class_names_list' adalah list berisi nama kelas (string) untuk setiap video
    # Contoh: class_names_list = ['jogging', 'walking', 'running', 'jogging', ...]
    
    # label_encoder = LabelEncoder()
    # integer_encoded = label_encoder.fit_transform(class_names_list)
    # NUM_CLASSES = len(label_encoder.classes_)
    
    # Konversi label integer menjadi one-hot encoding
    # y_one_hot = to_categorical(integer_encoded, num_classes=NUM_CLASSES)
    
    # Tampilkan contoh konversi
    # print(f"Label Asli Contoh: {class_names_list[0]}")
    # print(f"Label Integer Encoded: {integer_encoded[0]}")
    # print(f"Label One-Hot Encoded: {y_one_hot[0]}")
    # print(f"Kelas yang ditemukan: {label_encoder.classes_}")
    # Simpan label encoder untuk digunakan saat prediksi nanti
    # import joblib
    # joblib.dump(label_encoder, 'label_encoder.joblib')
    

Langkah 2: Merancang Model Deep Learning Video - Arsitektur 3D CNN

Setelah data berhasil dipersiapkan, langkah selanjutnya adalah mendefinisikan arsitektur model Convolutional Neural Network 3D (3D CNN) menggunakan Keras API yang terintegrasi dalam TensorFlow.

Memahami Konsep Dasar Arsitektur 3D CNN

Layer fundamental dalam 3D CNN adalah `Conv3D`. Berbeda signifikan dari layer `Conv2D` yang filternya (kernel) meluncur hanya pada dimensi spasial (lebar dan tinggi) sebuah gambar, filter pada `Conv3D` berbentuk 3D (kedalaman, lebar, tinggi) dan meluncur di atas volume data video (urutan frame). Kemampuan meluncur pada dimensi temporal (urutan frame) inilah yang memungkinkan `Conv3D` untuk mempelajari fitur-fitur gerakan dan perubahan antar frame, yang sangat penting untuk memahami aksi dalam video.

Sebuah arsitektur 3D CNN sederhana umumnya terdiri dari beberapa komponen berikut:

  • Beberapa blok yang terdiri dari layer `Conv3D` (dengan fungsi aktivasi seperti ReLU), diikuti oleh layer `MaxPooling3D`. `MaxPooling3D` berfungsi untuk mengurangi dimensi spasial dan/atau temporal, membuat representasi fitur lebih ringkas dan tahan terhadap variasi kecil.
  • Sebuah layer `Flatten` untuk mengubah output dari blok konvolusi terakhir (yang masih berbentuk tensor multi-dimensi) menjadi vektor satu dimensi.
  • Satu atau lebih layer `Dense` (fully connected) yang berfungsi sebagai classifier untuk mempelajari kombinasi fitur tingkat tinggi yang diekstrak oleh layer konvolusi. Layer `Dropout` sering ditambahkan di antara layer `Dense` untuk regularisasi, membantu mencegah overfitting.
  • Sebuah layer `Dense` output akhir dengan jumlah neuron sama dengan jumlah kelas aksi, dan menggunakan fungsi aktivasi `softmax`. Aktivasi `softmax` menghasilkan distribusi probabilitas di semua kelas, menunjukkan keyakinan model terhadap setiap kelas aksi.

Implementasi Model dengan Keras dan TensorFlow (Tutorial 3D CNN Keras)

Berikut adalah contoh implementasi arsitektur 3D CNN TensorFlow yang relatif sederhana menggunakan Keras Sequential API. Model ini cocok sebagai titik awal.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv3D, MaxPooling3D, Flatten, Dense, Dropout, Input
from tensorflow.keras.optimizers import Adam

def build_simple_3d_cnn(input_shape, num_classes):
    """Membangun arsitektur model 3D CNN sederhana menggunakan Keras."""
    model = Sequential(name="Simple3DCNN")
    # input_shape diharapkan dalam format: (frames, height, width, channels)
    # Contoh: input_shape = (NUM_FRAMES, IMG_HEIGHT, IMG_WIDTH, 3) 

    # --- Blok Konvolusi 3D Pertama ---
    # Filter 3D akan belajar fitur spatiotemporal dasar
    model.add(Conv3D(32, kernel_size=(3, 3, 3), activation='relu', padding='same', input_shape=input_shape))
    # Max Pooling untuk mengurangi dimensi spasial, mempertahankan dimensi temporal
    model.add(MaxPooling3D(pool_size=(1, 2, 2), padding='same'))

    # --- Blok Konvolusi 3D Kedua ---
    # Filter lebih banyak untuk fitur yang lebih kompleks
    model.add(Conv3D(64, kernel_size=(3, 3, 3), activation='relu', padding='same'))
    # Max Pooling untuk mengurangi dimensi spasial dan temporal
    model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
    
    # --- Blok Konvolusi 3D Ketiga (Opsional, bisa ditambahkan untuk kedalaman) ---
    # model.add(Conv3D(128, kernel_size=(3, 3, 3), activation='relu', padding='same'))
    # model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))

    # --- Flatten & Fully Connected Layers ---
    model.add(Flatten())
    # Layer Dense untuk klasifikasi fitur
    model.add(Dense(128, activation='relu'))
    # Dropout untuk regularisasi, mencegah overfitting
    model.add(Dropout(0.5)) 

    # --- Output Layer ---
    # Aktivasi Softmax untuk output probabilitas multikelas
    model.add(Dense(num_classes, activation='softmax'))

    return model

# Tentukan parameter bentuk input dan jumlah kelas
# INPUT_SHAPE = (NUM_FRAMES, IMG_HEIGHT, IMG_WIDTH, 3) # Sesuaikan dengan data Anda
# NUM_CLASSES = len(label_encoder.classes_) # Jumlah kelas dari data Anda

# Bangun instance model
# model = build_simple_3d_cnn(INPUT_SHAPE, NUM_CLASSES)

# Tampilkan ringkasan arsitektur model
# model.summary()

Output dari `model.summary()` akan memberikan gambaran detail tentang arsitektur yang baru saja Anda definisikan, termasuk bentuk output setiap layer dan jumlah parameter yang dapat dilatih:

Model: "Simple3DCNN"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv3d (Conv3D)             (None, 16, 64, 64, 32)    2624      
                                                                 
 max_pooling3d (MaxPooling3  (None, 16, 32, 32, 32)    0         
 D)                                                              
                                                                 
 conv3d_1 (Conv3D)           (None, 16, 32, 32, 64)    55360     
                                                                 
 max_pooling3d_1 (MaxPoolin  (None, 8, 16, 16, 64)     0         
 g3D)                                                            
                                                                 
 flatten (Flatten)           (None, 131072)            0         
                                                                 
 dense (Dense)               (None, 128)               16777344  
                                                                 
 dropout (Dropout)           (None, 128)               0         
                                                                 
 dense_1 (Dense)             (None, 5)                 645       # Contoh jika NUM_CLASSES = 5
                                                                 
=================================================================
Total params: 16,835,973
Trainable params: 16,835,973
Non-trainable params: 0
_________________________________________________________________
(Catatan: Jumlah parameter dan output shape akan bervariasi tergantung konfigurasi input dan arsitektur)

Langkah 3: Mengompilasi dan Melatih Model Klasifikasi Aksi Video

Setelah arsitektur model berhasil dibangun, langkah berikutnya adalah mengompilasi model tersebut dan kemudian melatihnya menggunakan data video yang telah kita persiapkan sebelumnya.

Kompilasi Model

Proses kompilasi mengonfigurasi model untuk proses pelatihan. Di sini, kita perlu menentukan tiga komponen utama:

  • Optimizer: Algoritma yang digunakan untuk memperbarui bobot (weights) model berdasarkan data dan fungsi loss. Pilihan populer adalah Adam, RMSprop, atau SGD. Learning rate (laju pembelajaran) adalah parameter penting dalam optimizer.
  • Loss Function (Fungsi Kerugian): Metrik yang digunakan untuk mengukur seberapa baik kinerja model pada data pelatihan. Tujuannya adalah meminimalkan nilai loss ini. Untuk klasifikasi multikelas dengan label one-hot encoded, `categorical_crossentropy` adalah pilihan yang umum. Jika label berupa integer, gunakan `sparse_categorical_crossentropy`.
  • Metrics (Metrik Evaluasi): Metrik yang digunakan untuk memantau kinerja model selama pelatihan dan pengujian. Metrik ini tidak digunakan untuk optimasi bobot, tetapi memberikan gambaran tentang seberapa baik model belajar. `accuracy` (akurasi) adalah metrik yang umum digunakan untuk tugas klasifikasi.
# Kompilasi model yang sudah dibangun
# learning_rate = 0.001 # Bisa di-tuning
# optimizer = Adam(learning_rate=learning_rate)

# model.compile(optimizer=optimizer, 
#               loss='categorical_crossentropy', # Sesuaikan jika label tidak one-hot
#               metrics=['accuracy'])

# print("Model berhasil dikompilasi.")

Memulai Proses Pelatihan Model (`model.fit`)

Dengan model yang sudah dikompilasi, kita siap untuk memulai proses pelatihan menggunakan metode `model.fit()`. Metode ini akan melatih model selama jumlah epoch tertentu menggunakan data pelatihan dan mengevaluasi kinerjanya pada data validasi di akhir setiap epoch.

  • X_train, y_train: Data input (tensor video) dan label target (one-hot encoded) untuk set pelatihan.
  • validation_data: Tuple berisi data validasi (`(X_val, y_val)`) yang digunakan untuk memantau kinerja pada data yang tidak terlihat selama pelatihan per epoch.
  • epochs: Jumlah iterasi penuh model akan melihat keseluruhan dataset pelatihan.
  • batch_size: Jumlah sampel data yang diproses sebelum model memperbarui bobotnya. Ukuran batch perlu disesuaikan berdasarkan kapasitas memori GPU Anda. Batch size yang lebih kecil membutuhkan lebih sedikit memori tetapi bisa membuat pelatihan lebih lama dan noisy.
  • callbacks (Opsional tapi sangat berguna): Fungsi yang dapat dieksekusi pada berbagai titik selama pelatihan (misalnya, di akhir setiap epoch). Contoh callback yang umum digunakan:
    • ModelCheckpoint: Menyimpan bobot model (atau seluruh model) secara berkala, biasanya ketika kinerja pada set validasi membaik (misalnya, `val_accuracy` tertinggi atau `val_loss` terendah).
    • EarlyStopping: Menghentikan pelatihan secara otomatis jika kinerja pada set validasi tidak menunjukkan peningkatan selama beberapa epoch berturut-turut (`patience`), mencegah overfitting dan menghemat waktu komputasi.
    • ReduceLROnPlateau: Mengurangi learning rate secara otomatis jika kinerja pada set validasi stagnan.
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau

# Tentukan parameter pelatihan
# EPOCHS = 50 # Jumlah epoch bisa disesuaikan
# BATCH_SIZE = 8 # Sesuaikan dengan memori GPU/CPU Anda

# Definisikan callbacks (sangat direkomendasikan)
# Path untuk menyimpan model terbaik
# checkpoint_filepath = 'best_model_3dcnn.keras' # Gunakan format .keras modern

# Callback untuk menyimpan model terbaik berdasarkan val_accuracy
# model_checkpoint = ModelCheckpoint(
#     filepath=checkpoint_filepath,
#     save_weights_only=False, # Simpan seluruh model
#     monitor='val_accuracy',
#     mode='max',
#     save_best_only=True, # Hanya simpan jika lebih baik dari sebelumnya
#     verbose=1
# )

# Callback untuk menghentikan pelatihan jika tidak ada peningkatan
# early_stopping = EarlyStopping(
#     monitor='val_loss', 
#     patience=10, # Jumlah epoch tanpa peningkatan sebelum berhenti
#     restore_best_weights=True, # Kembalikan bobot terbaik saat berhenti
#     verbose=1
# )

# Callback untuk mengurangi learning rate
# reduce_lr = ReduceLROnPlateau(
#     monitor='val_loss',
#     factor=0.2, # Faktor pengurangan LR (new_lr = lr * factor)
#     patience=5, 
#     min_lr=0.00001, # Batas bawah learning rate
#     verbose=1
# )

# Kumpulkan semua callbacks
# callbacks_list = [early_stopping, model_checkpoint, reduce_lr]

# Mulai proses pelatihan
# print("Memulai pelatihan model...")
# history = model.fit(
#     X_train, y_train,
#     validation_data=(X_val, y_val),
#     epochs=EPOCHS,
#     batch_size=BATCH_SIZE,
#     callbacks=callbacks_list, # Gunakan callbacks
#     verbose=1 # Tampilkan progress bar
# )

# print("Pelatihan selesai.")
# Muat model terbaik yang disimpan (jika menggunakan ModelCheckpoint dan EarlyStopping dengan restore_best_weights=False)
# model.load_weights(checkpoint_filepath)
# print("Bobot model terbaik telah dimuat.")

Selama proses pelatihan, Keras akan menampilkan log untuk setiap epoch, yang mencakup nilai loss dan metrik (misalnya, akurasi) pada set pelatihan dan validasi. Ini memungkinkan Anda memantau kemajuan pelatihan secara real-time.

Epoch 1/50
100/100 [==============================] - ETA: 0s - loss: 1.6094 - accuracy: 0.2375 
Epoch 1: val_accuracy improved from -inf to 0.35000, saving model to best_model_3dcnn.keras
100/100 [==============================] - 15s 140ms/step - loss: 1.6094 - accuracy: 0.2375 - val_loss: 1.4520 - val_accuracy: 0.3500 - lr: 0.0010

Epoch 2/50
100/100 [==============================] - ETA: 0s - loss: 1.3812 - accuracy: 0.4050
Epoch 2: val_accuracy improved from 0.35000 to 0.45000, saving model to best_model_3dcnn.keras
100/100 [==============================] - 13s 130ms/step - loss: 1.3812 - accuracy: 0.4050 - val_loss: 1.2890 - val_accuracy: 0.4500 - lr: 0.0010
...
Epoch 15/50
100/100 [==============================] - ETA: 0s - loss: 0.5123 - accuracy: 0.8100
Epoch 15: val_accuracy improved from 0.70500 to 0.72000, saving model to best_model_3dcnn.keras
100/100 [==============================] - 13s 131ms/step - loss: 0.5123 - accuracy: 0.8100 - val_loss: 0.8850 - val_accuracy: 0.7200 - lr: 0.0010
...
Epoch 26/50
 99/100 [============================>.] - ETA: 0s - loss: 0.2345 - accuracy: 0.9217
Restoring model weights from the end of the best epoch: 16.
Epoch 26: val_accuracy did not improve from 0.72500
Epoch 26: ReduceLROnPlateau reducing learning rate to 0.00020000000949949026.
100/100 [==============================] - 12s 125ms/step - loss: 0.2350 - accuracy: 0.9212 - val_loss: 1.0510 - val_accuracy: 0.7100 - lr: 0.0010
Epoch 26: early stopping
(Catatan: Angka dan output log ini adalah ilustrasi dan akan bervariasi)

Langkah 4: Mengevaluasi Kinerja Model 3D CNN Anda

Setelah proses pelatihan selesai (atau dihentikan oleh `EarlyStopping`), langkah krusial berikutnya adalah mengevaluasi kinerja final model Anda pada set data pengujian (`test set`). Data ini belum pernah dilihat oleh model selama proses pelatihan atau pemilihan hyperparameter.

Evaluasi Model pada Data Test

Gunakan metode `model.evaluate()` dengan data test (`X_test`, `y_test`) untuk mendapatkan metrik kinerja akhir.

# Pastikan model terbaik sudah dimuat jika menggunakan callbacks
# Jika EarlyStopping(restore_best_weights=True), model sudah dalam kondisi terbaik
# Jika tidak, muat manual: 
# from tensorflow.keras.models import load_model
# model = load_model('best_model_3dcnn.keras') 

# Evaluasi model pada data test
# print("Mengevaluasi model pada data test...")
# results = model.evaluate(X_test, y_test, batch_size=BATCH_SIZE, verbose=0)

# Ekstrak hasil evaluasi
# loss = results[0]
# accuracy = results[1]

# print(f"Test Loss: {loss:.4f}")
# print(f"Test Accuracy: {accuracy:.4f} ({accuracy*100:.2f}%)")

Interpretasi Hasil Evaluasi Analisis Video AI

Hasil dari `model.evaluate()` pada data test memberikan indikasi seberapa baik model dapat melakukan generalisasi pada data baru yang tidak dikenal.

  • Test Loss: Nilai fungsi kerugian pada data test. Semakin rendah nilainya, semakin baik model dalam memprediksi data test.
  • Test Accuracy: Persentase prediksi yang benar pada data test. Semakin tinggi nilainya, semakin akurat model dalam mengklasifikasikan aksi pada video baru.

Output yang mungkin Anda dapatkan:

Mengevaluasi model pada data test...
Test Loss: 0.9123
Test Accuracy: 0.7050 (70.50%)
(Catatan: Angka ini adalah ilustrasi) 

Akurasi sekitar 70% pada model sederhana ini mungkin sudah cukup baik, tergantung pada kompleksitas dataset. Namun, metrik ini saja tidak selalu cukup. Untuk pemahaman yang lebih mendalam:

  • Visualisasi Kurva Pelatihan: Plot nilai loss dan akurasi dari objek `history` (dikembalikan oleh `model.fit`) untuk set pelatihan dan validasi sepanjang epoch. Ini membantu mendiagnosis masalah seperti *overfitting* (kinerja baik di training tapi buruk di validasi) atau *underfitting* (kinerja buruk di kedua set).
  • Confusion Matrix: Matriks ini menunjukkan detail prediksi benar dan salah untuk setiap kelas. Ini sangat berguna untuk mengidentifikasi kelas mana yang sering tertukar oleh model.
  • Metrik Lain: Pertimbangkan juga metrik seperti Precision, Recall, dan F1-Score, terutama jika dataset Anda tidak seimbang (jumlah sampel antar kelas berbeda jauh).
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns # Untuk plot confusion matrix yang lebih baik
import numpy as np

def plot_training_history(history):
    """Membuat plot loss dan akurasi training & validasi."""
    # Pastikan metrik tersedia di history
    acc = history.history.get('accuracy')
    val_acc = history.history.get('val_accuracy')
    loss = history.history.get('loss')
    val_loss = history.history.get('val_loss')

    if acc is None or val_acc is None or loss is None or val_loss is None:
        print("Metrik 'accuracy'/'val_accuracy' atau 'loss'/'val_loss' tidak ditemukan dalam history.")
        return

    epochs_range = range(len(acc))

    plt.figure(figsize=(14, 6))
    
    plt.subplot(1, 2, 1)
    plt.plot(epochs_range, acc, label='Training Accuracy')
    plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    plt.legend(loc='lower right')
    plt.title('Training and Validation Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')

    plt.subplot(1, 2, 2)
    plt.plot(epochs_range, loss, label='Training Loss')
    plt.plot(epochs_range, val_loss, label='Validation Loss')
    plt.legend(loc='upper right')
    plt.title('Training and Validation Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    
    plt.tight_layout()
    plt.show()

# Panggil fungsi plot (jika objek history tersedia)
# if 'history' in locals():
#    plot_training_history(history)

def evaluate_and_report(model, X_test, y_test, label_encoder):
    """Evaluasi model, tampilkan laporan klasifikasi dan confusion matrix."""
    # Prediksi probabilitas pada data test
    y_pred_prob = model.predict(X_test)
    # Dapatkan kelas prediksi (indeks dengan probabilitas tertinggi)
    y_pred = np.argmax(y_pred_prob, axis=1)
    # Dapatkan kelas sebenarnya (jika y_test one-hot)
    y_true = np.argmax(y_test, axis=1)
    
    # Nama kelas dari label encoder
    class_names = label_encoder.classes_
    
    # Tampilkan Laporan Klasifikasi (Precision, Recall, F1-score)
    print("\nClassification Report:")
    print(classification_report(y_true, y_pred, target_names=class_names))
    
    # Tampilkan Confusion Matrix
    print("\nConfusion Matrix:")
    cm = confusion_matrix(y_true, y_pred)
    plt.figure(figsize=(8, 6))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)
    plt.xlabel('Predicted Label')
    plt.ylabel('True Label')
    plt.title('Confusion Matrix')
    plt.show()

# Panggil fungsi evaluasi lengkap
# if 'model' in locals() and 'X_test' in locals() and 'y_test' in locals() and 'label_encoder' in locals():
#    evaluate_and_report(model, X_test, y_test, label_encoder)

Langkah 5 (Opsional): Prediksi Pengenalan Aksi Video Baru

Setelah model Anda dilatih, dievaluasi, dan Anda puas dengan kinerjanya, Anda dapat menggunakannya untuk melakukan prediksi pada video baru yang belum pernah dilihat sebelumnya.

Preprocessing Video Baru untuk Prediksi

Sangat penting untuk memastikan bahwa video baru melalui langkah-langkah preprocessing yang **sama persis** seperti yang diterapkan pada data pelatihan. Ini meliputi:

  1. Ekstraksi jumlah frame yang sama (`NUM_FRAMES`).
  2. Mengubah ukuran setiap frame ke dimensi yang sama (`IMG_WIDTH`, `IMG_HEIGHT`).
  3. Konversi warna jika diperlukan (misal, BGR ke RGB jika model dilatih dengan RGB).
  4. Normalisasi nilai piksel ke rentang [0, 1].
  5. Menggabungkan frame menjadi tensor dengan shape `(NUM_FRAMES, IMG_HEIGHT, IMG_WIDTH, 3)`.
  6. Menambahkan dimensi *batch* di awal, karena model Keras mengharapkan input dalam bentuk batch. Shape akhir menjadi `(1, NUM_FRAMES, IMG_HEIGHT, IMG_WIDTH, 3)`.
import numpy as np
from tensorflow.keras.models import load_model
import joblib # Untuk memuat label encoder

# Muat model yang sudah dilatih (misal, model terbaik yang disimpan)
# try:
#     model = load_model('best_model_3dcnn.keras')
#     print("Model berhasil dimuat.")
# except Exception as e:
#     print(f"Error memuat model: {e}")
#     # Handle error, mungkin model belum dilatih atau path salah

# Muat label encoder yang disimpan saat preprocessing
# try: 
#     label_encoder = joblib.load('label_encoder.joblib')
#     print("Label encoder berhasil dimuat.")
# except Exception as e:
#     print(f"Error memuat label encoder: {e}")
#     # Handle error

# Path ke video baru yang ingin diprediksi
# new_video_path = 'path/to/your/new_video.mp4'

# Definisikan parameter preprocessing (HARUS SAMA dengan saat training)
# NUM_FRAMES = 16 
# IMG_HEIGHT = 64
# IMG_WIDTH = 64

def preprocess_single_video(video_path, num_frames, target_size):
    """Melakukan preprocessing lengkap untuk satu video."""
    # 1 & 2: Ekstraksi dan resizing frame (+ konversi warna jika ada di extract_frames)
    frames = extract_frames(video_path, num_frames, target_size)
    # 4: Normalisasi
    normalized_frames = normalize_frames(frames)
    # 6: Tambahkan dimensi batch
    input_tensor = np.expand_dims(normalized_frames, axis=0)
    # Pastikan shape sesuai: (1, num_frames, height, width, channels)
    print(f"Shape input tensor untuk prediksi: {input_tensor.shape}") 
    return input_tensor

# Lakukan preprocessing pada video baru
# if 'model' in locals() and 'label_encoder' in locals():
#    try:
#        input_tensor = preprocess_single_video(new_video_path, NUM_FRAMES, (IMG_WIDTH, IMG_HEIGHT))
#        # Lanjut ke prediksi
#    except Exception as e:
#        print(f"Error saat preprocessing video baru: {e}")

Melakukan Prediksi Aksi (Kode Python Klasifikasi Aksi)

Setelah video baru diproses menjadi tensor input yang sesuai, gunakan metode `model.predict()` untuk mendapatkan prediksi kelas aksi.

# Pastikan input_tensor sudah siap dan model serta label_encoder sudah dimuat

# Lakukan prediksi menggunakan model
# if 'input_tensor' in locals() and 'model' in locals() and 'label_encoder' in locals():
#    try:
#        predictions = model.predict(input_tensor)
#        
#        # predictions adalah array probabilitas untuk setiap kelas, misal: [[0.1, 0.05, 0.8, 0.03, 0.02]]
#        
#        # Dapatkan indeks kelas dengan probabilitas tertinggi
#        predicted_class_index = np.argmax(predictions[0])
#        
#        # Dapatkan nama kelas dari indeks menggunakan label encoder
#        predicted_class_name = label_encoder.inverse_transform([predicted_class_index])[0]
#        
#        # Dapatkan nilai probabilitas (keyakinan) untuk kelas yang diprediksi
#        prediction_probability = predictions[0][predicted_class_index]
#        
#        print(f"\nPrediksi Aksi untuk video '{new_video_path}':")
#        print(f"Kelas Diprediksi: {predicted_class_name}")
#        print(f"Probabilitas: {prediction_probability:.4f} ({prediction_probability*100:.2f}%)")
#        
#        # Opsional: Tampilkan probabilitas semua kelas
#        # print("\nProbabilitas per kelas:")
#        # for i, class_name in enumerate(label_encoder.classes_):
#        #     print(f"- {class_name}: {predictions[0][i]:.4f}")
#            
#    except Exception as e:
#        print(f"Error saat melakukan prediksi: {e}")

Output dari kode prediksi akan berupa nama kelas aksi yang paling mungkin terdeteksi dalam video, beserta tingkat keyakinan (probabilitas) dari prediksi tersebut.

Shape input tensor untuk prediksi: (1, 16, 64, 64, 3)

Prediksi Aksi untuk video 'path/to/your/new_video.mp4':
Kelas Diprediksi: jogging
Probabilitas: 0.8765 (87.65%)

(Catatan: Output ini adalah ilustrasi)

Kesimpulan dan Langkah Berikutnya dalam Computer Vision Tutorial

Selamat! Anda telah berhasil mengikuti tutorial klasifikasi aksi video ini, mulai dari pemahaman konsep dasar, persiapan data, hingga membangun, melatih, dan mengevaluasi model deep learning video 3D CNN sederhana menggunakan Keras dan TensorFlow. Anda kini memiliki fondasi pemahaman tentang bagaimana deep learning dapat diterapkan untuk tugas analisis video yang kompleks.

Namun, penting untuk diingat bahwa model yang kita bangun dalam tutorial ini adalah model dasar. Dunia analisis video AI sangat luas, dan masih banyak ruang untuk eksplorasi dan peningkatan, antara lain:

  • Arsitektur Lebih Canggih: Menggunakan arsitektur 3D CNN yang lebih modern dan terbukti efektif seperti C3D, I3D (Inflated 3D ConvNet), R(2+1)D, atau bahkan mengadaptasi arsitektur berbasis Transformer untuk video.
  • Dataset Lebih Besar: Melatih model pada dataset klasifikasi video publik yang lebih besar dan lebih beragam (seperti Kinetics, Moments in Time) untuk meningkatkan kemampuan generalisasi.
  • Augmentasi Data Video: Menerapkan teknik augmentasi data khusus untuk video (misalnya, flipping temporal, cropping spasial/temporal acak) untuk meningkatkan ketahanan model terhadap variasi.
  • Optimasi Hyperparameter: Melakukan pencarian sistematis untuk hyperparameter terbaik (misalnya, learning rate, batch size, jumlah layer/filter, parameter dropout) menggunakan teknik seperti Grid Search atau Bayesian Optimization.
  • Pendekatan Alternatif: Menjelajahi pendekatan lain seperti Two-Stream Networks (memproses frame dan optical flow secara terpisah) atau Video Transformers yang mulai menunjukkan hasil menjanjikan.
  • Tugas Lebih Lanjut: Mempelajari cara mengembangkan model AI video untuk tugas yang lebih kompleks seperti deteksi aksi temporal (mengetahui kapan aksi dimulai dan berakhir) atau *video captioning* (menghasilkan deskripsi teks untuk video).

Mengembangkan solusi analisis video AI yang andal dan sesuai kebutuhan bisnis seringkali memerlukan keahlian khusus dan sumber daya komputasi yang signifikan. Jika Anda tertarik untuk menerapkan solusi analisis video AI, deteksi aksi video menggunakan Python, atau teknologi computer vision lainnya untuk kebutuhan spesifik Anda, tim Kirim AI siap membantu. Kami memiliki pengalaman dalam membangun model deep learning video yang disesuaikan, menyediakan platform AI, serta layanan pengembangan kustom. Dengan solusi AI unggulan kami, termasuk pemanfaatan AI untuk SEO dan pembuatan konten, serta keahlian dalam pengembangan aplikasi, kami dapat membantu Anda memaksimalkan potensi data video Anda. Hubungi Kirim AI hari ini untuk konsultasi gratis dan mari wujudkan visi Anda melalui kekuatan kecerdasan buatan.

SEO Jago AIS
DITULIS OLEH

SEO Jago AI

Semua pekerjaan SEO ditangani secara otomatis oleh agen AI, memungkinkan Anda untuk lebih fokus membangun bisnis dan produk Anda.

Tanggapan (0 )