bram4627 commited on
Commit
7f3f3aa
1 Parent(s): a873967

Upload 6 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ static/keretaApi.jpg filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from asgiref.wsgi import WsgiToAsgi
3
+ from flask import Flask, request, render_template
4
+ import pickle, os
5
+ from fastapi.middleware.wsgi import WSGIMiddleware
6
+
7
+ # Initialize Flask app
8
+ flask_app = Flask(__name__)
9
+
10
+ def validasi_inputan(form_data):
11
+ errors = {}
12
+
13
+ if not form_data.get("XT_1"):
14
+ errors["XT_1"] = "XT_1 tidak boleh kosong."
15
+ else:
16
+ try:
17
+ XT_1 = float(form_data.get("XT_1"))
18
+ except ValueError:
19
+ errors["XT_1"] = "XT_1 harus berupa angka."
20
+
21
+ if not form_data.get("XT_2"):
22
+ errors["XT_2"] = "XT_2 tidak boleh kosong."
23
+ else:
24
+ try:
25
+ XT_2 = float(form_data.get("XT_2"))
26
+ except ValueError:
27
+ errors["XT_2"] = "XT_2 harus berupa angka."
28
+
29
+ if not form_data.get("XT_3"):
30
+ errors["XT_3"] = "XT_3 tidak boleh kosong."
31
+ else:
32
+ try:
33
+ XT_3 = float(form_data.get("XT_3"))
34
+ except ValueError:
35
+ errors["XT_3"] = "XT_3 harus berupa angka."
36
+
37
+ return errors
38
+
39
+ def validate_data(record):
40
+ errors = {}
41
+ if record["XT_1"] < 5000 or record["XT_1"] > 40000:
42
+ errors["XT_1"] = "XT_1 harus diantara 0 dan 1.0"
43
+
44
+ if record["XT_2"] < 5000 or record["XT_2"] > 40000:
45
+ errors["XT_2"] = "XT_2 harus diantara 0.0 dan 1.0"
46
+
47
+ if record["XT_3"] < 5000 or record["XT_3"] > 40000:
48
+ errors["XT_3"] = "XT_3 harus diantara 0.0 dan 1.0"
49
+
50
+ return errors
51
+
52
+ # Load models
53
+ linear_model_load = pickle.load(open('best_bagging_model.sav', 'rb'))
54
+ scaler_load = pickle.load(open('scaler.sav', 'rb'))
55
+
56
+ # Flask route
57
+ @flask_app.route("/", methods=["GET", "POST"])
58
+ def index():
59
+ prediction = None
60
+ errors = {}
61
+ if request.method == "POST":
62
+ # Validasi inputan tidak boleh kosong
63
+ errors = validasi_inputan(request.form)
64
+ if not errors:
65
+ record = {
66
+ "XT_1": float(request.form.get("XT_1")),
67
+ "XT_2": float(request.form.get("XT_2")),
68
+ "XT_3": float(request.form.get("XT_3")),
69
+ }
70
+
71
+ errors = validate_data(record)
72
+ if not errors:
73
+ # Data input untuk prediksi
74
+ input_data = [
75
+ record["XT_1"],
76
+ record["XT_2"],
77
+ record["XT_3"],
78
+ ]
79
+
80
+ # Normalisasi input data
81
+ input_data_normalized = scaler_load.transform([input_data])
82
+
83
+ # Membuat prediksi dari model
84
+ predicted_value_normalized = linear_model_load.predict(input_data_normalized)
85
+
86
+ # Menyesuaikan bentuk data untuk inverse_transform
87
+ predicted_value_normalized_full = [[predicted_value_normalized[0], 0, 0]]
88
+ predicted_value_full = scaler_load.inverse_transform(predicted_value_normalized_full)
89
+
90
+ # Mengambil elemen prediksi pertama sebagai hasil akhir
91
+ prediction = int(predicted_value_full[0][0])
92
+
93
+ return render_template('index.html', prediction=prediction, errors=errors, record=request.form)
94
+
95
+
96
+ # FastAPI app to mount Flask app
97
+ app = FastAPI()
98
+
99
+ # Mount Flask app inside FastAPI using WSGIMiddleware
100
+ app.mount("/", WSGIMiddleware(flask_app))
best_bagging_model.sav ADDED
Binary file (5.5 kB). View file
 
