Skip to main content

Evaluasi Model dengan Parameter scoring pada Cross-Validation

Pada materi sebelumnya, kita telah mempelajari Cross-Validation menggunakan fungsi cross_val_score().

Cross-validation membantu kita mengevaluasi performa model dengan membagi dataset menjadi beberapa bagian atau fold. Model kemudian dilatih dan dievaluasi beberapa kali menggunakan kombinasi data train dan validation yang berbeda.

Namun, ada satu hal penting:

Bagaimana jika kita tidak ingin menggunakan metrik default dari model?

Misalnya, pada model klasifikasi kita tidak hanya ingin mengetahui accuracy, tetapi juga ingin mengetahui:

  • Precision
  • Recall
  • F1-score

Begitu juga pada regresi, kita mungkin ingin mengevaluasi model menggunakan:

  • R²
  • MAE
  • MSE

Untuk menentukan metrik yang digunakan dalam cross_val_score(), Scikit-Learn menyediakan parameter:

scoring

Pada materi ini kita akan mempelajari bagaimana menggunakan parameter scoring untuk memilih metrik evaluasi yang sesuai.


Konsep Dasar Cross-Validation​

scikit-learn cross validation

Fungsi cross_val_score() digunakan untuk mengevaluasi model menggunakan beberapa fold.

Contoh:

from sklearn.model_selection import cross_val_score

scores = cross_val_score(
model,
X,
y,
cv=5
)

Dengan cv=5, dataset dibagi menjadi 5 fold.

Secara sederhana:

Fold 1 → Train + Validation
Fold 2 → Train + Validation
Fold 3 → Train + Validation
Fold 4 → Train + Validation
Fold 5 → Train + Validation

Setiap fold secara bergantian digunakan sebagai data validasi, sedangkan fold lainnya digunakan untuk training.

Hasilnya adalah beberapa nilai score:

Fold 1 → 0.82
Fold 2 → 0.79
Fold 3 → 0.85
Fold 4 → 0.81
Fold 5 → 0.83

Kita kemudian dapat menghitung rata-ratanya:

import numpy as np

np.mean(scores)

Misalnya hasilnya:

0.82

Artinya, rata-rata score model berdasarkan 5 fold adalah 0.82.


Mengapa Menggunakan Cross-Validation?​

Jika kita hanya menggunakan satu kali train_test_split(), hasil evaluasi dapat dipengaruhi oleh bagaimana dataset kebetulan terbagi.

Contohnya:

Train/Test Split

Training Data
↓
Model
↓
Test Data
↓
Score

Jika pembagian datanya berbeda, hasil score juga dapat berubah.

Cross-validation melakukan evaluasi beberapa kali:

┌── Fold 1 → Score
├── Fold 2 → Score
Dataset ─────┼── Fold 3 → Score
├── Fold 4 → Score
└── Fold 5 → Score
↓
Mean Score

Dengan demikian, kita memperoleh gambaran performa model yang lebih lengkap daripada hanya mengandalkan satu pembagian data.

Cross-validation bukan jaminan bahwa model bebas dari overfitting. Cross-validation terutama digunakan untuk memperoleh estimasi performa yang lebih stabil dan membantu proses pemilihan model atau hyperparameter.


Parameter scoring​

Secara umum, penggunaan cross_val_score() adalah:

cross_val_score(
estimator,
X,
y,
cv=5,
scoring=None
)

Parameter scoring menentukan metrik evaluasi yang digunakan.

Contohnya:

scoring="accuracy"

atau:

scoring="precision"

atau:

scoring="recall"

Untuk regresi:

scoring="r2"

atau:

scoring="neg_mean_absolute_error"

Apa yang Terjadi Jika scoring=None?​

Jika kita tidak menentukan scoring, nilainya secara default adalah:

scoring=None

Dalam kondisi tersebut, cross_val_score() menggunakan metode .score() dari estimator yang digunakan.

Artinya, metrik default bergantung pada model.

Contohnya:

Jenis Model.score() Default
RandomForestClassifierAccuracy
LogisticRegressionAccuracy
RandomForestRegressorR²
LinearRegressionR²

