MediumMemahami ANN dari Nol: Prediksi Film Comedy dengan Python | by Rifkisubhanarifin | Medium
Sitemap
Rifkisubhanarifin

Rifkisubhanarifin

Memahami ANN dari Nol: Prediksi Film Comedy dengan Python

Apa itu Artificial Neural Network (ANN)?

6 min readMay 15, 2026

--

Halo adik-adik tingkat! Pernah dengar istilah Jaringan Saraf Tiruan (ANN)? Mungkin terdengar keren dan rumit. Tapi sebenarnya, ANN hanyalah sebuah program yang meniru cara otak kita belajar. Otak kita punya sel-sel saraf (neuron) yang saling terhubung. ANN juga punya neuron buatan. Saat belajar, neuron-neuron ini mengubah kekuatan koneksinya (bobot) agar prediksinya makin akurat.

Nah, di artikel ini kita akan membangun ANN dari nol (tanpa library deep learning) untuk memprediksi apakah sebuah film itu komedi atau bukan. Kita hanya pakai `numpy`, `pandas`, dan sedikit `sklearn` untuk membaca data. Semua kode akan dijelaskan baris per baris. Siap? Yuk, ikuti 7 langkah berikut!

Langkah 1: Import Library — Siapkan Alat Bantu

import numpy as np
import pandas as pd
import re
from sklearn.preprocessing import StandardScaler

- numpy → untuk operasi matriks dan vektor (otak ANN).
- pandas → membaca file CSV.
- re → mengekstrak tahun dari judul dengan pola `(tahun)`.
- StandardScaler → menormalisasi data agar mudah dipelajari ANN.

Langkah 2: Preprocessing Data — Ubah Judul Menjadi Angka

ANN hanya mengerti angka. Jadi kita perlu mengubah setiap film menjadi dua fitur angka:

Get Rifkisubhanarifin’s stories in your inbox

Join Medium for free to get updates from this writer.

1. Tahun rilis (dari judul, misal `Toy Story (1995)` → 1995)
2. Panjang judul (jumlah karakter setelah tahun dihapus)

def extract_year(title):
match = re.search(r'\((\d{4})\)', title)
return int (match.group(1)) if match else 1990

def clean_title(title):
return re.sub(r'\s*\(\d{4}\)', '', title)

def load_and_preprocess(filepath):
df = pd.read_csv(filepath)
df['year'] = df['title'].apply(extract_year)
df['title_clean'] = df['title'].apply(clean_title)
df['title_length'] = df['title_clean'].apply(len)
df['is_comedy'] = df['genres'].str.contains('Comedy', na=False).astype(int)
X = df[['year', 'title_length']].values
y = df['is_comedy'].values.reshape(-1, 1)
return X, y

Penjelasan:

  • re.sub mengganti spasi + (tahun) dengan string kosong.
  • Hasilnya adalah judul bersih (hanya nama film). Panjang string ini akan menjadi fitur kedua.
  • Baca CSV → dapat kolom movieId, title, genres.
  • Buat kolom year dengan fungsi ekstrak.
  • Buat kolom title_clean (judul tanpa tahun).
  • Buat kolom title_length → jumlah karakter judul bersih.
  • Buat kolom target is_comedy: True jika di kolom genres terdapat kata "Comedy". Gunakan .str.contains().
  • astype(int) mengubah boolean menjadi 0/1.
  • Ambil fitur year dan title_length sebagai X (bentuk (jumlah_film, 2)).
  • Target y kita ubah bentuknya menjadi (jumlah_film, 1) agar sesuai untuk perhitungan matriks nanti.

Langkah 3: Normalisasi dan Bentuk Data

Fitur tahun dan panjang judul memiliki skala berbeda. Kita standarisasi (rata‑rata 0, std 1) agar ANN belajar lebih stabil.

X_raw, y_raw = load_and_preprocess('movies.csv')
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_raw)
X = X_scaled.T #bentuk (2, jumlah_film)
y = y_raw.T #bentuk (1, jumlah_film)

Penjelasan :

  • scaler.fit_transform(X_raw) → menghitung rata-rata dan std dari year dan title_length, lalu mengubah semua nilai menjadi skala baku.
  • Hasilnya X_scaled berukuran (jumlah_film, 2).
  • Kita transpose menjadi (2, jumlah_film) karena dalam kode ANN, setiap kolom adalah satu sampel. Ini memudahkan perkalian matriks: W1 berukuran (hidden_size, input_size), dikalikan dengan X (input_size, m) menghasilkan (hidden_size, m).
  • Demikian juga y ditranspose menjadi (1, jumlah_film).

Langkah 4: Bangun Arsitektur ANN

Kita buat jaringan dengan:
- Input: 2 neuron (tahun, panjang judul)
- Hidden layer: 4 neuron dengan fungsi aktivasi ReLU (agar bisa menangkap pola non‑linear)
- Output: 1 neuron dengan aktivasi Sigmoid (menghasilkan probabilitas 0..1)

