Bayangkan dua feature Toko Kopi Kita berdiri berdampingan: suhu siang bernilai 24-33, jumlah pengunjung bernilai 180-300. Bagi manusia tidak masalah, tetapi bagi model yang menghitung jarak atau gradien, kolom pengunjung terlihat “ribuan kali lebih penting” hanya karena angkanya lebih besar. Normalisasi, atau min-max scaling, menyeragamkan semua feature ke rentang [0, 1] sehingga keduanya berdiri setara di mata model. Pada chapter ini kita hitung rumusnya secara manual, bandingkan dengan MinMaxScaler dari scikit-learn, lalu uji kelemahannya yang paling terkenal: kepekaan terhadap pencilan.

Rumus Min-Max Scaling #

Normalisasi memetakan setiap nilai ke posisinya secara proporsional di dalam rentang kolomnya. Nilai terkecil menjadi 0, nilai terbesar menjadi 1, dan sisanya berdistribusi di antara keduanya:

text
x_baru = (x - min) / (max - min)

Rumus sesederhana itu, dan kita bisa membuktikannya langsung dengan pandas sebelum memakai pustaka mana pun:

python
import pandas as pd
from sklearn.preprocessing import MinMaxScaler

hari = pd.DataFrame({
    "suhu": [27, 30, 24, 29, 33, 28, 26, 31],
    "pengunjung": [210, 260, 180, 240, 300, 225, 195, 255],
})

manual = (hari - hari.min()) / (hari.max() - hari.min())
print("rumus manual (x - min) / (max - min):")
print(manual.round(3))

hasil = MinMaxScaler().fit_transform(hari)
print()
print("MinMaxScaler:")
print(pd.DataFrame(hasil, columns=hari.columns).round(3))
print()
print("min per kolom:", hasil.min(axis=0).round(3))
print("max per kolom:", hasil.max(axis=0).round(3))

Output yang Dihasilkan:

text
rumus manual (x - min) / (max - min):
    suhu  pengunjung
0  0.333       0.250
1  0.667       0.667
2  0.000       0.000
3  0.556       0.500
4  1.000       1.000
5  0.444       0.375
6  0.222       0.125
7  0.778       0.625

MinMaxScaler:
    suhu  pengunjung
0  0.333       0.250
1  0.667       0.667
2  0.000       0.000
3  0.556       0.500
4  1.000       1.000
5  0.444       0.375
6  0.222       0.125
7  0.778       0.625

min per kolom: [0. 0.]
max per kolom: [1. 1.]

Mari kita bedah baris per baris:

  1. Baris 4-7 (hari = pd.DataFrame(...)): dua feature dengan satuan berbeda — derajat dan orang. Inilah situasi yang memicu perlunya penskalaan.
  2. Baris 9 (manual = (hari - hari.min()) / ...): pandas menjalankan rumus min-max pada kedua kolom sekaligus. Hari bersuhu 24 (terkecil) menjadi 0,000; hari bersuhu 33 (terbesar) menjadi 1,000; hari dengan 180 pengunjung menjadi 0,000 di kolomnya sendiri.
  3. Baris 13 (MinMaxScaler().fit_transform(hari)): langkah fit mempelajari min dan max tiap kolom dari data, lalu transform menerapkan rumus yang sama. Hasilnya identik persis dengan perhitungan manual — satu konfirmasi bahwa tidak ada proses tersembunyi di balik pustaka.
  4. Baris 18-19 (hasil.min(axis=0), hasil.max(axis=0)): pemeriksaan kesehatan. Setiap kolom hasil kini berjalan dari 0 sampai 1, sehingga perbedaan satuan asli tidak lagi berpengaruh.

Kapan Normalisasi Dibutuhkan #

Tidak semua model memedulikan skala. Regresi linear dan pohon keputusan memproses tiap feature menurut koefisien atau ambangnya sendiri, sehingga penskalaan tidak mengubah hasilnya. Model lain sungguh memedulikan:

ModelAlasan butuh skala setaraNormalisasi cocok?
Jaring saraf (MLP)gradien bergerak lambat bila skala tak seragamya, masukan [0,1] lazim dipakai
K-Nearest Neighborsjarak Euclidean didominasi kolom berskala besarya
K-Means clusteringcentroid bergeser mengikuti kolom terbesarya
Regresi linear, pohontiap feature diproses terpisahtidak wajib

Normalisasi juga menjadi pilihan alami ketika skala memang bermakna tetap: piksel citra selalu berada di 0-255 sehingga membagi 255 (bentuk min-max dengan min tetap) membawanya ke [0,1] tanpa mengubah informasi apa pun.

Kepekaan terhadap Pencilan #

Kekuatan min-max scaling — memetakan rentang penuh ke [0,1] — sekaligus menjadi kelemahannya. Satu nilai ekstrem akan menetapkan batas rentang, dan seluruh nilai normal terhimpit ke sempit di dekat nol. Kita uji dengan menambahkan satu hari festival dengan 5.000 pengunjung:

python
import pandas as pd
from sklearn.preprocessing import MinMaxScaler

hari = pd.DataFrame({"pengunjung": [210, 260, 180, 240, 300, 225, 195, 255]})
festival = pd.DataFrame({"pengunjung": [5000]})

hari_festival = pd.concat([hari, festival], ignore_index=True)
hasil = MinMaxScaler().fit_transform(hari_festival)

perbandingan = pd.DataFrame({
    "pengunjung_asli": hari_festival["pengunjung"],
    "ternormalisasi": hasil.ravel().round(4),
})
print(perbandingan.to_string(index=False))

Output yang Dihasilkan:

text
 pengunjung_asli  ternormalisasi
             210          0.0062
             260          0.0166
             180          0.0000
             240          0.0124
             300          0.0249
             225          0.0093
             195          0.0031
             255          0.0156
            5000          1.0000

Mari kita baca hasilnya:

  1. Baris 4-5 (festival): satu baris baru bernilai 5.000 — entah benar-benar ramai, entah salah catat. Dalam delapan hari normal, nilai tertinggi hanya 300.
  2. Baris 7 (pd.concat(...)): baris festival digabungkan sehingga min dan max kolom berubah drastis menjadi 180 dan 5.000.
  3. Kolom ternormalisasi: seluruh hari normal kini berdesit di 0,000-0,025 — nyaris tidak ada jarak di antara mereka. Informasi “hari ini ramai, kemarin sepi” yang tadinya jelas kini nyaris rata. Satu pencilan berhasil memencetkan delapan observasi bermakna ke ujung sempit garis.

Rangkuman #

  • Normalisasi memetakan tiap kolom ke [0, 1] lewat rumus (x - min) / (max - min); MinMaxScaler menghasilkan angka yang identik dengan hitungan manual.
  • Penskalaan dibutuhkan model berbasis jarak dan gradien — jaring saraf, KNN, K-Means — dan tidak wajib untuk regresi linear maupun pohon keputusan.
  • Satu pencilan pada min atau max akan menghimpit seluruh nilai normal ke wilayah sempit; periksa pencilan atau beralih ke penskalaan yang tahan pencilan.
  • fit dilakukan pada data latih dan transform pada data baru — urutan yang akan kita tegaskan kembali pada chapter mencegah data leakage.

Min-max bukan satu-satunya cara menyeragamkan skala. Alternatifnya yang paling sering dipakai sebagai default justru tidak mengunci rentang [0,1], melainkan memusatkan data pada rata-rata nol — standardisasi, pembahasan chapter berikutnya.

Referensi #

  1. scikit-learn — Preprocessing Data
  2. pandas — User Guide