Jadi, lebih tepat memahami:

scoring=None
↓
Gunakan estimator.score()
↓
Metrik bergantung pada estimator

Bukan berarti scoring=None selalu menggunakan accuracy.


scoring pada Classification​

Untuk masalah klasifikasi, kita dapat memilih berbagai metrik.

Beberapa metrik yang umum digunakan:

ScoringMetrik
"accuracy"Accuracy
"precision"Precision
"recall"Recall
"f1"F1-score
"roc_auc"ROC-AUC

Pemilihan metrik bergantung pada tujuan evaluasi.


Menggunakan Accuracy​

Kita dapat menggunakan dataset Heart Disease sebagai contoh.

Misalnya dataset sudah tersedia dalam DataFrame:

import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier

np.random.seed(42)

X = heart_disease.drop("target", axis=1)
y = heart_disease["target"]

clf = RandomForestClassifier(
n_estimators=100,
random_state=42
)

Kemudian lakukan cross-validation:

cv_acc = cross_val_score(
clf,
X,
y,
cv=5,
scoring="accuracy"
)

print(cv_acc)

Contoh hasil:

[0.82 0.84 0.80 0.83 0.81]

Kita dapat menghitung rata-rata:

print(f"Cross-validated accuracy: {np.mean(cv_acc):.2f}")

Contoh:

Cross-validated accuracy: 0.82

Jika ingin menampilkan dalam bentuk persentase:

print(
f"Cross-validated accuracy: "
f"{np.mean(cv_acc) * 100:.2f}%"
)

Hasil:

Cross-validated accuracy: 82.00%

Accuracy dengan scoring=None​

Karena RandomForestClassifier menggunakan accuracy sebagai default scorer untuk .score(), kode berikut juga dapat digunakan:

cv_acc = cross_val_score(
clf,
X,
y,
cv=5,
scoring=None
)

Atau cukup:

cv_acc = cross_val_score(
clf,
X,
y,
cv=5
)

Keduanya menggunakan scorer default dari estimator.

Namun, jika kita ingin kode lebih eksplisit, kita dapat menuliskan:

scoring="accuracy"

Hal ini membuat pembaca kode langsung mengetahui metrik yang digunakan.


Menggunakan Precision​

Accuracy tidak selalu cukup untuk mengevaluasi model klasifikasi.

Misalnya kita ingin mengetahui:

Dari seluruh data yang diprediksi sebagai positif, berapa banyak yang benar-benar positif?

Metrik yang digunakan adalah Precision.

Kita dapat menggunakan:

cv_precision = cross_val_score(
clf,
X,
y,
cv=5,
scoring="precision"
)

Kemudian:

print(cv_precision)

Untuk menghitung rata-rata:

print(
f"Cross-validated precision: "
f"{np.mean(cv_precision):.2f}"
)

Contoh:

Cross-validated precision: 0.84

Menggunakan Recall​

Recall menjawab pertanyaan:

Dari seluruh data yang sebenarnya positif, berapa banyak yang berhasil ditemukan oleh model?

Gunakan:

cv_recall = cross_val_score(
clf,
X,
y,
cv=5,
scoring="recall"
)

Kemudian:

print(
f"Cross-validated recall: "
f"{np.mean(cv_recall):.2f}"
)

Contoh:

Cross-validated recall: 0.81

Menggunakan F1-Score​

F1-score menggabungkan precision dan recall dalam satu metrik.

Gunakan:

cv_f1 = cross_val_score(
clf,
X,
y,
cv=5,
scoring="f1"
)

print(
f"Cross-validated F1-score: "
f"{np.mean(cv_f1):.2f}"
)

Contoh:

Cross-validated F1-score: 0.82

F1-score sering berguna ketika kita ingin mempertimbangkan precision dan recall secara bersamaan.


Membandingkan Beberapa Metrik Klasifikasi​

Kita dapat menghitung beberapa metrik sekaligus:

cv_acc = cross_val_score(
clf,
X,
y,
cv=5,
scoring="accuracy"
)

cv_precision = cross_val_score(
clf,
X,
y,
cv=5,
scoring="precision"
)