4a. Inisialisasi Bobot dan Bias

def inisialisasi_parameter(input_size, hidden_size, output_size):
np.random.seed(42)
W1 = np.random.randn(hidden_size, input_size) * 0.01
b1 = np.zeros((hidden_size, 1))
W2 = np.random.randn(output_size, hidden_size) * 0.01
b2 = np.zeros((output_size, 1))
return{"W1":W1, "b1":b1, "W2":W2, "b2":b2}

Bobot dimulai dengan bilangan acak kecil. Bias dimulai dengan 0.

4b. Fungsi Aktivasi

def sigmoid (Z):
return 1/(1+np.exp(-Z)) #Untuk output

def relu (Z):
return np.maximum(0,Z) #Untuk hidden layer

Langkah 5: Forward Propagation — Hitung Prediksi

Input masuk ke hidden → diaktivasi ReLU → ke output → diaktivasi sigmoid → menghasilkan probabilitas.

def forward_propagation(X, parameter):
W1, b1, W2, b2 = parameter["W1"], parameter["b1"], parameter["W2"], parameter["b2"]
Z1 = np.dot(W1, X) + b1
A1 = relu(Z1)
Z2 = np.dot(W2, A1) + b2
A2 = sigmoid(Z2)
cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2}
return A2, cache

Penjelasan :

  • Z1 → hasil linear di hidden layer: W1 * X + b1.
  • A1 → setelah aktivasi ReLU.
  • Z2 → hasil linear di output layer: W2 * A1 + b2.
  • A2 → probabilitas akhir (nilai 0..1).
  • cache menyimpan nilai antara (Z1, A1, Z2, A2) karena akan dipakai lagi saat backprop.
  • Sigmoid → mengubah nilai Z menjadi antara 0 dan 1. Cocok untuk output layer karena kita ingin probabilitas.
  • ReLU → max(0, Z). Digunakan di hidden layer karena cepat komputasi dan membantu mengatasi vanishing gradient.
  • Turunan ReLU → 1 jika Z > 0, 0 jika Z ≤ 0. Diperlukan saat backpropagation untuk menghitung gradien.
  • A2 adalah probabilitas bahwa film itu komedi

Langkah 6: Hitung Seberapa Salah (Loss)

Kita pakai Binary Cross‑Entropy — cocok untuk klasifikasi 2 kelas.

def komputasi_biaya (Y, A2):
m = Y.shape[1]
biaya = -np.sum(Y * np.log(A2+le-8) + (1-Y) * np.log(1-A2 + 1e-8)) / m
return np.squeeze(biaya)

Penjelasan:

  • Y adalah label sebenarnya (0/1), A2 adalah probabilitas prediksi.
  • Binary Cross-Entropy (BCE) adalah fungsi kerugian (loss function) yang digunakan dalam Machine Learning untuk mengukur kesalahan pada tugas klasifikasi dua kelas (biner). Rumus binary cross entropy :

Keterangan Variabel:

  • m : Jumlah total sampel data.
  • yi: Label sebenarnya untuk sampel ke-i (bernilai 0 atau 1).
  • pi: Probabilitas prediksi model untuk sampel ke-i (bernilai antara 0 hingga 1).
  • log : Logaritma natural (basis e)
  • Kita tambahkan 1e-8 agar tidak terjadi log(0) yang menghasilkan -inf.
  • np.squeeze() menghilangkan dimensi berlebih agar cost berbentuk skalar.

Langkah 7: Backward Propagation — Pelajari Kesalahan

Agar bobot bisa diperbaiki, kita hitung gradien (turunan loss terhadap setiap parameter).