requirements.txt ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ attrs==23.1.0
2
+ beautifulsoup4==4.12.2
3
+ blinker==1.6.2
4
+ certifi==2023.7.22
5
+ cffi==1.15.1
6
+ charset-normalizer==3.3.2
7
+ click==8.1.7
8
+ colorama==0.4.6
9
+ contourpy==1.2.1
10
+ cycler==0.12.1
11
+ exceptiongroup==1.1.2
12
+ Flask==2.3.3
13
+ fonttools==4.52.1
14
+ gunicorn==22.0.0
15
+ h11==0.14.0
16
+ h5py==3.11.0
17
+ idna==3.4
18
+ inexactsearch==1.0.2
19
+ itsdangerous==2.1.2
20
+ Jinja2==3.1.2
21
+ joblib==1.3.2
22
+ kiwisolver==1.4.5
23
+ MarkupSafe==2.1.3
24
+ matplotlib==3.9.0
25
+ networkx==3.3
26
+ nltk==3.8.1
27
+ numpy==1.26.0
28
+ outcome==1.2.0
29
+ packaging==24.0
30
+ pandas==2.1.1
31
+ pillow==10.3.0
32
+ pycparser==2.21
33
+ pyparsing==3.1.2
34
+ PySocks==1.7.1
35
+ pyspellchecker==0.8.1
36
+ python-dateutil==2.8.2
37
+ pytz==2023.3.post1
38
+ regex==2024.5.15
39
+ requests==2.32.2
40
+ scikit-learn==1.2.2
41
+ scipy==1.11.2
42
+ selenium==4.9.0
43
+ silpa_common==0.3
44
+ six==1.16.0
45
+ sniffio==1.3.0
46
+ sortedcontainers==2.4.0
47
+ soundex==1.1.3
48
+ soupsieve==2.4.1
49
+ spellchecker==0.4
50
+ threadpoolctl==3.2.0
51
+ tqdm==4.66.4
52
+ trio==0.22.2
53
+ trio-websocket==0.10.3
54
+ tzdata==2023.3
55
+ urllib3==1.26.16
56
+ Werkzeug==2.3.7
57
+ wsproto==1.2.0
58
+ fastapi
59
+ uvicorn[standard]
60
+ asgiref
61
+ mlxtend
scaler.sav ADDED
Binary file (629 Bytes). View file
 
static/keretaApi.jpg ADDED

Git LFS Details

  • SHA256: a7f9e1b761951e5982fbf44db88cffb1d3b21abf615241138ff74b25a401bb57
  • Pointer size: 132 Bytes
  • Size of remote file: 5.2 MB