cv_recall = cross_val_score(
clf,
X,
y,
cv=5,
scoring="recall"
)

cv_f1 = cross_val_score(
clf,
X,
y,
cv=5,
scoring="f1"
)

Kemudian tampilkan hasilnya:

print(f"Accuracy : {np.mean(cv_acc):.2f}")
print(f"Precision: {np.mean(cv_precision):.2f}")
print(f"Recall : {np.mean(cv_recall):.2f}")
print(f"F1-score : {np.mean(cv_f1):.2f}")

Contoh output:

Accuracy : 0.82
Precision: 0.84
Recall : 0.81
F1-score : 0.82

Perhatikan bahwa satu model dapat memiliki beberapa nilai evaluasi karena setiap metrik mengukur aspek performa yang berbeda.


scoring pada Regression​

Pada masalah regresi, scoring=None akan menggunakan .score() dari estimator.

Untuk estimator regresi yang umum, seperti:

RandomForestRegressor

dan:

LinearRegression

metode .score() secara default menggunakan R².

Contoh:

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(
n_estimators=100,
random_state=42
)

Kemudian:

cv_r2 = cross_val_score(
model,
X,
y,
cv=5,
scoring=None
)

Kita dapat menghitung rata-ratanya:

print(
f"Cross-validated R²: "
f"{np.mean(cv_r2):.2f}"
)

Kita juga dapat menuliskan scoring secara eksplisit:

cv_r2 = cross_val_score(
model,
X,
y,
cv=5,
scoring="r2"
)

Menggunakan neg_mean_absolute_error​

Sebelumnya kita telah mempelajari Mean Absolute Error atau MAE.

Secara konsep:

MAE lebih kecil → lebih baik

Namun Scikit-Learn memiliki konvensi berbeda untuk parameter scoring.

Prinsip Higher is Better​

Scikit-Learn menggunakan prinsip:

Nilai scoring yang lebih tinggi selalu dianggap lebih baik.

Masalahnya, MAE secara normal memiliki prinsip:

MAE lebih kecil → lebih baik

Untuk menyesuaikan dengan konvensi Scikit-Learn, MAE ditulis sebagai:

scoring="neg_mean_absolute_error"

Scikit-Learn mengembalikan nilai negatif dari MAE.

Contoh:

cv_mae = cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_absolute_error"
)

print(cv_mae)

Contoh hasil:

[-2.31 -2.48 -2.17 -2.35 -2.29]

Kemudian:

print(
f"Cross-validated negative MAE: "
f"{np.mean(cv_mae):.2f}"
)

Hasil:

Cross-validated negative MAE: -2.32

Mengubah Negative MAE Menjadi MAE​

Karena hasil cross_val_score() menggunakan nilai negatif, kita dapat mengubahnya kembali menjadi MAE positif dengan memberikan tanda negatif:

mae = -np.mean(cv_mae)

print(f"Cross-validated MAE: {mae:.2f}")

Hasil:

Cross-validated MAE: 2.32

Dengan demikian, interpretasinya kembali seperti MAE biasa:

MAE = 2.32

Artinya, rata-rata absolute error model adalah sekitar 2.32 satuan target.

Mengapa Nilainya Dibuat Negatif?​

Secara konseptual:

MAE asli

0.00 ← lebih baik
1.00
2.00
3.00 ← lebih buruk

Tetapi cross_val_score() mengikuti aturan:

nilai lebih tinggi → lebih baik

Maka Scikit-Learn menggunakan:

negative MAE

0.00 ← lebih baik
-1.00
-2.00
-3.00 ← lebih buruk

Perhatikan:

-1.00 > -2.00

Sehingga nilai -1.00 dianggap lebih baik daripada -2.00.


Menggunakan neg_mean_squared_error​

Hal yang sama berlaku untuk Mean Squared Error (MSE).

Secara normal:

MSE lebih kecil → lebih baik

Tetapi dalam scoring Scikit-Learn digunakan:

scoring="neg_mean_squared_error"

Contoh:

cv_mse = cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_squared_error"
)

Kemudian:

