✅ 今日目标
综合应用本周所学的:
- 分类算法(SVM、决策树、随机森林等)
- 模型调参(GridSearchCV)
- 模型持久化(joblib)
- 特征工程与数据构造
构建一套完整的二分类建模流程
📘 项目任务说明
构建一个机器学习系统,用于判断学生是否及格,训练后保存模型,并支持预测新数据。
✅ 第一步:数据准备
模拟学生数据:
- 特征:成绩、性别、是否缺勤
- 标签:是否及格(>=60)
features: score, gender(0/1), absent(0/1)
label: 1 (pass), 0 (fail)
✅ 第二步:建模流程
- 拆分训练集 / 测试集
- 使用
Pipeline
组合数据预处理 + 分类器 - 使用
GridSearchCV
寻找最佳参数组合 - 保存训练好的模型(joblib)
- 提供预测函数,支持加载模型预测单个新样本
✅ 第三步:项目结构建议
student_pass_predictor/
├── train_model.py # 训练 + 网格搜索 + 保存模型
├── predictor.py # 加载模型 + 预测新数据
├── data/ # 存放模型或数据文件
│ └── svm_model.joblib
✅ 第四步:挑战加分项(进阶)
- 封装
StudentPredictor
类,支持fit/predict/save/load
方法 - 实现命令行调用支持
- 日志输出记录训练结果与模型参数
- 为预测写一个简单的 Flask Web 接口(未来任务)
🧾 今日总结
能力 | 具体体现 |
---|---|
模型构建 | 数据准备 → 建模 → 调参 → 测试 |
模型部署 | 保存模型,准备使用 |
编码组织 | 使用模块化脚本结构 |
综合思维 | 把“算法知识”转化为“工程实现” |
✅ 项目脚本:
train_model.py
(模型训练与保存)
# train_model.py - 训练学生是否及格预测模型并保存
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import classification_report, accuracy_score
from joblib import dump
import os
# 模拟学生数据:score, gender, absent(是否缺勤),label(是否及格)
np.random.seed(42)
size = 200
scores = np.random.randint(40, 100, size)
genders = np.random.choice([0, 1], size=size)
absents = np.random.choice([0, 1], size=size, p=[0.8, 0.2]) # 缺勤较少
labels = ((scores >= 60) & (absents == 0)).astype(int) # 缺勤也可能影响及格
X = np.column_stack(((scores - scores.mean()) / scores.std(), genders, absents))
y = labels
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 构建 pipeline
pipe = Pipeline([
('scaler', StandardScaler()),
('svc', SVC())
])
# 网格搜索参数
param_grid = {
'svc__C': [0.1, 1, 10],
'svc__kernel': ['linear', 'rbf'],
'svc__gamma': ['scale', 'auto']
}
grid = GridSearchCV(pipe, param_grid, cv=5, verbose=1, n_jobs=-1)
grid.fit(X_train, y_train)
# 模型评估
print("最佳参数:", grid.best_params_)
y_pred = grid.predict(X_test)
print("准确率:", accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred))
# 保存模型
os.makedirs("data", exist_ok=True)
dump(grid.best_estimator_, "data/svm_model.joblib")
print("模型已保存到 data/svm_model.joblib")
运行输出
最佳参数: {'svc__C': 10, 'svc__gamma': 'scale', 'svc__kernel': 'rbf'}
准确率: 0.975
precision recall f1-score support
0 1.00 0.94 0.97 17
1 0.96 1.00 0.98 23
accuracy 0.97 40
macro avg 0.98 0.97 0.97 40
weighted avg 0.98 0.97 0.97 40
模型已保存到 data/svm_model.joblib
predictor.py
(加载模型并预测新样本)
# predictor.py - 加载模型并预测新学生是否及格
from joblib import load
import numpy as np
import os
# 加载模型
model_path = "data/svm_model.joblib"
if not os.path.exists(model_path):
raise FileNotFoundError(f"未找到模型文件: {model_path}")
model = load(model_path)
print("✅ 模型加载成功")
# 示例新学生数据:[score, gender, absent]
def predict_pass(score, gender, absent):
score_std = (score - 70) / 15 # 简单标准化,建议保持一致性
x = np.array([[score_std, gender, absent]])
pred = model.predict(x)[0]
return "及格 ✅" if pred == 1 else "不及格 ❌"
# 示例:输入学生信息预测
if __name__ == "__main__":
while True:
try:
s = int(input("输入学生成绩(0-100):"))
g = int(input("输入性别(0=女,1=男):"))
a = int(input("是否缺勤(0=否,1=是):"))
result = predict_pass(s, g, a)
print(f"预测结果:{result}")
except Exception as e:
print("输入有误,请重试:", e)
print("-" * 40)
运行输出
✅ 模型加载成功
输入学生成绩(0-100):90
输入性别(0=女,1=男):0
是否缺勤(0=否,1=是):1
预测结果:不及格 ❌
----------------------------------------
输入学生成绩(0-100):60
输入性别(0=女,1=男):1
是否缺勤(0=否,1=是):0
预测结果:不及格 ❌
----------------------------------------
输入学生成绩(0-100):99
输入性别(0=女,1=男):1
是否缺勤(0=否,1=是):1
预测结果:不及格 ❌
----------------------------------------
输入学生成绩(0-100):100
输入性别(0=女,1=男):1
是否缺勤(0=否,1=是):0
预测结果:及格 ✅
----------------------------------------
输入学生成绩(0-100):