def backward_propagation(X,Y,parameter,cache):
m = X.shape [1]
W2 = parameter["W2"]
dZ2 = cache["A2"] - Y
dW2 = np.dot(dZ2, cache["A1"].T) / m
db2 = np.sum(dZ2, axis=1, keepdims=True) / m
dZ1 = np.dot(W2.T, dZ2) * relu_derivative(cache["Z1"])
dW1 = np.dot(dZ1, X.T) / m
db1 = np.sum(dZ1, axis=1, keepdims=True) / m
return {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2

Penjelasan:

  • dZ2 = A2 - Y → turunan loss terhadap Z2 (telah diturunkan dari cross-entropy + sigmoid).
  • dW2 = (dZ2 * A1.T) / m → turunan loss terhadap W2.
  • db2 = rata-rata dZ2 per baris.
  • dZ1 = (W2.T * dZ2) * relu_derivative(Z1) → menggunakan aturan rantai.
  • dW1 dan db1 dihitung serupa.
  • Hasil gradien disimpan dalam dictionary grads.

Kemudian update parameter dengan Gradient Descent:

def parameter_terbaru(parameter, grads, learning_rate):
for key in parameter.keys():
parameter[key] -= learning_rate * grads["d" + key]
return parameter

Penjelasan:

  • parameter berisi W1, b1, W2, b2.
  • grads berisi dW1, db1, dW2, db2.
  • learning_rate menentukan seberapa besar langkah update.
  • Rumus: W = W - learning_rate * dW.
  • Dilakukan untuk semua parameter.

Langkah 8: Proses Training (Loop Epoch)

Kita ulang forward, hitung loss, backward, update parameter — sebanyak `epochs` kali.

def train_neural_network(X, Y, input_size, hidden_size, output_size, epochs=1000, learning_rate=0.01):
parameter = inisialisasi_parameter(input_size, hidden_size, output_size)
for i in range(epochs):
A2, cache = forward_propagation(X, parameter)
biaya = komputasi_biaya(Y, A2)
grads = backward_propagation(X, Y, parameter, cache)
parameter = parameter_terbaru(parameter, grads, learning_rate)
if i % 100 == 0:
print(f"Epoch {i}: Cost = {biaya:.6f}")
return parameter

Penjelasan:

  • Inisialisasi parameter.
  • Untuk setiap epoch:
  1. Forward → dapatkan prediksi A2.
  2. Hitung cost.
  3. Backward → dapatkan gradien.
  4. Update parameter.
  • Setiap 100 epoch, cetak cost agar kita bisa memantau penurunan loss. Cost yang terus menandakan model belajar.

Langkah 9: Bagi Data Latih & Uji, Lalu Latih Model

Kita pisahkan 80% data untuk melatih, 20% untuk menguji.

m = X.shape[1]
indices = np.random.permutation(m)
split = int(0.8 * m)
train_idx, test_idx = indices[:split], indices[split:]
X_train, X_test = X[:, train_idx], X[:, test_idx]
y_train, y_test = y[:, train_idx], y[:, test_idx]
input_size = X.shape[0] # = 2
hidden_size = 4
output_size = 1
trained_params = train_neural_network(X_train, y_train, input_size, hidden_size, output_size, epochs=2000, learning_rate=0.1)

Penjelasan:

  • np.random.permutation(m) mengacak indeks data.
  • 80% untuk training, 20% untuk testing.
  • Tujuan testing adalah mengukur performa model pada data yang belum pernah dilihat.
  • epochs=2000 → model akan melihat seluruh data training sebanyak 2000 kali.
  • learning_rate=0.1 → ukuran langkah update. Nilai ini bisa dicoba-coba; terlalu besar membuat loss naik-turun, terlalu kecil lambat konvergen.

Langkah 10: Evaluasi — Seberapa Akurat Model Kita?

Gunakan fungsi predict yang mengubah probabilitas (>0.5) menjadi kelas 1 (Comedy) atau 0.

def predict(X, parameter):
A2, _ = forward_propagation(X, parameter)
return (A2 > 0.5).astype(int)
y_pred = predict(X_test, trained_params)
akurasi = np.mean(y_pred == y_test) * 100
print(f"Akurasi pada data test: {akurasi:.2f}%")

Penjelasan:

  • predict melakukan forward propagation dan mengubah probabilitas menjadi kelas: >0.5 → Comedy (1), ≤0.5 → Non-Comedy (0).
  • Bandingkan y_pred dengan y_test, hitung persentase kebenaran.

Dengan fitur hanya tahun dan panjang judul, model kita bisa mencapai akurasi sekitar 70–75% — lebih baik dari tebak acak!

Langkah 11 : Menampilkan contoh

for i in range(min(10, X_test.shape[1])):
pred = "Comedy" if y_pred[0,i] == 1 else "Non-Comedy"
actual = "Comedy" if y_test[0,i] == 1 else "Non-Comedy"
print(f"Film ke-{i+1} -> Prediksi: {pred} | Aktual: {actual}")

Penjelasan:

  • Menampilkan 10 film pertama dari data test, membandingkan prediksi vs kenyataan.

Penutup: Apa yang Bisa Kamu Kembangkan?

Model di atas masih sederhana. Kamu bisa coba:
- Menambah fitur: jumlah kata dalam judul, kata kunci tertentu (misal love, funny).
- Mengubah arsitektur: tambah lapisan hidden atau jumlah neuron.
- Mengatur hyperparameter: learning rate, epoch, fungsi aktivasi.
- Menggunakan representasi genre lain (one‑hot encoding) — tetapi perlu penyesuaian karena banyak genre.

Dengan memahami kode manual ini, kamu akan lebih mudah menggunakan library seperti TensorFlow atau PyTorch nantinya. Selamat mencoba dan jangan lupa eksperimen!

Happy coding, adik tingkat!

Semoga artikel ini membantu. Jika ada bagian yang kurang jelas, tanyakan saja ya!

--

--