print(cv_mse)

Contoh:

[-8.42 -9.15 -7.93 -8.76 -8.21]

Untuk mendapatkan MSE positif:

mse = -np.mean(cv_mse)

print(f"Cross-validated MSE: {mse:.2f}")

Contoh:

Cross-validated MSE: 8.49

Negative MSE dan RMSE​

Jika kita ingin mendapatkan RMSE, kita dapat menghitung akar kuadrat dari MSE.

Contoh:

import numpy as np

cv_mse = cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_squared_error"
)

mse = -np.mean(cv_mse)
rmse = np.sqrt(mse)

print(f"MSE : {mse:.2f}")
print(f"RMSE: {rmse:.2f}")

Misalnya:

MSE : 8.49
RMSE: 2.91

Dengan demikian, kita mendapatkan kembali MSE positif dan RMSE dalam satuan target.


Perbandingan Scoring Classification​

Berikut beberapa scoring yang umum digunakan:

ScoringMetrikPrinsip Umum
"accuracy"AccuracyLebih tinggi lebih baik
"precision"PrecisionLebih tinggi lebih baik
"recall"RecallLebih tinggi lebih baik
"f1"F1-scoreLebih tinggi lebih baik
"roc_auc"ROC-AUCLebih tinggi lebih baik

Contoh:

scoring="accuracy"
scoring="precision"
scoring="recall"
scoring="f1"

Perbandingan Scoring Regression​

Beberapa scoring yang umum digunakan:

ScoringMetrikNilai Lebih Tinggi
"r2"R²Lebih baik
"neg_mean_absolute_error"Negative MAELebih baik
"neg_mean_squared_error"Negative MSELebih baik
"neg_root_mean_squared_error"Negative RMSELebih baik

Perhatikan bahwa metrik error menggunakan prefix:

neg_

karena Scikit-Learn menggunakan konvensi higher is better.


Hal Penting tentang neg_​

Kesalahan umum yang sering terjadi adalah menganggap:

-2.0 lebih buruk daripada -3.0

Padahal dalam konteks scoring:

-2.0 > -3.0

Karena higher is better, maka:

-2.0 → lebih baik
-3.0 → lebih buruk

Tetapi ketika kita mengubahnya kembali menjadi MAE positif:

mae = -np.mean(cv_mae)

maka interpretasinya kembali menjadi:

MAE = 2.0 → lebih baik
MAE = 3.0 → lebih buruk

Jadi, jangan langsung menginterpretasikan nilai negatif sebagai MAE sebenarnya.


Contoh Lengkap Classification​

Berikut contoh evaluasi beberapa metrik sekaligus:

import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier

X = heart_disease.drop("target", axis=1)
y = heart_disease["target"]

clf = RandomForestClassifier(
n_estimators=100,
random_state=42
)

cv_acc = cross_val_score(
clf,
X,
y,
cv=5,
scoring="accuracy"
)

cv_precision = cross_val_score(
clf,
X,
y,
cv=5,
scoring="precision"
)

cv_recall = cross_val_score(
clf,
X,
y,
cv=5,
scoring="recall"
)

cv_f1 = cross_val_score(
clf,
X,
y,
cv=5,
scoring="f1"
)

print(f"Accuracy : {np.mean(cv_acc):.2f}")
print(f"Precision: {np.mean(cv_precision):.2f}")
print(f"Recall : {np.mean(cv_recall):.2f}")
print(f"F1-score : {np.mean(cv_f1):.2f}")

Output dapat terlihat seperti:

Accuracy : 0.82
Precision: 0.84
Recall : 0.81
F1-score : 0.82

Contoh Lengkap Regression​

Contoh evaluasi menggunakan R², MAE, dan MSE:

import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(
n_estimators=100,
random_state=42
)

cv_r2 = cross_val_score(
model,
X,
y,
cv=5,
scoring="r2"
)

cv_mae = cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_absolute_error"
)

cv_mse = cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_squared_error"
)

r2 = np.mean(cv_r2)
mae = -np.mean(cv_mae)
mse = -np.mean(cv_mse)
rmse = np.sqrt(mse)