templates/index.html ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Prediksi Jumlah Penumpang Bulan Depan</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link
9
+ href="https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.3.0/flowbite.min.css"
10
+ rel="stylesheet"
11
+ />
12
+ </head>
13
+ <body class="bg-[url('{{url_for("static", filename="keretaApi.jpg")}}')] bg-cover bg-center bg-no-repeat h-screen flex items-center justify-center">
14
+ <div class="container mx-auto max-w-lg">
15
+ <div
16
+ class="px-4 py-6 flex flex-col justify-center items-center w-full"
17
+ >
18
+ <div class="mb-8 w-full text-center">
19
+ <h1 class="text-3xl text-white font-bold">Jumlah Penumpang Kereta Api</h1>
20
+ <h1 class="text-lg text-white font-bold">Prediksi</h1>
21
+ </div>
22
+
23
+ <div class="w-full">
24
+ <div class="bg-white p-6 rounded-lg shadow-md text-justify">
25
+ <h2 class="text-xl font-semibold mb-4 text-center">MASUKKAN DATA</h2>
26
+ <form method="POST" action="">
27
+ <div class="grid grid-cols-2 gap-4 w-full mb-4">
28
+ <div class="col-span-2 xl:col-span-1">
29
+ <label class="block text-sm font-medium text-zinc-700">XT_1</label>
30
+ <div class="mt-1 flex rounded-md shadow-sm">
31
+ <input
32
+ name="XT_1"
33
+ type="number"
34
+ class="w-full mt-1 px-4 py-2 border rounded-md bg-gray-100"
35
+ placeholder="Contoh: 0.1"
36
+ step="0.01"
37
+ value="{{ record['XT_1'] }}"
38
+ required
39
+ />
40
+ </div>
41
+ {% if errors.XT_1 %}
42
+ <p class="text-red-500 text-xs italic">{{ errors.XT_1 }}</p>
43
+ {% endif %}
44
+ </div>
45
+
46
+ <div class="col-span-2 xl:col-span-1">
47
+ <label class="block text-sm font-medium text-zinc-700">XT_2</label>
48
+ <div class="mt-1 flex rounded-md shadow-sm">
49
+ <input
50
+ name="XT_2"
51
+ type="number"
52
+ class="w-full mt-1 px-4 py-2 border rounded-md bg-gray-100"
53
+ placeholder="Contoh: 0.1"
54
+ step="0.01"
55
+ value="{{ record['XT_2'] }}"
56
+ required
57
+ />
58
+ </div>
59
+ {% if errors.XT_2 %}
60
+ <p class="text-red-500 text-xs italic">{{ errors.XT_2 }}</p>
61
+ {% endif %}
62
+ </div>
63
+
64
+ <div class="col-span-2 xl:col-span-1">
65
+ <label class="block text-sm font-medium text-zinc-700">XT_3</label>
66
+ <div class="mt-1 flex rounded-md shadow-sm">
67
+ <input
68
+ name="XT_3"
69
+ type="number"
70
+ class="w-full mt-1 px-4 py-2 border rounded-md bg-gray-100"
71
+ placeholder="Contoh: 0.1"
72
+ step="0.01"
73
+ value="{{ record['XT_3'] }}"
74
+ required
75
+ />
76
+ </div>
77
+ {% if errors.XT_3 %}
78
+ <p class="text-red-500 text-xs italic">{{ errors.XT_3 }}</p>
79
+ {% endif %}
80
+ </div>
81
+ </div>
82
+
83
+ <div class="flex justify-center gap-2">
84
+ <button
85
+ type="button"
86
+ id="clear-button"
87
+ class="text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5"
88
+ >
89
+ Bersihkan
90
+ </button>
91
+ <button
92
+ type="submit"
93
+ class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 focus:outline-none"
94
+ >
95
+ Kirim
96
+ </button>
97
+ </div>
98
+ </form>
99
+ </div>
100
+
101
+ {% if prediction is not none %}
102
+ <div class="flex justify-center items-center mt-6 p-6 rounded-lg shadow-md bg-blue-500 text-center">
103
+ <div>
104
+ <p class="text-white text-4xl lg:text-6xl font-bold">{{ prediction }}</p>
105
+ <p class="text-white text-xl mt-2">Prediksi Jumlah Penumpang untuk Bulan Depan</p>
106
+ </div>
107
+ </div>
108
+ {% endif %}
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <script>
114
+ document
115
+ .getElementById("clear-button")
116
+ .addEventListener("click", function () {
117
+ const inputs = document.querySelectorAll('input[type="number"]');
118
+ inputs.forEach((input) => (input.value = ""));
119
+ });
120
+ </script>
121
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.3.0/flowbite.min.js"></script>
122
+ </body>
123
+ </html>