GradOnTrack / app.py
namngo's picture
Update app.py
f02fbc5 verified
import streamlit as st
import numpy as np
import joblib
# ===== Load models =====
model_full = joblib.load("random_forest_model_full.pkl")
model_important = joblib.load("random_forest_model_importainfeature.pkl")
# ===== Setup page =====
st.set_page_config(page_title="Dự đoán tốt nghiệp đúng hạn", page_icon="🎓", layout="wide")
# ===== Custom CSS =====
st.markdown("""
<style>
html, body, [class*="css"] {
font-family: 'Poppins', sans-serif;
}
.block-container {
padding: 2rem 2rem 2rem 2rem;
}
.stButton button {
background: linear-gradient(90deg, #4F8BF9 0%, #8E2DE2 100%);
border: none;
padding: 0.75em 1.5em;
border-radius: 8px;
color: white;
font-size: 18px;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True)
# ===== HEADER =====
st.markdown("<h1 style='text-align: center; color: #003366; font-size: 28px;'>🎓 DỰ ĐOÁN KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN</h1>", unsafe_allow_html=True)
st.markdown("<h4 style='text-align: center; color: #666;'>Áp dụng cho sinh viên năm 3</h4>", unsafe_allow_html=True)
st.write("---")
# ===========================
# BỘ 8 VÍ DỤ
# ===========================
sample_options = [
"Không ví dụ",
"CNTT (Full) – Đúng hạn",
"CNTT (Full) – Không đúng hạn",
"Kinh tế (Full) – Đúng hạn",
"Kinh tế (Full) – Không đúng hạn",
"CNTT (Simple) – Đúng hạn",
"CNTT (Simple) – Không đúng hạn",
"Kinh tế (Simple) – Đúng hạn",
"Kinh tế (Simple) – Không đúng hạn",
]
sample_option = st.selectbox("📝 Chọn ví dụ:", sample_options)
# ===== FULL DATA EXAMPLES =====
sample_cntt_full_ok = {
"name": "Nguyễn Văn A",
"student_id": "10117001",
"major": "Công nghệ thông tin",
"semester_data": [
0,0,0,0,17,7,7,8.5,6,
0,0,0,0,17,7,7,8.3,5,
0,0,0,0,17,7,7,8.0,5,
0,0,0,0,17,7,6,8.2,6,
0,0,0,0,19,7,6,8.1,6,
0,0,3,1,19,7,6,7.9,5
]
}
sample_cntt_full_fail = {
"name": "Nguyễn Văn B",
"student_id": "10117002",
"major": "Công nghệ thông tin",
"semester_data": [
1,3,5,2,15,6,4,5.5,2,
2,3,6,3,16,6,3,5.2,2,
2,4,7,3,17,7,3,4.9,1,
3,4,8,4,17,7,3,4.8,1,
3,5,9,4,18,7,3,4.7,1,
4,6,10,5,18,7,2,4.5,0
]
}
sample_kinhte_full_ok = {
"name": "Trần Thị C",
"student_id": "11418001",
"major": "Kinh tế",
"semester_data": [
0,0,0,0,16,6,6,7.0,5,
0,0,0,0,18,7,7,8.2,6,
0,0,0,0,17,7,7,7.8,5,
0,0,0,0,17,7,7,8.0,6,
0,0,0,0,19,7,7,8.3,6,
0,0,0,0,19,7,7,8.1,6
]
}
sample_kinhte_full_fail = {
"name": "Trần Thị D",
"student_id": "11418002",
"major": "Kinh tế",
"semester_data": [
1,2,3,2,15,6,4,5.6,2,
1,3,4,3,15,6,4,5.3,2,
2,4,5,3,16,7,4,5.2,2,
2,5,6,3,17,7,4,5.0,1,
3,6,7,4,17,7,3,4.9,1,
4,7,8,5,18,7,3,4.7,1
]
}
# ===== SIMPLE DATA EXAMPLES =====
sample_cntt_simple_ok = {
"name": "Nguyễn Văn E",
"student_id": "10118001",
"major": "Công nghệ thông tin",
"semester_data": [
17,0,7.2,
17,0,7.0,
18,0,6.8,
18,0,6.9,
19,0,7.1,
19,0,7.0
]
}
sample_cntt_simple_fail = {
"name": "Nguyễn Văn F",
"student_id": "10118002",
"major": "Công nghệ thông tin",
"semester_data": [
12,10,5.2,
12,12,5.0,
13,14,4.8,
14,13,4.7,
15,12,4.9,
15,13,4.6
]
}
sample_kinhte_simple_ok = {
"name": "Trần Thị G",
"student_id": "11418003",
"major": "Kinh tế",
"semester_data": [
17,0,7.5,
17,0,7.2,
17,0,7.0,
18,0,7.3,
18,0,7.4,
19,0,7.5
]
}
sample_kinhte_simple_fail = {
"name": "Trần Thị H",
"student_id": "11418004",
"major": "Kinh tế",
"semester_data": [
12,10,5.3,
12,11,5.0,
13,12,4.9,
13,13,4.8,
14,12,4.7,
14,13,4.5
]
}
# ==============================
# LOAD CORRESPONDING EXAMPLE
# ==============================
example_data = None
if sample_option == "CNTT (Full) – Đúng hạn":
example_data = sample_cntt_full_ok
elif sample_option == "CNTT (Full) – Không đúng hạn":
example_data = sample_cntt_full_fail
elif sample_option == "Kinh tế (Full) – Đúng hạn":
example_data = sample_kinhte_full_ok
elif sample_option == "Kinh tế (Full) – Không đúng hạn":
example_data = sample_kinhte_full_fail
elif sample_option == "CNTT (Simple) – Đúng hạn":
example_data = sample_cntt_simple_ok
elif sample_option == "CNTT (Simple) – Không đúng hạn":
example_data = sample_cntt_simple_fail
elif sample_option == "Kinh tế (Simple) – Đúng hạn":
example_data = sample_kinhte_simple_ok
elif sample_option == "Kinh tế (Simple) – Không đúng hạn":
example_data = sample_kinhte_simple_fail
# ===============================
# PERSONAL INFO
# ===============================
if example_data:
name = st.text_input("👤 Họ và tên", value=example_data["name"])
student_id = st.text_input("🎓 Mã sinh viên", value=example_data["student_id"])
major = st.selectbox("📚 Ngành học",
["Công nghệ thông tin", "Kinh tế"],
index=0 if example_data["major"] == "Công nghệ thông tin" else 1)
else:
name = st.text_input("👤 Họ và tên")
student_id = st.text_input("🎓 Mã sinh viên")
major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"])
st.write("---")
# ===============================
# INPUT FUNCTIONS
# ===============================
def input_semester(semester_label, default_values=None):
with st.expander(f"📖 {semester_label}", expanded=True):
col1, col2 = st.columns(2)
with col1:
somon0thi = st.number_input("Số môn không thi", 0,
value=default_values[0] if default_values else 0,
key=f"sm0_{semester_label}")
sotc0thi = st.number_input("Số tín chỉ không thi", 0,
value=default_values[1] if default_values else 0,
key=f"tc0_{semester_label}")
sotcno = st.number_input("Số tín chỉ nợ", 0,
value=default_values[2] if default_values else 0,
key=f"tcno_{semester_label}")
mhno = st.number_input("Số môn không đạt", 0,
value=default_values[3] if default_values else 0,
key=f"mhno_{semester_label}")
with col2:
TCHK = st.number_input("Tổng tín chỉ học kỳ", 0,
value=default_values[4] if default_values else 0,
key=f"tchk_{semester_label}")
smhk = st.number_input("Số môn học kỳ", 0,
value=default_values[5] if default_values else 0,
key=f"smhk_{semester_label}")
mhpass = st.number_input("Số môn đạt", 0,
value=default_values[6] if default_values else 0,
key=f"mhpass_{semester_label}")
TBCHK = st.number_input("GPA", 0.0, 10.0,
value=default_values[7] if default_values else 0.0,
step=0.01,
key=f"gpa_{semester_label}")
xep_loai_selected = st.selectbox("Xếp loại", list(range(7)),
index=default_values[8] if default_values else 0,
key=f"xeploai_{semester_label}")
sotc_qua = st.number_input("Số tín chỉ qua môn", 0,
value=TCHK - sotcno if default_values else 0,
key=f"tcqua_{semester_label}")
return [
somon0thi, sotc0thi, sotcno, mhno,
TCHK, smhk, mhpass, TBCHK, xep_loai_selected, sotc_qua
]
def input_important_features(semester_label, default_values=None):
with st.expander(f"📘 {semester_label}", expanded=True):
col1, col2 = st.columns(2)
with col1:
sotc_qua = st.number_input("Số tín chỉ đạt", 0,
value=default_values[0] if default_values else 0,
key=f"tcqua_imp_{semester_label}")
sotcno = st.number_input("Số tín chỉ nợ", 0,
value=default_values[1] if default_values else 0,
key=f"tcno_imp_{semester_label}")
with col2:
TBCHK = st.number_input("Điểm trung bình", 0.0, 10.0,
value=default_values[2] if default_values else 0.0,
step=0.01,
key=f"gpa_imp_{semester_label}")
return [sotc_qua, sotcno, TBCHK]
# ===============================
# GENERATE FINAL FEATURES
# ===============================
data = []
semesters = ["HỌC KỲ I", "HỌC KỲ II", "HỌC KỲ III", "HỌC KỲ IV", "HỌC KỲ V", "HỌC KỲ VI"]
model_type = st.sidebar.selectbox("🧠 Chọn mô hình dự báo:",
["Dùng toàn bộ đặc trưng", "Dùng đặc trưng quan trọng"])
# ===============================
# FULL MODEL (61 features)
# ===============================
if model_type == "Dùng toàn bộ đặc trưng":
st.subheader("🔢 Nhập thông tin học kỳ (Full Data)")
full_features = []
sotc_qua_list = []
for idx, sem in enumerate(semesters):
default_values = None
if example_data and len(example_data["semester_data"]) == 54:
default_values = example_data["semester_data"][idx*9:(idx+1)*9]
sem_values = input_semester(sem, default_values)
# 9 features đầu
full_features += sem_values[:9]
# sotc_qua để riêng
sotc_qua_list.append(sem_values[9])
nganh = 0 if major == "Công nghệ thông tin" else 1
# THỨ TỰ MÔ HÌNH FULL:
final_features = np.array(
full_features + [nganh] + sotc_qua_list
).reshape(1, -1)
# ===============================
# SIMPLE MODEL (18 features)
# ===============================
else:
st.subheader("✨ Nhập thông tin rút gọn (Simple Data)")
simple_features = []
for idx, sem in enumerate(semesters):
default_values = None
if example_data and len(example_data["semester_data"]) == 18:
default_values = example_data["semester_data"][idx*3:(idx+1)*3]
sotc_qua, sotcno, TBCHK = input_important_features(sem, default_values)
# đúng thứ tự mô hình simple
simple_features += [sotc_qua, sotcno, TBCHK]
final_features = np.array(simple_features).reshape(1, -1)
# ===============================
# PREDICT BUTTON
# ===============================
st.write("---")
if st.button("🎯 DỰ BÁO"):
# FULL FEATURES (61 inputs)
if model_type == "Dùng toàn bộ đặc trưng":
prediction = model_full.predict(final_features)
if prediction[0] == 1:
st.success(f"🎉 KẾT QUẢ: BẠN {name} CÓ KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN!")
st.balloons()
else:
st.error(f"⚠️ KẾT QUẢ: BẠN {name} CÓ NGUY CƠ **KHÔNG TỐT NGHIỆP ĐÚNG HẠN**.")
st.snow()
# SIMPLE FEATURES (18 inputs)
else:
prediction = model_important.predict(final_features)
if prediction[0] == 1:
st.success(f"🎉 KẾT QUẢ: BẠN {name} CÓ KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN!")
st.balloons()
else:
st.error(f"⚠️ KẾT QUẢ: BẠN {name} CÓ NGUY CƠ **KHÔNG TỐT NGHIỆP ĐÚNG HẠN**.")
st.snow()