print(f"R² : {r2:.2f}")
print(f"MAE : {mae:.2f}")
print(f"MSE : {mse:.2f}")
print(f"RMSE: {rmse:.2f}")

Contoh output:

R² : 0.78
MAE : 2.31
MSE : 8.42
RMSE: 2.90

Jangan Membandingkan Angka Metrik Secara Langsung​

Penting untuk memahami bahwa setiap metrik mengukur sesuatu yang berbeda.

Misalnya:

R² = 0.78
MAE = 2.31
MSE = 8.42
RMSE = 2.90

Kita tidak dapat mengatakan:

0.78 lebih baik daripada 2.31

atau:

2.31 lebih baik daripada 8.42

Karena metrik tersebut memiliki makna dan skala yang berbeda.

Yang benar adalah membandingkan model menggunakan metrik yang sama.

Contoh:

Model A → MAE = 2.31
Model B → MAE = 2.75

Untuk MAE, nilai yang lebih kecil menunjukkan error rata-rata yang lebih kecil.

Begitu juga:

Model A → R² = 0.78
Model B → R² = 0.71

Untuk R², nilai yang lebih tinggi menunjukkan performa yang lebih baik menurut metrik tersebut pada data evaluasi yang sama.


scoring dan Tujuan Evaluasi​

Pemilihan scoring harus disesuaikan dengan tujuan machine learning.

Contohnya pada klasifikasi:

Apakah semua prediksi harus benar?
↓
Accuracy

Jika fokus pada ketepatan prediksi positif:

Precision

Jika fokus pada menemukan sebanyak mungkin kasus positif:

Recall

Jika ingin mempertimbangkan precision dan recall secara bersamaan:

F1-score

Pada regresi:

Ingin proporsi variasi target yang dijelaskan?
↓
R²

Jika ingin mengetahui rata-rata besar error dalam satuan target:

MAE

Jika ingin memberikan penalti lebih besar terhadap error yang besar:

MSE / RMSE

Cross-Validation Bukan Model Final​

Hal penting lainnya adalah memahami bahwa:

cross_val_score()

digunakan untuk evaluasi, bukan menghasilkan satu model final yang siap digunakan sebagai model produksi.

Misalnya:

scores = cross_val_score(
model,
X,
y,
cv=5,
scoring="accuracy"
)

Hasilnya adalah score dari beberapa fold:

Fold 1 → 0.82
Fold 2 → 0.84
Fold 3 → 0.80
Fold 4 → 0.83
Fold 5 → 0.81

Kemudian kita dapat menghitung:

np.mean(scores)

untuk memperoleh rata-rata score.

Jika setelah evaluasi kita sudah menentukan model dan hyperparameter yang akan digunakan, model final tetap perlu dilatih menggunakan data training yang sesuai.


Hindari Data Leakage​

Jika preprocessing diperlukan, proses preprocessing sebaiknya dilakukan dengan benar di dalam proses cross-validation.

Contohnya, untuk scaling:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

model = Pipeline([
("scaler", StandardScaler()),
("model", LogisticRegression())
])

Kemudian:

scores = cross_val_score(
model,
X,
y,
cv=5,
scoring="accuracy"
)

Dengan Pipeline, proses scaling dilakukan secara terpisah pada setiap training fold sehingga informasi dari validation fold tidak digunakan untuk mempelajari parameter preprocessing.

Ini membantu mencegah data leakage.


Alur Penggunaan scoring​

Secara keseluruhan, workflow dapat digambarkan seperti berikut:

Dataset
│
▼
Tentukan X dan y
│
▼
Pilih Model
│
▼
Tentukan Cross-Validation
│
▼
Tentukan scoring
│
├── accuracy
├── precision
├── recall
├── f1
├── r2
├── neg_mean_absolute_error
└── neg_mean_squared_error
│
▼
cross_val_score()
│
▼
Score setiap Fold
│
▼
Mean Score
│
▼
Evaluasi Performa Model

Kesalahan yang Sering Terjadi​

Menganggap scoring=None selalu Accuracy​

Tidak selalu.

scoring=None

