为什么不用深度学习
这个场景是表格数据回归预测,不是图像识别。数据量有限(全国高校 × 省份 × 年份),LightGBM 等梯度提升模型在表格数据上通常比神经网络效果更好,且训练速度快。
技术栈
Python
├── Pandas 数据清洗和处理
├── LightGBM 预测最低录取位次
├── FastAPI 后端 API
├── SQLAlchemy 数据库 ORM
└── Vue3 前端展示
第一层:位次换算
真正决定录取的是位次,而非分数。同一个位次在不同年份对应的分数不同:
import pandas as pd
# 读取当年一分一段表
score_table = pd.read_csv("score_rank_2025.csv")
# 结构:score, rank(分数→位次)
def score_to_rank(score: int, year: int) -> int:
df = score_table[score_table["year"] == year]
row = df[df["score"] == score]
if row.empty:
# 取最接近的分数
row = df.iloc[(df["score"] - score).abs().argsort()[:1]]
return int(row["rank"].values[0])
位次越小录取概率越高(1 代表全省第一名)。
第二层:训练预测模型
历史录取数据结构:
| year | school | major | province | min_rank | plan_count |
|---|---|---|---|---|---|
| 2023 | 清华 | 计算机 | 江苏 | 235 | 15 |
| 2024 | 清华 | 计算机 | 江苏 | 198 | 12 |
import lightgbm as lgb
from sklearn.model_selection import train_test_split
df = pd.read_csv("admission_history.csv")
features = ["year", "school_id", "major_id", "province_id", "plan_count"]
target = "min_rank"
X_train, X_test, y_train, y_test = train_test_split(
df[features], df[target], test_size=0.2, random_state=42
)
model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05)
model.fit(X_train, y_train)
也可以替换为 XGBRegressor 或 CatBoostRegressor,效果相近。
第三层:计算录取概率
基于历史波动区间:
def admission_probability(school_id, major_id, province_id, student_rank: int, year: int) -> float:
# 预测今年最低录取位次
predicted_min_rank = model.predict([[year, school_id, major_id, province_id, plan_count]])[0]
# 历史波动标准差
history = df[(df.school_id == school_id) & (df.major_id == major_id)]
std = history["min_rank"].std()
# 学生位次越小(越靠前)于预测线,概率越高
z = (predicted_min_rank - student_rank) / (std + 1)
from scipy.stats import norm
return float(norm.cdf(z))
输出 0.0~1.0 的概率值。
冲/稳/保 分类
def classify(prob: float) -> str:
if prob >= 0.8:
return "保" # 稳上
elif prob >= 0.5:
return "稳" # 有竞争力
else:
return "冲" # 有风险但值得一试
FastAPI 接口
from fastapi import FastAPI
app = FastAPI()
@app.get("/predict")
def predict(school: str, major: str, province: str, score: int, year: int):
rank = score_to_rank(score, year)
prob = admission_probability(school, major, province, rank, year)
label = classify(prob)
return {
"rank": rank,
"probability": round(prob, 3),
"label": label
}
模型效果优化
- 特征工程:加入招生人数变化趋势、学校综合排名、专业热度
- 位次分段:分段训练(Top 1000 / 1000~10000 / 10000+),各段波动规律不同
- 时序权重:近年数据给更高权重(
sample_weight参数) - 多省合并训练:数据量小时跨省训练,加省份编码作为特征
数据来源
历年录取数据可从各省教育考试院官网下载,或使用第三方爬虫整理的开源数据集(GitHub 搜索”高考录取数据”)。确保数据包含:学校、专业、省份、年份、最低分、最低位次、计划人数。
