Silvio0 commited on
Commit
8f4ea9c
·
verified ·
1 Parent(s): 49b1c05

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -129
app.py CHANGED
@@ -1,130 +1,127 @@
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)
 
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
+ port = int(os.environ.get('PORT', 5000))
 
 
 
127
  app.run(debug=True, port=port)