berarti cross_val_score() menggunakan scorer default dari estimator melalui .score().

Contoh umum:

Classifier → Accuracy
Regressor → R²

Namun tetap periksa dokumentasi estimator yang digunakan jika ingin memastikan perilakunya.


Menganggap Negative MAE adalah MAE Sebenarnya​

Jika hasil:

-2.31

jangan langsung mengatakan:

MAE = -2.31

MAE sebenarnya tidak bernilai negatif.

Gunakan:

mae = -np.mean(cv_mae)

sehingga:

MAE = 2.31

Membandingkan MAE dan MSE Secara Langsung​

Misalnya:

MAE = 2.3
MSE = 8.4

Jangan menyimpulkan MSE lebih buruk hanya karena:

8.4 > 2.3

Keduanya memiliki skala dan satuan yang berbeda.


Menggunakan Metrik yang Tidak Sesuai Tujuan​

Accuracy mungkin terlihat tinggi, tetapi belum tentu menjadi metrik yang paling informatif.

Misalnya dataset sangat tidak seimbang:

99% → Class 0
1% → Class 1

Model yang selalu memprediksi Class 0 dapat memperoleh accuracy tinggi meskipun gagal menemukan Class 1.

Dalam situasi seperti ini, precision, recall, F1-score, atau metrik lain dapat memberikan informasi tambahan yang lebih relevan terhadap tujuan analisis.


Ringkasan​

Parameter scoring pada cross_val_score() memungkinkan kita menentukan metrik evaluasi yang digunakan selama cross-validation.

Sintaks dasarnya:

cross_val_score(
model,
X,
y,
cv=5,
scoring="accuracy"
)

Jika:

scoring=None

maka Scikit-Learn menggunakan scorer default dari estimator, yaitu metode .score().

Untuk klasifikasi, beberapa scoring yang umum adalah:

accuracy
precision
recall
f1
roc_auc

Untuk regresi:

r2
neg_mean_absolute_error
neg_mean_squared_error
neg_root_mean_squared_error

Metrik error menggunakan prefix neg_ karena Scikit-Learn menerapkan prinsip:

Higher is better

Sehingga:

Negative MAE
-1.5 → lebih baik
-2.5 → lebih buruk

Setelah dikonversi kembali:

MAE
1.5 → lebih baik
2.5 → lebih buruk

Cheat Sheet​

Classification​

cross_val_score(
clf,
X,
y,
cv=5,
scoring="accuracy"
)
cross_val_score(
clf,
X,
y,
cv=5,
scoring="precision"
)
cross_val_score(
clf,
X,
y,
cv=5,
scoring="recall"
)
cross_val_score(
clf,
X,
y,
cv=5,
scoring="f1"
)

Regression​

cross_val_score(
model,
X,
y,
cv=5,
scoring="r2"
)
cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_absolute_error"
)
cross_val_score(
model,
X,
y,
cv=5,
scoring="neg_mean_squared_error"
)

Kesimpulan​

Parameter scoring memberikan fleksibilitas dalam mengevaluasi model menggunakan metrik yang sesuai dengan tujuan machine learning.

Hal terpenting yang perlu diingat:

  1. cross_val_score() dapat melakukan evaluasi menggunakan beberapa fold.
  2. scoring=None menggunakan scorer default dari estimator melalui .score().
  3. Kita dapat menentukan metrik secara eksplisit menggunakan string.
  4. Classification dapat menggunakan accuracy, precision, recall, F1, ROC-AUC, dan metrik lainnya.
  5. Regression dapat menggunakan R², MAE, MSE, RMSE, dan metrik lainnya.
  6. Scikit-Learn menggunakan prinsip higher is better untuk scoring.
  7. Karena itu, metrik error seperti MAE dan MSE menggunakan bentuk neg_.
  8. Negative MAE atau Negative MSE perlu dikonversi kembali jika ingin mendapatkan nilai error positif.
  9. Model harus dibandingkan menggunakan metrik yang sama pada data evaluasi yang sama.
  10. Pemilihan scoring harus disesuaikan dengan tujuan dan karakteristik masalah machine learning.

Referensi​