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(""" """, unsafe_allow_html=True) # ===== HEADER ===== st.markdown("

🎓 DỰ ĐOÁN KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN

", unsafe_allow_html=True) st.markdown("

Áp dụng cho sinh viên năm 3

", 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()