Silvio0 commited on
Commit
a2e0fbb
·
verified ·
1 Parent(s): 021b268

Upload 6 files

Browse files
Jenis Kelamin_encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8987a4ea8a06636aa2d9f715ba4269575cd5243e81da5a2baf70007e6dfb937f
3
+ size 496
Stunting_encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:557d458e536f7ad3ce9aa6dce013455356e18bf0e24ff458a4547fd83918da6d
3
+ size 517
api_predict.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ import joblib
4
+ import numpy as np
5
+ import os
6
+
7
+ # Inisialisasi aplikasi Flask
8
+ app = Flask(__name__)
9
+ CORS(app) # Mengizinkan Cross-Origin Resource Sharing
10
+
11
+ # --- TAHAP 1: MUAT SEMUA MODEL ---
12
+ # Kita sekarang memuat SEMUA 4 file .joblib
13
+ try:
14
+ # 1. Model utama untuk prediksi
15
+ model = joblib.load("best_model.joblib")
16
+
17
+ # 2. Scaler untuk fitur numerik (umur, tinggi, berat)
18
+ scaler = joblib.load("scaler.joblib")
19
+
20
+ # 3. Encoder untuk fitur 'Jenis Kelamin' (input)
21
+ # PERHATIKAN: Nama file pakai spasi, harus sama persis
22
+ jk_encoder = joblib.load("Jenis Kelamin_encoder.joblib")
23
+
24
+ # 4. Encoder untuk target 'Stunting' (output)
25
+ stunting_encoder = joblib.load("Stunting_encoder.joblib")
26
+
27
+ print("Semua 4 model (model, scaler, 2 encoder) berhasil dimuat!")
28
+
29
+ except Exception as e:
30
+ print(f"Error saat memuat model: {e}")
31
+ model = None
32
+ scaler = None
33
+ jk_encoder = None
34
+ stunting_encoder = None
35
+
36
+ # --- TAHAP 2: ENDPOINT PREDIKSI DENGAN PREPROCESSING ---
37
+ # Ini adalah inti dari API Anda.
38
+ @app.route('/predict', methods=['POST'])
39
+ def predict():
40
+ # Cek apakah semua model sudah siap
41
+ if not all([model, scaler, jk_encoder, stunting_encoder]):
42
+ return jsonify({"error": "Satu atau lebih file model gagal dimuat di server"}), 500
43
+
44
+ try:
45
+ # 1. Ambil data JSON yang dikirim oleh React
46
+ data = request.get_json()
47
+
48
+ # React HARUS mengirim JSON dengan key yang SAMA PERSIS seperti ini:
49
+ # {
50
+ # "jenis_kelamin": "Laki-laki", // (atau "Perempuan")
51
+ # "umur": 24, // (angka)
52
+ # "tinggi": 85.5, // (angka)
53
+ # "berat": 10.1 // (angka)
54
+ # }
55
+
56
+ # --- MULAI PREPROCESSING ---
57
+ # Kita harus mengulang langkah yang sama persis seperti saat training
58
+
59
+ # 2. Ambil data mentah dari JSON
60
+ jk_string = data['jenis_kelamin']
61
+ umur = data['umur']
62
+ tinggi = data['tinggi']
63
+ berat = data['berat']
64
+
65
+ # 3. ENCODE 'Jenis Kelamin' (String -> Angka)
66
+ # Input: ["Laki-laki"] -> Output: [0]
67
+ # Kita ambil elemen pertama [0] untuk mendapatkan angkanya saja
68
+ jk_encoded = jk_encoder.transform([jk_string])[0]
69
+
70
+ # 4. SCALE Fitur Numerik (Angka -> Angka Skala 0-1)
71
+ # Scaler dilatih dengan urutan: ['Umur (bulan)', 'Tinggi Badan (cm)', 'Berat Badan (kg)']
72
+ # Kita harus memasukkan data dengan urutan yang SAMA PERSIS.
73
+ # Input harus 2D array, contoh: [[24, 85.5, 10.1]]
74
+ numerical_features = [[umur, tinggi, berat]]
75
+ scaled_features = scaler.transform(numerical_features)
76
+
77
+ # Outputnya adalah 2D array, contoh: [[0.25, 0.4, 0.3]]
78
+ # Kita ambil baris pertama [0]
79
+ umur_scaled = scaled_features[0][0]
80
+ tinggi_scaled = scaled_features[0][1]
81
+ berat_scaled = scaled_features[0][2]
82
+
83
+ # 5. GABUNGKAN SEMUA FITUR
84
+ # Model utama dilatih dengan urutan:
85
+ # ['Jenis Kelamin', 'Umur (bulan)', 'Tinggi Badan (cm)', 'Berat Badan (kg)']
86
+ # Kita gabungkan fitur yg sudah di-encode dan di-scale sesuai urutan itu
87
+
88
+ final_features_list = [jk_encoded, umur_scaled, tinggi_scaled, berat_scaled]
89
+
90
+ # 6. Ubah jadi 2D Numpy Array
91
+ # Sesuai format yang diterima model .predict()
92
+ final_features = [np.array(final_features_list)]
93
+
94
+ # --- SELESAI PREPROCESSING ---
95
+
96
+ # 7. Lakukan Prediksi
97
+ # Input: [[0, 0.25, 0.4, 0.3]]
98
+ prediction_encoded = model.predict(final_features)
99
+ # Output: [1] (Contoh)
100
+
101
+ # 8. UBAH PREDIKSI (Angka -> String)
102
+ # Kita pakai stunting_encoder untuk mengubah angka hasil prediksi
103
+ # kembali menjadi label string yang bisa dibaca manusia.
104
+ # Input: [1] -> Output: ["Stunted"]
105
+ prediction_string = stunting_encoder.inverse_transform(prediction_encoded)
106
+
107
+ # 9. Ambil hasil string-nya
108
+ output = prediction_string[0] # "Stunted"
109
+
110
+ # 10. Kirim hasil akhir ke React
111
+ return jsonify({'prediction': output})
112
+
113
+ except KeyError as e:
114
+ # Ini terjadi jika React salah kirim key JSON
115
+ # (misal: "nama" bukan "jenis_kelamin")
116
+ return jsonify({"error": f"Key JSON tidak ditemukan: {str(e)}. Pastikan key adalah 'jenis_kelamin', 'umur', 'tinggi', dan 'berat'."}), 400
117
+
118
+ except Exception as e:
119
+ # Tangkap error lainnya (misal: user kirim "Pria" bukan "Laki-laki")
120
+ return jsonify({"error": f"Terjadi error saat prediksi: {str(e)}"}), 400
121
+
122
+ # --- INI BAGIAN PENTING UNTUK HOSTING vs LOCALHOST ---
123
+ # (Tidak perlu diubah, sudah benar)
124
+
125
+ if __name__ == '__main__':
126
+ # Ambil port dari environment variable, atau pakai 5000 jika tidak ada
127
+ port = int(os.environ.get('PORT', 5000))
128
+
129
+ # Jalankan HANYA untuk development di localhost
130
+ app.run(debug=True, port=port)
best_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:36d3f382cda864f1d23f8ab6cc709411d5efa059b065fd8c65fe28cccb556563
3
+ size 81417
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ flask
2
+ flask-cors
3
+ joblib
4
+ numpy
5
+ scikit-learn
6
+ gunicorn
scaler.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3d7d20f5fafde261747c01a6ad0d7f9f19f2a2c722ca6855432392abf0adb2ae
3
+ size 1103