Memahami ANN dari Nol: Prediksi Film Comedy dengan Python
Apa itu Artificial Neural Network (ANN)?
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, yPenjelasan:
re.submengganti 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
yeardengan fungsi ekstrak. - Buat kolom
title_clean(judul tanpa tahun). - Buat kolom
title_length→ jumlah karakter judul bersih. - Buat kolom target
is_comedy:Truejika di kolomgenresterdapat kata "Comedy". Gunakan.str.contains(). astype(int)mengubah boolean menjadi 0/1.- Ambil fitur
yeardantitle_lengthsebagaiX(bentuk(jumlah_film, 2)). - Target
ykita 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 dariyeardantitle_length, lalu mengubah semua nilai menjadi skala baku.- Hasilnya
X_scaledberukuran(jumlah_film, 2). - Kita transpose menjadi
(2, jumlah_film)karena dalam kode ANN, setiap kolom adalah satu sampel. Ini memudahkan perkalian matriks:W1berukuran(hidden_size, input_size), dikalikan denganX(input_size, m) menghasilkan(hidden_size, m). - Demikian juga
yditranspose 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 layerLangkah 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, cachePenjelasan :
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).cachemenyimpan nilai antara (Z1, A1, Z2, A2) karena akan dipakai lagi saat backprop.- Sigmoid → mengubah nilai
Zmenjadi 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:
Yadalah label sebenarnya (0/1),A2adalah 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-8agar tidak terjadilog(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": db2Penjelasan:
dZ2 = A2 - Y→ turunan loss terhadapZ2(telah diturunkan dari cross-entropy + sigmoid).dW2=(dZ2 * A1.T) / m→ turunan loss terhadap W2.db2= rata-ratadZ2per baris.dZ1=(W2.T * dZ2) * relu_derivative(Z1)→ menggunakan aturan rantai.dW1dandb1dihitung 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 parameterPenjelasan:
parameterberisiW1, b1, W2, b2.gradsberisidW1, db1, dW2, db2.learning_ratemenentukan 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 parameterPenjelasan:
- Inisialisasi parameter.
- Untuk setiap epoch:
- Forward → dapatkan prediksi
A2. - Hitung cost.
- Backward → dapatkan gradien.
- 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:
predictmelakukan forward propagation dan mengubah probabilitas menjadi kelas: >0.5 → Comedy (1), ≤0.5 → Non-Comedy (0).- Bandingkan
y_preddengany_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!



