一、项目简介
在服务器监控、金融风控、物联网设备巡检、业务指标监测等场景中,"异常检测"是非常常见的需求。传统做法往往依赖人工配置固定阈值,例如 CPU 大于 90% 就报警,但真实业务中的异常通常与多个指标同时相关:CPU、内存、磁盘 IO、请求量、失败率等指标组合起来才更能说明问题。
本文实现一个完整的 Python 全栈项目:基于机器学习的异常检测系统。系统不是单纯讲算法,而是围绕真实 Web 产品展开,包含用户注册登录、JWT 鉴权、模型管理、训练样本录入、异常检测、检测历史和仪表盘统计。
项目最终效果:
- 用户注册/登录后进入系统;
- 创建一个异常检测模型,例如"服务器资源异常检测";
- 输入正常历史样本训练基线;
- 提交新数据,后端计算异常分数;
- 根据阈值判断是否异常;
- 前端展示检测结果、历史记录和统计数据。
二、技术栈
本项目采用标准前后端分离架构:
| 层级 | 技术 |
|---|---|
| 后端框架 | FastAPI |
| 数据库 | SQLite |
| ORM | SQLAlchemy |
| 数据校验 | Pydantic |
| 用户认证 | Passlib 密码哈希 + JWT Token |
| 异常检测算法 | 多维 Z-Score 距离 |
| 前端框架 | Vue 3 |
| 构建工具 | Vite |
| 接口通信 | Fetch API + Bearer Token |
三、系统架构
系统分为三层:
text
Vue 3/Vite 前端
│ HTTP + JSON + JWT
▼
FastAPI REST API
│ SQLAlchemy ORM
▼
SQLite 数据库
核心流程如下:
- 用户在前端注册或登录;
- 后端校验密码,签发 JWT;
- 前端将 Token 保存到 localStorage;
- 后续请求在 Header 中携带
Authorization: Bearer <access_token>; - 后端鉴权通过后,允许访问模型、训练、检测等业务接口;
- 异常检测服务根据训练样本计算均值、标准差,并对新样本计算异常分数。
四、功能模块
1. 用户认证模块
- 用户注册;
- 用户登录;
- 密码哈希存储;
- JWT Token 生成;
- 当前用户信息获取;
- 业务接口鉴权保护。
2. 检测模型模块
- 创建检测模型;
- 配置特征名;
- 配置异常阈值;
- 查看模型列表。
3. 模型训练模块
用户输入多行历史正常样本,系统计算每个特征的:
- 均值 mean;
- 标准差 std。
这些参数会保存到数据库中,作为后续异常检测的基线。
4. 异常检测模块
用户提交一条新数据,系统计算每个特征的 Z-Score:
text
z = abs((value - mean) / std)
然后计算多维距离:
text
score = sqrt(z1² + z2² + ... + zn²)
当 score >= threshold 时,标记为异常。
5. 仪表盘模块
- 模型总数;
- 检测事件总数;
- 异常事件总数;
- 最新检测事件。
五、数据库/数据模型设计
系统包含三张核心表。
users 用户表
| 字段 | 说明 |
|---|---|
| id | 用户 ID |
| username | 用户名 |
| 邮箱 | |
| hashed_password | 哈希后的密码 |
| is_active | 是否启用 |
| created_at | 创建时间 |
datasets 检测模型表
| 字段 | 说明 |
|---|---|
| id | 模型 ID |
| name | 模型名称 |
| description | 描述 |
| feature_names | 特征名 JSON |
| mean_vector | 均值向量 JSON |
| std_vector | 标准差向量 JSON |
| threshold | 异常阈值 |
| owner_id | 所属用户 |
| created_at | 创建时间 |
events 检测事件表
| 字段 | 说明 |
|---|---|
| id | 事件 ID |
| dataset_id | 所属模型 |
| raw_values | 输入特征值 JSON |
| score | 异常分数 |
| is_anomaly | 是否异常 |
| note | 备注 |
| created_at | 创建时间 |
六、后端接口设计
| 方法 | 路径 | 说明 | 是否鉴权 |
|---|---|---|---|
| GET | /api/health |
健康检查 | 否 |
| POST | /api/auth/register |
注册 | 否 |
| POST | /api/auth/login |
登录 | 否 |
| GET | /api/auth/me |
当前用户 | 是 |
| GET | /api/dashboard |
仪表盘 | 是 |
| POST | /api/datasets |
创建模型 | 是 |
| GET | /api/datasets |
模型列表 | 是 |
| POST | /api/datasets/{id}/train |
训练模型 | 是 |
| POST | /api/datasets/{id}/events |
提交检测 | 是 |
| GET | /api/datasets/{id}/events |
检测历史 | 是 |
七、前端页面设计
前端使用 Vue 3 单页应用,主要页面区域如下:
- 登录/注册卡片:未登录时展示,可切换注册与登录;
- 顶部导航栏:展示系统标题、当前用户、退出按钮;
- 统计卡片:展示模型数量、检测事件、异常事件;
- 模型创建区:创建检测模型,配置特征和阈值;
- 模型列表区:选择当前要训练/检测的模型;
- 训练区域:输入多行样本并训练基线;
- 检测区域:输入待检测数据并显示结果;
- 历史表格:展示检测记录。
八、核心代码讲解
1. 数据库连接
backend/app/database.py 使用 SQLAlchemy 创建 SQLite 连接:
python
SQLALCHEMY_DATABASE_URL = "sqlite:///./anomaly.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
get_db() 作为 FastAPI 依赖注入,确保每个请求拥有独立数据库会话。
2. 密码哈希与 JWT 鉴权
backend/app/auth.py 中使用 Passlib 处理密码:
python
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
登录成功后生成 JWT:
python
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
业务接口通过 get_current_user() 解析 Token,保护核心资源。
3. 异常检测算法
backend/app/anomaly.py 实现轻量机器学习检测逻辑:
python
def train_zscore_model(samples: List[List[float]]) -> Tuple[List[float], List[float]]:
width = validate_samples(samples)
means = []
stds = []
for index in range(width):
column = [float(row[index]) for row in samples]
means.append(mean(column))
std_value = pstdev(column)
stds.append(std_value if std_value > 1e-9 else 1.0)
return means, stds
检测阶段:
python
def anomaly_score(values: List[float], means: List[float], stds: List[float]) -> float:
z_scores = [abs((float(v) - m) / s) for v, m, s in zip(values, means, stds)]
return math.sqrt(sum(z * z for z in z_scores))
这种算法非常适合教学项目:实现简单、可解释性强,并且支持多维特征。
4. FastAPI 路由
训练接口会先检查模型是否属于当前用户,再更新模型参数:
python
@app.post("/api/datasets/{dataset_id}/train")
def train(dataset_id: int, payload: schemas.TrainRequest, db: Session = Depends(get_db), current_user: models.User = Depends(auth.get_current_user)):
dataset = crud.get_dataset(db, current_user.id, dataset_id)
if not dataset:
raise HTTPException(status_code=404, detail="数据集不存在")
return dataset_to_out(crud.train_dataset(db, dataset, payload.samples))
检测接口同样受到鉴权保护:
python
@app.post("/api/datasets/{dataset_id}/events")
def detect(dataset_id: int, payload: schemas.EventCreate, db: Session = Depends(get_db), current_user: models.User = Depends(auth.get_current_user)):
dataset = crud.get_dataset(db, current_user.id, dataset_id)
if not dataset:
raise HTTPException(status_code=404, detail="数据集不存在")
return event_to_out(crud.create_event(db, dataset, payload))
5. Vue 3 鉴权请求封装
frontend/src/api.js 封装统一请求逻辑:
javascript
export async function request(path, options = {}) {
const headers = { 'Content-Type': 'application/json', ...(options.headers || {}) }
const token = getToken()
if (token) headers.Authorization = `Bearer ${token}`
const response = await fetch(`${API_BASE}${path}`, { ...options, headers })
const data = await response.json().catch(() => ({}))
if (!response.ok) throw new Error(data.detail || '请求失败')
return data
}
登录后前端保存 Token:
javascript
setSession(data.access_token, data.user)
退出登录时清理本地状态:
javascript
clearSession()
user.value = null
九、部署与运行步骤
项目源码位于 project/ 目录。
1. 启动后端
bash
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
后端默认地址:
text
http://localhost:8000
接口文档地址:
text
http://localhost:8000/docs
2. 启动前端
bash
cd project/frontend
npm install
npm run dev
前端默认开发地址通常为:
text
http://localhost:5173
3. 初始化使用
无需手动建表,FastAPI 启动时会自动创建 SQLite 表结构。首次进入前端后:
- 注册账号;
- 创建检测模型;
- 输入训练样本;
- 提交检测数据;
- 查看异常结果和历史记录。
十、项目总结
这个项目把"机器学习异常检测"放到了完整全栈业务系统中,而不是只停留在算法脚本层面。通过 FastAPI 提供 REST API,SQLite 保存用户、模型和检测事件,Vue 3/Vite 构建交互式前端,实现了从用户认证到业务接口保护、从模型训练到异常检测展示的完整闭环。
项目还可以继续扩展:
- 引入 Isolation Forest、One-Class SVM 等更复杂算法;
- 增加 CSV 批量导入训练样本;
- 增加告警通知,如邮件、企业微信、钉钉;
- 增加管理员后台和多租户权限;
- 使用 Docker Compose 一键部署。
对于学习 Python 全栈开发、FastAPI 鉴权、Vue 3 前端开发以及机器学习工程化落地,本项目都具有较好的实践价值。