Compare commits

...

8 Commits

Author SHA1 Message Date
eab1a62ffb fix: backend/core/generate_evaluation_plots.py 2026-03-20 17:05:02 +08:00
6d42d9dac3 fix: 脚本入口路径 2026-03-20 17:03:27 +08:00
1e1d4b0d17 fix:generate_evaluation_plots 2026-03-20 17:01:30 +08:00
cc85e3807a fix:评估对齐 2026-03-20 16:52:24 +08:00
77e38fd15b feat: 升级深度学习模型为 Temporal Fusion Transformer 架构
- 将 LSTMMLPRegressor 重构为 TemporalFusionRegressor,采用 Transformer Encoder 替代 LSTM
   - 新增 LearnedAttentionPooling 和 GatedResidualBlock 模块增强模型表达能力
   - 优化训练策略,使用 OneCycleLR 调度器和样本加权机制
   - 改进缺勤事件采样算法,基于压力、健康、家庭等维度更精确地计算缺勤时长
   - 更新 .gitignore 排除原始数据文件,删除不再使用的原始 CSV 文件
2026-03-20 16:30:08 +08:00
ff0fbf96f7 docs: 添加题目名称技术路线预期结果文档
- 新增毕业设计题目说明、技术路线规划和预期结果描述
   - 优化深度学习模型代码,支持 PyTorch 可选依赖
2026-03-20 16:14:11 +08:00
844cf9a130 feat(training): strengthen lstm-mlp with embeddings and early stopping 2026-03-12 18:56:06 +08:00
d70bd54c41 fix(training): patch lightgbm sklearn compatibility 2026-03-12 18:15:09 +08:00
21 changed files with 1758 additions and 12997 deletions

362
README.md
View File

@@ -1,253 +1,279 @@
# 基于多维特征挖掘的员工缺勤分析与预测系统 # 中国企业员工缺勤分析与预测系统
## 项目简介 ## 项目简介
系统基于 UCI Absenteeism 数据集,利用机器学习算法对员工考勤数据进行深度分析,挖掘影响缺勤的多维度特征,构建缺勤预测模型,为企业人力资源管理提供科学、客观的决策支持 项目面向企业人力资源管理与运营分析场景,围绕员工缺勤事件构建了一个集数据分析、风险预测、群体画像与可视化展示于一体的毕业设计系统。系统支持缺勤趋势分析、影响因素挖掘、单次缺勤时长预测、多模型对比以及员工群体聚类展示
## 功能特性 后端采用 `Flask + scikit-learn + PyTorch`,前端采用 `Vue 3 + Element Plus + ECharts`。当前版本同时支持传统机器学习模型和 `LSTM+MLP` 深度学习模型。
### F01 数据概览与全局统计 ## 功能模块
- 基础统计指标展示(样本总数、员工总数、缺勤总时长等)
### 1. 数据概览
- 基础统计指标展示
- 月度缺勤趋势分析 - 月度缺勤趋势分析
- 星期分布分析 - 星期分布分析
- 缺勤原因分布分析 - 请假类型与原因分布分析
- 季节分布分析 - 季节分布分析
### F02 多维特征挖掘与影响因素分析 ### 2. 影响因素分析
- 特征重要性排序(基于随机森林)
- 相关性热力图分析
- 群体对比分析(饮酒/吸烟/学历/子女等维度)
### F03 员工缺勤风险预测 - 特征重要性排序
- 单次缺勤预测 - 相关性热力图
- 风险等级评估(低/中/高) - 多维群体对比分析
- 模型性能展示R²、MSE、RMSE、MAE
### F04 员工画像与群体聚类 ### 3. 缺勤预测
- K-Means 聚类结果展示
- 员工群体雷达图 - 单次缺勤时长预测
- 聚类散点图可视化 - 风险等级评估
- 多模型结果对比
- 传统模型与深度学习模型切换
### 4. 员工画像
- 聚类结果展示
- 群体画像分析
- 群体散点图可视化
## 技术栈 ## 技术栈
### 后端 ### 后端
- Python 3.11 - Python 3.11
- Flask 2.3.3 - Flask 2.3.3
- scikit-learn 1.3.0 - Flask-CORS 4.0.0
- XGBoost 1.7.6
- LightGBM 4.1.0
- pandas 2.0.3 - pandas 2.0.3
- numpy 1.24.3 - numpy 1.24.3
- scikit-learn 1.3.0
- xgboost 1.7.6
- lightgbm 4.1.0
- PyTorch 2.6.0
### 前端 ### 前端
- Vue 3.4
- Element Plus 2.4 - Vue 3
- ECharts 5.4 - Vite
- Axios 1.6 - Element Plus
- Vue Router 4.2 - ECharts
- Vite 5.0 - Axios
- Vue Router
## 项目结构
```text
forsetsystem/
├── backend/
│ ├── api/ # 接口层
│ ├── core/ # 数据生成、特征工程、训练、聚类、深度学习
│ ├── services/ # 业务服务层
│ ├── data/
│ │ └── raw/
│ │ └── china_enterprise_absence_events.csv
│ ├── models/ # 模型文件与训练工件
│ ├── app.py # 后端入口
│ ├── config.py # 项目配置
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ ├── router/
│ │ ├── styles/
│ │ ├── views/
│ │ ├── App.vue
│ │ └── main.js
│ ├── package.json
│ └── vite.config.js
├── docs/ # 系统文档、论文文档与安装说明
└── README.md
```
## 环境要求 ## 环境要求
| 项目 | 要求 | | 项目 | 要求 |
|------|------| |------|------|
| 操作系统 | Windows 10/11、Linux、macOS | | 操作系统 | Windows 10 / Windows 11 |
| Python | 3.11 | | Python | 3.11 |
| Node.js | 16.0+ |
| Conda | Anaconda 或 Miniconda | | Conda | Anaconda 或 Miniconda |
| pnpm | 8.0+ | | Node.js | 16+ |
| pnpm | 8+ |
| CUDA | 建议与 PyTorch `cu124` 轮子匹配 |
## 安装部署 ## 安装部署
### 1. 克隆项目 推荐使用 `conda` 虚拟环境,并优先安装官方 GPU 版 `PyTorch`
```bash ### 1. 创建并激活 conda 环境
git clone <repository-url>
cd forsetsystem
```
### 2. 后端环境配置
#### 创建 Conda 环境
```powershell ```powershell
conda create -n forsetenv python=3.11 -y conda create -n forsetenv python=3.11 -y
conda activate forsetenv conda activate forsetenv
``` ```
#### 安装机器学习库(使用 conda-forge ### 2. 安装 PyTorch GPU 版
```powershell ```powershell
conda install -c conda-forge pandas=2.0.3 numpy=1.24.3 scikit-learn=1.3.0 xgboost=1.7.6 lightgbm=4.1.0 joblib=1.3.1 -y pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124
``` ```
#### 安装 Web 框架 ### 3. 安装其余后端依赖
```powershell ```powershell
pip install Flask==2.3.3 Flask-CORS==4.0.0 python-dotenv==1.0.0 pip install Flask==2.3.3 Flask-CORS==4.0.0 python-dotenv==1.0.0
pip install pandas==2.0.3 numpy==1.24.3 scikit-learn==1.3.0 joblib==1.3.1
pip install xgboost==1.7.6 lightgbm==4.1.0
``` ```
#### 验证安装 如需直接使用依赖文件,可在安装 GPU 版 `PyTorch` 后执行:
```powershell ```powershell
python -c "import pandas,numpy,sklearn,xgboost,lightgbm,flask;print('All libraries installed successfully')" pip install -r backend/requirements.txt
``` ```
#### 训练模型 ### 4. 安装前端依赖
```powershell ```powershell
cd backend
python core/train_model.py
```
### 3. 前端环境配置
```bash
cd frontend cd frontend
pnpm install pnpm install
``` ```
## 运行说明 ## 启动方式
### 启动后端服务 ### 1. 生成数据集
```powershell ```powershell
conda activate forsetenv
cd backend cd backend
python core/generate_dataset.py
```
### 2. 训练模型
```powershell
python core/train_model.py
```
### 3. 启动后端
```powershell
python app.py python app.py
``` ```
后端服务运行在 http://localhost:5000 后端默认地址:
### 启动前端服务 ```text
http://127.0.0.1:5000
```
```bash ### 4. 启动前端
cd frontend
```powershell
cd ..\frontend
pnpm dev pnpm dev
``` ```
前端服务运行在 http://localhost:5173 前端默认地址:
### 访问系统 ```text
http://127.0.0.1:5173
打开浏览器访问 http://localhost:5173
## 项目结构
```
forsetsystem/
├── backend/ # 后端项目
│ ├── api/ # API 接口层
│ │ ├── overview_routes.py # 数据概览接口
│ │ ├── analysis_routes.py # 影响因素分析接口
│ │ ├── predict_routes.py # 预测接口
│ │ └── cluster_routes.py # 聚类接口
│ ├── services/ # 业务逻辑层
│ ├── core/ # 核心算法层
│ │ ├── preprocessing.py # 数据预处理
│ │ ├── feature_mining.py # 特征挖掘
│ │ ├── train_model.py # 模型训练
│ │ └── clustering.py # 聚类分析
│ ├── data/ # 数据存储
│ ├── models/ # 模型存储
│ ├── utils/ # 工具函数
│ ├── app.py # 应用入口
│ ├── config.py # 配置文件
│ └── requirements.txt # 依赖清单
├── frontend/ # 前端项目
│ ├── src/
│ │ ├── api/ # API 调用
│ │ ├── views/ # 页面组件
│ │ ├── router/ # 路由配置
│ │ ├── App.vue # 根组件
│ │ └── main.js # 入口文件
│ ├── index.html
│ ├── package.json
│ └── vite.config.js
├── data/ # 原始数据
│ └── Absenteeism_at_work.csv
├── docs/ # 项目文档
│ ├── 00_需求规格说明书.md
│ ├── 01_系统架构设计.md
│ ├── 02_接口设计文档.md
│ ├── 03_数据设计文档.md
│ └── 04_UI原型设计.md
└── README.md
``` ```
## API 接口 ## 模型说明
### 数据概览模块 当前系统支持以下模型类型:
| 接口 | 方法 | 说明 |
|------|------|------|
| /api/overview/stats | GET | 基础统计指标 |
| /api/overview/trend | GET | 月度缺勤趋势 |
| /api/overview/weekday | GET | 星期分布 |
| /api/overview/reasons | GET | 缺勤原因分布 |
| /api/overview/seasons | GET | 季节分布 |
### 影响因素分析模块 - `random_forest`
| 接口 | 方法 | 说明 | - `gradient_boosting`
|------|------|------| - `extra_trees`
| /api/analysis/importance | GET | 特征重要性 | - `xgboost`
| /api/analysis/correlation | GET | 相关性矩阵 | - `lightgbm`
| /api/analysis/compare | GET | 群体对比分析 | - `lstm_mlp`
### 预测模块 其中:
| 接口 | 方法 | 说明 |
|------|------|------|
| /api/predict/single | POST | 单次预测 |
| /api/predict/model-info | GET | 模型信息 |
### 聚类模块 - 传统模型适合结构化特征解释与特征重要性分析
| 接口 | 方法 | 说明 | - `LSTM+MLP` 适合结合事件序列与静态特征进行预测
|------|------|------|
| /api/cluster/result | GET | 聚类结果 |
| /api/cluster/profile | GET | 群体画像 |
| /api/cluster/scatter | GET | 散点数据 |
## 作者信息 ## 数据与训练文件
- **作者**:张硕 常用路径如下:
- **学校**:河南农业大学软件学院
- **项目类型**:本科毕业设计
- **完成时间**2026年3月
## 后续改进计划 - 数据集文件:[china_enterprise_absence_events.csv](D:/VScodeProject/forsetsystem/backend/data/raw/china_enterprise_absence_events.csv)
- 配置文件:[config.py](D:/VScodeProject/forsetsystem/backend/config.py)
- 数据生成脚本:[generate_dataset.py](D:/VScodeProject/forsetsystem/backend/core/generate_dataset.py)
- 模型训练脚本:[train_model.py](D:/VScodeProject/forsetsystem/backend/core/train_model.py)
- 深度学习脚本:[deep_learning_model.py](D:/VScodeProject/forsetsystem/backend/core/deep_learning_model.py)
### 模型优化 ## 接口概览
- [ ] 引入深度学习模型(如 LSTM处理时序特征
- [ ] 增加模型解释性分析SHAP 值可视化)
- [ ] 实现模型自动调参Optuna/Hyperopt
- [ ] 支持多模型集成预测
### 功能扩展 ### 数据概览
- [ ] 增加用户认证与权限管理
- [ ] 支持自定义数据集上传与分析
- [ ] 增加数据导出功能Excel/PDF 报告)
- [ ] 实现预测结果的批量导出
- [ ] 增加数据可视化大屏展示
### 技术改进 - `GET /api/overview/stats`
- [ ] 后端迁移至 FastAPI 提升性能 - `GET /api/overview/trend`
- [ ] 引入 Redis 缓存常用查询结果 - `GET /api/overview/weekday`
- [ ] 使用 Docker 容器化部署 - `GET /api/overview/reasons`
- [ ] 增加 CI/CD 自动化测试与部署 - `GET /api/overview/seasons`
- [ ] 前端状态管理迁移至 Pinia
### 数据层面 ### 影响因素分析
- [ ] 支持数据库存储MySQL/PostgreSQL
- [ ] 实现数据增量更新机制
- [ ] 增加数据质量检测与清洗功能
## 参考资料 - `GET /api/analysis/importance`
- `GET /api/analysis/correlation`
- `GET /api/analysis/compare`
- [UCI Machine Learning Repository - Absenteeism at work Data Set](https://archive.ics.uci.edu/ml/datasets/Absenteeism+at+work) ### 缺勤预测
- [Flask 官方文档](https://flask.palletsprojects.com/)
- [Vue 3 官方文档](https://vuejs.org/) - `GET /api/predict/models`
- [Element Plus 组件库](https://element-plus.org/) - `GET /api/predict/model-info`
- [ECharts 图表库](https://echarts.apache.org/) - `POST /api/predict/single`
- `POST /api/predict/compare`
### 员工画像
- `GET /api/cluster/result`
- `GET /api/cluster/profile`
- `GET /api/cluster/scatter`
## 文档目录
详细设计文档见:
- [docs/README.md](D:/VScodeProject/forsetsystem/docs/README.md)
- [09_环境配置与安装说明.md](D:/VScodeProject/forsetsystem/docs/09_环境配置与安装说明.md)
## 常见问题
### 1. `flask_cors` 缺失
执行:
```powershell
pip install Flask-CORS
```
### 2. `xgboost` 或 `lightgbm` 缺失
执行:
```powershell
pip install xgboost==1.7.6 lightgbm==4.1.0
```
### 3. PyTorch 被安装成 CPU 版
请重新执行官方 GPU 安装命令:
```powershell
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124
```
### 4. 如何确认当前使用的是 conda 环境
```powershell
conda info --envs
where python
```
## 项目信息
- 作者:张硕
- 学校:河南农业大学软件学院
- 项目类型:本科毕业设计
- 完成时间2026 年 3 月

2
backend/.gitignore vendored
View File

@@ -67,3 +67,5 @@ Thumbs.db
.dmypy.json .dmypy.json
dmypy.json dmypy.json
models models
data

View File

@@ -25,6 +25,8 @@ TEST_SIZE = 0.2
TARGET_COLUMN = '缺勤时长(小时)' TARGET_COLUMN = '缺勤时长(小时)'
EMPLOYEE_ID_COLUMN = '员工编号' EMPLOYEE_ID_COLUMN = '员工编号'
COMPANY_ID_COLUMN = '企业编号' COMPANY_ID_COLUMN = '企业编号'
EVENT_SEQUENCE_COLUMN = '事件序号'
EVENT_DATE_INDEX_COLUMN = '事件日期索引'
WEEKDAY_NAMES = { WEEKDAY_NAMES = {
1: '周一', 1: '周一',
@@ -127,6 +129,10 @@ FEATURE_NAME_CN = {
'是否临时请假': '临时请假', '是否临时请假': '临时请假',
'是否连续缺勤': '连续缺勤', '是否连续缺勤': '连续缺勤',
'前一工作日是否加班': '前一工作日加班', '前一工作日是否加班': '前一工作日加班',
'事件日期': '事件日期',
'事件日期索引': '事件日期索引',
'事件序号': '事件序号',
'员工历史事件数': '员工历史事件数',
'缺勤时长(小时)': '缺勤时长', '缺勤时长(小时)': '缺勤时长',
'加班通勤压力指数': '加班通勤压力指数', '加班通勤压力指数': '加班通勤压力指数',
'家庭负担指数': '家庭负担指数', '家庭负担指数': '家庭负担指数',

View File

@@ -0,0 +1,712 @@
from __future__ import annotations
import copy
import os
from typing import Dict, List, Optional, Tuple
import numpy as np
import pandas as pd
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import config
from core.model_features import engineer_features
try:
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset
except ImportError:
torch = None
nn = None
DataLoader = None
Dataset = object
WINDOW_SIZE = 8
SEQUENCE_FEATURES = [
'缺勤月份',
'星期几',
'是否节假日前后',
'请假类型',
'请假原因大类',
'是否提供医院证明',
'是否临时请假',
'是否连续缺勤',
'前一工作日是否加班',
'月均加班时长',
'通勤时长分钟',
'是否夜班岗位',
'是否慢性病史',
'加班通勤压力指数',
'缺勤历史强度',
]
STATIC_FEATURES = [
'所属行业',
'婚姻状态',
'岗位序列',
'岗位级别',
'年龄',
'司龄年数',
'子女数量',
'班次类型',
'绩效等级',
'BMI',
'健康风险指数',
'家庭负担指数',
'岗位稳定性指数',
]
DEFAULT_EPOCHS = 80
DEFAULT_BATCH_SIZE = 128
EARLY_STOPPING_PATIENCE = 16
TRANSFORMER_D_MODEL = 160
TRANSFORMER_HEADS = 5
TRANSFORMER_LAYERS = 3
BaseTorchModule = nn.Module if nn is not None else object
class SequenceStaticDataset(Dataset):
def __init__(
self,
seq_num: np.ndarray,
seq_cat: np.ndarray,
static_num: np.ndarray,
static_cat: np.ndarray,
targets: np.ndarray,
):
self.seq_num = torch.tensor(seq_num, dtype=torch.float32)
self.seq_cat = torch.tensor(seq_cat, dtype=torch.long)
self.static_num = torch.tensor(static_num, dtype=torch.float32)
self.static_cat = torch.tensor(static_cat, dtype=torch.long)
self.targets = torch.tensor(targets, dtype=torch.float32)
def __len__(self) -> int:
return len(self.targets)
def __getitem__(self, index: int):
return (
self.seq_num[index],
self.seq_cat[index],
self.static_num[index],
self.static_cat[index],
self.targets[index],
)
class LearnedAttentionPooling(BaseTorchModule):
def __init__(self, hidden_dim: int):
super().__init__()
self.score = nn.Sequential(
nn.Linear(hidden_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, 1),
)
def forward(self, sequence_x: torch.Tensor) -> torch.Tensor:
attn_scores = self.score(sequence_x).squeeze(-1)
attn_weights = torch.softmax(attn_scores, dim=1)
return torch.sum(sequence_x * attn_weights.unsqueeze(-1), dim=1)
class GatedResidualBlock(BaseTorchModule):
def __init__(self, input_dim: int, hidden_dim: int, dropout: float = 0.15):
super().__init__()
self.proj = nn.Linear(input_dim, hidden_dim) if input_dim != hidden_dim else nn.Identity()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.LayerNorm(hidden_dim),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(hidden_dim, hidden_dim),
)
self.gate = nn.Sequential(
nn.Linear(hidden_dim * 2, hidden_dim),
nn.Sigmoid(),
)
self.out_norm = nn.LayerNorm(hidden_dim)
def forward(self, x: torch.Tensor) -> torch.Tensor:
residual = self.proj(x)
transformed = self.net(x)
gate = self.gate(torch.cat([residual, transformed], dim=-1))
return self.out_norm(residual + transformed * gate)
class TemporalFusionRegressor(BaseTorchModule):
def __init__(
self,
seq_num_dim: int,
static_num_dim: int,
seq_cat_cardinalities: List[int],
static_cat_cardinalities: List[int],
):
super().__init__()
self.seq_cat_embeddings = nn.ModuleList(
[nn.Embedding(cardinality, _embedding_dim(cardinality)) for cardinality in seq_cat_cardinalities]
)
self.static_cat_embeddings = nn.ModuleList(
[nn.Embedding(cardinality, _embedding_dim(cardinality)) for cardinality in static_cat_cardinalities]
)
seq_cat_dim = sum(embedding.embedding_dim for embedding in self.seq_cat_embeddings)
static_cat_dim = sum(embedding.embedding_dim for embedding in self.static_cat_embeddings)
seq_input_dim = seq_num_dim + seq_cat_dim
static_input_dim = static_num_dim + static_cat_dim
self.position_embedding = nn.Parameter(torch.randn(WINDOW_SIZE, TRANSFORMER_D_MODEL) * 0.02)
self.seq_projection = nn.Sequential(
nn.Linear(seq_input_dim, TRANSFORMER_D_MODEL),
nn.LayerNorm(TRANSFORMER_D_MODEL),
nn.GELU(),
nn.Dropout(0.12),
)
encoder_layer = nn.TransformerEncoderLayer(
d_model=TRANSFORMER_D_MODEL,
nhead=TRANSFORMER_HEADS,
dim_feedforward=TRANSFORMER_D_MODEL * 3,
dropout=0.15,
activation='gelu',
batch_first=True,
norm_first=True,
)
self.sequence_encoder = nn.TransformerEncoder(
encoder_layer,
num_layers=TRANSFORMER_LAYERS,
)
self.sequence_pool = LearnedAttentionPooling(TRANSFORMER_D_MODEL)
self.sequence_head = nn.Sequential(
nn.Linear(TRANSFORMER_D_MODEL * 3, 192),
nn.LayerNorm(192),
nn.GELU(),
nn.Dropout(0.18),
nn.Linear(192, 128),
nn.GELU(),
)
self.static_net = nn.Sequential(
GatedResidualBlock(static_input_dim, 128, dropout=0.15),
GatedResidualBlock(128, 96, dropout=0.12),
)
self.context_gate = nn.Sequential(
nn.Linear(128 + 96, 128 + 96),
nn.Sigmoid(),
)
self.fusion = nn.Sequential(
GatedResidualBlock(128 + 96, 160, dropout=0.18),
nn.Dropout(0.12),
nn.Linear(160, 96),
nn.GELU(),
nn.Dropout(0.08),
nn.Linear(96, 1),
)
self.shortcut_head = nn.Sequential(
nn.Linear(seq_num_dim + static_num_dim, 64),
nn.LayerNorm(64),
nn.GELU(),
nn.Dropout(0.08),
nn.Linear(64, 1),
)
def _embed_categorical(self, inputs: torch.Tensor, embeddings: nn.ModuleList) -> Optional[torch.Tensor]:
if not embeddings:
return None
parts = [embedding(inputs[..., index]) for index, embedding in enumerate(embeddings)]
return torch.cat(parts, dim=-1)
def forward(self, seq_num_x, seq_cat_x, static_num_x, static_cat_x):
seq_parts = [seq_num_x]
seq_embedded = self._embed_categorical(seq_cat_x, self.seq_cat_embeddings)
if seq_embedded is not None:
seq_parts.append(seq_embedded)
seq_input = torch.cat(seq_parts, dim=-1)
seq_input = self.seq_projection(seq_input)
seq_input = seq_input + self.position_embedding.unsqueeze(0)
sequence_context = self.sequence_encoder(seq_input)
sequence_last = sequence_context[:, -1, :]
sequence_mean = sequence_context.mean(dim=1)
sequence_attended = self.sequence_pool(sequence_context)
sequence_repr = self.sequence_head(torch.cat([sequence_last, sequence_mean, sequence_attended], dim=1))
static_parts = [static_num_x]
static_embedded = self._embed_categorical(static_cat_x, self.static_cat_embeddings)
if static_embedded is not None:
static_parts.append(static_embedded)
static_input = torch.cat(static_parts, dim=-1)
static_repr = self.static_net(static_input)
fused = torch.cat([sequence_repr, static_repr], dim=1)
fused = fused * self.context_gate(fused)
shortcut = self.shortcut_head(torch.cat([seq_num_x[:, -1, :], static_num_x], dim=1))
return (self.fusion(fused) + shortcut).squeeze(1)
class LSTMMLPRegressor(TemporalFusionRegressor):
pass
def is_available() -> bool:
return torch is not None
def _embedding_dim(cardinality: int) -> int:
return int(min(24, max(4, round(cardinality ** 0.35 * 2))))
def _split_feature_types(df: pd.DataFrame, features: List[str]) -> Tuple[List[str], List[str]]:
categorical = []
numerical = []
for feature in features:
if feature not in df.columns:
continue
if pd.api.types.is_numeric_dtype(df[feature]):
numerical.append(feature)
else:
categorical.append(feature)
return categorical, numerical
def _fit_category_maps(df: pd.DataFrame, features: List[str]) -> Dict[str, Dict[str, int]]:
category_maps = {}
for feature in features:
if feature not in df.columns:
continue
values = sorted(df[feature].astype(str).fillna('__MISSING__').unique().tolist())
category_maps[feature] = {value: idx + 1 for idx, value in enumerate(values)}
return category_maps
def _encode_categorical_series(values: pd.Series, mapping: Dict[str, int]) -> np.ndarray:
return values.astype(str).fillna('__MISSING__').map(lambda value: mapping.get(value, 0)).to_numpy(dtype=np.int64)
def _safe_standardize(values: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
if values.shape[1] == 0:
return np.zeros((0,), dtype=np.float32), np.ones((0,), dtype=np.float32)
mean = values.mean(axis=0)
std = values.std(axis=0)
std = np.where(std < 1e-6, 1.0, std)
return mean.astype(np.float32), std.astype(np.float32)
def _build_feature_layout(train_df: pd.DataFrame) -> Dict[str, List[str]]:
used_features = sorted(set(SEQUENCE_FEATURES + STATIC_FEATURES))
seq_cat_features, seq_num_features = _split_feature_types(train_df, SEQUENCE_FEATURES)
static_cat_features, static_num_features = _split_feature_types(train_df, STATIC_FEATURES)
all_cat_features = sorted(set(seq_cat_features + static_cat_features))
return {
'used_features': used_features,
'seq_cat_features': seq_cat_features,
'seq_num_features': seq_num_features,
'static_cat_features': static_cat_features,
'static_num_features': static_num_features,
'all_cat_features': all_cat_features,
}
def _build_sequence_arrays(
df: pd.DataFrame,
feature_layout: Dict[str, List[str]],
category_maps: Dict[str, Dict[str, int]],
target_transform: str,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
df = engineer_features(df.copy())
for feature in feature_layout['used_features']:
if feature not in df.columns:
df[feature] = 0
df = df.sort_values(
[config.EMPLOYEE_ID_COLUMN, config.EVENT_DATE_INDEX_COLUMN, config.EVENT_SEQUENCE_COLUMN]
).reset_index(drop=True)
sequence_num_samples = []
sequence_cat_samples = []
static_num_samples = []
static_cat_samples = []
targets = []
for _, group in df.groupby(config.EMPLOYEE_ID_COLUMN, sort=False):
seq_num_values = group[feature_layout['seq_num_features']].astype(float).to_numpy(dtype=np.float32)
static_num_values = group[feature_layout['static_num_features']].astype(float).to_numpy(dtype=np.float32)
target_values = group[config.TARGET_COLUMN].astype(float).to_numpy(dtype=np.float32)
if feature_layout['seq_cat_features']:
seq_cat_values = np.column_stack(
[
_encode_categorical_series(group[feature], category_maps[feature])
for feature in feature_layout['seq_cat_features']
]
).astype(np.int64)
else:
seq_cat_values = np.zeros((len(group), 0), dtype=np.int64)
if feature_layout['static_cat_features']:
static_cat_values = np.column_stack(
[
_encode_categorical_series(group[feature], category_maps[feature])
for feature in feature_layout['static_cat_features']
]
).astype(np.int64)
else:
static_cat_values = np.zeros((len(group), 0), dtype=np.int64)
for index in range(len(group)):
start_index = max(0, index - WINDOW_SIZE + 1)
num_slice = seq_num_values[start_index: index + 1]
cat_slice = seq_cat_values[start_index: index + 1]
num_window = np.zeros((WINDOW_SIZE, len(feature_layout['seq_num_features'])), dtype=np.float32)
cat_window = np.zeros((WINDOW_SIZE, len(feature_layout['seq_cat_features'])), dtype=np.int64)
num_window[-len(num_slice):] = num_slice
if len(feature_layout['seq_cat_features']) > 0:
cat_window[-len(cat_slice):] = cat_slice
sequence_num_samples.append(num_window)
sequence_cat_samples.append(cat_window)
static_num_samples.append(static_num_values[index].astype(np.float32))
static_cat_samples.append(static_cat_values[index].astype(np.int64))
targets.append(float(target_values[index]))
targets_array = np.array(targets, dtype=np.float32)
if target_transform == 'log1p':
targets_array = np.log1p(np.clip(targets_array, a_min=0, a_max=None)).astype(np.float32)
return (
np.array(sequence_num_samples, dtype=np.float32),
np.array(sequence_cat_samples, dtype=np.int64),
np.array(static_num_samples, dtype=np.float32),
np.array(static_cat_samples, dtype=np.int64),
targets_array,
)
def _train_validation_split(train_df: pd.DataFrame, validation_ratio: float = 0.15) -> Tuple[pd.DataFrame, pd.DataFrame]:
employee_ids = train_df[config.EMPLOYEE_ID_COLUMN].dropna().astype(str).unique().tolist()
rng = np.random.default_rng(config.RANDOM_STATE)
rng.shuffle(employee_ids)
validation_count = max(1, int(len(employee_ids) * validation_ratio))
validation_ids = set(employee_ids[:validation_count])
validation_df = train_df[train_df[config.EMPLOYEE_ID_COLUMN].astype(str).isin(validation_ids)].copy()
fit_df = train_df[~train_df[config.EMPLOYEE_ID_COLUMN].astype(str).isin(validation_ids)].copy()
if fit_df.empty or validation_df.empty:
split_index = max(1, int(len(train_df) * (1 - validation_ratio)))
fit_df = train_df.iloc[:split_index].copy()
validation_df = train_df.iloc[split_index:].copy()
return fit_df, validation_df
def _prepare_inference_window(
df: pd.DataFrame,
feature_layout: Dict[str, List[str]],
category_maps: Dict[str, Dict[str, int]],
default_sequence_num_prefix: np.ndarray,
default_sequence_cat_prefix: np.ndarray,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
df = engineer_features(df.copy())
for feature in feature_layout['used_features']:
if feature not in df.columns:
df[feature] = 0
row = df.iloc[0]
seq_num_row = row[feature_layout['seq_num_features']].astype(float).to_numpy(dtype=np.float32)
static_num_row = row[feature_layout['static_num_features']].astype(float).to_numpy(dtype=np.float32)
if feature_layout['seq_cat_features']:
seq_cat_row = np.array(
[category_maps[feature].get(str(row[feature]), 0) for feature in feature_layout['seq_cat_features']],
dtype=np.int64,
)
else:
seq_cat_row = np.zeros((0,), dtype=np.int64)
if feature_layout['static_cat_features']:
static_cat_row = np.array(
[category_maps[feature].get(str(row[feature]), 0) for feature in feature_layout['static_cat_features']],
dtype=np.int64,
)
else:
static_cat_row = np.zeros((0,), dtype=np.int64)
sequence_num_window = np.vstack([default_sequence_num_prefix, seq_num_row.reshape(1, -1)]).astype(np.float32)
if len(feature_layout['seq_cat_features']) > 0:
sequence_cat_window = np.vstack([default_sequence_cat_prefix, seq_cat_row.reshape(1, -1)]).astype(np.int64)
else:
sequence_cat_window = np.zeros((WINDOW_SIZE, 0), dtype=np.int64)
return sequence_num_window, sequence_cat_window, static_num_row, static_cat_row
def _evaluate_model(
model: nn.Module,
loader: DataLoader,
device: torch.device,
target_transform: str,
) -> Tuple[float, Dict[str, float]]:
model.eval()
predictions = []
targets = []
with torch.no_grad():
for batch_seq_num, batch_seq_cat, batch_static_num, batch_static_cat, batch_target in loader:
batch_seq_num = batch_seq_num.to(device)
batch_seq_cat = batch_seq_cat.to(device)
batch_static_num = batch_static_num.to(device)
batch_static_cat = batch_static_cat.to(device)
batch_predictions = model(batch_seq_num, batch_seq_cat, batch_static_num, batch_static_cat)
predictions.append(batch_predictions.cpu().numpy())
targets.append(batch_target.numpy())
y_pred = np.concatenate(predictions) if predictions else np.array([], dtype=np.float32)
y_true = np.concatenate(targets) if targets else np.array([], dtype=np.float32)
if target_transform == 'log1p':
y_pred_eval = np.expm1(y_pred)
y_true_eval = np.expm1(y_true)
else:
y_pred_eval = y_pred
y_true_eval = y_true
y_pred_eval = np.clip(y_pred_eval, a_min=0, a_max=None)
mse = mean_squared_error(y_true_eval, y_pred_eval)
metrics = {
'r2': float(r2_score(y_true_eval, y_pred_eval)),
'mse': float(mse),
'rmse': float(np.sqrt(mse)),
'mae': float(mean_absolute_error(y_true_eval, y_pred_eval)),
}
return metrics['rmse'], metrics
def _compute_sample_weights(targets: torch.Tensor, target_transform: str) -> torch.Tensor:
if target_transform == 'log1p':
base_targets = torch.expm1(targets)
else:
base_targets = targets
normalized = torch.clamp(base_targets / 12.0, min=0.0, max=2.0)
return 1.0 + normalized * 0.8
def train_lstm_mlp(
train_df: pd.DataFrame,
test_df: pd.DataFrame,
model_path: str,
target_transform: str = 'log1p',
epochs: int = DEFAULT_EPOCHS,
batch_size: int = DEFAULT_BATCH_SIZE,
) -> Optional[Dict]:
if torch is None:
return None
fit_df, validation_df = _train_validation_split(train_df)
feature_layout = _build_feature_layout(fit_df)
category_maps = _fit_category_maps(fit_df, feature_layout['all_cat_features'])
train_seq_num, train_seq_cat, train_static_num, train_static_cat, y_train = _build_sequence_arrays(
fit_df, feature_layout, category_maps, target_transform
)
val_seq_num, val_seq_cat, val_static_num, val_static_cat, y_val = _build_sequence_arrays(
validation_df, feature_layout, category_maps, target_transform
)
test_seq_num, test_seq_cat, test_static_num, test_static_cat, y_test_aligned = _build_sequence_arrays(
test_df, feature_layout, category_maps, target_transform
)
seq_mean, seq_std = _safe_standardize(train_seq_num.reshape(-1, train_seq_num.shape[-1]))
static_mean, static_std = _safe_standardize(train_static_num)
train_seq_num = ((train_seq_num - seq_mean) / seq_std).astype(np.float32)
val_seq_num = ((val_seq_num - seq_mean) / seq_std).astype(np.float32)
test_seq_num = ((test_seq_num - seq_mean) / seq_std).astype(np.float32)
train_static_num = ((train_static_num - static_mean) / static_std).astype(np.float32)
val_static_num = ((val_static_num - static_mean) / static_std).astype(np.float32)
test_static_num = ((test_static_num - static_mean) / static_std).astype(np.float32)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
if device.type == 'cuda':
print(f'[lstm_mlp] Training device: CUDA ({torch.cuda.get_device_name(device)})')
else:
print('[lstm_mlp] Training device: CPU')
model = TemporalFusionRegressor(
seq_num_dim=train_seq_num.shape[-1],
static_num_dim=train_static_num.shape[-1],
seq_cat_cardinalities=[len(category_maps[feature]) + 1 for feature in feature_layout['seq_cat_features']],
static_cat_cardinalities=[len(category_maps[feature]) + 1 for feature in feature_layout['static_cat_features']],
).to(device)
optimizer = torch.optim.AdamW(model.parameters(), lr=9e-4, weight_decay=3e-4)
criterion = nn.SmoothL1Loss(beta=0.28, reduction='none')
train_loader = DataLoader(
SequenceStaticDataset(train_seq_num, train_seq_cat, train_static_num, train_static_cat, y_train),
batch_size=batch_size,
shuffle=True,
drop_last=False,
)
val_loader = DataLoader(
SequenceStaticDataset(val_seq_num, val_seq_cat, val_static_num, val_static_cat, y_val),
batch_size=batch_size,
shuffle=False,
)
total_steps = max(20, epochs * max(1, len(train_loader)))
scheduler = torch.optim.lr_scheduler.OneCycleLR(
optimizer,
max_lr=0.0014,
total_steps=total_steps,
pct_start=0.12,
div_factor=12.0,
final_div_factor=40.0,
)
best_state = None
best_metrics = None
best_val_rmse = float('inf')
stale_epochs = 0
for epoch in range(epochs):
model.train()
running_loss = 0.0
for batch_seq_num, batch_seq_cat, batch_static_num, batch_static_cat, batch_target in train_loader:
batch_seq_num = batch_seq_num.to(device)
batch_seq_cat = batch_seq_cat.to(device)
batch_static_num = batch_static_num.to(device)
batch_static_cat = batch_static_cat.to(device)
batch_target = batch_target.to(device)
optimizer.zero_grad(set_to_none=True)
predictions = model(batch_seq_num, batch_seq_cat, batch_static_num, batch_static_cat)
sample_weights = _compute_sample_weights(batch_target, target_transform)
loss = criterion(predictions, batch_target)
loss = (loss * sample_weights).mean()
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
scheduler.step()
running_loss += float(loss.item()) * len(batch_target)
train_loss = running_loss / max(1, len(train_loader.dataset))
val_rmse, val_metrics = _evaluate_model(model, val_loader, device, target_transform)
improved = val_rmse + 1e-4 < best_val_rmse
if improved:
best_val_rmse = val_rmse
best_metrics = val_metrics
best_state = copy.deepcopy(model.state_dict())
stale_epochs = 0
else:
stale_epochs += 1
if epoch == 0 or (epoch + 1) % 5 == 0 or improved:
print(
f'[lstm_mlp] epoch={epoch + 1:02d} train_loss={train_loss:.4f} '
f'val_r2={val_metrics["r2"]:.4f} val_rmse={val_metrics["rmse"]:.4f}'
)
if stale_epochs >= EARLY_STOPPING_PATIENCE:
print(f'[lstm_mlp] Early stopping at epoch {epoch + 1}')
break
if best_state is None:
best_state = copy.deepcopy(model.state_dict())
model.load_state_dict(best_state)
model.eval()
with torch.no_grad():
predictions = model(
torch.tensor(test_seq_num, dtype=torch.float32).to(device),
torch.tensor(test_seq_cat, dtype=torch.long).to(device),
torch.tensor(test_static_num, dtype=torch.float32).to(device),
torch.tensor(test_static_cat, dtype=torch.long).to(device),
).cpu().numpy()
if target_transform == 'log1p':
y_pred = np.expm1(predictions)
y_true = np.expm1(y_test_aligned)
else:
y_pred = predictions
y_true = y_test_aligned
y_pred = np.clip(y_pred, a_min=0, a_max=None)
mse = mean_squared_error(y_true, y_pred)
default_sequence_num_prefix = train_seq_num[:, :-1, :].mean(axis=0).astype(np.float32)
if train_seq_cat.shape[-1] > 0:
default_sequence_cat_prefix = np.rint(train_seq_cat[:, :-1, :].mean(axis=0)).astype(np.int64)
else:
default_sequence_cat_prefix = np.zeros((WINDOW_SIZE - 1, 0), dtype=np.int64)
bundle = {
'state_dict': model.state_dict(),
'architecture': 'temporal_fusion_transformer',
'window_size': WINDOW_SIZE,
'target_transform': target_transform,
'feature_layout': feature_layout,
'category_maps': category_maps,
'seq_mean': seq_mean,
'seq_std': seq_std,
'static_mean': static_mean,
'static_std': static_std,
'default_sequence_num_prefix': default_sequence_num_prefix,
'default_sequence_cat_prefix': default_sequence_cat_prefix,
'seq_num_dim': train_seq_num.shape[-1],
'static_num_dim': train_static_num.shape[-1],
'seq_cat_cardinalities': [len(category_maps[feature]) + 1 for feature in feature_layout['seq_cat_features']],
'static_cat_cardinalities': [len(category_maps[feature]) + 1 for feature in feature_layout['static_cat_features']],
'best_validation_metrics': best_metrics,
}
torch.save(bundle, model_path)
return {
'metrics': {
'r2': round(float(r2_score(y_true, y_pred)), 4),
'mse': round(float(mse), 4),
'rmse': round(float(np.sqrt(mse)), 4),
'mae': round(float(mean_absolute_error(y_true, y_pred)), 4),
},
'metadata': {
'sequence_window_size': WINDOW_SIZE,
'sequence_feature_names': SEQUENCE_FEATURES,
'static_feature_names': STATIC_FEATURES,
'deep_learning_architecture': 'temporal_fusion_transformer',
'deep_validation_r2': round(float(best_metrics['r2']), 4) if best_metrics else None,
},
}
def load_lstm_mlp_bundle(model_path: str) -> Optional[Dict]:
if torch is None or not os.path.exists(model_path):
return None
bundle = torch.load(model_path, map_location='cpu', weights_only=False)
model = LSTMMLPRegressor(
seq_num_dim=bundle['seq_num_dim'],
static_num_dim=bundle['static_num_dim'],
seq_cat_cardinalities=bundle['seq_cat_cardinalities'],
static_cat_cardinalities=bundle['static_cat_cardinalities'],
)
model.load_state_dict(bundle['state_dict'])
model.eval()
bundle['model'] = model
return bundle
def predict_lstm_mlp(bundle: Dict, current_df: pd.DataFrame) -> float:
sequence_num_window, sequence_cat_window, static_num_row, static_cat_row = _prepare_inference_window(
current_df,
bundle['feature_layout'],
bundle['category_maps'],
bundle['default_sequence_num_prefix'],
bundle['default_sequence_cat_prefix'],
)
sequence_num_window = ((sequence_num_window - bundle['seq_mean']) / bundle['seq_std']).astype(np.float32)
static_num_row = ((static_num_row - bundle['static_mean']) / bundle['static_std']).astype(np.float32)
with torch.no_grad():
prediction = bundle['model'](
torch.tensor(sequence_num_window, dtype=torch.float32).unsqueeze(0),
torch.tensor(sequence_cat_window, dtype=torch.long).unsqueeze(0),
torch.tensor(static_num_row, dtype=torch.float32).unsqueeze(0),
torch.tensor(static_cat_row, dtype=torch.long).unsqueeze(0),
).cpu().numpy()[0]
if bundle.get('target_transform') == 'log1p':
prediction = np.expm1(prediction)
return float(max(0.5, prediction))

View File

@@ -161,68 +161,109 @@ def sample_event(rng, employee):
weekday = int(rng.integers(1, 8)) weekday = int(rng.integers(1, 8))
near_holiday = int(rng.random() < (0.3 if month in [1, 2, 4, 5, 9, 10] else 0.16)) near_holiday = int(rng.random() < (0.3 if month in [1, 2, 4, 5, 9, 10] else 0.16))
leave_type_items = ['病假', '事假', '年假', '调休', '婚假', '丧假', '产检育儿假', '工伤假', '其他'] leave_type_items = ['病假', '事假', '年假', '调休', '婚假', '丧假', '产检育儿假', '工伤假', '其他']
leave_type = weighted_choice(rng, leave_type_items, [0.3, 0.22, 0.12, 0.14, 0.03, 0.02, 0.06, 0.02, 0.09]) leave_probs = [0.26, 0.22, 0.11, 0.14, 0.03, 0.02, 0.07, 0.03, 0.12]
if employee['子女数量'] > 0 and rng.random() < 0.14: if employee['是否慢性病史'] == 1 or employee['年度体检异常标记'] == 1:
reason_category = '子女照护' leave_probs = [0.34, 0.18, 0.08, 0.1, 0.02, 0.02, 0.08, 0.04, 0.14]
elif employee['子女数量'] >= 2:
leave_probs = [0.22, 0.24, 0.1, 0.12, 0.03, 0.02, 0.12, 0.02, 0.13]
leave_type = weighted_choice(rng, leave_type_items, leave_probs)
if leave_type in ['病假', '工伤假']:
reason_category = weighted_choice(rng, ['身体不适', '就医复查', '职业疲劳'], [0.52, 0.3, 0.18])
elif leave_type == '产检育儿假':
reason_category = weighted_choice(rng, ['子女照护', '家庭事务', '身体不适'], [0.6, 0.25, 0.15])
elif leave_type in ['婚假', '丧假']:
reason_category = weighted_choice(rng, ['家庭事务', '突发事件'], [0.72, 0.28])
elif leave_type in ['年假', '调休']:
reason_category = weighted_choice(rng, ['职业疲劳', '家庭事务', '交通受阻'], [0.52, 0.28, 0.2])
else: else:
reason_category = weighted_choice( reason_category = weighted_choice(
rng, rng,
['身体不适', '家庭事务', '交通受阻', '突发事件', '职业疲劳', '就医复查'], ['身体不适', '家庭事务', '子女照护', '交通受阻', '突发事件', '职业疲劳'],
[0.28, 0.19, 0.09, 0.11, 0.2, 0.13], [0.2, 0.22, 0.14, 0.12, 0.12, 0.2],
)
medical_certificate = int(
leave_type in ['病假', '工伤假']
or reason_category in ['身体不适', '就医复查']
or (employee['是否慢性病史'] == 1 and leave_type == '其他')
)
urgent_leave = int(
leave_type in ['病假', '工伤假']
or reason_category in ['突发事件', '身体不适']
or (near_holiday == 0 and leave_type == '事假' and rng.random() < 0.35)
)
continuous_absence = int(
leave_type in ['病假', '工伤假', '产检育儿假']
and (employee['近90天缺勤次数'] >= 2 or employee['近180天请假总时长'] >= 28)
)
previous_overtime = int(
employee['月均加班时长'] >= 30
or (employee['月均加班时长'] >= 24 and weekday in [1, 2, 5])
or (employee['是否夜班岗位'] == 1 and rng.random() < 0.65)
) )
medical_certificate = int(leave_type in ['病假', '工伤假'] or reason_category in ['身体不适', '就医复查'])
urgent_leave = int(rng.random() < (0.45 if leave_type in ['病假', '事假', '工伤假'] else 0.18))
continuous_absence = int(rng.random() < (0.2 if leave_type in ['病假', '产检育儿假', '工伤假'] else 0.08))
previous_overtime = int(rng.random() < min(0.85, employee['月均加班时长'] / 65))
season = season_from_month(month) season = season_from_month(month)
channel = weighted_choice(rng, ['系统申请', '主管代提', '临时电话报备'], [0.68, 0.18, 0.14]) channel = weighted_choice(rng, ['系统申请', '主管代提', '临时电话报备'], [0.68, 0.18, 0.14])
base = 0.95 pressure_score = (
base += min(employee['月均加班时长'] / 28, 1.8) employee['月均加班时长'] * 0.032
base += min(employee['通勤时长分钟'] / 65, 1.2) + employee['通勤时长分钟'] * 0.018
base += employee['是否夜班岗位'] * 0.9 + employee['是否夜班岗位'] * 0.75
base += employee['是否慢性病史'] * 1.25 + employee['是否跨城通勤'] * 0.32
base += employee['年度体检异常标记'] * 0.6 + previous_overtime * 0.35
base += 0.35 * employee['子女数量'] )
base += 0.5 if employee['心理压力等级'] == '' else (0.2 if employee['心理压力等级'] == '' else -0.1) health_score = (
base += 0.4 if employee['是否跨城通勤'] else 0 employee['是否慢性病史'] * 1.2
base += 0.35 if previous_overtime else 0 + employee['年度体检异常标记'] * 0.55
base += 0.35 if near_holiday else 0 + (employee['BMI'] >= 28) * 0.3
base += 0.3 if continuous_absence else 0 + (employee['近30天睡眠时长均值'] < 6.4) * 0.45
base += 0.3 if employee['近90天缺勤次数'] >= 3 else 0 )
base -= 0.35 if employee['绩效等级'] == 'A' else (0.15 if employee['绩效等级'] == 'B' else 0) family_score = employee['子女数量'] * 0.18 + employee['是否独生子女家庭负担'] * 0.28
base -= min(employee['司龄年数'] / 40, 0.5) resilience_score = (
base -= min(employee['每周运动频次'] * 0.08, 0.3) (0.55 if employee['绩效等级'] == 'A' else 0.25 if employee['绩效等级'] == 'B' else 0.0)
base -= 0.2 if employee['近30天睡眠时长均值'] >= 7.5 else 0 + min(employee['司龄年数'] / 26, 0.65)
+ min(employee['每周运动频次'] * 0.06, 0.25)
)
base = 0.35
base += pressure_score
base += health_score
base += family_score
base += 0.4 if employee['心理压力等级'] == '' else (0.18 if employee['心理压力等级'] == '' else -0.05)
base += 0.18 if near_holiday else 0.0
base += 0.35 if continuous_absence else 0.0
base += 0.28 if employee['近90天缺勤次数'] >= 3 else 0.0
base += 0.18 if employee['近180天请假总时长'] >= 36 else 0.0
base -= resilience_score
leave_bonus = { leave_bonus = {
'病假': 2.0, '病假': 2.1,
'事假': 0.8, '事假': 0.8,
'年假': 0.1, '年假': 0.15,
'调休': 0.1, '调休': 0.1,
'婚假': 3.0, '婚假': 3.1,
'丧假': 2.8, '丧假': 2.8,
'产检育儿假': 2.4, '产检育儿假': 2.35,
'工伤假': 3.8, '工伤假': 3.9,
'其他': 0.5, '其他': 0.55,
} }
reason_bonus = { reason_bonus = {
'身体不适': 1.0, '身体不适': 1.0,
'家庭事务': 0.5, '家庭事务': 0.55,
'子女照护': 0.8, '子女照护': 0.75,
'交通受阻': 0.2, '交通受阻': 0.2,
'突发事件': 0.6, '突发事件': 0.6,
'职业疲劳': 0.7, '职业疲劳': 0.7,
'就医复查': 1.2, '就医复查': 1.15,
} }
industry_bonus = { industry_bonus = {
'制造业': 0.35, '制造业': 0.42,
'互联网': 0.2, '互联网': 0.22,
'零售连锁': 0.25, '零售连锁': 0.28,
'物流运输': 0.4, '物流运输': 0.5,
'金融服务': 0.1, '金融服务': 0.12,
'医药健康': 0.2, '医药健康': 0.24,
'建筑工程': 0.35, '建筑工程': 0.4,
} }
season_bonus = {1: 0.35, 2: 0.0, 3: 0.15, 4: 0.05} season_bonus = {1: 0.35, 2: 0.0, 3: 0.15, 4: 0.05}
weekday_bonus = {1: 0.05, 2: 0.0, 3: 0.0, 4: 0.05, 5: 0.15, 6: 0.25, 7: 0.3} weekday_bonus = {1: 0.05, 2: 0.0, 3: 0.0, 4: 0.05, 5: 0.15, 6: 0.25, 7: 0.3}
@@ -233,18 +274,21 @@ def sample_event(rng, employee):
duration += industry_bonus[employee['所属行业']] duration += industry_bonus[employee['所属行业']]
duration += season_bonus[season] duration += season_bonus[season]
duration += weekday_bonus[weekday] duration += weekday_bonus[weekday]
duration += 0.55 if medical_certificate else 0 duration += 0.55 if medical_certificate else 0.0
duration += 0.4 if urgent_leave else -0.05 duration += 0.28 if urgent_leave else -0.06
duration += rng.normal(0, 0.9)
if leave_type in ['', '丧假', '工伤假'] and rng.random() < 0.5: if leave_type == '' and employee['是否慢性病史'] == 1:
duration += rng.uniform(1.5, 5) duration += 0.85
if leave_type == '' and employee['是否慢性病史'] == 1 and rng.random() < 0.35: if leave_type == '工伤':
duration += rng.uniform(1, 4) duration += 1.0 + employee['是否夜班岗位'] * 0.3
if leave_type in ['婚假', '丧假']:
duration += 0.7 + 0.18 * near_holiday
if leave_type == '产检育儿假':
duration += 0.55 + employee['子女数量'] * 0.12
if leave_type in ['年假', '调休']: if leave_type in ['年假', '调休']:
duration *= rng.uniform(0.7, 0.95) duration *= 0.82 if near_holiday == 0 else 0.9
duration = round(float(np.clip(duration, 0.5, 24.0)), 1) duration = round(float(np.clip(duration + rng.normal(0, 0.35), 0.5, 18.0)), 1)
event = employee.copy() event = employee.copy()
event.update({ event.update({
@@ -264,6 +308,28 @@ def sample_event(rng, employee):
return event return event
def attach_event_timeline(df):
df = df.copy()
rng = np.random.default_rng(config.RANDOM_STATE)
base_date = np.datetime64('2025-01-01')
timelines = []
for employee_id, group in df.groupby('员工编号', sort=False):
group = group.copy().reset_index(drop=True)
event_count = len(group)
offsets = np.sort(rng.integers(0, 365, size=event_count))
group['事件日期'] = [
str(pd.Timestamp(base_date + np.timedelta64(int(offset), 'D')).date())
for offset in offsets
]
group['事件日期索引'] = offsets.astype(int)
group['事件序号'] = np.arange(1, event_count + 1)
group['员工历史事件数'] = event_count
timelines.append(group)
return pd.concat(timelines, ignore_index=True)
def validate_dataset(df): def validate_dataset(df):
required_columns = [ required_columns = [
'员工编号', '员工编号',
@@ -273,6 +339,9 @@ def validate_dataset(df):
'通勤时长分钟', '通勤时长分钟',
'是否慢性病史', '是否慢性病史',
'请假类型', '请假类型',
'事件序号',
'事件日期索引',
'员工历史事件数',
'缺勤时长(小时)', '缺勤时长(小时)',
] ]
for column in required_columns: for column in required_columns:
@@ -309,7 +378,7 @@ def generate_dataset(output_path=None, sample_count=12000, random_state=None):
for idx in employee_idx: for idx in employee_idx:
events.append(sample_event(rng, employees[int(idx)])) events.append(sample_event(rng, employees[int(idx)]))
df = pd.DataFrame(events) df = attach_event_timeline(pd.DataFrame(events))
validate_dataset(df) validate_dataset(df)
if output_path: if output_path:

View File

@@ -0,0 +1,330 @@
import json
import os
import sys
from pathlib import Path
import joblib
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import config
from core.deep_learning_model import (
_build_sequence_arrays,
load_lstm_mlp_bundle,
)
from core.model_features import (
NUMERICAL_OUTLIER_COLUMNS,
TARGET_COLUMN,
apply_outlier_bounds,
engineer_features,
fit_outlier_bounds,
make_target_bins,
normalize_columns,
)
from core.preprocessing import get_clean_data
matplotlib.rcParams['font.sans-serif'] = [
'Microsoft YaHei',
'SimHei',
'Noto Sans CJK SC',
'Arial Unicode MS',
'DejaVu Sans',
]
matplotlib.rcParams['axes.unicode_minus'] = False
BASE_DIR = Path(config.BASE_DIR)
MODELS_DIR = Path(config.MODELS_DIR)
OUTPUT_DIR = BASE_DIR / 'outputs' / 'eval_figures'
PREDICTION_CSV = OUTPUT_DIR / 'lstm_predictions.csv'
SUMMARY_JSON = OUTPUT_DIR / 'evaluation_summary.json'
MODEL_DISPLAY_NAMES = {
'lstm_mlp': '时序注意力融合网络',
'xgboost': 'XGBoost',
'gradient_boosting': 'GBDT',
'random_forest': '随机森林',
'extra_trees': '极端随机树',
'lightgbm': 'LightGBM',
}
def ensure_output_dir():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
def load_metrics():
metrics_path = MODELS_DIR / 'model_metrics.pkl'
if not metrics_path.exists():
raise FileNotFoundError(f'未找到模型评估文件: {metrics_path}')
metrics = joblib.load(metrics_path)
return dict(sorted(metrics.items(), key=lambda item: item[1].get('r2', -999), reverse=True))
def get_test_split():
raw_df = normalize_columns(get_clean_data())
target_bins = make_target_bins(raw_df[TARGET_COLUMN].values)
raw_train_df, raw_test_df = train_test_split(
raw_df,
test_size=config.TEST_SIZE,
random_state=config.RANDOM_STATE,
stratify=target_bins,
)
return raw_train_df.reset_index(drop=True), raw_test_df.reset_index(drop=True)
def classify_risk(values):
values = np.asarray(values, dtype=float)
return np.where(values < 4, '低风险', np.where(values <= 8, '中风险', '高风险'))
def load_lstm_predictions():
model_path = MODELS_DIR / 'lstm_mlp_model.pt'
if not model_path.exists():
raise FileNotFoundError(f'未找到深度学习模型文件: {model_path}')
bundle = load_lstm_mlp_bundle(str(model_path))
if bundle is None:
raise RuntimeError('无法加载深度学习模型,请确认 torch 环境和模型文件正常。')
raw_train_df, raw_test_df = get_test_split()
outlier_bounds = fit_outlier_bounds(raw_train_df, NUMERICAL_OUTLIER_COLUMNS)
fit_df = apply_outlier_bounds(raw_train_df, outlier_bounds)
test_df = apply_outlier_bounds(raw_test_df, outlier_bounds)
feature_layout = bundle['feature_layout']
category_maps = bundle['category_maps']
target_transform = bundle['target_transform']
_, _, _, _, _ = _build_sequence_arrays(
fit_df,
feature_layout,
category_maps,
target_transform,
)
test_seq_num, test_seq_cat, test_static_num, test_static_cat, y_test = _build_sequence_arrays(
test_df,
feature_layout,
category_maps,
target_transform,
)
test_seq_num = ((test_seq_num - bundle['seq_mean']) / bundle['seq_std']).astype(np.float32)
test_static_num = ((test_static_num - bundle['static_mean']) / bundle['static_std']).astype(np.float32)
import torch
model = bundle['model']
model.eval()
with torch.no_grad():
predictions = model(
torch.tensor(test_seq_num, dtype=torch.float32),
torch.tensor(test_seq_cat, dtype=torch.long),
torch.tensor(test_static_num, dtype=torch.float32),
torch.tensor(test_static_cat, dtype=torch.long),
).cpu().numpy()
if target_transform == 'log1p':
y_true = np.expm1(y_test)
y_pred = np.expm1(predictions)
else:
y_true = y_test
y_pred = predictions
y_true = np.asarray(y_true, dtype=float)
y_pred = np.clip(np.asarray(y_pred, dtype=float), a_min=0.0, a_max=None)
residuals = y_pred - y_true
prediction_df = pd.DataFrame({
'真实值': np.round(y_true, 4),
'预测值': np.round(y_pred, 4),
'残差': np.round(residuals, 4),
'真实风险等级': classify_risk(y_true),
'预测风险等级': classify_risk(y_pred),
})
prediction_df.to_csv(PREDICTION_CSV, index=False, encoding='utf-8-sig')
return prediction_df
def plot_model_comparison(metrics):
model_names = [MODEL_DISPLAY_NAMES.get(name, name) for name in metrics.keys()]
r2_values = [metrics[name]['r2'] for name in metrics]
rmse_values = [metrics[name]['rmse'] for name in metrics]
mae_values = [metrics[name]['mae'] for name in metrics]
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
bar_colors = ['#0f766e' if name == 'lstm_mlp' else '#94a3b8' for name in metrics.keys()]
axes[0].bar(model_names, r2_values, color=bar_colors)
axes[0].set_title('模型R2对比')
axes[0].set_ylabel('R2')
axes[0].tick_params(axis='x', rotation=20)
axes[1].bar(model_names, rmse_values, color=bar_colors)
axes[1].set_title('模型RMSE对比')
axes[1].set_ylabel('RMSE')
axes[1].tick_params(axis='x', rotation=20)
axes[2].bar(model_names, mae_values, color=bar_colors)
axes[2].set_title('模型MAE对比')
axes[2].set_ylabel('MAE')
axes[2].tick_params(axis='x', rotation=20)
fig.tight_layout()
fig.savefig(OUTPUT_DIR / '01_模型性能对比.png', dpi=220, bbox_inches='tight')
plt.close(fig)
def plot_actual_vs_pred(prediction_df):
y_true = prediction_df['真实值'].to_numpy()
y_pred = prediction_df['预测值'].to_numpy()
max_value = max(float(y_true.max()), float(y_pred.max()))
fig, ax = plt.subplots(figsize=(7, 7))
ax.scatter(y_true, y_pred, s=18, alpha=0.55, color='#0f766e', edgecolors='none')
ax.plot([0, max_value], [0, max_value], color='#dc2626', linestyle='--', linewidth=1.5)
ax.set_title('LSTM模型真实值与预测值对比')
ax.set_xlabel('真实缺勤时长(小时)')
ax.set_ylabel('预测缺勤时长(小时)')
fig.tight_layout()
fig.savefig(OUTPUT_DIR / '02_LSTM真实值_vs_预测值.png', dpi=220, bbox_inches='tight')
plt.close(fig)
def plot_residuals(prediction_df):
y_pred = prediction_df['预测值'].to_numpy()
residuals = prediction_df['残差'].to_numpy()
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].hist(residuals, bins=30, color='#2563eb', alpha=0.85, edgecolor='white')
axes[0].axvline(0, color='#dc2626', linestyle='--', linewidth=1.2)
axes[0].set_title('LSTM残差分布')
axes[0].set_xlabel('残差(预测值 - 真实值)')
axes[0].set_ylabel('样本数')
axes[1].scatter(y_pred, residuals, s=18, alpha=0.55, color='#7c3aed', edgecolors='none')
axes[1].axhline(0, color='#dc2626', linestyle='--', linewidth=1.2)
axes[1].set_title('LSTM残差散点图')
axes[1].set_xlabel('预测缺勤时长(小时)')
axes[1].set_ylabel('残差')
fig.tight_layout()
fig.savefig(OUTPUT_DIR / '03_LSTM残差分析.png', dpi=220, bbox_inches='tight')
plt.close(fig)
def plot_confusion_matrix(prediction_df):
labels = ['低风险', '中风险', '高风险']
cm = confusion_matrix(
prediction_df['真实风险等级'],
prediction_df['预测风险等级'],
labels=labels,
)
fig, ax = plt.subplots(figsize=(6, 5))
image = ax.imshow(cm, cmap='GnBu')
ax.set_title('LSTM风险等级混淆矩阵')
ax.set_xlabel('预测类别')
ax.set_ylabel('真实类别')
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels)
ax.set_yticks(range(len(labels)))
ax.set_yticklabels(labels)
for row in range(cm.shape[0]):
for col in range(cm.shape[1]):
ax.text(col, row, int(cm[row, col]), ha='center', va='center', color='#111827')
fig.colorbar(image, ax=ax, fraction=0.046, pad=0.04)
fig.tight_layout()
fig.savefig(OUTPUT_DIR / '04_LSTM风险等级混淆矩阵.png', dpi=220, bbox_inches='tight')
plt.close(fig)
def plot_feature_importance():
candidate_files = [
('xgboost', MODELS_DIR / 'xgboost_model.pkl'),
('random_forest', MODELS_DIR / 'random_forest_model.pkl'),
('extra_trees', MODELS_DIR / 'extra_trees_model.pkl'),
]
selected_features_path = MODELS_DIR / 'selected_features.pkl'
feature_names_path = MODELS_DIR / 'feature_names.pkl'
selected_features = joblib.load(selected_features_path) if selected_features_path.exists() else None
feature_names = joblib.load(feature_names_path) if feature_names_path.exists() else None
for model_name, model_path in candidate_files:
if not model_path.exists():
continue
model = joblib.load(model_path)
if not hasattr(model, 'feature_importances_'):
continue
importances = model.feature_importances_
names = selected_features or feature_names or [f'feature_{idx}' for idx in range(len(importances))]
if len(names) != len(importances):
names = [f'feature_{idx}' for idx in range(len(importances))]
top_items = sorted(zip(names, importances), key=lambda item: item[1], reverse=True)[:15]
top_items.reverse()
fig, ax = plt.subplots(figsize=(8, 6))
ax.barh(
[config.FEATURE_NAME_CN.get(name, name) for name, _ in top_items],
[float(value) for _, value in top_items],
color='#0f766e',
)
ax.set_title(f'{MODEL_DISPLAY_NAMES.get(model_name, model_name)}特征重要性 Top15')
ax.set_xlabel('重要性')
fig.tight_layout()
fig.savefig(OUTPUT_DIR / '05_特征重要性_Top15.png', dpi=220, bbox_inches='tight')
plt.close(fig)
return model_name
return None
def save_summary(metrics, prediction_df, feature_model_name):
residuals = prediction_df['残差'].to_numpy()
summary = {
'best_model': next(iter(metrics.keys())),
'metrics': metrics,
'lstm_prediction_summary': {
'prediction_count': int(len(prediction_df)),
'residual_mean': round(float(residuals.mean()), 4),
'residual_std': round(float(residuals.std()), 4),
'risk_accuracy': round(
float((prediction_df['真实风险等级'] == prediction_df['预测风险等级']).mean()),
4,
),
},
'feature_importance_model': feature_model_name,
'generated_files': sorted([file.name for file in OUTPUT_DIR.iterdir() if file.is_file()]),
}
SUMMARY_JSON.write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding='utf-8')
def main():
ensure_output_dir()
metrics = load_metrics()
prediction_df = load_lstm_predictions()
plot_model_comparison(metrics)
plot_actual_vs_pred(prediction_df)
plot_residuals(prediction_df)
plot_confusion_matrix(prediction_df)
feature_model_name = plot_feature_importance()
save_summary(metrics, prediction_df, feature_model_name)
print(f'评估图片已生成: {OUTPUT_DIR}')
print(f'LSTM预测明细: {PREDICTION_CSV}')
print(f'评估摘要: {SUMMARY_JSON}')
if __name__ == '__main__':
main()

View File

@@ -1,6 +1,7 @@
import os import os
import sys import sys
import time import time
import inspect
from datetime import datetime from datetime import datetime
import joblib import joblib
@@ -14,6 +15,8 @@ from sklearn.preprocessing import RobustScaler
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import config import config
from core.deep_learning_model import is_available as deep_learning_available
from core.deep_learning_model import train_lstm_mlp
from core.model_features import ( from core.model_features import (
NUMERICAL_OUTLIER_COLUMNS, NUMERICAL_OUTLIER_COLUMNS,
ORDINAL_COLUMNS, ORDINAL_COLUMNS,
@@ -43,6 +46,41 @@ except ImportError:
xgb = None xgb = None
def patch_lightgbm_sklearn_compatibility():
if lgb is None:
return
try:
from sklearn.utils.validation import check_X_y
except Exception:
return
params = inspect.signature(check_X_y).parameters
if 'force_all_finite' in params:
return
def wrapped_check_X_y(*args, force_all_finite=None, **kwargs):
if (
force_all_finite is not None
and 'ensure_all_finite' in params
and 'ensure_all_finite' not in kwargs
):
kwargs['ensure_all_finite'] = force_all_finite
return check_X_y(*args, **kwargs)
try:
import lightgbm.compat as lgb_compat
import lightgbm.sklearn as lgb_sklearn
lgb_compat._LGBMCheckXY = wrapped_check_X_y
lgb_sklearn._LGBMCheckXY = wrapped_check_X_y
except Exception:
pass
patch_lightgbm_sklearn_compatibility()
def print_training_log(model_name, start_time, best_score, best_params, n_iter, cv_folds): def print_training_log(model_name, start_time, best_score, best_params, n_iter, cv_folds):
elapsed = time.time() - start_time elapsed = time.time() - start_time
print(f' {"-" * 50}') print(f' {"-" * 50}')
@@ -68,6 +106,10 @@ class OptimizedModelTrainer:
self.feature_k = 22 self.feature_k = 22
self.target_transform = 'log1p' self.target_transform = 'log1p'
self.enabled_models = ['random_forest', 'gradient_boosting', 'extra_trees', 'lightgbm', 'xgboost'] self.enabled_models = ['random_forest', 'gradient_boosting', 'extra_trees', 'lightgbm', 'xgboost']
if deep_learning_available():
self.enabled_models.append('lstm_mlp')
self.raw_train_df = None
self.raw_test_df = None
def analyze_data(self, df): def analyze_data(self, df):
y = df[TARGET_COLUMN] y = df[TARGET_COLUMN]
@@ -96,19 +138,21 @@ class OptimizedModelTrainer:
return self.feature_selector.transform(X) if self.feature_selector else X return self.feature_selector.transform(X) if self.feature_selector else X
def prepare_data(self): def prepare_data(self):
df = normalize_columns(get_clean_data()) raw_df = normalize_columns(get_clean_data())
df = prepare_modeling_dataframe(df) self.analyze_data(prepare_modeling_dataframe(raw_df.copy()))
self.analyze_data(df)
target_bins = make_target_bins(df[TARGET_COLUMN].values) target_bins = make_target_bins(raw_df[TARGET_COLUMN].values)
train_df, test_df = train_test_split( raw_train_df, raw_test_df = train_test_split(
df, raw_df,
test_size=config.TEST_SIZE, test_size=config.TEST_SIZE,
random_state=config.RANDOM_STATE, random_state=config.RANDOM_STATE,
stratify=target_bins, stratify=target_bins,
) )
train_df = train_df.reset_index(drop=True) self.raw_train_df = raw_train_df.reset_index(drop=True)
test_df = test_df.reset_index(drop=True) self.raw_test_df = raw_test_df.reset_index(drop=True)
train_df = prepare_modeling_dataframe(self.raw_train_df)
test_df = prepare_modeling_dataframe(self.raw_test_df)
self.outlier_bounds = fit_outlier_bounds(train_df, NUMERICAL_OUTLIER_COLUMNS) self.outlier_bounds = fit_outlier_bounds(train_df, NUMERICAL_OUTLIER_COLUMNS)
train_df = apply_outlier_bounds(train_df, self.outlier_bounds) train_df = apply_outlier_bounds(train_df, self.outlier_bounds)
@@ -138,7 +182,8 @@ class OptimizedModelTrainer:
'feature_count_after_selection': int(X_train.shape[1]), 'feature_count_after_selection': int(X_train.shape[1]),
'training_date': datetime.now().strftime('%Y-%m-%d'), 'training_date': datetime.now().strftime('%Y-%m-%d'),
'target_transform': self.target_transform, 'target_transform': self.target_transform,
'available_models': list(self.enabled_models), 'available_models': [],
'deep_learning_available': False,
} }
return X_train, X_test, y_train, y_test return X_train, X_test, y_train, y_test
@@ -206,6 +251,7 @@ class OptimizedModelTrainer:
def train_lightgbm(self, X_train, y_train): def train_lightgbm(self, X_train, y_train):
if lgb is None: if lgb is None:
return return
try:
self._run_search( self._run_search(
'lightgbm', 'lightgbm',
lgb.LGBMRegressor(random_state=config.RANDOM_STATE, n_jobs=-1, verbose=-1), lgb.LGBMRegressor(random_state=config.RANDOM_STATE, n_jobs=-1, verbose=-1),
@@ -220,6 +266,10 @@ class OptimizedModelTrainer:
X_train, X_train,
y_train, y_train,
) )
except Exception as exc:
print(f' {"-" * 50}')
print(' Model: lightgbm')
print(f' Skipped: {exc}')
def train_xgboost(self, X_train, y_train): def train_xgboost(self, X_train, y_train):
if xgb is None: if xgb is None:
@@ -254,6 +304,7 @@ class OptimizedModelTrainer:
os.makedirs(config.MODELS_DIR, exist_ok=True) os.makedirs(config.MODELS_DIR, exist_ok=True)
for name, model in self.models.items(): for name, model in self.models.items():
joblib.dump(model, os.path.join(config.MODELS_DIR, f'{name}_model.pkl')) joblib.dump(model, os.path.join(config.MODELS_DIR, f'{name}_model.pkl'))
self.training_metadata['available_models'] = list(self.model_metrics.keys())
joblib.dump(self.scaler, config.SCALER_PATH) joblib.dump(self.scaler, config.SCALER_PATH)
joblib.dump(self.feature_names, os.path.join(config.MODELS_DIR, 'feature_names.pkl')) joblib.dump(self.feature_names, os.path.join(config.MODELS_DIR, 'feature_names.pkl'))
joblib.dump(self.selected_features, os.path.join(config.MODELS_DIR, 'selected_features.pkl')) joblib.dump(self.selected_features, os.path.join(config.MODELS_DIR, 'selected_features.pkl'))
@@ -282,6 +333,23 @@ class OptimizedModelTrainer:
self.model_metrics[name] = metrics self.model_metrics[name] = metrics
print(f' {name:20s} R2={metrics["r2"]:.4f} RMSE={metrics["rmse"]:.4f} MAE={metrics["mae"]:.4f}') print(f' {name:20s} R2={metrics["r2"]:.4f} RMSE={metrics["rmse"]:.4f} MAE={metrics["mae"]:.4f}')
if 'lstm_mlp' in self.enabled_models and self.raw_train_df is not None and self.raw_test_df is not None:
deep_model_path = os.path.join(config.MODELS_DIR, 'lstm_mlp_model.pt')
deep_result = train_lstm_mlp(
self.raw_train_df,
self.raw_test_df,
deep_model_path,
target_transform=self.target_transform,
)
if deep_result:
self.model_metrics['lstm_mlp'] = deep_result['metrics']
self.training_metadata['deep_learning_available'] = True
self.training_metadata.update(deep_result['metadata'])
print(
f' {"lstm_mlp":20s} R2={deep_result["metrics"]["r2"]:.4f} '
f'RMSE={deep_result["metrics"]["rmse"]:.4f} MAE={deep_result["metrics"]["mae"]:.4f}'
)
self.save_models() self.save_models()
return self.model_metrics return self.model_metrics

View File

@@ -1,741 +0,0 @@
ID;Reason for absence;Month of absence;Day of the week;Seasons;Transportation expense;Distance from Residence to Work;Service time;Age;Work load Average/day ;Hit target;Disciplinary failure;Education;Son;Social drinker;Social smoker;Pet;Weight;Height;Body mass index;Absenteeism time in hours
11;26;7;3;1;289;36;13;33;239.554;97;0;1;2;1;0;1;90;172;30;4
36;0;7;3;1;118;13;18;50;239.554;97;1;1;1;1;0;0;98;178;31;0
3;23;7;4;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;2
7;7;7;5;1;279;5;14;39;239.554;97;0;1;2;1;1;0;68;168;24;4
11;23;7;5;1;289;36;13;33;239.554;97;0;1;2;1;0;1;90;172;30;2
3;23;7;6;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;2
10;22;7;6;1;361;52;3;28;239.554;97;0;1;1;1;0;4;80;172;27;8
20;23;7;6;1;260;50;11;36;239.554;97;0;1;4;1;0;0;65;168;23;4
14;19;7;2;1;155;12;14;34;239.554;97;0;1;2;1;0;0;95;196;25;40
1;22;7;2;1;235;11;14;37;239.554;97;0;3;1;0;0;1;88;172;29;8
20;1;7;2;1;260;50;11;36;239.554;97;0;1;4;1;0;0;65;168;23;8
20;1;7;3;1;260;50;11;36;239.554;97;0;1;4;1;0;0;65;168;23;8
20;11;7;4;1;260;50;11;36;239.554;97;0;1;4;1;0;0;65;168;23;8
3;11;7;4;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;1
3;23;7;4;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;4
24;14;7;6;1;246;25;16;41;239.554;97;0;1;0;1;0;0;67;170;23;8
3;23;7;6;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;2
3;21;7;2;1;179;51;18;38;239.554;97;0;1;0;1;0;0;89;170;31;8
6;11;7;5;1;189;29;13;33;239.554;97;0;1;2;0;0;2;69;167;25;8
33;23;8;4;1;248;25;14;47;205.917;92;0;1;2;0;0;1;86;165;32;2
18;10;8;4;1;330;16;4;28;205.917;92;0;2;0;0;0;0;84;182;25;8
3;11;8;2;1;179;51;18;38;205.917;92;0;1;0;1;0;0;89;170;31;1
10;13;8;2;1;361;52;3;28;205.917;92;0;1;1;1;0;4;80;172;27;40
20;28;8;6;1;260;50;11;36;205.917;92;0;1;4;1;0;0;65;168;23;4
11;18;8;2;1;289;36;13;33;205.917;92;0;1;2;1;0;1;90;172;30;8
10;25;8;2;1;361;52;3;28;205.917;92;0;1;1;1;0;4;80;172;27;7
11;23;8;3;1;289;36;13;33;205.917;92;0;1;2;1;0;1;90;172;30;1
30;28;8;4;1;157;27;6;29;205.917;92;0;1;0;1;1;0;75;185;22;4
11;18;8;4;1;289;36;13;33;205.917;92;0;1;2;1;0;1;90;172;30;8
3;23;8;6;1;179;51;18;38;205.917;92;0;1;0;1;0;0;89;170;31;2
3;18;8;2;1;179;51;18;38;205.917;92;0;1;0;1;0;0;89;170;31;8
2;18;8;5;1;235;29;12;48;205.917;92;0;1;1;0;1;5;88;163;33;8
1;23;8;5;1;235;11;14;37;205.917;92;0;3;1;0;0;1;88;172;29;4
2;18;8;2;1;235;29;12;48;205.917;92;0;1;1;0;1;5;88;163;33;8
3;23;8;2;1;179;51;18;38;205.917;92;0;1;0;1;0;0;89;170;31;2
10;23;8;2;1;361;52;3;28;205.917;92;0;1;1;1;0;4;80;172;27;1
11;24;8;3;1;289;36;13;33;205.917;92;0;1;2;1;0;1;90;172;30;8
19;11;8;5;1;291;50;12;32;205.917;92;0;1;0;1;0;0;65;169;23;4
2;28;8;6;1;235;29;12;48;205.917;92;0;1;1;0;1;5;88;163;33;8
20;23;8;6;1;260;50;11;36;205.917;92;0;1;4;1;0;0;65;168;23;4
27;23;9;3;1;184;42;7;27;241.476;92;0;1;0;0;0;0;58;167;21;2
34;23;9;2;1;118;10;10;37;241.476;92;0;1;0;0;0;0;83;172;28;4
3;23;9;3;1;179;51;18;38;241.476;92;0;1;0;1;0;0;89;170;31;4
5;19;9;3;1;235;20;13;43;241.476;92;0;1;1;1;0;0;106;167;38;8
14;23;9;4;1;155;12;14;34;241.476;92;0;1;2;1;0;0;95;196;25;2
34;23;9;2;1;118;10;10;37;241.476;92;0;1;0;0;0;0;83;172;28;3
3;23;9;3;1;179;51;18;38;241.476;92;0;1;0;1;0;0;89;170;31;3
15;23;9;5;1;291;31;12;40;241.476;92;0;1;1;1;0;1;73;171;25;4
20;22;9;6;1;260;50;11;36;241.476;92;0;1;4;1;0;0;65;168;23;8
15;14;9;2;4;291;31;12;40;241.476;92;0;1;1;1;0;1;73;171;25;32
20;0;9;2;4;260;50;11;36;241.476;92;1;1;4;1;0;0;65;168;23;0
29;0;9;2;4;225;26;9;28;241.476;92;1;1;1;0;0;2;69;169;24;0
28;23;9;3;4;225;26;9;28;241.476;92;0;1;1;0;0;2;69;169;24;2
34;23;9;3;4;118;10;10;37;241.476;92;0;1;0;0;0;0;83;172;28;2
11;0;9;3;4;289;36;13;33;241.476;92;1;1;2;1;0;1;90;172;30;0
36;0;9;3;4;118;13;18;50;241.476;92;1;1;1;1;0;0;98;178;31;0
28;18;9;4;4;225;26;9;28;241.476;92;0;1;1;0;0;2;69;169;24;3
3;23;9;4;4;179;51;18;38;241.476;92;0;1;0;1;0;0;89;170;31;3
13;0;9;4;4;369;17;12;31;241.476;92;1;1;3;1;0;0;70;169;25;0
33;23;9;6;4;248;25;14;47;241.476;92;0;1;2;0;0;1;86;165;32;1
3;23;9;6;4;179;51;18;38;241.476;92;0;1;0;1;0;0;89;170;31;3
20;23;9;6;4;260;50;11;36;241.476;92;0;1;4;1;0;0;65;168;23;4
3;23;10;3;4;179;51;18;38;253.465;93;0;1;0;1;0;0;89;170;31;3
34;23;10;3;4;118;10;10;37;253.465;93;0;1;0;0;0;0;83;172;28;3
36;0;10;4;4;118;13;18;50;253.465;93;1;1;1;1;0;0;98;178;31;0
22;23;10;5;4;179;26;9;30;253.465;93;0;3;0;0;0;0;56;171;19;1
3;23;10;6;4;179;51;18;38;253.465;93;0;1;0;1;0;0;89;170;31;3
28;23;10;6;4;225;26;9;28;253.465;93;0;1;1;0;0;2;69;169;24;3
34;23;10;3;4;118;10;10;37;253.465;93;0;1;0;0;0;0;83;172;28;3
28;23;10;4;4;225;26;9;28;253.465;93;0;1;1;0;0;2;69;169;24;2
33;23;10;4;4;248;25;14;47;253.465;93;0;1;2;0;0;1;86;165;32;2
15;23;10;5;4;291;31;12;40;253.465;93;0;1;1;1;0;1;73;171;25;5
3;23;10;4;4;179;51;18;38;253.465;93;0;1;0;1;0;0;89;170;31;8
28;23;10;4;4;225;26;9;28;253.465;93;0;1;1;0;0;2;69;169;24;3
20;19;10;5;4;260;50;11;36;253.465;93;0;1;4;1;0;0;65;168;23;16
15;14;10;3;4;291;31;12;40;253.465;93;0;1;1;1;0;1;73;171;25;8
28;28;10;3;4;225;26;9;28;253.465;93;0;1;1;0;0;2;69;169;24;2
11;26;10;4;4;289;36;13;33;253.465;93;0;1;2;1;0;1;90;172;30;8
10;23;10;6;4;361;52;3;28;253.465;93;0;1;1;1;0;4;80;172;27;1
20;28;10;6;4;260;50;11;36;253.465;93;0;1;4;1;0;0;65;168;23;3
3;23;11;5;4;179;51;18;38;306.345;93;0;1;0;1;0;0;89;170;31;1
28;23;11;4;4;225;26;9;28;306.345;93;0;1;1;0;0;2;69;169;24;1
3;13;11;5;4;179;51;18;38;306.345;93;0;1;0;1;0;0;89;170;31;8
17;21;11;5;4;179;22;17;40;306.345;93;0;2;2;0;1;0;63;170;22;8
15;23;11;5;4;291;31;12;40;306.345;93;0;1;1;1;0;1;73;171;25;5
14;10;11;2;4;155;12;14;34;306.345;93;0;1;2;1;0;0;95;196;25;32
6;22;11;2;4;189;29;13;33;306.345;93;0;1;2;0;0;2;69;167;25;8
15;14;11;2;4;291;31;12;40;306.345;93;0;1;1;1;0;1;73;171;25;40
28;23;11;4;4;225;26;9;28;306.345;93;0;1;1;0;0;2;69;169;24;1
14;6;11;6;4;155;12;14;34;306.345;93;0;1;2;1;0;0;95;196;25;8
28;23;11;4;4;225;26;9;28;306.345;93;0;1;1;0;0;2;69;169;24;3
17;21;11;4;4;179;22;17;40;306.345;93;0;2;2;0;1;0;63;170;22;8
28;13;11;6;4;225;26;9;28;306.345;93;0;1;1;0;0;2;69;169;24;3
20;28;11;6;4;260;50;11;36;306.345;93;0;1;4;1;0;0;65;168;23;4
33;28;11;2;4;248;25;14;47;306.345;93;0;1;2;0;0;1;86;165;32;1
28;28;11;3;4;225;26;9;28;306.345;93;0;1;1;0;0;2;69;169;24;3
11;7;11;4;4;289;36;13;33;306.345;93;0;1;2;1;0;1;90;172;30;24
15;23;11;5;4;291;31;12;40;306.345;93;0;1;1;1;0;1;73;171;25;3
33;23;12;3;4;248;25;14;47;261.306;97;0;1;2;0;0;1;86;165;32;1
34;19;12;3;4;118;10;10;37;261.306;97;0;1;0;0;0;0;83;172;28;64
36;23;12;4;4;118;13;18;50;261.306;97;0;1;1;1;0;0;98;178;31;2
1;26;12;4;4;235;11;14;37;261.306;97;0;3;1;0;0;1;88;172;29;8
28;23;12;5;4;225;26;9;28;261.306;97;0;1;1;0;0;2;69;169;24;2
20;26;12;6;4;260;50;11;36;261.306;97;0;1;4;1;0;0;65;168;23;8
34;19;12;3;4;118;10;10;37;261.306;97;0;1;0;0;0;0;83;172;28;56
10;22;12;4;4;361;52;3;28;261.306;97;0;1;1;1;0;4;80;172;27;8
28;28;12;5;4;225;26;9;28;261.306;97;0;1;1;0;0;2;69;169;24;3
20;28;12;6;4;260;50;11;36;261.306;97;0;1;4;1;0;0;65;168;23;3
28;23;12;3;4;225;26;9;28;261.306;97;0;1;1;0;0;2;69;169;24;2
10;22;12;4;4;361;52;3;28;261.306;97;0;1;1;1;0;4;80;172;27;8
34;27;12;6;4;118;10;10;37;261.306;97;0;1;0;0;0;0;83;172;28;2
24;19;12;6;2;246;25;16;41;261.306;97;0;1;0;1;0;0;67;170;23;8
28;23;12;6;2;225;26;9;28;261.306;97;0;1;1;0;0;2;69;169;24;2
28;23;1;4;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;1
34;19;1;2;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;1
34;27;1;3;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;1
14;18;1;3;2;155;12;14;34;308.593;95;0;1;2;1;0;0;95;196;25;8
28;27;1;4;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;2
27;23;1;5;2;184;42;7;27;308.593;95;0;1;0;0;0;0;58;167;21;2
28;28;1;5;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;2
28;27;1;6;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;1
34;27;1;2;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
28;27;1;3;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;2
34;27;1;3;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;4;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;5;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;6;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;2;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;3;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
22;18;1;3;2;179;26;9;30;308.593;95;0;3;0;0;0;0;56;171;19;8
11;18;1;3;2;289;36;13;33;308.593;95;0;1;2;1;0;1;90;172;30;8
34;27;1;4;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
27;23;1;5;2;184;42;7;27;308.593;95;0;1;0;0;0;0;58;167;21;2
34;27;1;5;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;2
34;27;1;2;2;118;10;10;37;308.593;95;0;1;0;0;0;0;83;172;28;0
28;23;1;3;2;225;26;9;28;308.593;95;0;1;1;0;0;2;69;169;24;1
11;22;1;5;2;289;36;13;33;308.593;95;0;1;2;1;0;1;90;172;30;3
27;23;2;6;2;184;42;7;27;302.585;99;0;1;0;0;0;0;58;167;21;1
24;1;2;4;2;246;25;16;41;302.585;99;0;1;0;1;0;0;67;170;23;8
3;11;2;4;2;179;51;18;38;302.585;99;0;1;0;1;0;0;89;170;31;8
14;28;2;5;2;155;12;14;34;302.585;99;0;1;2;1;0;0;95;196;25;2
6;23;2;5;2;189;29;13;33;302.585;99;0;1;2;0;0;2;69;167;25;8
20;28;2;6;2;260;50;11;36;302.585;99;0;1;4;1;0;0;65;168;23;2
11;22;2;6;2;289;36;13;33;302.585;99;0;1;2;1;0;1;90;172;30;8
31;11;2;2;2;388;15;9;50;302.585;99;0;1;0;0;0;0;76;178;24;8
31;1;2;3;2;388;15;9;50;302.585;99;0;1;0;0;0;0;76;178;24;8
28;28;2;2;2;225;26;9;28;302.585;99;0;1;1;0;0;2;69;169;24;2
28;23;2;3;2;225;26;9;28;302.585;99;0;1;1;0;0;2;69;169;24;2
22;23;2;3;2;179;26;9;30;302.585;99;0;3;0;0;0;0;56;171;19;1
27;23;2;3;2;184;42;7;27;302.585;99;0;1;0;0;0;0;58;167;21;8
28;25;2;5;2;225;26;9;28;302.585;99;0;1;1;0;0;2;69;169;24;3
18;18;2;2;2;330;16;4;28;302.585;99;0;2;0;0;0;0;84;182;25;8
18;23;2;3;2;330;16;4;28;302.585;99;0;2;0;0;0;0;84;182;25;1
28;23;2;4;2;225;26;9;28;302.585;99;0;1;1;0;0;2;69;169;24;1
6;19;2;5;2;189;29;13;33;302.585;99;0;1;2;0;0;2;69;167;25;8
19;28;3;3;2;291;50;12;32;343.253;95;0;1;0;1;0;0;65;169;23;2
20;19;3;3;2;260;50;11;36;343.253;95;0;1;4;1;0;0;65;168;23;8
30;19;3;3;2;157;27;6;29;343.253;95;0;1;0;1;1;0;75;185;22;3
17;17;3;3;2;179;22;17;40;343.253;95;0;2;2;0;1;0;63;170;22;8
15;22;3;4;2;291;31;12;40;343.253;95;0;1;1;1;0;1;73;171;25;8
20;13;3;4;2;260;50;11;36;343.253;95;0;1;4;1;0;0;65;168;23;8
22;13;3;5;2;179;26;9;30;343.253;95;0;3;0;0;0;0;56;171;19;8
33;14;3;6;2;248;25;14;47;343.253;95;0;1;2;0;0;1;86;165;32;3
20;13;3;6;2;260;50;11;36;343.253;95;0;1;4;1;0;0;65;168;23;40
17;11;3;2;2;179;22;17;40;343.253;95;0;2;2;0;1;0;63;170;22;40
14;1;3;2;2;155;12;14;34;343.253;95;0;1;2;1;0;0;95;196;25;16
20;26;3;2;2;260;50;11;36;343.253;95;0;1;4;1;0;0;65;168;23;16
14;13;3;3;2;155;12;14;34;343.253;95;0;1;2;1;0;0;95;196;25;8
11;6;3;5;2;289;36;13;33;343.253;95;0;1;2;1;0;1;90;172;30;8
17;8;3;5;2;179;22;17;40;343.253;95;0;2;2;0;1;0;63;170;22;8
20;28;3;6;2;260;50;11;36;343.253;95;0;1;4;1;0;0;65;168;23;4
28;23;3;6;2;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;1
7;14;3;2;2;279;5;14;39;343.253;95;0;1;2;1;1;0;68;168;24;8
3;13;3;3;2;179;51;18;38;343.253;95;0;1;0;1;0;0;89;170;31;24
28;23;3;4;2;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;2
28;11;3;2;3;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;8
22;13;3;2;3;179;26;9;30;343.253;95;0;3;0;0;0;0;56;171;19;1
28;11;3;3;3;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;8
28;11;3;4;3;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;16
3;13;3;4;3;179;51;18;38;343.253;95;0;1;0;1;0;0;89;170;31;3
7;14;3;5;3;279;5;14;39;343.253;95;0;1;2;1;1;0;68;168;24;16
28;28;3;6;3;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;2
33;14;3;6;3;248;25;14;47;343.253;95;0;1;2;0;0;1;86;165;32;3
28;28;3;2;3;225;26;9;28;343.253;95;0;1;1;0;0;2;69;169;24;1
15;28;4;4;3;291;31;12;40;326.452;96;0;1;1;1;0;1;73;171;25;1
28;23;4;4;3;225;26;9;28;326.452;96;0;1;1;0;0;2;69;169;24;1
14;28;4;3;3;155;12;14;34;326.452;96;0;1;2;1;0;0;95;196;25;1
24;13;4;4;3;246;25;16;41;326.452;96;0;1;0;1;0;0;67;170;23;24
14;23;4;5;3;155;12;14;34;326.452;96;0;1;2;1;0;0;95;196;25;1
28;28;4;6;3;225;26;9;28;326.452;96;0;1;1;0;0;2;69;169;24;2
20;28;4;6;3;260;50;11;36;326.452;96;0;1;4;1;0;0;65;168;23;4
3;13;4;4;3;179;51;18;38;326.452;96;0;1;0;1;0;0;89;170;31;24
36;23;4;5;3;118;13;18;50;326.452;96;0;1;1;1;0;0;98;178;31;1
15;23;4;6;3;291;31;12;40;326.452;96;0;1;1;1;0;1;73;171;25;3
24;14;4;6;3;246;25;16;41;326.452;96;0;1;0;1;0;0;67;170;23;8
15;28;4;6;3;291;31;12;40;326.452;96;0;1;1;1;0;1;73;171;25;1
33;28;4;6;3;248;25;14;47;326.452;96;0;1;2;0;0;1;86;165;32;8
20;19;4;6;3;260;50;11;36;326.452;96;0;1;4;1;0;0;65;168;23;56
11;19;4;3;3;289;36;13;33;326.452;96;0;1;2;1;0;1;90;172;30;8
14;12;4;4;3;155;12;14;34;326.452;96;0;1;2;1;0;0;95;196;25;24
23;19;4;4;3;378;49;11;36;326.452;96;0;1;2;0;1;4;65;174;21;8
11;13;4;5;3;289;36;13;33;326.452;96;0;1;2;1;0;1;90;172;30;16
1;7;4;6;3;235;11;14;37;326.452;96;0;3;1;0;0;1;88;172;29;3
2;0;4;2;3;235;29;12;48;326.452;96;1;1;1;0;1;5;88;163;33;0
11;13;5;4;3;289;36;13;33;378.884;92;0;1;2;1;0;1;90;172;30;8
14;28;5;5;3;155;12;14;34;378.884;92;0;1;2;1;0;0;95;196;25;2
14;28;5;2;3;155;12;14;34;378.884;92;0;1;2;1;0;0;95;196;25;1
3;18;5;3;3;179;51;18;38;378.884;92;0;1;0;1;0;0;89;170;31;8
28;19;5;3;3;225;26;9;28;378.884;92;0;1;1;0;0;2;69;169;24;8
27;7;5;4;3;184;42;7;27;378.884;92;0;1;0;0;0;0;58;167;21;4
14;28;5;2;3;155;12;14;34;378.884;92;0;1;2;1;0;0;95;196;25;2
3;12;5;3;3;179;51;18;38;378.884;92;0;1;0;1;0;0;89;170;31;1
11;13;5;4;3;289;36;13;33;378.884;92;0;1;2;1;0;1;90;172;30;24
7;0;5;4;3;279;5;14;39;378.884;92;1;1;2;1;1;0;68;168;24;0
18;0;5;4;3;330;16;4;28;378.884;92;1;2;0;0;0;0;84;182;25;0
23;0;5;4;3;378;49;11;36;378.884;92;1;1;2;0;1;4;65;174;21;0
31;0;5;4;3;388;15;9;50;378.884;92;1;1;0;0;0;0;76;178;24;0
3;11;5;3;3;179;51;18;38;378.884;92;0;1;0;1;0;0;89;170;31;1
36;13;5;4;3;118;13;18;50;378.884;92;0;1;1;1;0;0;98;178;31;24
10;22;5;6;3;361;52;3;28;378.884;92;0;1;1;1;0;4;80;172;27;8
24;19;6;2;3;246;25;16;41;377.550;94;0;1;0;1;0;0;67;170;23;8
10;22;6;2;3;361;52;3;28;377.550;94;0;1;1;1;0;4;80;172;27;8
24;10;6;3;3;246;25;16;41;377.550;94;0;1;0;1;0;0;67;170;23;24
15;23;6;5;3;291;31;12;40;377.550;94;0;1;1;1;0;1;73;171;25;4
24;10;6;6;3;246;25;16;41;377.550;94;0;1;0;1;0;0;67;170;23;8
3;11;6;2;3;179;51;18;38;377.550;94;0;1;0;1;0;0;89;170;31;8
14;23;6;2;3;155;12;14;34;377.550;94;0;1;2;1;0;0;95;196;25;4
24;10;6;2;3;246;25;16;41;377.550;94;0;1;0;1;0;0;67;170;23;8
36;13;6;4;3;118;13;18;50;377.550;94;0;1;1;1;0;0;98;178;31;8
1;13;6;6;3;235;11;14;37;377.550;94;0;3;1;0;0;1;88;172;29;16
36;23;6;3;3;118;13;18;50;377.550;94;0;1;1;1;0;0;98;178;31;1
36;13;6;4;3;118;13;18;50;377.550;94;0;1;1;1;0;0;98;178;31;80
23;22;6;5;3;378;49;11;36;377.550;94;0;1;2;0;1;4;65;174;21;8
3;11;6;6;3;179;51;18;38;377.550;94;0;1;0;1;0;0;89;170;31;2
32;28;6;2;1;289;48;29;49;377.550;94;0;1;0;0;0;2;108;172;36;2
28;28;6;5;1;225;26;9;28;377.550;94;0;1;1;0;0;2;69;169;24;2
14;19;7;3;1;155;12;14;34;275.312;98;0;1;2;1;0;0;95;196;25;16
36;1;7;4;1;118;13;18;50;275.312;98;0;1;1;1;0;0;98;178;31;8
34;5;7;6;1;118;10;10;37;275.312;98;0;1;0;0;0;0;83;172;28;8
34;26;7;6;1;118;10;10;37;275.312;98;0;1;0;0;0;0;83;172;28;4
18;26;7;3;1;330;16;4;28;275.312;98;0;2;0;0;0;0;84;182;25;8
22;18;7;5;1;179;26;9;30;275.312;98;0;3;0;0;0;0;56;171;19;8
14;25;7;6;1;155;12;14;34;275.312;98;0;1;2;1;0;0;95;196;25;2
18;1;7;2;1;330;16;4;28;275.312;98;0;2;0;0;0;0;84;182;25;8
18;1;7;3;1;330;16;4;28;275.312;98;0;2;0;0;0;0;84;182;25;8
30;25;7;2;1;157;27;6;29;275.312;98;0;1;0;1;1;0;75;185;22;3
10;22;7;3;1;361;52;3;28;275.312;98;0;1;1;1;0;4;80;172;27;8
11;26;7;4;1;289;36;13;33;275.312;98;0;1;2;1;0;1;90;172;30;8
3;26;7;5;1;179;51;18;38;275.312;98;0;1;0;1;0;0;89;170;31;8
11;19;7;2;1;289;36;13;33;275.312;98;0;1;2;1;0;1;90;172;30;32
11;19;7;5;1;289;36;13;33;275.312;98;0;1;2;1;0;1;90;172;30;8
20;0;7;5;1;260;50;11;36;275.312;98;1;1;4;1;0;0;65;168;23;0
11;19;8;6;1;289;36;13;33;265.615;94;0;1;2;1;0;1;90;172;30;8
30;19;8;6;1;157;27;6;29;265.615;94;0;1;0;1;1;0;75;185;22;3
11;23;8;2;1;289;36;13;33;265.615;94;0;1;2;1;0;1;90;172;30;1
9;18;8;3;1;228;14;16;58;265.615;94;0;1;2;0;0;1;65;172;22;8
26;13;8;5;1;300;26;13;43;265.615;94;0;1;2;1;1;1;77;175;25;1
26;14;8;5;1;300;26;13;43;265.615;94;0;1;2;1;1;1;77;175;25;2
20;28;8;6;1;260;50;11;36;265.615;94;0;1;4;1;0;0;65;168;23;4
11;23;8;3;1;289;36;13;33;265.615;94;0;1;2;1;0;1;90;172;30;4
33;23;8;4;1;248;25;14;47;265.615;94;0;1;2;0;0;1;86;165;32;1
21;11;8;5;1;268;11;8;33;265.615;94;0;2;0;0;0;0;79;178;25;8
22;23;8;5;1;179;26;9;30;265.615;94;0;3;0;0;0;0;56;171;19;1
36;13;8;5;1;118;13;18;50;265.615;94;0;1;1;1;0;0;98;178;31;3
33;25;8;2;1;248;25;14;47;265.615;94;0;1;2;0;0;1;86;165;32;2
1;23;8;3;1;235;11;14;37;265.615;94;0;3;1;0;0;1;88;172;29;1
36;23;8;5;1;118;13;18;50;265.615;94;0;1;1;1;0;0;98;178;31;1
1;19;8;5;1;235;11;14;37;265.615;94;0;3;1;0;0;1;88;172;29;8
10;8;8;3;1;361;52;3;28;265.615;94;0;1;1;1;0;4;80;172;27;8
27;6;8;4;1;184;42;7;27;265.615;94;0;1;0;0;0;0;58;167;21;8
3;11;9;2;1;179;51;18;38;294.217;81;0;1;0;1;0;0;89;170;31;8
3;23;9;6;1;179;51;18;38;294.217;81;0;1;0;1;0;0;89;170;31;3
11;19;9;4;1;289;36;13;33;294.217;81;0;1;2;1;0;1;90;172;30;24
5;0;9;5;1;235;20;13;43;294.217;81;1;1;1;1;0;0;106;167;38;0
24;9;9;2;1;246;25;16;41;294.217;81;0;1;0;1;0;0;67;170;23;16
15;28;9;3;1;291;31;12;40;294.217;81;0;1;1;1;0;1;73;171;25;3
8;0;9;3;1;231;35;14;39;294.217;81;1;1;2;1;0;2;100;170;35;0
19;0;9;3;1;291;50;12;32;294.217;81;1;1;0;1;0;0;65;169;23;0
3;13;9;4;1;179;51;18;38;294.217;81;0;1;0;1;0;0;89;170;31;8
24;9;9;4;1;246;25;16;41;294.217;81;0;1;0;1;0;0;67;170;23;32
3;23;9;5;1;179;51;18;38;294.217;81;0;1;0;1;0;0;89;170;31;1
15;28;9;6;1;291;31;12;40;294.217;81;0;1;1;1;0;1;73;171;25;4
20;28;9;6;1;260;50;11;36;294.217;81;0;1;4;1;0;0;65;168;23;4
5;26;9;4;4;235;20;13;43;294.217;81;0;1;1;1;0;0;106;167;38;8
36;28;9;5;4;118;13;18;50;294.217;81;0;1;1;1;0;0;98;178;31;1
5;0;9;5;4;235;20;13;43;294.217;81;1;1;1;1;0;0;106;167;38;0
15;28;9;6;4;291;31;12;40;294.217;81;0;1;1;1;0;1;73;171;25;3
15;7;9;2;4;291;31;12;40;294.217;81;0;1;1;1;0;1;73;171;25;40
3;13;9;2;4;179;51;18;38;294.217;81;0;1;0;1;0;0;89;170;31;8
11;24;10;2;4;289;36;13;33;265.017;88;0;1;2;1;0;1;90;172;30;8
1;26;10;2;4;235;11;14;37;265.017;88;0;3;1;0;0;1;88;172;29;4
11;26;10;2;4;289;36;13;33;265.017;88;0;1;2;1;0;1;90;172;30;8
11;22;10;6;4;289;36;13;33;265.017;88;0;1;2;1;0;1;90;172;30;8
36;0;10;6;4;118;13;18;50;265.017;88;1;1;1;1;0;0;98;178;31;0
33;0;10;6;4;248;25;14;47;265.017;88;1;1;2;0;0;1;86;165;32;0
22;1;10;2;4;179;26;9;30;265.017;88;0;3;0;0;0;0;56;171;19;8
34;7;10;2;4;118;10;10;37;265.017;88;0;1;0;0;0;0;83;172;28;3
13;22;10;2;4;369;17;12;31;265.017;88;0;1;3;1;0;0;70;169;25;8
3;28;10;4;4;179;51;18;38;265.017;88;0;1;0;1;0;0;89;170;31;1
22;1;10;4;4;179;26;9;30;265.017;88;0;3;0;0;0;0;56;171;19;64
5;0;10;4;4;235;20;13;43;265.017;88;1;1;1;1;0;0;106;167;38;0
11;19;10;5;4;289;36;13;33;265.017;88;0;1;2;1;0;1;90;172;30;16
20;28;10;6;4;260;50;11;36;265.017;88;0;1;4;1;0;0;65;168;23;3
5;0;10;6;4;235;20;13;43;265.017;88;1;1;1;1;0;0;106;167;38;0
5;23;10;2;4;235;20;13;43;265.017;88;0;1;1;1;0;0;106;167;38;2
5;23;10;2;4;235;20;13;43;265.017;88;0;1;1;1;0;0;106;167;38;2
36;28;10;3;4;118;13;18;50;265.017;88;0;1;1;1;0;0;98;178;31;1
15;28;10;3;4;291;31;12;40;265.017;88;0;1;1;1;0;1;73;171;25;4
22;23;10;5;4;179;26;9;30;265.017;88;0;3;0;0;0;0;56;171;19;16
36;28;10;5;4;118;13;18;50;265.017;88;0;1;1;1;0;0;98;178;31;1
10;10;10;2;4;361;52;3;28;265.017;88;0;1;1;1;0;4;80;172;27;8
20;0;10;3;4;260;50;11;36;265.017;88;1;1;4;1;0;0;65;168;23;0
15;0;10;3;4;291;31;12;40;265.017;88;1;1;1;1;0;1;73;171;25;0
30;0;10;3;4;157;27;6;29;265.017;88;1;1;0;1;1;0;75;185;22;0
22;1;10;4;4;179;26;9;30;265.017;88;0;3;0;0;0;0;56;171;19;5
22;7;10;4;4;179;26;9;30;265.017;88;0;3;0;0;0;0;56;171;19;5
36;23;10;5;4;118;13;18;50;265.017;88;0;1;1;1;0;0;98;178;31;1
34;11;11;2;4;118;10;10;37;284.031;97;0;1;0;0;0;0;83;172;28;8
33;23;11;2;4;248;25;14;47;284.031;97;0;1;2;0;0;1;86;165;32;2
3;6;11;3;4;179;51;18;38;284.031;97;0;1;0;1;0;0;89;170;31;8
20;28;11;6;4;260;50;11;36;284.031;97;0;1;4;1;0;0;65;168;23;3
15;23;11;2;4;291;31;12;40;284.031;97;0;1;1;1;0;1;73;171;25;1
23;1;11;2;4;378;49;11;36;284.031;97;0;1;2;0;1;4;65;174;21;8
14;11;11;2;4;155;12;14;34;284.031;97;0;1;2;1;0;0;95;196;25;120
5;26;11;2;4;235;20;13;43;284.031;97;0;1;1;1;0;0;106;167;38;8
18;0;11;3;4;330;16;4;28;284.031;97;1;2;0;0;0;0;84;182;25;0
1;18;11;4;4;235;11;14;37;284.031;97;0;3;1;0;0;1;88;172;29;1
34;11;11;4;4;118;10;10;37;284.031;97;0;1;0;0;0;0;83;172;28;3
1;25;11;5;4;235;11;14;37;284.031;97;0;3;1;0;0;1;88;172;29;2
3;28;11;5;4;179;51;18;38;284.031;97;0;1;0;1;0;0;89;170;31;3
24;13;11;6;4;246;25;16;41;284.031;97;0;1;0;1;0;0;67;170;23;8
15;12;11;6;4;291;31;12;40;284.031;97;0;1;1;1;0;1;73;171;25;4
24;13;11;2;4;246;25;16;41;284.031;97;0;1;0;1;0;0;67;170;23;8
3;28;11;3;4;179;51;18;38;284.031;97;0;1;0;1;0;0;89;170;31;1
20;10;11;4;4;260;50;11;36;284.031;97;0;1;4;1;0;0;65;168;23;8
20;15;11;6;4;260;50;11;36;284.031;97;0;1;4;1;0;0;65;168;23;8
23;0;11;6;4;378;49;11;36;284.031;97;1;1;2;0;1;4;65;174;21;0
7;0;11;3;4;279;5;14;39;284.031;97;1;1;2;1;1;0;68;168;24;0
3;23;11;5;4;179;51;18;38;284.031;97;0;1;0;1;0;0;89;170;31;1
28;12;12;2;4;225;26;9;28;236.629;93;0;1;1;0;0;2;69;169;24;3
3;28;12;2;4;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;2
3;28;12;2;4;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;1
1;23;12;2;4;235;11;14;37;236.629;93;0;3;1;0;0;1;88;172;29;3
36;28;12;3;4;118;13;18;50;236.629;93;0;1;1;1;0;0;98;178;31;1
20;28;12;6;4;260;50;11;36;236.629;93;0;1;4;1;0;0;65;168;23;4
24;4;12;5;4;246;25;16;41;236.629;93;0;1;0;1;0;0;67;170;23;8
3;28;12;5;4;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;1
3;28;12;6;4;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;1
22;23;12;3;4;179;26;9;30;236.629;93;0;3;0;0;0;0;56;171;19;1
34;25;12;3;4;118;10;10;37;236.629;93;0;1;0;0;0;0;83;172;28;8
1;25;12;5;4;235;11;14;37;236.629;93;0;3;1;0;0;1;88;172;29;2
3;28;12;6;4;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;1
5;13;12;3;2;235;20;13;43;236.629;93;0;1;1;1;0;0;106;167;38;8
1;14;12;3;2;235;11;14;37;236.629;93;0;3;1;0;0;1;88;172;29;4
20;26;12;4;2;260;50;11;36;236.629;93;0;1;4;1;0;0;65;168;23;8
30;28;12;2;2;157;27;6;29;236.629;93;0;1;0;1;1;0;75;185;22;2
3;28;12;2;2;179;51;18;38;236.629;93;0;1;0;1;0;0;89;170;31;3
11;19;12;2;2;289;36;13;33;236.629;93;0;1;2;1;0;1;90;172;30;8
28;23;1;4;2;225;26;9;28;330.061;100;0;1;1;0;0;2;69;169;24;5
34;19;1;2;2;118;10;10;37;330.061;100;0;1;0;0;0;0;83;172;28;32
14;23;1;2;2;155;12;14;34;330.061;100;0;1;2;1;0;0;95;196;25;2
1;13;1;3;2;235;11;14;37;330.061;100;0;3;1;0;0;1;88;172;29;1
14;23;1;3;2;155;12;14;34;330.061;100;0;1;2;1;0;0;95;196;25;4
11;26;1;2;2;289;36;13;33;330.061;100;0;1;2;1;0;1;90;172;30;8
15;3;1;4;2;291;31;12;40;330.061;100;0;1;1;1;0;1;73;171;25;8
5;26;1;2;2;235;20;13;43;330.061;100;0;1;1;1;0;0;106;167;38;8
36;26;1;2;2;118;13;18;50;330.061;100;0;1;1;1;0;0;98;178;31;4
3;28;1;4;2;179;51;18;38;330.061;100;0;1;0;1;0;0;89;170;31;1
3;28;1;6;2;179;51;18;38;330.061;100;0;1;0;1;0;0;89;170;31;1
34;28;2;3;2;118;10;10;37;251.818;96;0;1;0;0;0;0;83;172;28;2
3;27;2;4;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
28;7;2;4;2;225;26;9;28;251.818;96;0;1;1;0;0;2;69;169;24;1
11;22;2;6;2;289;36;13;33;251.818;96;0;1;2;1;0;1;90;172;30;3
20;28;2;6;2;260;50;11;36;251.818;96;0;1;4;1;0;0;65;168;23;3
3;23;2;6;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
3;27;2;2;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;2
3;27;2;4;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
3;10;2;5;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;8
24;26;2;5;2;246;25;16;41;251.818;96;0;1;0;1;0;0;67;170;23;8
3;27;2;6;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
6;22;2;2;2;189;29;13;33;251.818;96;0;1;2;0;0;2;69;167;25;8
3;27;2;2;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
24;23;2;3;2;246;25;16;41;251.818;96;0;1;0;1;0;0;67;170;23;2
15;23;2;3;2;291;31;12;40;251.818;96;0;1;1;1;0;1;73;171;25;2
30;11;2;4;2;157;27;6;29;251.818;96;0;1;0;1;1;0;75;185;22;16
3;27;2;4;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
3;27;2;6;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
24;10;2;6;2;246;25;16;41;251.818;96;0;1;0;1;0;0;67;170;23;24
3;27;2;4;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
3;27;2;6;2;179;51;18;38;251.818;96;0;1;0;1;0;0;89;170;31;3
34;18;3;3;2;118;10;10;37;244.387;98;0;1;0;0;0;0;83;172;28;8
24;19;3;4;2;246;25;16;41;244.387;98;0;1;0;1;0;0;67;170;23;16
24;28;3;6;2;246;25;16;41;244.387;98;0;1;0;1;0;0;67;170;23;2
20;28;3;6;2;260;50;11;36;244.387;98;0;1;4;1;0;0;65;168;23;4
3;28;3;2;2;179;51;18;38;244.387;98;0;1;0;1;0;0;89;170;31;2
1;22;3;2;2;235;11;14;37;244.387;98;0;3;1;0;0;1;88;172;29;8
17;22;3;3;2;179;22;17;40;244.387;98;0;2;2;0;1;0;63;170;22;8
23;22;3;3;2;378;49;11;36;244.387;98;0;1;2;0;1;4;65;174;21;8
3;28;3;2;2;179;51;18;38;244.387;98;0;1;0;1;0;0;89;170;31;16
10;22;3;4;2;361;52;3;28;244.387;98;0;1;1;1;0;4;80;172;27;8
13;0;3;4;2;369;17;12;31;244.387;98;1;1;3;1;0;0;70;169;25;0
1;21;3;5;2;235;11;14;37;244.387;98;0;3;1;0;0;1;88;172;29;8
36;23;3;6;3;118;13;18;50;244.387;98;0;1;1;1;0;0;98;178;31;2
36;14;3;3;3;118;13;18;50;244.387;98;0;1;1;1;0;0;98;178;31;3
36;13;3;4;3;118;13;18;50;244.387;98;0;1;1;1;0;0;98;178;31;8
1;0;3;5;3;235;11;14;37;244.387;98;1;3;1;0;0;1;88;172;29;0
24;0;3;5;3;246;25;16;41;244.387;98;1;1;0;1;0;0;67;170;23;0
36;0;3;5;3;118;13;18;50;244.387;98;1;1;1;1;0;0;98;178;31;0
3;28;3;6;3;179;51;18;38;244.387;98;0;1;0;1;0;0;89;170;31;8
11;22;3;6;3;289;36;13;33;244.387;98;0;1;2;1;0;1;90;172;30;8
20;19;3;2;3;260;50;11;36;244.387;98;0;1;4;1;0;0;65;168;23;8
24;28;3;3;3;246;25;16;41;244.387;98;0;1;0;1;0;0;67;170;23;2
3;28;4;4;3;179;51;18;38;239.409;98;0;1;0;1;0;0;89;170;31;4
20;28;4;6;3;260;50;11;36;239.409;98;0;1;4;1;0;0;65;168;23;3
18;26;4;6;3;330;16;4;28;239.409;98;0;2;0;0;0;0;84;182;25;4
13;22;4;2;3;369;17;12;31;239.409;98;0;1;3;1;0;0;70;169;25;4
33;26;4;2;3;248;25;14;47;239.409;98;0;1;2;0;0;1;86;165;32;4
18;23;4;4;3;330;16;4;28;239.409;98;0;2;0;0;0;0;84;182;25;8
3;28;4;4;3;179;51;18;38;239.409;98;0;1;0;1;0;0;89;170;31;8
36;23;4;2;3;118;13;18;50;239.409;98;0;1;1;1;0;0;98;178;31;1
36;13;4;4;3;118;13;18;50;239.409;98;0;1;1;1;0;0;98;178;31;120
26;28;4;6;3;300;26;13;43;239.409;98;0;1;2;1;1;1;77;175;25;8
20;28;4;6;3;260;50;11;36;239.409;98;0;1;4;1;0;0;65;168;23;4
3;28;4;2;3;179;51;18;38;239.409;98;0;1;0;1;0;0;89;170;31;4
34;11;4;4;3;118;10;10;37;239.409;98;0;1;0;0;0;0;83;172;28;2
5;13;5;2;3;235;20;13;43;246.074;99;0;1;1;1;0;0;106;167;38;16
33;23;5;4;3;248;25;14;47;246.074;99;0;1;2;0;0;1;86;165;32;2
13;10;5;2;3;369;17;12;31;246.074;99;0;1;3;1;0;0;70;169;25;8
22;23;5;4;3;179;26;9;30;246.074;99;0;3;0;0;0;0;56;171;19;3
3;28;5;4;3;179;51;18;38;246.074;99;0;1;0;1;0;0;89;170;31;4
10;23;5;5;3;361;52;3;28;246.074;99;0;1;1;1;0;4;80;172;27;1
20;28;5;6;3;260;50;11;36;246.074;99;0;1;4;1;0;0;65;168;23;3
17;11;5;2;3;179;22;17;40;246.074;99;0;2;2;0;1;0;63;170;22;2
17;8;5;2;3;179;22;17;40;246.074;99;0;2;2;0;1;0;63;170;22;3
9;18;5;4;3;228;14;16;58;246.074;99;0;1;2;0;0;1;65;172;22;8
28;25;5;4;3;225;26;9;28;246.074;99;0;1;1;0;0;2;69;169;24;3
18;13;5;6;3;330;16;4;28;246.074;99;0;2;0;0;0;0;84;182;25;8
22;25;5;2;3;179;26;9;30;246.074;99;0;3;0;0;0;0;56;171;19;2
34;28;5;2;3;118;10;10;37;246.074;99;0;1;0;0;0;0;83;172;28;1
1;1;5;2;3;235;11;14;37;246.074;99;0;3;1;0;0;1;88;172;29;8
22;23;5;4;3;179;26;9;30;246.074;99;0;3;0;0;0;0;56;171;19;3
34;23;6;2;3;118;10;10;37;253.957;95;0;1;0;0;0;0;83;172;28;3
3;28;6;2;3;179;51;18;38;253.957;95;0;1;0;1;0;0;89;170;31;3
34;28;6;3;3;118;10;10;37;253.957;95;0;1;0;0;0;0;83;172;28;2
28;23;6;5;3;225;26;9;28;253.957;95;0;1;1;0;0;2;69;169;24;4
20;28;6;6;3;260;50;11;36;253.957;95;0;1;4;1;0;0;65;168;23;4
3;0;6;6;3;179;51;18;38;253.957;95;1;1;0;1;0;0;89;170;31;0
15;13;6;2;3;291;31;12;40;253.957;95;0;1;1;1;0;1;73;171;25;40
3;28;6;2;3;179;51;18;38;253.957;95;0;1;0;1;0;0;89;170;31;24
24;28;6;3;3;246;25;16;41;253.957;95;0;1;0;1;0;0;67;170;23;3
3;28;6;2;3;179;51;18;38;253.957;95;0;1;0;1;0;0;89;170;31;4
5;26;6;3;3;235;20;13;43;253.957;95;0;1;1;1;0;0;106;167;38;8
3;28;6;2;1;179;51;18;38;253.957;95;0;1;0;1;0;0;89;170;31;2
28;23;6;4;1;225;26;9;28;253.957;95;0;1;1;0;0;2;69;169;24;2
36;23;6;4;1;118;13;18;50;253.957;95;0;1;1;1;0;0;98;178;31;2
3;5;6;4;1;179;51;18;38;253.957;95;0;1;0;1;0;0;89;170;31;8
22;21;6;4;1;179;26;9;30;253.957;95;0;3;0;0;0;0;56;171;19;2
24;28;6;6;1;246;25;16;41;253.957;95;0;1;0;1;0;0;67;170;23;2
18;11;6;3;1;330;16;4;28;253.957;95;0;2;0;0;0;0;84;182;25;1
1;13;6;3;1;235;11;14;37;253.957;95;0;3;1;0;0;1;88;172;29;8
22;23;7;5;1;179;26;9;30;230.290;92;0;3;0;0;0;0;56;171;19;2
28;25;7;5;1;225;26;9;28;230.290;92;0;1;1;0;0;2;69;169;24;4
20;13;7;6;1;260;50;11;36;230.290;92;0;1;4;1;0;0;65;168;23;8
21;7;7;2;1;268;11;8;33;230.290;92;0;2;0;0;0;0;79;178;25;8
18;25;7;6;1;330;16;4;28;230.290;92;0;2;0;0;0;0;84;182;25;8
34;26;7;6;1;118;10;10;37;230.290;92;0;1;0;0;0;0;83;172;28;8
20;26;7;2;1;260;50;11;36;230.290;92;0;1;4;1;0;0;65;168;23;4
34;28;7;3;1;118;10;10;37;230.290;92;0;1;0;0;0;0;83;172;28;8
26;15;7;2;1;300;26;13;43;230.290;92;0;1;2;1;1;1;77;175;25;8
2;23;7;2;1;235;29;12;48;230.290;92;0;1;1;0;1;5;88;163;33;1
24;28;7;3;1;246;25;16;41;230.290;92;0;1;0;1;0;0;67;170;23;2
28;9;7;3;1;225;26;9;28;230.290;92;0;1;1;0;0;2;69;169;24;112
3;28;7;3;1;179;51;18;38;230.290;92;0;1;0;1;0;0;89;170;31;1
36;23;7;6;1;118;13;18;50;230.290;92;0;1;1;1;0;0;98;178;31;1
10;22;7;6;1;361;52;3;28;230.290;92;0;1;1;1;0;4;80;172;27;8
11;22;7;2;1;289;36;13;33;230.290;92;0;1;2;1;0;1;90;172;30;8
5;26;7;2;1;235;20;13;43;230.290;92;0;1;1;1;0;0;106;167;38;8
24;28;7;3;1;246;25;16;41;230.290;92;0;1;0;1;0;0;67;170;23;2
15;28;7;5;1;291;31;12;40;230.290;92;0;1;1;1;0;1;73;171;25;1
7;23;7;5;1;279;5;14;39;230.290;92;0;1;2;1;1;0;68;168;24;2
3;25;8;5;1;179;51;18;38;249.797;93;0;1;0;1;0;0;89;170;31;4
17;25;8;2;1;179;22;17;40;249.797;93;0;2;2;0;1;0;63;170;22;1
24;28;8;3;1;246;25;16;41;249.797;93;0;1;0;1;0;0;67;170;23;4
34;28;8;3;1;118;10;10;37;249.797;93;0;1;0;0;0;0;83;172;28;4
11;26;8;3;1;289;36;13;33;249.797;93;0;1;2;1;0;1;90;172;30;8
5;26;8;3;1;235;20;13;43;249.797;93;0;1;1;1;0;0;106;167;38;8
15;28;8;5;1;291;31;12;40;249.797;93;0;1;1;1;0;1;73;171;25;4
3;25;8;2;1;179;51;18;38;249.797;93;0;1;0;1;0;0;89;170;31;4
17;25;8;3;1;179;22;17;40;249.797;93;0;2;2;0;1;0;63;170;22;8
18;23;8;5;1;330;16;4;28;249.797;93;0;2;0;0;0;0;84;182;25;16
1;23;8;3;1;235;11;14;37;249.797;93;0;3;1;0;0;1;88;172;29;4
24;28;8;3;1;246;25;16;41;249.797;93;0;1;0;1;0;0;67;170;23;1
34;28;8;3;1;118;10;10;37;249.797;93;0;1;0;0;0;0;83;172;28;5
15;28;8;5;1;291;31;12;40;249.797;93;0;1;1;1;0;1;73;171;25;2
20;28;8;2;1;260;50;11;36;249.797;93;0;1;4;1;0;0;65;168;23;3
24;28;9;3;1;246;25;16;41;261.756;87;0;1;0;1;0;0;67;170;23;1
24;28;9;3;1;246;25;16;41;261.756;87;0;1;0;1;0;0;67;170;23;1
34;28;9;3;1;118;10;10;37;261.756;87;0;1;0;0;0;0;83;172;28;3
14;23;9;3;1;155;12;14;34;261.756;87;0;1;2;1;0;0;95;196;25;2
15;28;9;5;1;291;31;12;40;261.756;87;0;1;1;1;0;1;73;171;25;2
22;23;9;6;1;179;26;9;30;261.756;87;0;3;0;0;0;0;56;171;19;8
33;23;9;6;1;248;25;14;47;261.756;87;0;1;2;0;0;1;86;165;32;1
3;23;9;2;1;179;51;18;38;261.756;87;0;1;0;1;0;0;89;170;31;4
28;23;9;4;1;225;26;9;28;261.756;87;0;1;1;0;0;2;69;169;24;1
22;23;9;2;1;179;26;9;30;261.756;87;0;3;0;0;0;0;56;171;19;2
13;23;9;3;4;369;17;12;31;261.756;87;0;1;3;1;0;0;70;169;25;8
10;22;9;3;4;361;52;3;28;261.756;87;0;1;1;1;0;4;80;172;27;8
32;4;10;5;4;289;48;29;49;284.853;91;0;1;0;0;0;2;108;172;36;1
25;11;10;5;4;235;16;8;32;284.853;91;0;3;0;0;0;0;75;178;25;3
24;26;10;6;4;246;25;16;41;284.853;91;0;1;0;1;0;0;67;170;23;8
32;14;10;4;4;289;48;29;49;284.853;91;0;1;0;0;0;2;108;172;36;3
15;28;10;4;4;291;31;12;40;284.853;91;0;1;1;1;0;1;73;171;25;2
34;23;10;3;4;118;10;10;37;284.853;91;0;1;0;0;0;0;83;172;28;2
32;23;10;5;4;289;48;29;49;284.853;91;0;1;0;0;0;2;108;172;36;2
15;23;10;6;4;291;31;12;40;284.853;91;0;1;1;1;0;1;73;171;25;1
28;23;10;3;4;225;26;9;28;284.853;91;0;1;1;0;0;2;69;169;24;2
13;23;10;3;4;369;17;12;31;284.853;91;0;1;3;1;0;0;70;169;25;8
13;23;10;3;4;369;17;12;31;284.853;91;0;1;3;1;0;0;70;169;25;3
28;23;10;3;4;225;26;9;28;284.853;91;0;1;1;0;0;2;69;169;24;4
13;26;10;3;4;369;17;12;31;284.853;91;0;1;3;1;0;0;70;169;25;8
3;28;10;4;4;179;51;18;38;284.853;91;0;1;0;1;0;0;89;170;31;3
9;1;10;4;4;228;14;16;58;284.853;91;0;1;2;0;0;1;65;172;22;1
15;23;10;4;4;291;31;12;40;284.853;91;0;1;1;1;0;1;73;171;25;1
13;10;10;5;4;369;17;12;31;284.853;91;0;1;3;1;0;0;70;169;25;8
28;13;10;5;4;225;26;9;28;284.853;91;0;1;1;0;0;2;69;169;24;1
13;10;10;6;4;369;17;12;31;284.853;91;0;1;3;1;0;0;70;169;25;8
28;10;10;6;4;225;26;9;28;284.853;91;0;1;1;0;0;2;69;169;24;3
6;23;10;2;4;189;29;13;33;284.853;91;0;1;2;0;0;2;69;167;25;8
25;6;10;2;4;235;16;8;32;284.853;91;0;3;0;0;0;0;75;178;25;8
33;10;10;2;4;248;25;14;47;284.853;91;0;1;2;0;0;1;86;165;32;8
28;0;10;2;4;225;26;9;28;284.853;91;1;1;1;0;0;2;69;169;24;0
28;13;10;3;4;225;26;9;28;284.853;91;0;1;1;0;0;2;69;169;24;3
3;21;11;3;4;179;51;18;38;268.519;93;0;1;0;1;0;0;89;170;31;1
34;28;11;4;4;118;10;10;37;268.519;93;0;1;0;0;0;0;83;172;28;3
18;2;11;4;4;330;16;4;28;268.519;93;0;2;0;0;0;0;84;182;25;24
3;28;11;6;4;179;51;18;38;268.519;93;0;1;0;1;0;0;89;170;31;1
34;9;11;3;4;118;10;10;37;268.519;93;0;1;0;0;0;0;83;172;28;8
11;24;11;4;4;289;36;13;33;268.519;93;0;1;2;1;0;1;90;172;30;8
25;1;11;6;4;235;16;8;32;268.519;93;0;3;0;0;0;0;75;178;25;8
28;23;11;6;4;225;26;9;28;268.519;93;0;1;1;0;0;2;69;169;24;4
10;22;11;3;4;361;52;3;28;268.519;93;0;1;1;1;0;4;80;172;27;8
15;28;11;4;4;291;31;12;40;268.519;93;0;1;1;1;0;1;73;171;25;2
34;13;11;5;4;118;10;10;37;268.519;93;0;1;0;0;0;0;83;172;28;2
28;14;11;5;4;225;26;9;28;268.519;93;0;1;1;0;0;2;69;169;24;3
3;28;11;2;4;179;51;18;38;268.519;93;0;1;0;1;0;0;89;170;31;1
34;23;11;2;4;118;10;10;37;268.519;93;0;1;0;0;0;0;83;172;28;8
34;8;11;3;4;118;10;10;37;268.519;93;0;1;0;0;0;0;83;172;28;8
28;23;11;3;4;225;26;9;28;268.519;93;0;1;1;0;0;2;69;169;24;2
15;0;11;3;4;291;31;12;40;268.519;93;1;1;1;1;0;1;73;171;25;0
11;0;11;4;4;289;36;13;33;268.519;93;1;1;2;1;0;1;90;172;30;0
33;14;11;5;4;248;25;14;47;268.519;93;0;1;2;0;0;1;86;165;32;4
5;0;11;5;4;235;20;13;43;268.519;93;1;1;1;1;0;0;106;167;38;0
28;23;11;6;4;225;26;9;28;268.519;93;0;1;1;0;0;2;69;169;24;2
13;26;11;6;4;369;17;12;31;268.519;93;0;1;3;1;0;0;70;169;25;8
10;28;11;2;4;361;52;3;28;268.519;93;0;1;1;1;0;4;80;172;27;2
3;13;12;3;4;179;51;18;38;280.549;98;0;1;0;1;0;0;89;170;31;32
15;28;12;4;4;291;31;12;40;280.549;98;0;1;1;1;0;1;73;171;25;1
28;23;12;4;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;3
22;13;12;6;4;179;26;9;30;280.549;98;0;3;0;0;0;0;56;171;19;1
28;23;12;6;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;3
28;23;12;4;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;3
10;14;12;5;4;361;52;3;28;280.549;98;0;1;1;1;0;4;80;172;27;4
17;18;12;6;4;179;22;17;40;280.549;98;0;2;2;0;1;0;63;170;22;2
5;26;12;6;4;235;20;13;43;280.549;98;0;1;1;1;0;0;106;167;38;8
12;18;12;2;4;233;51;1;31;280.549;98;0;2;1;1;0;8;68;178;21;8
22;13;12;3;4;179;26;9;30;280.549;98;0;3;0;0;0;0;56;171;19;16
28;23;12;3;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;2
28;23;12;5;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;3
28;23;12;2;4;225;26;9;28;280.549;98;0;1;1;0;0;2;69;169;24;2
14;18;12;3;2;155;12;14;34;280.549;98;0;1;2;1;0;0;95;196;25;80
22;12;1;2;2;179;26;9;30;313.532;96;0;3;0;0;0;0;56;171;19;24
22;12;1;5;2;179;26;9;30;313.532;96;0;3;0;0;0;0;56;171;19;16
17;25;1;5;2;179;22;17;40;313.532;96;0;2;2;0;1;0;63;170;22;2
17;25;1;6;2;179;22;17;40;313.532;96;0;2;2;0;1;0;63;170;22;2
22;13;1;2;2;179;26;9;30;313.532;96;0;3;0;0;0;0;56;171;19;3
17;25;1;4;2;179;22;17;40;313.532;96;0;2;2;0;1;0;63;170;22;2
32;10;1;5;2;289;48;29;49;313.532;96;0;1;0;0;0;2;108;172;36;8
17;18;1;6;2;179;22;17;40;313.532;96;0;2;2;0;1;0;63;170;22;3
22;27;1;2;2;179;26;9;30;313.532;96;0;3;0;0;0;0;56;171;19;2
14;18;1;3;2;155;12;14;34;313.532;96;0;1;2;1;0;0;95;196;25;8
22;27;1;4;2;179;26;9;30;313.532;96;0;3;0;0;0;0;56;171;19;2
3;27;1;4;2;179;51;18;38;313.532;96;0;1;0;1;0;0;89;170;31;3
11;13;1;4;2;289;36;13;33;313.532;96;0;1;2;1;0;1;90;172;30;8
3;27;1;5;2;179;51;18;38;313.532;96;0;1;0;1;0;0;89;170;31;3
3;27;1;6;2;179;51;18;38;313.532;96;0;1;0;1;0;0;89;170;31;2
3;13;2;3;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;8
28;23;2;3;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;3
33;1;2;4;2;248;25;14;47;264.249;97;0;1;2;0;0;1;86;165;32;8
3;27;2;4;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
28;28;2;5;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;3
3;27;2;5;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
22;27;2;5;2;179;26;9;30;264.249;97;0;3;0;0;0;0;56;171;19;2
29;28;2;6;2;225;15;15;41;264.249;97;0;4;2;1;0;2;94;182;28;2
3;27;2;6;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
12;19;2;2;2;233;51;1;31;264.249;97;0;2;1;1;0;8;68;178;21;2
3;27;2;2;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
28;7;2;3;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;8
3;27;2;4;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;3
3;27;2;5;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;3
28;25;2;5;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;3
22;13;2;5;2;179;26;9;30;264.249;97;0;3;0;0;0;0;56;171;19;2
17;23;2;6;2;179;22;17;40;264.249;97;0;2;2;0;1;0;63;170;22;2
3;27;2;6;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;3
12;12;2;4;2;233;51;1;31;264.249;97;0;2;1;1;0;8;68;178;21;3
22;27;2;4;2;179;26;9;30;264.249;97;0;3;0;0;0;0;56;171;19;2
3;27;2;4;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
3;13;2;5;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;8
3;27;2;6;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
14;25;2;2;2;155;12;14;34;264.249;97;0;1;2;1;0;0;95;196;25;5
25;25;2;2;2;235;16;8;32;264.249;97;0;3;0;0;0;0;75;178;25;3
3;27;2;2;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
28;7;2;2;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;2
3;27;2;3;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
33;23;2;3;2;248;25;14;47;264.249;97;0;1;2;0;0;1;86;165;32;2
28;25;2;3;2;225;26;9;28;264.249;97;0;1;1;0;0;2;69;169;24;2
3;27;2;4;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
3;27;2;5;2;179;51;18;38;264.249;97;0;1;0;1;0;0;89;170;31;2
25;25;2;6;2;235;16;8;32;264.249;97;0;3;0;0;0;0;75;178;25;2
3;27;3;2;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;2
33;23;3;2;2;248;25;14;47;222.196;99;0;1;2;0;0;1;86;165;32;2
9;25;3;3;2;228;14;16;58;222.196;99;0;1;2;0;0;1;65;172;22;3
33;25;3;3;2;248;25;14;47;222.196;99;0;1;2;0;0;1;86;165;32;3
9;12;3;3;2;228;14;16;58;222.196;99;0;1;2;0;0;1;65;172;22;112
3;27;3;4;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;2
28;27;3;5;2;225;26;9;28;222.196;99;0;1;1;0;0;2;69;169;24;2
3;27;3;5;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
28;25;3;5;2;225;26;9;28;222.196;99;0;1;1;0;0;2;69;169;24;2
22;27;3;6;2;179;26;9;30;222.196;99;0;3;0;0;0;0;56;171;19;3
25;25;3;2;2;235;16;8;32;222.196;99;0;3;0;0;0;0;75;178;25;3
10;19;3;2;2;361;52;3;28;222.196;99;0;1;1;1;0;4;80;172;27;8
3;13;3;3;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;8
3;27;3;4;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;2
3;27;3;5;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
22;27;3;6;2;179;26;9;30;222.196;99;0;3;0;0;0;0;56;171;19;2
3;10;3;2;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;4
33;13;3;2;2;248;25;14;47;222.196;99;0;1;2;0;0;1;86;165;32;2
3;27;3;2;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
28;7;3;2;2;225;26;9;28;222.196;99;0;1;1;0;0;2;69;169;24;8
3;27;3;3;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;2
11;23;3;4;2;289;36;13;33;222.196;99;0;1;2;1;0;1;90;172;30;8
9;25;3;4;2;228;14;16;58;222.196;99;0;1;2;0;0;1;65;172;22;2
3;27;3;4;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;2
33;23;3;5;2;248;25;14;47;222.196;99;0;1;2;0;0;1;86;165;32;3
3;27;3;5;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
22;23;3;6;2;179;26;9;30;222.196;99;0;3;0;0;0;0;56;171;19;2
3;27;3;6;2;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
3;27;3;3;3;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
16;23;3;4;3;118;15;24;46;222.196;99;0;1;2;1;1;0;75;175;25;8
14;13;3;4;3;155;12;14;34;222.196;99;0;1;2;1;0;0;95;196;25;24
3;27;3;4;3;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
3;27;3;5;3;179;51;18;38;222.196;99;0;1;0;1;0;0;89;170;31;3
22;13;3;2;3;179;26;9;30;222.196;99;0;3;0;0;0;0;56;171;19;2
11;19;3;2;3;289;36;13;33;222.196;99;0;1;2;1;0;1;90;172;30;104
13;22;3;4;3;369;17;12;31;222.196;99;0;1;3;1;0;0;70;169;25;8
28;13;4;2;3;225;26;9;28;246.288;91;0;1;1;0;0;2;69;169;24;8
34;10;4;2;3;118;10;10;37;246.288;91;0;1;0;0;0;0;83;172;28;8
10;19;4;3;3;361;52;3;28;246.288;91;0;1;1;1;0;4;80;172;27;8
33;19;4;4;3;248;25;14;47;246.288;91;0;1;2;0;0;1;86;165;32;8
6;13;4;5;3;189;29;13;33;246.288;91;0;1;2;0;0;2;69;167;25;8
22;27;4;6;3;179;26;9;30;246.288;91;0;3;0;0;0;0;56;171;19;2
13;7;4;2;3;369;17;12;31;246.288;91;0;1;3;1;0;0;70;169;25;24
17;16;4;3;3;179;22;17;40;246.288;91;0;2;2;0;1;0;63;170;22;2
36;23;4;3;3;118;13;18;50;246.288;91;0;1;1;1;0;0;98;178;31;3
10;23;4;3;3;361;52;3;28;246.288;91;0;1;1;1;0;4;80;172;27;2
34;10;4;4;3;118;10;10;37;246.288;91;0;1;0;0;0;0;83;172;28;2
1;22;4;6;3;235;11;14;37;246.288;91;0;3;1;0;0;1;88;172;29;8
22;27;4;6;3;179;26;9;30;246.288;91;0;3;0;0;0;0;56;171;19;2
28;19;4;2;3;225;26;9;28;246.288;91;0;1;1;0;0;2;69;169;24;8
25;16;4;3;3;235;16;8;32;246.288;91;0;3;0;0;0;0;75;178;25;3
22;27;4;6;3;179;26;9;30;246.288;91;0;3;0;0;0;0;56;171;19;2
14;28;4;3;3;155;12;14;34;246.288;91;0;1;2;1;0;0;95;196;25;4
28;19;4;5;3;225;26;9;28;246.288;91;0;1;1;0;0;2;69;169;24;8
36;14;4;5;3;118;13;18;50;246.288;91;0;1;1;1;0;0;98;178;31;2
22;27;4;6;3;179;26;9;30;246.288;91;0;3;0;0;0;0;56;171;19;2
1;22;5;2;3;235;11;14;37;237.656;99;0;3;1;0;0;1;88;172;29;8
29;19;5;4;3;225;15;15;41;237.656;99;0;4;2;1;0;2;94;182;28;3
25;28;5;4;3;235;16;8;32;237.656;99;0;3;0;0;0;0;75;178;25;2
34;8;5;4;3;118;10;10;37;237.656;99;0;1;0;0;0;0;83;172;28;3
5;26;5;4;3;235;20;13;43;237.656;99;0;1;1;1;0;0;106;167;38;8
22;13;5;5;3;179;26;9;30;237.656;99;0;3;0;0;0;0;56;171;19;1
15;28;5;5;3;291;31;12;40;237.656;99;0;1;1;1;0;1;73;171;25;2
29;14;5;5;3;225;15;15;41;237.656;99;0;4;2;1;0;2;94;182;28;8
26;19;5;6;3;300;26;13;43;237.656;99;0;1;2;1;1;1;77;175;25;64
29;22;5;6;3;225;15;15;41;237.656;99;0;4;2;1;0;2;94;182;28;8
22;27;5;6;3;179;26;9;30;237.656;99;0;3;0;0;0;0;56;171;19;2
36;23;5;2;3;118;13;18;50;237.656;99;0;1;1;1;0;0;98;178;31;2
36;5;5;3;3;118;13;18;50;237.656;99;0;1;1;1;0;0;98;178;31;3
34;28;5;3;3;118;10;10;37;237.656;99;0;1;0;0;0;0;83;172;28;1
36;0;5;3;3;118;13;18;50;237.656;99;1;1;1;1;0;0;98;178;31;0
22;27;5;4;3;179;26;9;30;237.656;99;0;3;0;0;0;0;56;171;19;2
23;0;5;4;3;378;49;11;36;237.656;99;1;1;2;0;1;4;65;174;21;0
17;16;5;6;3;179;22;17;40;237.656;99;0;2;2;0;1;0;63;170;22;1
14;10;5;2;3;155;12;14;34;237.656;99;0;1;2;1;0;0;95;196;25;48
25;10;5;2;3;235;16;8;32;237.656;99;0;3;0;0;0;0;75;178;25;8
15;22;5;4;3;291;31;12;40;237.656;99;0;1;1;1;0;1;73;171;25;8
17;10;5;4;3;179;22;17;40;237.656;99;0;2;2;0;1;0;63;170;22;8
28;6;5;4;3;225;26;9;28;237.656;99;0;1;1;0;0;2;69;169;24;3
18;10;5;5;3;330;16;4;28;237.656;99;0;2;0;0;0;0;84;182;25;8
25;23;5;5;3;235;16;8;32;237.656;99;0;3;0;0;0;0;75;178;25;2
15;28;5;5;3;291;31;12;40;237.656;99;0;1;1;1;0;1;73;171;25;2
22;27;5;6;3;179;26;9;30;237.656;99;0;3;0;0;0;0;56;171;19;2
10;7;5;2;3;361;52;3;28;237.656;99;0;1;1;1;0;4;80;172;27;8
14;23;5;4;3;155;12;14;34;237.656;99;0;1;2;1;0;0;95;196;25;2
17;25;5;6;3;179;22;17;40;237.656;99;0;2;2;0;1;0;63;170;22;8
14;10;5;6;3;155;12;14;34;237.656;99;0;1;2;1;0;0;95;196;25;8
28;11;5;2;3;225;26;9;28;237.656;99;0;1;1;0;0;2;69;169;24;1
16;7;6;4;3;118;15;24;46;275.089;96;0;1;2;1;1;0;75;175;25;8
22;27;6;4;3;179;26;9;30;275.089;96;0;3;0;0;0;0;56;171;19;3
34;26;6;6;3;118;10;10;37;275.089;96;0;1;0;0;0;0;83;172;28;8
34;10;6;4;3;118;10;10;37;275.089;96;0;1;0;0;0;0;83;172;28;8
23;22;6;5;3;378;49;11;36;275.089;96;0;1;2;0;1;4;65;174;21;8
36;19;6;5;3;118;13;18;50;275.089;96;0;1;1;1;0;0;98;178;31;24
12;19;6;6;3;233;51;1;31;275.089;96;0;2;1;1;0;8;68;178;21;8
22;27;6;6;3;179;26;9;30;275.089;96;0;3;0;0;0;0;56;171;19;2
2;0;6;2;3;235;29;12;48;275.089;96;1;1;1;0;1;5;88;163;33;0
21;0;6;2;3;268;11;8;33;275.089;96;1;2;0;0;0;0;79;178;25;0
36;19;6;5;3;118;13;18;50;275.089;96;0;1;1;1;0;0;98;178;31;3
22;13;6;5;3;179;26;9;30;275.089;96;0;3;0;0;0;0;56;171;19;2
15;28;6;5;3;291;31;12;40;275.089;96;0;1;1;1;0;1;73;171;25;2
22;13;6;2;1;179;26;9;30;275.089;96;0;3;0;0;0;0;56;171;19;3
34;25;6;2;1;118;10;10;37;275.089;96;0;1;0;0;0;0;83;172;28;3
12;22;6;5;1;233;51;1;31;275.089;96;0;2;1;1;0;8;68;178;21;8
34;8;6;6;1;118;10;10;37;275.089;96;0;1;0;0;0;0;83;172;28;2
34;10;6;4;1;118;10;10;37;275.089;96;0;1;0;0;0;0;83;172;28;3
12;22;6;4;1;233;51;1;31;275.089;96;0;2;1;1;0;8;68;178;21;3
5;26;7;4;1;235;20;13;43;264.604;93;0;1;1;1;0;0;106;167;38;4
12;19;7;6;1;233;51;1;31;264.604;93;0;2;1;1;0;8;68;178;21;2
9;6;7;2;1;228;14;16;58;264.604;93;0;1;2;0;0;1;65;172;22;8
34;28;7;2;1;118;10;10;37;264.604;93;0;1;0;0;0;0;83;172;28;4
9;6;7;3;1;228;14;16;58;264.604;93;0;1;2;0;0;1;65;172;22;120
6;22;7;3;1;189;29;13;33;264.604;93;0;1;2;0;0;2;69;167;25;16
34;23;7;4;1;118;10;10;37;264.604;93;0;1;0;0;0;0;83;172;28;2
10;22;7;4;1;361;52;3;28;264.604;93;0;1;1;1;0;4;80;172;27;8
28;22;7;4;1;225;26;9;28;264.604;93;0;1;1;0;0;2;69;169;24;8
13;13;7;2;1;369;17;12;31;264.604;93;0;1;3;1;0;0;70;169;25;80
11;14;7;3;1;289;36;13;33;264.604;93;0;1;2;1;0;1;90;172;30;8
1;11;7;3;1;235;11;14;37;264.604;93;0;3;1;0;0;1;88;172;29;4
4;0;0;3;1;118;14;13;40;271.219;95;0;1;1;1;0;8;98;170;34;0
8;0;0;4;2;231;35;14;39;271.219;95;0;1;2;1;0;2;100;170;35;0
35;0;0;6;3;179;45;14;53;271.219;95;0;1;1;0;0;1;77;175;25;0
1 ID Reason for absence Month of absence Day of the week Seasons Transportation expense Distance from Residence to Work Service time Age Work load Average/day Hit target Disciplinary failure Education Son Social drinker Social smoker Pet Weight Height Body mass index Absenteeism time in hours
2 11 26 7 3 1 289 36 13 33 239.554 97 0 1 2 1 0 1 90 172 30 4
3 36 0 7 3 1 118 13 18 50 239.554 97 1 1 1 1 0 0 98 178 31 0
4 3 23 7 4 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 2
5 7 7 7 5 1 279 5 14 39 239.554 97 0 1 2 1 1 0 68 168 24 4
6 11 23 7 5 1 289 36 13 33 239.554 97 0 1 2 1 0 1 90 172 30 2
7 3 23 7 6 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 2
8 10 22 7 6 1 361 52 3 28 239.554 97 0 1 1 1 0 4 80 172 27 8
9 20 23 7 6 1 260 50 11 36 239.554 97 0 1 4 1 0 0 65 168 23 4
10 14 19 7 2 1 155 12 14 34 239.554 97 0 1 2 1 0 0 95 196 25 40
11 1 22 7 2 1 235 11 14 37 239.554 97 0 3 1 0 0 1 88 172 29 8
12 20 1 7 2 1 260 50 11 36 239.554 97 0 1 4 1 0 0 65 168 23 8
13 20 1 7 3 1 260 50 11 36 239.554 97 0 1 4 1 0 0 65 168 23 8
14 20 11 7 4 1 260 50 11 36 239.554 97 0 1 4 1 0 0 65 168 23 8
15 3 11 7 4 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 1
16 3 23 7 4 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 4
17 24 14 7 6 1 246 25 16 41 239.554 97 0 1 0 1 0 0 67 170 23 8
18 3 23 7 6 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 2
19 3 21 7 2 1 179 51 18 38 239.554 97 0 1 0 1 0 0 89 170 31 8
20 6 11 7 5 1 189 29 13 33 239.554 97 0 1 2 0 0 2 69 167 25 8
21 33 23 8 4 1 248 25 14 47 205.917 92 0 1 2 0 0 1 86 165 32 2
22 18 10 8 4 1 330 16 4 28 205.917 92 0 2 0 0 0 0 84 182 25 8
23 3 11 8 2 1 179 51 18 38 205.917 92 0 1 0 1 0 0 89 170 31 1
24 10 13 8 2 1 361 52 3 28 205.917 92 0 1 1 1 0 4 80 172 27 40
25 20 28 8 6 1 260 50 11 36 205.917 92 0 1 4 1 0 0 65 168 23 4
26 11 18 8 2 1 289 36 13 33 205.917 92 0 1 2 1 0 1 90 172 30 8
27 10 25 8 2 1 361 52 3 28 205.917 92 0 1 1 1 0 4 80 172 27 7
28 11 23 8 3 1 289 36 13 33 205.917 92 0 1 2 1 0 1 90 172 30 1
29 30 28 8 4 1 157 27 6 29 205.917 92 0 1 0 1 1 0 75 185 22 4
30 11 18 8 4 1 289 36 13 33 205.917 92 0 1 2 1 0 1 90 172 30 8
31 3 23 8 6 1 179 51 18 38 205.917 92 0 1 0 1 0 0 89 170 31 2
32 3 18 8 2 1 179 51 18 38 205.917 92 0 1 0 1 0 0 89 170 31 8
33 2 18 8 5 1 235 29 12 48 205.917 92 0 1 1 0 1 5 88 163 33 8
34 1 23 8 5 1 235 11 14 37 205.917 92 0 3 1 0 0 1 88 172 29 4
35 2 18 8 2 1 235 29 12 48 205.917 92 0 1 1 0 1 5 88 163 33 8
36 3 23 8 2 1 179 51 18 38 205.917 92 0 1 0 1 0 0 89 170 31 2
37 10 23 8 2 1 361 52 3 28 205.917 92 0 1 1 1 0 4 80 172 27 1
38 11 24 8 3 1 289 36 13 33 205.917 92 0 1 2 1 0 1 90 172 30 8
39 19 11 8 5 1 291 50 12 32 205.917 92 0 1 0 1 0 0 65 169 23 4
40 2 28 8 6 1 235 29 12 48 205.917 92 0 1 1 0 1 5 88 163 33 8
41 20 23 8 6 1 260 50 11 36 205.917 92 0 1 4 1 0 0 65 168 23 4
42 27 23 9 3 1 184 42 7 27 241.476 92 0 1 0 0 0 0 58 167 21 2
43 34 23 9 2 1 118 10 10 37 241.476 92 0 1 0 0 0 0 83 172 28 4
44 3 23 9 3 1 179 51 18 38 241.476 92 0 1 0 1 0 0 89 170 31 4
45 5 19 9 3 1 235 20 13 43 241.476 92 0 1 1 1 0 0 106 167 38 8
46 14 23 9 4 1 155 12 14 34 241.476 92 0 1 2 1 0 0 95 196 25 2
47 34 23 9 2 1 118 10 10 37 241.476 92 0 1 0 0 0 0 83 172 28 3
48 3 23 9 3 1 179 51 18 38 241.476 92 0 1 0 1 0 0 89 170 31 3
49 15 23 9 5 1 291 31 12 40 241.476 92 0 1 1 1 0 1 73 171 25 4
50 20 22 9 6 1 260 50 11 36 241.476 92 0 1 4 1 0 0 65 168 23 8
51 15 14 9 2 4 291 31 12 40 241.476 92 0 1 1 1 0 1 73 171 25 32
52 20 0 9 2 4 260 50 11 36 241.476 92 1 1 4 1 0 0 65 168 23 0
53 29 0 9 2 4 225 26 9 28 241.476 92 1 1 1 0 0 2 69 169 24 0
54 28 23 9 3 4 225 26 9 28 241.476 92 0 1 1 0 0 2 69 169 24 2
55 34 23 9 3 4 118 10 10 37 241.476 92 0 1 0 0 0 0 83 172 28 2
56 11 0 9 3 4 289 36 13 33 241.476 92 1 1 2 1 0 1 90 172 30 0
57 36 0 9 3 4 118 13 18 50 241.476 92 1 1 1 1 0 0 98 178 31 0
58 28 18 9 4 4 225 26 9 28 241.476 92 0 1 1 0 0 2 69 169 24 3
59 3 23 9 4 4 179 51 18 38 241.476 92 0 1 0 1 0 0 89 170 31 3
60 13 0 9 4 4 369 17 12 31 241.476 92 1 1 3 1 0 0 70 169 25 0
61 33 23 9 6 4 248 25 14 47 241.476 92 0 1 2 0 0 1 86 165 32 1
62 3 23 9 6 4 179 51 18 38 241.476 92 0 1 0 1 0 0 89 170 31 3
63 20 23 9 6 4 260 50 11 36 241.476 92 0 1 4 1 0 0 65 168 23 4
64 3 23 10 3 4 179 51 18 38 253.465 93 0 1 0 1 0 0 89 170 31 3
65 34 23 10 3 4 118 10 10 37 253.465 93 0 1 0 0 0 0 83 172 28 3
66 36 0 10 4 4 118 13 18 50 253.465 93 1 1 1 1 0 0 98 178 31 0
67 22 23 10 5 4 179 26 9 30 253.465 93 0 3 0 0 0 0 56 171 19 1
68 3 23 10 6 4 179 51 18 38 253.465 93 0 1 0 1 0 0 89 170 31 3
69 28 23 10 6 4 225 26 9 28 253.465 93 0 1 1 0 0 2 69 169 24 3
70 34 23 10 3 4 118 10 10 37 253.465 93 0 1 0 0 0 0 83 172 28 3
71 28 23 10 4 4 225 26 9 28 253.465 93 0 1 1 0 0 2 69 169 24 2
72 33 23 10 4 4 248 25 14 47 253.465 93 0 1 2 0 0 1 86 165 32 2
73 15 23 10 5 4 291 31 12 40 253.465 93 0 1 1 1 0 1 73 171 25 5
74 3 23 10 4 4 179 51 18 38 253.465 93 0 1 0 1 0 0 89 170 31 8
75 28 23 10 4 4 225 26 9 28 253.465 93 0 1 1 0 0 2 69 169 24 3
76 20 19 10 5 4 260 50 11 36 253.465 93 0 1 4 1 0 0 65 168 23 16
77 15 14 10 3 4 291 31 12 40 253.465 93 0 1 1 1 0 1 73 171 25 8
78 28 28 10 3 4 225 26 9 28 253.465 93 0 1 1 0 0 2 69 169 24 2
79 11 26 10 4 4 289 36 13 33 253.465 93 0 1 2 1 0 1 90 172 30 8
80 10 23 10 6 4 361 52 3 28 253.465 93 0 1 1 1 0 4 80 172 27 1
81 20 28 10 6 4 260 50 11 36 253.465 93 0 1 4 1 0 0 65 168 23 3
82 3 23 11 5 4 179 51 18 38 306.345 93 0 1 0 1 0 0 89 170 31 1
83 28 23 11 4 4 225 26 9 28 306.345 93 0 1 1 0 0 2 69 169 24 1
84 3 13 11 5 4 179 51 18 38 306.345 93 0 1 0 1 0 0 89 170 31 8
85 17 21 11 5 4 179 22 17 40 306.345 93 0 2 2 0 1 0 63 170 22 8
86 15 23 11 5 4 291 31 12 40 306.345 93 0 1 1 1 0 1 73 171 25 5
87 14 10 11 2 4 155 12 14 34 306.345 93 0 1 2 1 0 0 95 196 25 32
88 6 22 11 2 4 189 29 13 33 306.345 93 0 1 2 0 0 2 69 167 25 8
89 15 14 11 2 4 291 31 12 40 306.345 93 0 1 1 1 0 1 73 171 25 40
90 28 23 11 4 4 225 26 9 28 306.345 93 0 1 1 0 0 2 69 169 24 1
91 14 6 11 6 4 155 12 14 34 306.345 93 0 1 2 1 0 0 95 196 25 8
92 28 23 11 4 4 225 26 9 28 306.345 93 0 1 1 0 0 2 69 169 24 3
93 17 21 11 4 4 179 22 17 40 306.345 93 0 2 2 0 1 0 63 170 22 8
94 28 13 11 6 4 225 26 9 28 306.345 93 0 1 1 0 0 2 69 169 24 3
95 20 28 11 6 4 260 50 11 36 306.345 93 0 1 4 1 0 0 65 168 23 4
96 33 28 11 2 4 248 25 14 47 306.345 93 0 1 2 0 0 1 86 165 32 1
97 28 28 11 3 4 225 26 9 28 306.345 93 0 1 1 0 0 2 69 169 24 3
98 11 7 11 4 4 289 36 13 33 306.345 93 0 1 2 1 0 1 90 172 30 24
99 15 23 11 5 4 291 31 12 40 306.345 93 0 1 1 1 0 1 73 171 25 3
100 33 23 12 3 4 248 25 14 47 261.306 97 0 1 2 0 0 1 86 165 32 1
101 34 19 12 3 4 118 10 10 37 261.306 97 0 1 0 0 0 0 83 172 28 64
102 36 23 12 4 4 118 13 18 50 261.306 97 0 1 1 1 0 0 98 178 31 2
103 1 26 12 4 4 235 11 14 37 261.306 97 0 3 1 0 0 1 88 172 29 8
104 28 23 12 5 4 225 26 9 28 261.306 97 0 1 1 0 0 2 69 169 24 2
105 20 26 12 6 4 260 50 11 36 261.306 97 0 1 4 1 0 0 65 168 23 8
106 34 19 12 3 4 118 10 10 37 261.306 97 0 1 0 0 0 0 83 172 28 56
107 10 22 12 4 4 361 52 3 28 261.306 97 0 1 1 1 0 4 80 172 27 8
108 28 28 12 5 4 225 26 9 28 261.306 97 0 1 1 0 0 2 69 169 24 3
109 20 28 12 6 4 260 50 11 36 261.306 97 0 1 4 1 0 0 65 168 23 3
110 28 23 12 3 4 225 26 9 28 261.306 97 0 1 1 0 0 2 69 169 24 2
111 10 22 12 4 4 361 52 3 28 261.306 97 0 1 1 1 0 4 80 172 27 8
112 34 27 12 6 4 118 10 10 37 261.306 97 0 1 0 0 0 0 83 172 28 2
113 24 19 12 6 2 246 25 16 41 261.306 97 0 1 0 1 0 0 67 170 23 8
114 28 23 12 6 2 225 26 9 28 261.306 97 0 1 1 0 0 2 69 169 24 2
115 28 23 1 4 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 1
116 34 19 1 2 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 1
117 34 27 1 3 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 1
118 14 18 1 3 2 155 12 14 34 308.593 95 0 1 2 1 0 0 95 196 25 8
119 28 27 1 4 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 2
120 27 23 1 5 2 184 42 7 27 308.593 95 0 1 0 0 0 0 58 167 21 2
121 28 28 1 5 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 2
122 28 27 1 6 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 1
123 34 27 1 2 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
124 28 27 1 3 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 2
125 34 27 1 3 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
126 34 27 1 4 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
127 34 27 1 5 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
128 34 27 1 6 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
129 34 27 1 2 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
130 34 27 1 3 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
131 22 18 1 3 2 179 26 9 30 308.593 95 0 3 0 0 0 0 56 171 19 8
132 11 18 1 3 2 289 36 13 33 308.593 95 0 1 2 1 0 1 90 172 30 8
133 34 27 1 4 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
134 27 23 1 5 2 184 42 7 27 308.593 95 0 1 0 0 0 0 58 167 21 2
135 34 27 1 5 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 2
136 34 27 1 2 2 118 10 10 37 308.593 95 0 1 0 0 0 0 83 172 28 0
137 28 23 1 3 2 225 26 9 28 308.593 95 0 1 1 0 0 2 69 169 24 1
138 11 22 1 5 2 289 36 13 33 308.593 95 0 1 2 1 0 1 90 172 30 3
139 27 23 2 6 2 184 42 7 27 302.585 99 0 1 0 0 0 0 58 167 21 1
140 24 1 2 4 2 246 25 16 41 302.585 99 0 1 0 1 0 0 67 170 23 8
141 3 11 2 4 2 179 51 18 38 302.585 99 0 1 0 1 0 0 89 170 31 8
142 14 28 2 5 2 155 12 14 34 302.585 99 0 1 2 1 0 0 95 196 25 2
143 6 23 2 5 2 189 29 13 33 302.585 99 0 1 2 0 0 2 69 167 25 8
144 20 28 2 6 2 260 50 11 36 302.585 99 0 1 4 1 0 0 65 168 23 2
145 11 22 2 6 2 289 36 13 33 302.585 99 0 1 2 1 0 1 90 172 30 8
146 31 11 2 2 2 388 15 9 50 302.585 99 0 1 0 0 0 0 76 178 24 8
147 31 1 2 3 2 388 15 9 50 302.585 99 0 1 0 0 0 0 76 178 24 8
148 28 28 2 2 2 225 26 9 28 302.585 99 0 1 1 0 0 2 69 169 24 2
149 28 23 2 3 2 225 26 9 28 302.585 99 0 1 1 0 0 2 69 169 24 2
150 22 23 2 3 2 179 26 9 30 302.585 99 0 3 0 0 0 0 56 171 19 1
151 27 23 2 3 2 184 42 7 27 302.585 99 0 1 0 0 0 0 58 167 21 8
152 28 25 2 5 2 225 26 9 28 302.585 99 0 1 1 0 0 2 69 169 24 3
153 18 18 2 2 2 330 16 4 28 302.585 99 0 2 0 0 0 0 84 182 25 8
154 18 23 2 3 2 330 16 4 28 302.585 99 0 2 0 0 0 0 84 182 25 1
155 28 23 2 4 2 225 26 9 28 302.585 99 0 1 1 0 0 2 69 169 24 1
156 6 19 2 5 2 189 29 13 33 302.585 99 0 1 2 0 0 2 69 167 25 8
157 19 28 3 3 2 291 50 12 32 343.253 95 0 1 0 1 0 0 65 169 23 2
158 20 19 3 3 2 260 50 11 36 343.253 95 0 1 4 1 0 0 65 168 23 8
159 30 19 3 3 2 157 27 6 29 343.253 95 0 1 0 1 1 0 75 185 22 3
160 17 17 3 3 2 179 22 17 40 343.253 95 0 2 2 0 1 0 63 170 22 8
161 15 22 3 4 2 291 31 12 40 343.253 95 0 1 1 1 0 1 73 171 25 8
162 20 13 3 4 2 260 50 11 36 343.253 95 0 1 4 1 0 0 65 168 23 8
163 22 13 3 5 2 179 26 9 30 343.253 95 0 3 0 0 0 0 56 171 19 8
164 33 14 3 6 2 248 25 14 47 343.253 95 0 1 2 0 0 1 86 165 32 3
165 20 13 3 6 2 260 50 11 36 343.253 95 0 1 4 1 0 0 65 168 23 40
166 17 11 3 2 2 179 22 17 40 343.253 95 0 2 2 0 1 0 63 170 22 40
167 14 1 3 2 2 155 12 14 34 343.253 95 0 1 2 1 0 0 95 196 25 16
168 20 26 3 2 2 260 50 11 36 343.253 95 0 1 4 1 0 0 65 168 23 16
169 14 13 3 3 2 155 12 14 34 343.253 95 0 1 2 1 0 0 95 196 25 8
170 11 6 3 5 2 289 36 13 33 343.253 95 0 1 2 1 0 1 90 172 30 8
171 17 8 3 5 2 179 22 17 40 343.253 95 0 2 2 0 1 0 63 170 22 8
172 20 28 3 6 2 260 50 11 36 343.253 95 0 1 4 1 0 0 65 168 23 4
173 28 23 3 6 2 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 1
174 7 14 3 2 2 279 5 14 39 343.253 95 0 1 2 1 1 0 68 168 24 8
175 3 13 3 3 2 179 51 18 38 343.253 95 0 1 0 1 0 0 89 170 31 24
176 28 23 3 4 2 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 2
177 28 11 3 2 3 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 8
178 22 13 3 2 3 179 26 9 30 343.253 95 0 3 0 0 0 0 56 171 19 1
179 28 11 3 3 3 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 8
180 28 11 3 4 3 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 16
181 3 13 3 4 3 179 51 18 38 343.253 95 0 1 0 1 0 0 89 170 31 3
182 7 14 3 5 3 279 5 14 39 343.253 95 0 1 2 1 1 0 68 168 24 16
183 28 28 3 6 3 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 2
184 33 14 3 6 3 248 25 14 47 343.253 95 0 1 2 0 0 1 86 165 32 3
185 28 28 3 2 3 225 26 9 28 343.253 95 0 1 1 0 0 2 69 169 24 1
186 15 28 4 4 3 291 31 12 40 326.452 96 0 1 1 1 0 1 73 171 25 1
187 28 23 4 4 3 225 26 9 28 326.452 96 0 1 1 0 0 2 69 169 24 1
188 14 28 4 3 3 155 12 14 34 326.452 96 0 1 2 1 0 0 95 196 25 1
189 24 13 4 4 3 246 25 16 41 326.452 96 0 1 0 1 0 0 67 170 23 24
190 14 23 4 5 3 155 12 14 34 326.452 96 0 1 2 1 0 0 95 196 25 1
191 28 28 4 6 3 225 26 9 28 326.452 96 0 1 1 0 0 2 69 169 24 2
192 20 28 4 6 3 260 50 11 36 326.452 96 0 1 4 1 0 0 65 168 23 4
193 3 13 4 4 3 179 51 18 38 326.452 96 0 1 0 1 0 0 89 170 31 24
194 36 23 4 5 3 118 13 18 50 326.452 96 0 1 1 1 0 0 98 178 31 1
195 15 23 4 6 3 291 31 12 40 326.452 96 0 1 1 1 0 1 73 171 25 3
196 24 14 4 6 3 246 25 16 41 326.452 96 0 1 0 1 0 0 67 170 23 8
197 15 28 4 6 3 291 31 12 40 326.452 96 0 1 1 1 0 1 73 171 25 1
198 33 28 4 6 3 248 25 14 47 326.452 96 0 1 2 0 0 1 86 165 32 8
199 20 19 4 6 3 260 50 11 36 326.452 96 0 1 4 1 0 0 65 168 23 56
200 11 19 4 3 3 289 36 13 33 326.452 96 0 1 2 1 0 1 90 172 30 8
201 14 12 4 4 3 155 12 14 34 326.452 96 0 1 2 1 0 0 95 196 25 24
202 23 19 4 4 3 378 49 11 36 326.452 96 0 1 2 0 1 4 65 174 21 8
203 11 13 4 5 3 289 36 13 33 326.452 96 0 1 2 1 0 1 90 172 30 16
204 1 7 4 6 3 235 11 14 37 326.452 96 0 3 1 0 0 1 88 172 29 3
205 2 0 4 2 3 235 29 12 48 326.452 96 1 1 1 0 1 5 88 163 33 0
206 11 13 5 4 3 289 36 13 33 378.884 92 0 1 2 1 0 1 90 172 30 8
207 14 28 5 5 3 155 12 14 34 378.884 92 0 1 2 1 0 0 95 196 25 2
208 14 28 5 2 3 155 12 14 34 378.884 92 0 1 2 1 0 0 95 196 25 1
209 3 18 5 3 3 179 51 18 38 378.884 92 0 1 0 1 0 0 89 170 31 8
210 28 19 5 3 3 225 26 9 28 378.884 92 0 1 1 0 0 2 69 169 24 8
211 27 7 5 4 3 184 42 7 27 378.884 92 0 1 0 0 0 0 58 167 21 4
212 14 28 5 2 3 155 12 14 34 378.884 92 0 1 2 1 0 0 95 196 25 2
213 3 12 5 3 3 179 51 18 38 378.884 92 0 1 0 1 0 0 89 170 31 1
214 11 13 5 4 3 289 36 13 33 378.884 92 0 1 2 1 0 1 90 172 30 24
215 7 0 5 4 3 279 5 14 39 378.884 92 1 1 2 1 1 0 68 168 24 0
216 18 0 5 4 3 330 16 4 28 378.884 92 1 2 0 0 0 0 84 182 25 0
217 23 0 5 4 3 378 49 11 36 378.884 92 1 1 2 0 1 4 65 174 21 0
218 31 0 5 4 3 388 15 9 50 378.884 92 1 1 0 0 0 0 76 178 24 0
219 3 11 5 3 3 179 51 18 38 378.884 92 0 1 0 1 0 0 89 170 31 1
220 36 13 5 4 3 118 13 18 50 378.884 92 0 1 1 1 0 0 98 178 31 24
221 10 22 5 6 3 361 52 3 28 378.884 92 0 1 1 1 0 4 80 172 27 8
222 24 19 6 2 3 246 25 16 41 377.550 94 0 1 0 1 0 0 67 170 23 8
223 10 22 6 2 3 361 52 3 28 377.550 94 0 1 1 1 0 4 80 172 27 8
224 24 10 6 3 3 246 25 16 41 377.550 94 0 1 0 1 0 0 67 170 23 24
225 15 23 6 5 3 291 31 12 40 377.550 94 0 1 1 1 0 1 73 171 25 4
226 24 10 6 6 3 246 25 16 41 377.550 94 0 1 0 1 0 0 67 170 23 8
227 3 11 6 2 3 179 51 18 38 377.550 94 0 1 0 1 0 0 89 170 31 8
228 14 23 6 2 3 155 12 14 34 377.550 94 0 1 2 1 0 0 95 196 25 4
229 24 10 6 2 3 246 25 16 41 377.550 94 0 1 0 1 0 0 67 170 23 8
230 36 13 6 4 3 118 13 18 50 377.550 94 0 1 1 1 0 0 98 178 31 8
231 1 13 6 6 3 235 11 14 37 377.550 94 0 3 1 0 0 1 88 172 29 16
232 36 23 6 3 3 118 13 18 50 377.550 94 0 1 1 1 0 0 98 178 31 1
233 36 13 6 4 3 118 13 18 50 377.550 94 0 1 1 1 0 0 98 178 31 80
234 23 22 6 5 3 378 49 11 36 377.550 94 0 1 2 0 1 4 65 174 21 8
235 3 11 6 6 3 179 51 18 38 377.550 94 0 1 0 1 0 0 89 170 31 2
236 32 28 6 2 1 289 48 29 49 377.550 94 0 1 0 0 0 2 108 172 36 2
237 28 28 6 5 1 225 26 9 28 377.550 94 0 1 1 0 0 2 69 169 24 2
238 14 19 7 3 1 155 12 14 34 275.312 98 0 1 2 1 0 0 95 196 25 16
239 36 1 7 4 1 118 13 18 50 275.312 98 0 1 1 1 0 0 98 178 31 8
240 34 5 7 6 1 118 10 10 37 275.312 98 0 1 0 0 0 0 83 172 28 8
241 34 26 7 6 1 118 10 10 37 275.312 98 0 1 0 0 0 0 83 172 28 4
242 18 26 7 3 1 330 16 4 28 275.312 98 0 2 0 0 0 0 84 182 25 8
243 22 18 7 5 1 179 26 9 30 275.312 98 0 3 0 0 0 0 56 171 19 8
244 14 25 7 6 1 155 12 14 34 275.312 98 0 1 2 1 0 0 95 196 25 2
245 18 1 7 2 1 330 16 4 28 275.312 98 0 2 0 0 0 0 84 182 25 8
246 18 1 7 3 1 330 16 4 28 275.312 98 0 2 0 0 0 0 84 182 25 8
247 30 25 7 2 1 157 27 6 29 275.312 98 0 1 0 1 1 0 75 185 22 3
248 10 22 7 3 1 361 52 3 28 275.312 98 0 1 1 1 0 4 80 172 27 8
249 11 26 7 4 1 289 36 13 33 275.312 98 0 1 2 1 0 1 90 172 30 8
250 3 26 7 5 1 179 51 18 38 275.312 98 0 1 0 1 0 0 89 170 31 8
251 11 19 7 2 1 289 36 13 33 275.312 98 0 1 2 1 0 1 90 172 30 32
252 11 19 7 5 1 289 36 13 33 275.312 98 0 1 2 1 0 1 90 172 30 8
253 20 0 7 5 1 260 50 11 36 275.312 98 1 1 4 1 0 0 65 168 23 0
254 11 19 8 6 1 289 36 13 33 265.615 94 0 1 2 1 0 1 90 172 30 8
255 30 19 8 6 1 157 27 6 29 265.615 94 0 1 0 1 1 0 75 185 22 3
256 11 23 8 2 1 289 36 13 33 265.615 94 0 1 2 1 0 1 90 172 30 1
257 9 18 8 3 1 228 14 16 58 265.615 94 0 1 2 0 0 1 65 172 22 8
258 26 13 8 5 1 300 26 13 43 265.615 94 0 1 2 1 1 1 77 175 25 1
259 26 14 8 5 1 300 26 13 43 265.615 94 0 1 2 1 1 1 77 175 25 2
260 20 28 8 6 1 260 50 11 36 265.615 94 0 1 4 1 0 0 65 168 23 4
261 11 23 8 3 1 289 36 13 33 265.615 94 0 1 2 1 0 1 90 172 30 4
262 33 23 8 4 1 248 25 14 47 265.615 94 0 1 2 0 0 1 86 165 32 1
263 21 11 8 5 1 268 11 8 33 265.615 94 0 2 0 0 0 0 79 178 25 8
264 22 23 8 5 1 179 26 9 30 265.615 94 0 3 0 0 0 0 56 171 19 1
265 36 13 8 5 1 118 13 18 50 265.615 94 0 1 1 1 0 0 98 178 31 3
266 33 25 8 2 1 248 25 14 47 265.615 94 0 1 2 0 0 1 86 165 32 2
267 1 23 8 3 1 235 11 14 37 265.615 94 0 3 1 0 0 1 88 172 29 1
268 36 23 8 5 1 118 13 18 50 265.615 94 0 1 1 1 0 0 98 178 31 1
269 1 19 8 5 1 235 11 14 37 265.615 94 0 3 1 0 0 1 88 172 29 8
270 10 8 8 3 1 361 52 3 28 265.615 94 0 1 1 1 0 4 80 172 27 8
271 27 6 8 4 1 184 42 7 27 265.615 94 0 1 0 0 0 0 58 167 21 8
272 3 11 9 2 1 179 51 18 38 294.217 81 0 1 0 1 0 0 89 170 31 8
273 3 23 9 6 1 179 51 18 38 294.217 81 0 1 0 1 0 0 89 170 31 3
274 11 19 9 4 1 289 36 13 33 294.217 81 0 1 2 1 0 1 90 172 30 24
275 5 0 9 5 1 235 20 13 43 294.217 81 1 1 1 1 0 0 106 167 38 0
276 24 9 9 2 1 246 25 16 41 294.217 81 0 1 0 1 0 0 67 170 23 16
277 15 28 9 3 1 291 31 12 40 294.217 81 0 1 1 1 0 1 73 171 25 3
278 8 0 9 3 1 231 35 14 39 294.217 81 1 1 2 1 0 2 100 170 35 0
279 19 0 9 3 1 291 50 12 32 294.217 81 1 1 0 1 0 0 65 169 23 0
280 3 13 9 4 1 179 51 18 38 294.217 81 0 1 0 1 0 0 89 170 31 8
281 24 9 9 4 1 246 25 16 41 294.217 81 0 1 0 1 0 0 67 170 23 32
282 3 23 9 5 1 179 51 18 38 294.217 81 0 1 0 1 0 0 89 170 31 1
283 15 28 9 6 1 291 31 12 40 294.217 81 0 1 1 1 0 1 73 171 25 4
284 20 28 9 6 1 260 50 11 36 294.217 81 0 1 4 1 0 0 65 168 23 4
285 5 26 9 4 4 235 20 13 43 294.217 81 0 1 1 1 0 0 106 167 38 8
286 36 28 9 5 4 118 13 18 50 294.217 81 0 1 1 1 0 0 98 178 31 1
287 5 0 9 5 4 235 20 13 43 294.217 81 1 1 1 1 0 0 106 167 38 0
288 15 28 9 6 4 291 31 12 40 294.217 81 0 1 1 1 0 1 73 171 25 3
289 15 7 9 2 4 291 31 12 40 294.217 81 0 1 1 1 0 1 73 171 25 40
290 3 13 9 2 4 179 51 18 38 294.217 81 0 1 0 1 0 0 89 170 31 8
291 11 24 10 2 4 289 36 13 33 265.017 88 0 1 2 1 0 1 90 172 30 8
292 1 26 10 2 4 235 11 14 37 265.017 88 0 3 1 0 0 1 88 172 29 4
293 11 26 10 2 4 289 36 13 33 265.017 88 0 1 2 1 0 1 90 172 30 8
294 11 22 10 6 4 289 36 13 33 265.017 88 0 1 2 1 0 1 90 172 30 8
295 36 0 10 6 4 118 13 18 50 265.017 88 1 1 1 1 0 0 98 178 31 0
296 33 0 10 6 4 248 25 14 47 265.017 88 1 1 2 0 0 1 86 165 32 0
297 22 1 10 2 4 179 26 9 30 265.017 88 0 3 0 0 0 0 56 171 19 8
298 34 7 10 2 4 118 10 10 37 265.017 88 0 1 0 0 0 0 83 172 28 3
299 13 22 10 2 4 369 17 12 31 265.017 88 0 1 3 1 0 0 70 169 25 8
300 3 28 10 4 4 179 51 18 38 265.017 88 0 1 0 1 0 0 89 170 31 1
301 22 1 10 4 4 179 26 9 30 265.017 88 0 3 0 0 0 0 56 171 19 64
302 5 0 10 4 4 235 20 13 43 265.017 88 1 1 1 1 0 0 106 167 38 0
303 11 19 10 5 4 289 36 13 33 265.017 88 0 1 2 1 0 1 90 172 30 16
304 20 28 10 6 4 260 50 11 36 265.017 88 0 1 4 1 0 0 65 168 23 3
305 5 0 10 6 4 235 20 13 43 265.017 88 1 1 1 1 0 0 106 167 38 0
306 5 23 10 2 4 235 20 13 43 265.017 88 0 1 1 1 0 0 106 167 38 2
307 5 23 10 2 4 235 20 13 43 265.017 88 0 1 1 1 0 0 106 167 38 2
308 36 28 10 3 4 118 13 18 50 265.017 88 0 1 1 1 0 0 98 178 31 1
309 15 28 10 3 4 291 31 12 40 265.017 88 0 1 1 1 0 1 73 171 25 4
310 22 23 10 5 4 179 26 9 30 265.017 88 0 3 0 0 0 0 56 171 19 16
311 36 28 10 5 4 118 13 18 50 265.017 88 0 1 1 1 0 0 98 178 31 1
312 10 10 10 2 4 361 52 3 28 265.017 88 0 1 1 1 0 4 80 172 27 8
313 20 0 10 3 4 260 50 11 36 265.017 88 1 1 4 1 0 0 65 168 23 0
314 15 0 10 3 4 291 31 12 40 265.017 88 1 1 1 1 0 1 73 171 25 0
315 30 0 10 3 4 157 27 6 29 265.017 88 1 1 0 1 1 0 75 185 22 0
316 22 1 10 4 4 179 26 9 30 265.017 88 0 3 0 0 0 0 56 171 19 5
317 22 7 10 4 4 179 26 9 30 265.017 88 0 3 0 0 0 0 56 171 19 5
318 36 23 10 5 4 118 13 18 50 265.017 88 0 1 1 1 0 0 98 178 31 1
319 34 11 11 2 4 118 10 10 37 284.031 97 0 1 0 0 0 0 83 172 28 8
320 33 23 11 2 4 248 25 14 47 284.031 97 0 1 2 0 0 1 86 165 32 2
321 3 6 11 3 4 179 51 18 38 284.031 97 0 1 0 1 0 0 89 170 31 8
322 20 28 11 6 4 260 50 11 36 284.031 97 0 1 4 1 0 0 65 168 23 3
323 15 23 11 2 4 291 31 12 40 284.031 97 0 1 1 1 0 1 73 171 25 1
324 23 1 11 2 4 378 49 11 36 284.031 97 0 1 2 0 1 4 65 174 21 8
325 14 11 11 2 4 155 12 14 34 284.031 97 0 1 2 1 0 0 95 196 25 120
326 5 26 11 2 4 235 20 13 43 284.031 97 0 1 1 1 0 0 106 167 38 8
327 18 0 11 3 4 330 16 4 28 284.031 97 1 2 0 0 0 0 84 182 25 0
328 1 18 11 4 4 235 11 14 37 284.031 97 0 3 1 0 0 1 88 172 29 1
329 34 11 11 4 4 118 10 10 37 284.031 97 0 1 0 0 0 0 83 172 28 3
330 1 25 11 5 4 235 11 14 37 284.031 97 0 3 1 0 0 1 88 172 29 2
331 3 28 11 5 4 179 51 18 38 284.031 97 0 1 0 1 0 0 89 170 31 3
332 24 13 11 6 4 246 25 16 41 284.031 97 0 1 0 1 0 0 67 170 23 8
333 15 12 11 6 4 291 31 12 40 284.031 97 0 1 1 1 0 1 73 171 25 4
334 24 13 11 2 4 246 25 16 41 284.031 97 0 1 0 1 0 0 67 170 23 8
335 3 28 11 3 4 179 51 18 38 284.031 97 0 1 0 1 0 0 89 170 31 1
336 20 10 11 4 4 260 50 11 36 284.031 97 0 1 4 1 0 0 65 168 23 8
337 20 15 11 6 4 260 50 11 36 284.031 97 0 1 4 1 0 0 65 168 23 8
338 23 0 11 6 4 378 49 11 36 284.031 97 1 1 2 0 1 4 65 174 21 0
339 7 0 11 3 4 279 5 14 39 284.031 97 1 1 2 1 1 0 68 168 24 0
340 3 23 11 5 4 179 51 18 38 284.031 97 0 1 0 1 0 0 89 170 31 1
341 28 12 12 2 4 225 26 9 28 236.629 93 0 1 1 0 0 2 69 169 24 3
342 3 28 12 2 4 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 2
343 3 28 12 2 4 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 1
344 1 23 12 2 4 235 11 14 37 236.629 93 0 3 1 0 0 1 88 172 29 3
345 36 28 12 3 4 118 13 18 50 236.629 93 0 1 1 1 0 0 98 178 31 1
346 20 28 12 6 4 260 50 11 36 236.629 93 0 1 4 1 0 0 65 168 23 4
347 24 4 12 5 4 246 25 16 41 236.629 93 0 1 0 1 0 0 67 170 23 8
348 3 28 12 5 4 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 1
349 3 28 12 6 4 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 1
350 22 23 12 3 4 179 26 9 30 236.629 93 0 3 0 0 0 0 56 171 19 1
351 34 25 12 3 4 118 10 10 37 236.629 93 0 1 0 0 0 0 83 172 28 8
352 1 25 12 5 4 235 11 14 37 236.629 93 0 3 1 0 0 1 88 172 29 2
353 3 28 12 6 4 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 1
354 5 13 12 3 2 235 20 13 43 236.629 93 0 1 1 1 0 0 106 167 38 8
355 1 14 12 3 2 235 11 14 37 236.629 93 0 3 1 0 0 1 88 172 29 4
356 20 26 12 4 2 260 50 11 36 236.629 93 0 1 4 1 0 0 65 168 23 8
357 30 28 12 2 2 157 27 6 29 236.629 93 0 1 0 1 1 0 75 185 22 2
358 3 28 12 2 2 179 51 18 38 236.629 93 0 1 0 1 0 0 89 170 31 3
359 11 19 12 2 2 289 36 13 33 236.629 93 0 1 2 1 0 1 90 172 30 8
360 28 23 1 4 2 225 26 9 28 330.061 100 0 1 1 0 0 2 69 169 24 5
361 34 19 1 2 2 118 10 10 37 330.061 100 0 1 0 0 0 0 83 172 28 32
362 14 23 1 2 2 155 12 14 34 330.061 100 0 1 2 1 0 0 95 196 25 2
363 1 13 1 3 2 235 11 14 37 330.061 100 0 3 1 0 0 1 88 172 29 1
364 14 23 1 3 2 155 12 14 34 330.061 100 0 1 2 1 0 0 95 196 25 4
365 11 26 1 2 2 289 36 13 33 330.061 100 0 1 2 1 0 1 90 172 30 8
366 15 3 1 4 2 291 31 12 40 330.061 100 0 1 1 1 0 1 73 171 25 8
367 5 26 1 2 2 235 20 13 43 330.061 100 0 1 1 1 0 0 106 167 38 8
368 36 26 1 2 2 118 13 18 50 330.061 100 0 1 1 1 0 0 98 178 31 4
369 3 28 1 4 2 179 51 18 38 330.061 100 0 1 0 1 0 0 89 170 31 1
370 3 28 1 6 2 179 51 18 38 330.061 100 0 1 0 1 0 0 89 170 31 1
371 34 28 2 3 2 118 10 10 37 251.818 96 0 1 0 0 0 0 83 172 28 2
372 3 27 2 4 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
373 28 7 2 4 2 225 26 9 28 251.818 96 0 1 1 0 0 2 69 169 24 1
374 11 22 2 6 2 289 36 13 33 251.818 96 0 1 2 1 0 1 90 172 30 3
375 20 28 2 6 2 260 50 11 36 251.818 96 0 1 4 1 0 0 65 168 23 3
376 3 23 2 6 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
377 3 27 2 2 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 2
378 3 27 2 4 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
379 3 10 2 5 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 8
380 24 26 2 5 2 246 25 16 41 251.818 96 0 1 0 1 0 0 67 170 23 8
381 3 27 2 6 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
382 6 22 2 2 2 189 29 13 33 251.818 96 0 1 2 0 0 2 69 167 25 8
383 3 27 2 2 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
384 24 23 2 3 2 246 25 16 41 251.818 96 0 1 0 1 0 0 67 170 23 2
385 15 23 2 3 2 291 31 12 40 251.818 96 0 1 1 1 0 1 73 171 25 2
386 30 11 2 4 2 157 27 6 29 251.818 96 0 1 0 1 1 0 75 185 22 16
387 3 27 2 4 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
388 3 27 2 6 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
389 24 10 2 6 2 246 25 16 41 251.818 96 0 1 0 1 0 0 67 170 23 24
390 3 27 2 4 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
391 3 27 2 6 2 179 51 18 38 251.818 96 0 1 0 1 0 0 89 170 31 3
392 34 18 3 3 2 118 10 10 37 244.387 98 0 1 0 0 0 0 83 172 28 8
393 24 19 3 4 2 246 25 16 41 244.387 98 0 1 0 1 0 0 67 170 23 16
394 24 28 3 6 2 246 25 16 41 244.387 98 0 1 0 1 0 0 67 170 23 2
395 20 28 3 6 2 260 50 11 36 244.387 98 0 1 4 1 0 0 65 168 23 4
396 3 28 3 2 2 179 51 18 38 244.387 98 0 1 0 1 0 0 89 170 31 2
397 1 22 3 2 2 235 11 14 37 244.387 98 0 3 1 0 0 1 88 172 29 8
398 17 22 3 3 2 179 22 17 40 244.387 98 0 2 2 0 1 0 63 170 22 8
399 23 22 3 3 2 378 49 11 36 244.387 98 0 1 2 0 1 4 65 174 21 8
400 3 28 3 2 2 179 51 18 38 244.387 98 0 1 0 1 0 0 89 170 31 16
401 10 22 3 4 2 361 52 3 28 244.387 98 0 1 1 1 0 4 80 172 27 8
402 13 0 3 4 2 369 17 12 31 244.387 98 1 1 3 1 0 0 70 169 25 0
403 1 21 3 5 2 235 11 14 37 244.387 98 0 3 1 0 0 1 88 172 29 8
404 36 23 3 6 3 118 13 18 50 244.387 98 0 1 1 1 0 0 98 178 31 2
405 36 14 3 3 3 118 13 18 50 244.387 98 0 1 1 1 0 0 98 178 31 3
406 36 13 3 4 3 118 13 18 50 244.387 98 0 1 1 1 0 0 98 178 31 8
407 1 0 3 5 3 235 11 14 37 244.387 98 1 3 1 0 0 1 88 172 29 0
408 24 0 3 5 3 246 25 16 41 244.387 98 1 1 0 1 0 0 67 170 23 0
409 36 0 3 5 3 118 13 18 50 244.387 98 1 1 1 1 0 0 98 178 31 0
410 3 28 3 6 3 179 51 18 38 244.387 98 0 1 0 1 0 0 89 170 31 8
411 11 22 3 6 3 289 36 13 33 244.387 98 0 1 2 1 0 1 90 172 30 8
412 20 19 3 2 3 260 50 11 36 244.387 98 0 1 4 1 0 0 65 168 23 8
413 24 28 3 3 3 246 25 16 41 244.387 98 0 1 0 1 0 0 67 170 23 2
414 3 28 4 4 3 179 51 18 38 239.409 98 0 1 0 1 0 0 89 170 31 4
415 20 28 4 6 3 260 50 11 36 239.409 98 0 1 4 1 0 0 65 168 23 3
416 18 26 4 6 3 330 16 4 28 239.409 98 0 2 0 0 0 0 84 182 25 4
417 13 22 4 2 3 369 17 12 31 239.409 98 0 1 3 1 0 0 70 169 25 4
418 33 26 4 2 3 248 25 14 47 239.409 98 0 1 2 0 0 1 86 165 32 4
419 18 23 4 4 3 330 16 4 28 239.409 98 0 2 0 0 0 0 84 182 25 8
420 3 28 4 4 3 179 51 18 38 239.409 98 0 1 0 1 0 0 89 170 31 8
421 36 23 4 2 3 118 13 18 50 239.409 98 0 1 1 1 0 0 98 178 31 1
422 36 13 4 4 3 118 13 18 50 239.409 98 0 1 1 1 0 0 98 178 31 120
423 26 28 4 6 3 300 26 13 43 239.409 98 0 1 2 1 1 1 77 175 25 8
424 20 28 4 6 3 260 50 11 36 239.409 98 0 1 4 1 0 0 65 168 23 4
425 3 28 4 2 3 179 51 18 38 239.409 98 0 1 0 1 0 0 89 170 31 4
426 34 11 4 4 3 118 10 10 37 239.409 98 0 1 0 0 0 0 83 172 28 2
427 5 13 5 2 3 235 20 13 43 246.074 99 0 1 1 1 0 0 106 167 38 16
428 33 23 5 4 3 248 25 14 47 246.074 99 0 1 2 0 0 1 86 165 32 2
429 13 10 5 2 3 369 17 12 31 246.074 99 0 1 3 1 0 0 70 169 25 8
430 22 23 5 4 3 179 26 9 30 246.074 99 0 3 0 0 0 0 56 171 19 3
431 3 28 5 4 3 179 51 18 38 246.074 99 0 1 0 1 0 0 89 170 31 4
432 10 23 5 5 3 361 52 3 28 246.074 99 0 1 1 1 0 4 80 172 27 1
433 20 28 5 6 3 260 50 11 36 246.074 99 0 1 4 1 0 0 65 168 23 3
434 17 11 5 2 3 179 22 17 40 246.074 99 0 2 2 0 1 0 63 170 22 2
435 17 8 5 2 3 179 22 17 40 246.074 99 0 2 2 0 1 0 63 170 22 3
436 9 18 5 4 3 228 14 16 58 246.074 99 0 1 2 0 0 1 65 172 22 8
437 28 25 5 4 3 225 26 9 28 246.074 99 0 1 1 0 0 2 69 169 24 3
438 18 13 5 6 3 330 16 4 28 246.074 99 0 2 0 0 0 0 84 182 25 8
439 22 25 5 2 3 179 26 9 30 246.074 99 0 3 0 0 0 0 56 171 19 2
440 34 28 5 2 3 118 10 10 37 246.074 99 0 1 0 0 0 0 83 172 28 1
441 1 1 5 2 3 235 11 14 37 246.074 99 0 3 1 0 0 1 88 172 29 8
442 22 23 5 4 3 179 26 9 30 246.074 99 0 3 0 0 0 0 56 171 19 3
443 34 23 6 2 3 118 10 10 37 253.957 95 0 1 0 0 0 0 83 172 28 3
444 3 28 6 2 3 179 51 18 38 253.957 95 0 1 0 1 0 0 89 170 31 3
445 34 28 6 3 3 118 10 10 37 253.957 95 0 1 0 0 0 0 83 172 28 2
446 28 23 6 5 3 225 26 9 28 253.957 95 0 1 1 0 0 2 69 169 24 4
447 20 28 6 6 3 260 50 11 36 253.957 95 0 1 4 1 0 0 65 168 23 4
448 3 0 6 6 3 179 51 18 38 253.957 95 1 1 0 1 0 0 89 170 31 0
449 15 13 6 2 3 291 31 12 40 253.957 95 0 1 1 1 0 1 73 171 25 40
450 3 28 6 2 3 179 51 18 38 253.957 95 0 1 0 1 0 0 89 170 31 24
451 24 28 6 3 3 246 25 16 41 253.957 95 0 1 0 1 0 0 67 170 23 3
452 3 28 6 2 3 179 51 18 38 253.957 95 0 1 0 1 0 0 89 170 31 4
453 5 26 6 3 3 235 20 13 43 253.957 95 0 1 1 1 0 0 106 167 38 8
454 3 28 6 2 1 179 51 18 38 253.957 95 0 1 0 1 0 0 89 170 31 2
455 28 23 6 4 1 225 26 9 28 253.957 95 0 1 1 0 0 2 69 169 24 2
456 36 23 6 4 1 118 13 18 50 253.957 95 0 1 1 1 0 0 98 178 31 2
457 3 5 6 4 1 179 51 18 38 253.957 95 0 1 0 1 0 0 89 170 31 8
458 22 21 6 4 1 179 26 9 30 253.957 95 0 3 0 0 0 0 56 171 19 2
459 24 28 6 6 1 246 25 16 41 253.957 95 0 1 0 1 0 0 67 170 23 2
460 18 11 6 3 1 330 16 4 28 253.957 95 0 2 0 0 0 0 84 182 25 1
461 1 13 6 3 1 235 11 14 37 253.957 95 0 3 1 0 0 1 88 172 29 8
462 22 23 7 5 1 179 26 9 30 230.290 92 0 3 0 0 0 0 56 171 19 2
463 28 25 7 5 1 225 26 9 28 230.290 92 0 1 1 0 0 2 69 169 24 4
464 20 13 7 6 1 260 50 11 36 230.290 92 0 1 4 1 0 0 65 168 23 8
465 21 7 7 2 1 268 11 8 33 230.290 92 0 2 0 0 0 0 79 178 25 8
466 18 25 7 6 1 330 16 4 28 230.290 92 0 2 0 0 0 0 84 182 25 8
467 34 26 7 6 1 118 10 10 37 230.290 92 0 1 0 0 0 0 83 172 28 8
468 20 26 7 2 1 260 50 11 36 230.290 92 0 1 4 1 0 0 65 168 23 4
469 34 28 7 3 1 118 10 10 37 230.290 92 0 1 0 0 0 0 83 172 28 8
470 26 15 7 2 1 300 26 13 43 230.290 92 0 1 2 1 1 1 77 175 25 8
471 2 23 7 2 1 235 29 12 48 230.290 92 0 1 1 0 1 5 88 163 33 1
472 24 28 7 3 1 246 25 16 41 230.290 92 0 1 0 1 0 0 67 170 23 2
473 28 9 7 3 1 225 26 9 28 230.290 92 0 1 1 0 0 2 69 169 24 112
474 3 28 7 3 1 179 51 18 38 230.290 92 0 1 0 1 0 0 89 170 31 1
475 36 23 7 6 1 118 13 18 50 230.290 92 0 1 1 1 0 0 98 178 31 1
476 10 22 7 6 1 361 52 3 28 230.290 92 0 1 1 1 0 4 80 172 27 8
477 11 22 7 2 1 289 36 13 33 230.290 92 0 1 2 1 0 1 90 172 30 8
478 5 26 7 2 1 235 20 13 43 230.290 92 0 1 1 1 0 0 106 167 38 8
479 24 28 7 3 1 246 25 16 41 230.290 92 0 1 0 1 0 0 67 170 23 2
480 15 28 7 5 1 291 31 12 40 230.290 92 0 1 1 1 0 1 73 171 25 1
481 7 23 7 5 1 279 5 14 39 230.290 92 0 1 2 1 1 0 68 168 24 2
482 3 25 8 5 1 179 51 18 38 249.797 93 0 1 0 1 0 0 89 170 31 4
483 17 25 8 2 1 179 22 17 40 249.797 93 0 2 2 0 1 0 63 170 22 1
484 24 28 8 3 1 246 25 16 41 249.797 93 0 1 0 1 0 0 67 170 23 4
485 34 28 8 3 1 118 10 10 37 249.797 93 0 1 0 0 0 0 83 172 28 4
486 11 26 8 3 1 289 36 13 33 249.797 93 0 1 2 1 0 1 90 172 30 8
487 5 26 8 3 1 235 20 13 43 249.797 93 0 1 1 1 0 0 106 167 38 8
488 15 28 8 5 1 291 31 12 40 249.797 93 0 1 1 1 0 1 73 171 25 4
489 3 25 8 2 1 179 51 18 38 249.797 93 0 1 0 1 0 0 89 170 31 4
490 17 25 8 3 1 179 22 17 40 249.797 93 0 2 2 0 1 0 63 170 22 8
491 18 23 8 5 1 330 16 4 28 249.797 93 0 2 0 0 0 0 84 182 25 16
492 1 23 8 3 1 235 11 14 37 249.797 93 0 3 1 0 0 1 88 172 29 4
493 24 28 8 3 1 246 25 16 41 249.797 93 0 1 0 1 0 0 67 170 23 1
494 34 28 8 3 1 118 10 10 37 249.797 93 0 1 0 0 0 0 83 172 28 5
495 15 28 8 5 1 291 31 12 40 249.797 93 0 1 1 1 0 1 73 171 25 2
496 20 28 8 2 1 260 50 11 36 249.797 93 0 1 4 1 0 0 65 168 23 3
497 24 28 9 3 1 246 25 16 41 261.756 87 0 1 0 1 0 0 67 170 23 1
498 24 28 9 3 1 246 25 16 41 261.756 87 0 1 0 1 0 0 67 170 23 1
499 34 28 9 3 1 118 10 10 37 261.756 87 0 1 0 0 0 0 83 172 28 3
500 14 23 9 3 1 155 12 14 34 261.756 87 0 1 2 1 0 0 95 196 25 2
501 15 28 9 5 1 291 31 12 40 261.756 87 0 1 1 1 0 1 73 171 25 2
502 22 23 9 6 1 179 26 9 30 261.756 87 0 3 0 0 0 0 56 171 19 8
503 33 23 9 6 1 248 25 14 47 261.756 87 0 1 2 0 0 1 86 165 32 1
504 3 23 9 2 1 179 51 18 38 261.756 87 0 1 0 1 0 0 89 170 31 4
505 28 23 9 4 1 225 26 9 28 261.756 87 0 1 1 0 0 2 69 169 24 1
506 22 23 9 2 1 179 26 9 30 261.756 87 0 3 0 0 0 0 56 171 19 2
507 13 23 9 3 4 369 17 12 31 261.756 87 0 1 3 1 0 0 70 169 25 8
508 10 22 9 3 4 361 52 3 28 261.756 87 0 1 1 1 0 4 80 172 27 8
509 32 4 10 5 4 289 48 29 49 284.853 91 0 1 0 0 0 2 108 172 36 1
510 25 11 10 5 4 235 16 8 32 284.853 91 0 3 0 0 0 0 75 178 25 3
511 24 26 10 6 4 246 25 16 41 284.853 91 0 1 0 1 0 0 67 170 23 8
512 32 14 10 4 4 289 48 29 49 284.853 91 0 1 0 0 0 2 108 172 36 3
513 15 28 10 4 4 291 31 12 40 284.853 91 0 1 1 1 0 1 73 171 25 2
514 34 23 10 3 4 118 10 10 37 284.853 91 0 1 0 0 0 0 83 172 28 2
515 32 23 10 5 4 289 48 29 49 284.853 91 0 1 0 0 0 2 108 172 36 2
516 15 23 10 6 4 291 31 12 40 284.853 91 0 1 1 1 0 1 73 171 25 1
517 28 23 10 3 4 225 26 9 28 284.853 91 0 1 1 0 0 2 69 169 24 2
518 13 23 10 3 4 369 17 12 31 284.853 91 0 1 3 1 0 0 70 169 25 8
519 13 23 10 3 4 369 17 12 31 284.853 91 0 1 3 1 0 0 70 169 25 3
520 28 23 10 3 4 225 26 9 28 284.853 91 0 1 1 0 0 2 69 169 24 4
521 13 26 10 3 4 369 17 12 31 284.853 91 0 1 3 1 0 0 70 169 25 8
522 3 28 10 4 4 179 51 18 38 284.853 91 0 1 0 1 0 0 89 170 31 3
523 9 1 10 4 4 228 14 16 58 284.853 91 0 1 2 0 0 1 65 172 22 1
524 15 23 10 4 4 291 31 12 40 284.853 91 0 1 1 1 0 1 73 171 25 1
525 13 10 10 5 4 369 17 12 31 284.853 91 0 1 3 1 0 0 70 169 25 8
526 28 13 10 5 4 225 26 9 28 284.853 91 0 1 1 0 0 2 69 169 24 1
527 13 10 10 6 4 369 17 12 31 284.853 91 0 1 3 1 0 0 70 169 25 8
528 28 10 10 6 4 225 26 9 28 284.853 91 0 1 1 0 0 2 69 169 24 3
529 6 23 10 2 4 189 29 13 33 284.853 91 0 1 2 0 0 2 69 167 25 8
530 25 6 10 2 4 235 16 8 32 284.853 91 0 3 0 0 0 0 75 178 25 8
531 33 10 10 2 4 248 25 14 47 284.853 91 0 1 2 0 0 1 86 165 32 8
532 28 0 10 2 4 225 26 9 28 284.853 91 1 1 1 0 0 2 69 169 24 0
533 28 13 10 3 4 225 26 9 28 284.853 91 0 1 1 0 0 2 69 169 24 3
534 3 21 11 3 4 179 51 18 38 268.519 93 0 1 0 1 0 0 89 170 31 1
535 34 28 11 4 4 118 10 10 37 268.519 93 0 1 0 0 0 0 83 172 28 3
536 18 2 11 4 4 330 16 4 28 268.519 93 0 2 0 0 0 0 84 182 25 24
537 3 28 11 6 4 179 51 18 38 268.519 93 0 1 0 1 0 0 89 170 31 1
538 34 9 11 3 4 118 10 10 37 268.519 93 0 1 0 0 0 0 83 172 28 8
539 11 24 11 4 4 289 36 13 33 268.519 93 0 1 2 1 0 1 90 172 30 8
540 25 1 11 6 4 235 16 8 32 268.519 93 0 3 0 0 0 0 75 178 25 8
541 28 23 11 6 4 225 26 9 28 268.519 93 0 1 1 0 0 2 69 169 24 4
542 10 22 11 3 4 361 52 3 28 268.519 93 0 1 1 1 0 4 80 172 27 8
543 15 28 11 4 4 291 31 12 40 268.519 93 0 1 1 1 0 1 73 171 25 2
544 34 13 11 5 4 118 10 10 37 268.519 93 0 1 0 0 0 0 83 172 28 2
545 28 14 11 5 4 225 26 9 28 268.519 93 0 1 1 0 0 2 69 169 24 3
546 3 28 11 2 4 179 51 18 38 268.519 93 0 1 0 1 0 0 89 170 31 1
547 34 23 11 2 4 118 10 10 37 268.519 93 0 1 0 0 0 0 83 172 28 8
548 34 8 11 3 4 118 10 10 37 268.519 93 0 1 0 0 0 0 83 172 28 8
549 28 23 11 3 4 225 26 9 28 268.519 93 0 1 1 0 0 2 69 169 24 2
550 15 0 11 3 4 291 31 12 40 268.519 93 1 1 1 1 0 1 73 171 25 0
551 11 0 11 4 4 289 36 13 33 268.519 93 1 1 2 1 0 1 90 172 30 0
552 33 14 11 5 4 248 25 14 47 268.519 93 0 1 2 0 0 1 86 165 32 4
553 5 0 11 5 4 235 20 13 43 268.519 93 1 1 1 1 0 0 106 167 38 0
554 28 23 11 6 4 225 26 9 28 268.519 93 0 1 1 0 0 2 69 169 24 2
555 13 26 11 6 4 369 17 12 31 268.519 93 0 1 3 1 0 0 70 169 25 8
556 10 28 11 2 4 361 52 3 28 268.519 93 0 1 1 1 0 4 80 172 27 2
557 3 13 12 3 4 179 51 18 38 280.549 98 0 1 0 1 0 0 89 170 31 32
558 15 28 12 4 4 291 31 12 40 280.549 98 0 1 1 1 0 1 73 171 25 1
559 28 23 12 4 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 3
560 22 13 12 6 4 179 26 9 30 280.549 98 0 3 0 0 0 0 56 171 19 1
561 28 23 12 6 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 3
562 28 23 12 4 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 3
563 10 14 12 5 4 361 52 3 28 280.549 98 0 1 1 1 0 4 80 172 27 4
564 17 18 12 6 4 179 22 17 40 280.549 98 0 2 2 0 1 0 63 170 22 2
565 5 26 12 6 4 235 20 13 43 280.549 98 0 1 1 1 0 0 106 167 38 8
566 12 18 12 2 4 233 51 1 31 280.549 98 0 2 1 1 0 8 68 178 21 8
567 22 13 12 3 4 179 26 9 30 280.549 98 0 3 0 0 0 0 56 171 19 16
568 28 23 12 3 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 2
569 28 23 12 5 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 3
570 28 23 12 2 4 225 26 9 28 280.549 98 0 1 1 0 0 2 69 169 24 2
571 14 18 12 3 2 155 12 14 34 280.549 98 0 1 2 1 0 0 95 196 25 80
572 22 12 1 2 2 179 26 9 30 313.532 96 0 3 0 0 0 0 56 171 19 24
573 22 12 1 5 2 179 26 9 30 313.532 96 0 3 0 0 0 0 56 171 19 16
574 17 25 1 5 2 179 22 17 40 313.532 96 0 2 2 0 1 0 63 170 22 2
575 17 25 1 6 2 179 22 17 40 313.532 96 0 2 2 0 1 0 63 170 22 2
576 22 13 1 2 2 179 26 9 30 313.532 96 0 3 0 0 0 0 56 171 19 3
577 17 25 1 4 2 179 22 17 40 313.532 96 0 2 2 0 1 0 63 170 22 2
578 32 10 1 5 2 289 48 29 49 313.532 96 0 1 0 0 0 2 108 172 36 8
579 17 18 1 6 2 179 22 17 40 313.532 96 0 2 2 0 1 0 63 170 22 3
580 22 27 1 2 2 179 26 9 30 313.532 96 0 3 0 0 0 0 56 171 19 2
581 14 18 1 3 2 155 12 14 34 313.532 96 0 1 2 1 0 0 95 196 25 8
582 22 27 1 4 2 179 26 9 30 313.532 96 0 3 0 0 0 0 56 171 19 2
583 3 27 1 4 2 179 51 18 38 313.532 96 0 1 0 1 0 0 89 170 31 3
584 11 13 1 4 2 289 36 13 33 313.532 96 0 1 2 1 0 1 90 172 30 8
585 3 27 1 5 2 179 51 18 38 313.532 96 0 1 0 1 0 0 89 170 31 3
586 3 27 1 6 2 179 51 18 38 313.532 96 0 1 0 1 0 0 89 170 31 2
587 3 13 2 3 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 8
588 28 23 2 3 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 3
589 33 1 2 4 2 248 25 14 47 264.249 97 0 1 2 0 0 1 86 165 32 8
590 3 27 2 4 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
591 28 28 2 5 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 3
592 3 27 2 5 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
593 22 27 2 5 2 179 26 9 30 264.249 97 0 3 0 0 0 0 56 171 19 2
594 29 28 2 6 2 225 15 15 41 264.249 97 0 4 2 1 0 2 94 182 28 2
595 3 27 2 6 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
596 12 19 2 2 2 233 51 1 31 264.249 97 0 2 1 1 0 8 68 178 21 2
597 3 27 2 2 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
598 28 7 2 3 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 8
599 3 27 2 4 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 3
600 3 27 2 5 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 3
601 28 25 2 5 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 3
602 22 13 2 5 2 179 26 9 30 264.249 97 0 3 0 0 0 0 56 171 19 2
603 17 23 2 6 2 179 22 17 40 264.249 97 0 2 2 0 1 0 63 170 22 2
604 3 27 2 6 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 3
605 12 12 2 4 2 233 51 1 31 264.249 97 0 2 1 1 0 8 68 178 21 3
606 22 27 2 4 2 179 26 9 30 264.249 97 0 3 0 0 0 0 56 171 19 2
607 3 27 2 4 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
608 3 13 2 5 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 8
609 3 27 2 6 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
610 14 25 2 2 2 155 12 14 34 264.249 97 0 1 2 1 0 0 95 196 25 5
611 25 25 2 2 2 235 16 8 32 264.249 97 0 3 0 0 0 0 75 178 25 3
612 3 27 2 2 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
613 28 7 2 2 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 2
614 3 27 2 3 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
615 33 23 2 3 2 248 25 14 47 264.249 97 0 1 2 0 0 1 86 165 32 2
616 28 25 2 3 2 225 26 9 28 264.249 97 0 1 1 0 0 2 69 169 24 2
617 3 27 2 4 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
618 3 27 2 5 2 179 51 18 38 264.249 97 0 1 0 1 0 0 89 170 31 2
619 25 25 2 6 2 235 16 8 32 264.249 97 0 3 0 0 0 0 75 178 25 2
620 3 27 3 2 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 2
621 33 23 3 2 2 248 25 14 47 222.196 99 0 1 2 0 0 1 86 165 32 2
622 9 25 3 3 2 228 14 16 58 222.196 99 0 1 2 0 0 1 65 172 22 3
623 33 25 3 3 2 248 25 14 47 222.196 99 0 1 2 0 0 1 86 165 32 3
624 9 12 3 3 2 228 14 16 58 222.196 99 0 1 2 0 0 1 65 172 22 112
625 3 27 3 4 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 2
626 28 27 3 5 2 225 26 9 28 222.196 99 0 1 1 0 0 2 69 169 24 2
627 3 27 3 5 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
628 28 25 3 5 2 225 26 9 28 222.196 99 0 1 1 0 0 2 69 169 24 2
629 22 27 3 6 2 179 26 9 30 222.196 99 0 3 0 0 0 0 56 171 19 3
630 25 25 3 2 2 235 16 8 32 222.196 99 0 3 0 0 0 0 75 178 25 3
631 10 19 3 2 2 361 52 3 28 222.196 99 0 1 1 1 0 4 80 172 27 8
632 3 13 3 3 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 8
633 3 27 3 4 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 2
634 3 27 3 5 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
635 22 27 3 6 2 179 26 9 30 222.196 99 0 3 0 0 0 0 56 171 19 2
636 3 10 3 2 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 4
637 33 13 3 2 2 248 25 14 47 222.196 99 0 1 2 0 0 1 86 165 32 2
638 3 27 3 2 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
639 28 7 3 2 2 225 26 9 28 222.196 99 0 1 1 0 0 2 69 169 24 8
640 3 27 3 3 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 2
641 11 23 3 4 2 289 36 13 33 222.196 99 0 1 2 1 0 1 90 172 30 8
642 9 25 3 4 2 228 14 16 58 222.196 99 0 1 2 0 0 1 65 172 22 2
643 3 27 3 4 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 2
644 33 23 3 5 2 248 25 14 47 222.196 99 0 1 2 0 0 1 86 165 32 3
645 3 27 3 5 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
646 22 23 3 6 2 179 26 9 30 222.196 99 0 3 0 0 0 0 56 171 19 2
647 3 27 3 6 2 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
648 3 27 3 3 3 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
649 16 23 3 4 3 118 15 24 46 222.196 99 0 1 2 1 1 0 75 175 25 8
650 14 13 3 4 3 155 12 14 34 222.196 99 0 1 2 1 0 0 95 196 25 24
651 3 27 3 4 3 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
652 3 27 3 5 3 179 51 18 38 222.196 99 0 1 0 1 0 0 89 170 31 3
653 22 13 3 2 3 179 26 9 30 222.196 99 0 3 0 0 0 0 56 171 19 2
654 11 19 3 2 3 289 36 13 33 222.196 99 0 1 2 1 0 1 90 172 30 104
655 13 22 3 4 3 369 17 12 31 222.196 99 0 1 3 1 0 0 70 169 25 8
656 28 13 4 2 3 225 26 9 28 246.288 91 0 1 1 0 0 2 69 169 24 8
657 34 10 4 2 3 118 10 10 37 246.288 91 0 1 0 0 0 0 83 172 28 8
658 10 19 4 3 3 361 52 3 28 246.288 91 0 1 1 1 0 4 80 172 27 8
659 33 19 4 4 3 248 25 14 47 246.288 91 0 1 2 0 0 1 86 165 32 8
660 6 13 4 5 3 189 29 13 33 246.288 91 0 1 2 0 0 2 69 167 25 8
661 22 27 4 6 3 179 26 9 30 246.288 91 0 3 0 0 0 0 56 171 19 2
662 13 7 4 2 3 369 17 12 31 246.288 91 0 1 3 1 0 0 70 169 25 24
663 17 16 4 3 3 179 22 17 40 246.288 91 0 2 2 0 1 0 63 170 22 2
664 36 23 4 3 3 118 13 18 50 246.288 91 0 1 1 1 0 0 98 178 31 3
665 10 23 4 3 3 361 52 3 28 246.288 91 0 1 1 1 0 4 80 172 27 2
666 34 10 4 4 3 118 10 10 37 246.288 91 0 1 0 0 0 0 83 172 28 2
667 1 22 4 6 3 235 11 14 37 246.288 91 0 3 1 0 0 1 88 172 29 8
668 22 27 4 6 3 179 26 9 30 246.288 91 0 3 0 0 0 0 56 171 19 2
669 28 19 4 2 3 225 26 9 28 246.288 91 0 1 1 0 0 2 69 169 24 8
670 25 16 4 3 3 235 16 8 32 246.288 91 0 3 0 0 0 0 75 178 25 3
671 22 27 4 6 3 179 26 9 30 246.288 91 0 3 0 0 0 0 56 171 19 2
672 14 28 4 3 3 155 12 14 34 246.288 91 0 1 2 1 0 0 95 196 25 4
673 28 19 4 5 3 225 26 9 28 246.288 91 0 1 1 0 0 2 69 169 24 8
674 36 14 4 5 3 118 13 18 50 246.288 91 0 1 1 1 0 0 98 178 31 2
675 22 27 4 6 3 179 26 9 30 246.288 91 0 3 0 0 0 0 56 171 19 2
676 1 22 5 2 3 235 11 14 37 237.656 99 0 3 1 0 0 1 88 172 29 8
677 29 19 5 4 3 225 15 15 41 237.656 99 0 4 2 1 0 2 94 182 28 3
678 25 28 5 4 3 235 16 8 32 237.656 99 0 3 0 0 0 0 75 178 25 2
679 34 8 5 4 3 118 10 10 37 237.656 99 0 1 0 0 0 0 83 172 28 3
680 5 26 5 4 3 235 20 13 43 237.656 99 0 1 1 1 0 0 106 167 38 8
681 22 13 5 5 3 179 26 9 30 237.656 99 0 3 0 0 0 0 56 171 19 1
682 15 28 5 5 3 291 31 12 40 237.656 99 0 1 1 1 0 1 73 171 25 2
683 29 14 5 5 3 225 15 15 41 237.656 99 0 4 2 1 0 2 94 182 28 8
684 26 19 5 6 3 300 26 13 43 237.656 99 0 1 2 1 1 1 77 175 25 64
685 29 22 5 6 3 225 15 15 41 237.656 99 0 4 2 1 0 2 94 182 28 8
686 22 27 5 6 3 179 26 9 30 237.656 99 0 3 0 0 0 0 56 171 19 2
687 36 23 5 2 3 118 13 18 50 237.656 99 0 1 1 1 0 0 98 178 31 2
688 36 5 5 3 3 118 13 18 50 237.656 99 0 1 1 1 0 0 98 178 31 3
689 34 28 5 3 3 118 10 10 37 237.656 99 0 1 0 0 0 0 83 172 28 1
690 36 0 5 3 3 118 13 18 50 237.656 99 1 1 1 1 0 0 98 178 31 0
691 22 27 5 4 3 179 26 9 30 237.656 99 0 3 0 0 0 0 56 171 19 2
692 23 0 5 4 3 378 49 11 36 237.656 99 1 1 2 0 1 4 65 174 21 0
693 17 16 5 6 3 179 22 17 40 237.656 99 0 2 2 0 1 0 63 170 22 1
694 14 10 5 2 3 155 12 14 34 237.656 99 0 1 2 1 0 0 95 196 25 48
695 25 10 5 2 3 235 16 8 32 237.656 99 0 3 0 0 0 0 75 178 25 8
696 15 22 5 4 3 291 31 12 40 237.656 99 0 1 1 1 0 1 73 171 25 8
697 17 10 5 4 3 179 22 17 40 237.656 99 0 2 2 0 1 0 63 170 22 8
698 28 6 5 4 3 225 26 9 28 237.656 99 0 1 1 0 0 2 69 169 24 3
699 18 10 5 5 3 330 16 4 28 237.656 99 0 2 0 0 0 0 84 182 25 8
700 25 23 5 5 3 235 16 8 32 237.656 99 0 3 0 0 0 0 75 178 25 2
701 15 28 5 5 3 291 31 12 40 237.656 99 0 1 1 1 0 1 73 171 25 2
702 22 27 5 6 3 179 26 9 30 237.656 99 0 3 0 0 0 0 56 171 19 2
703 10 7 5 2 3 361 52 3 28 237.656 99 0 1 1 1 0 4 80 172 27 8
704 14 23 5 4 3 155 12 14 34 237.656 99 0 1 2 1 0 0 95 196 25 2
705 17 25 5 6 3 179 22 17 40 237.656 99 0 2 2 0 1 0 63 170 22 8
706 14 10 5 6 3 155 12 14 34 237.656 99 0 1 2 1 0 0 95 196 25 8
707 28 11 5 2 3 225 26 9 28 237.656 99 0 1 1 0 0 2 69 169 24 1
708 16 7 6 4 3 118 15 24 46 275.089 96 0 1 2 1 1 0 75 175 25 8
709 22 27 6 4 3 179 26 9 30 275.089 96 0 3 0 0 0 0 56 171 19 3
710 34 26 6 6 3 118 10 10 37 275.089 96 0 1 0 0 0 0 83 172 28 8
711 34 10 6 4 3 118 10 10 37 275.089 96 0 1 0 0 0 0 83 172 28 8
712 23 22 6 5 3 378 49 11 36 275.089 96 0 1 2 0 1 4 65 174 21 8
713 36 19 6 5 3 118 13 18 50 275.089 96 0 1 1 1 0 0 98 178 31 24
714 12 19 6 6 3 233 51 1 31 275.089 96 0 2 1 1 0 8 68 178 21 8
715 22 27 6 6 3 179 26 9 30 275.089 96 0 3 0 0 0 0 56 171 19 2
716 2 0 6 2 3 235 29 12 48 275.089 96 1 1 1 0 1 5 88 163 33 0
717 21 0 6 2 3 268 11 8 33 275.089 96 1 2 0 0 0 0 79 178 25 0
718 36 19 6 5 3 118 13 18 50 275.089 96 0 1 1 1 0 0 98 178 31 3
719 22 13 6 5 3 179 26 9 30 275.089 96 0 3 0 0 0 0 56 171 19 2
720 15 28 6 5 3 291 31 12 40 275.089 96 0 1 1 1 0 1 73 171 25 2
721 22 13 6 2 1 179 26 9 30 275.089 96 0 3 0 0 0 0 56 171 19 3
722 34 25 6 2 1 118 10 10 37 275.089 96 0 1 0 0 0 0 83 172 28 3
723 12 22 6 5 1 233 51 1 31 275.089 96 0 2 1 1 0 8 68 178 21 8
724 34 8 6 6 1 118 10 10 37 275.089 96 0 1 0 0 0 0 83 172 28 2
725 34 10 6 4 1 118 10 10 37 275.089 96 0 1 0 0 0 0 83 172 28 3
726 12 22 6 4 1 233 51 1 31 275.089 96 0 2 1 1 0 8 68 178 21 3
727 5 26 7 4 1 235 20 13 43 264.604 93 0 1 1 1 0 0 106 167 38 4
728 12 19 7 6 1 233 51 1 31 264.604 93 0 2 1 1 0 8 68 178 21 2
729 9 6 7 2 1 228 14 16 58 264.604 93 0 1 2 0 0 1 65 172 22 8
730 34 28 7 2 1 118 10 10 37 264.604 93 0 1 0 0 0 0 83 172 28 4
731 9 6 7 3 1 228 14 16 58 264.604 93 0 1 2 0 0 1 65 172 22 120
732 6 22 7 3 1 189 29 13 33 264.604 93 0 1 2 0 0 2 69 167 25 16
733 34 23 7 4 1 118 10 10 37 264.604 93 0 1 0 0 0 0 83 172 28 2
734 10 22 7 4 1 361 52 3 28 264.604 93 0 1 1 1 0 4 80 172 27 8
735 28 22 7 4 1 225 26 9 28 264.604 93 0 1 1 0 0 2 69 169 24 8
736 13 13 7 2 1 369 17 12 31 264.604 93 0 1 3 1 0 0 70 169 25 80
737 11 14 7 3 1 289 36 13 33 264.604 93 0 1 2 1 0 1 90 172 30 8
738 1 11 7 3 1 235 11 14 37 264.604 93 0 3 1 0 0 1 88 172 29 4
739 4 0 0 3 1 118 14 13 40 271.219 95 0 1 1 1 0 8 98 170 34 0
740 8 0 0 4 2 231 35 14 39 271.219 95 0 1 2 1 0 2 100 170 35 0
741 35 0 0 6 3 179 45 14 53 271.219 95 0 1 1 0 0 1 77 175 25 0

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ numpy==1.24.3
scikit-learn==1.3.0 scikit-learn==1.3.0
xgboost==1.7.6 xgboost==1.7.6
lightgbm==4.1.0 lightgbm==4.1.0
torch==2.6.0
joblib==1.3.1 joblib==1.3.1
# Utilities # Utilities

View File

@@ -4,6 +4,7 @@ import joblib
import numpy as np import numpy as np
import config import config
from core.deep_learning_model import load_lstm_mlp_bundle, predict_lstm_mlp
from core.model_features import ( from core.model_features import (
align_feature_frame, align_feature_frame,
apply_label_encoders, apply_label_encoders,
@@ -20,6 +21,11 @@ MODEL_INFO = {
'gradient_boosting': {'name': 'gradient_boosting', 'name_cn': 'GBDT', 'description': '梯度提升决策树'}, 'gradient_boosting': {'name': 'gradient_boosting', 'name_cn': 'GBDT', 'description': '梯度提升决策树'},
'extra_trees': {'name': 'extra_trees', 'name_cn': '极端随机树', 'description': '高随机性的树模型'}, 'extra_trees': {'name': 'extra_trees', 'name_cn': '极端随机树', 'description': '高随机性的树模型'},
'stacking': {'name': 'stacking', 'name_cn': 'Stacking集成', 'description': '多模型融合'}, 'stacking': {'name': 'stacking', 'name_cn': 'Stacking集成', 'description': '多模型融合'},
'lstm_mlp': {
'name': 'lstm_mlp',
'name_cn': '时序注意力融合网络',
'description': 'Transformer时序编码 + 静态特征门控融合的深度学习模型',
},
} }
@@ -50,6 +56,7 @@ class PredictService:
'gradient_boosting': 'gradient_boosting_model.pkl', 'gradient_boosting': 'gradient_boosting_model.pkl',
'extra_trees': 'extra_trees_model.pkl', 'extra_trees': 'extra_trees_model.pkl',
'stacking': 'stacking_model.pkl', 'stacking': 'stacking_model.pkl',
'lstm_mlp': 'lstm_mlp_model.pt',
} }
allowed_models = self.training_metadata.get('available_models') allowed_models = self.training_metadata.get('available_models')
if allowed_models: if allowed_models:
@@ -59,6 +66,11 @@ class PredictService:
path = os.path.join(config.MODELS_DIR, filename) path = os.path.join(config.MODELS_DIR, filename)
if os.path.exists(path): if os.path.exists(path):
try: try:
if name == 'lstm_mlp':
bundle = load_lstm_mlp_bundle(path)
if bundle is not None:
self.models[name] = bundle
else:
self.models[name] = joblib.load(path) self.models[name] = joblib.load(path)
except Exception as exc: except Exception as exc:
print(f'Failed to load model {name}: {exc}') print(f'Failed to load model {name}: {exc}')
@@ -107,6 +119,10 @@ class PredictService:
features = self._prepare_features(data) features = self._prepare_features(data)
try: try:
if model_type == 'lstm_mlp':
current_df = build_prediction_dataframe(data)
predicted_hours = predict_lstm_mlp(self.models[model_type], current_df)
else:
predicted_hours = self.models[model_type].predict([features])[0] predicted_hours = self.models[model_type].predict([features])[0]
predicted_hours = self._inverse_transform_prediction(predicted_hours) predicted_hours = self._inverse_transform_prediction(predicted_hours)
predicted_hours = max(0.5, float(predicted_hours)) predicted_hours = max(0.5, float(predicted_hours))
@@ -196,6 +212,8 @@ class PredictService:
'test_samples': self.training_metadata.get('test_samples', 0), 'test_samples': self.training_metadata.get('test_samples', 0),
'feature_count': self.training_metadata.get('feature_count_after_selection', 0), 'feature_count': self.training_metadata.get('feature_count_after_selection', 0),
'training_date': self.training_metadata.get('training_date', ''), 'training_date': self.training_metadata.get('training_date', ''),
'sequence_window_size': self.training_metadata.get('sequence_window_size', 0),
'deep_learning_available': self.training_metadata.get('deep_learning_available', False),
}, },
} }

View File

@@ -5,7 +5,7 @@
系统采用前后端分离架构: 系统采用前后端分离架构:
- 前端Vue 3 + Vue Router + Element Plus + ECharts - 前端Vue 3 + Vue Router + Element Plus + ECharts
- 后端Flask + Pandas + Scikit-learn + Joblib - 后端Flask + Pandas + Scikit-learn + PyTorch + Joblib
- 数据层CSV 数据文件 + 模型文件 - 数据层CSV 数据文件 + 模型文件
整体架构分为四层: 整体架构分为四层:
@@ -53,6 +53,7 @@
- `preprocessing.py`:数据清洗与预处理 - `preprocessing.py`:数据清洗与预处理
- `model_features.py`:特征构建与预测输入映射 - `model_features.py`:特征构建与预测输入映射
- `train_model.py`:模型训练与评估 - `train_model.py`:模型训练与评估
- `deep_learning_model.py`LSTM+MLP 深度学习训练与推理
- `feature_mining.py`:相关性分析与群体对比 - `feature_mining.py`:相关性分析与群体对比
- `clustering.py`K-Means 聚类分析 - `clustering.py`K-Means 聚类分析
@@ -67,6 +68,12 @@
5. 训练多种模型并评估性能 5. 训练多种模型并评估性能
6. 保存模型、特征信息和训练元数据 6. 保存模型、特征信息和训练元数据
其中深度学习路径采用:
- `LSTM` 处理员工最近多次缺勤事件构成的时间窗口序列
- `MLP` 处理员工静态属性特征
- 融合层输出缺勤时长回归结果
### 4.2 预测流程 ### 4.2 预测流程
1. 前端输入核心预测字段 1. 前端输入核心预测字段
@@ -121,6 +128,12 @@ frontend/
- 适合传统机器学习建模 - 适合传统机器学习建模
- 提供随机森林、GBDT、Extra Trees 等成熟算法 - 提供随机森林、GBDT、Extra Trees 等成熟算法
### 6.4 PyTorch
- 用于实现 LSTM+MLP 深度学习模型
- 支持将时序特征与静态特征进行融合建模
- 便于在论文中增加深度学习对比实验内容
## 7. 部署方式 ## 7. 部署方式
- 本地前端开发服务器Vite - 本地前端开发服务器Vite
@@ -133,3 +146,4 @@ frontend/
- 前后端职责明确 - 前后端职责明确
- 支持快速展示图表与预测效果 - 支持快速展示图表与预测效果
- 支持后续扩展为数据库或更复杂模型架构 - 支持后续扩展为数据库或更复杂模型架构
- 同时支持传统机器学习模型与深度学习模型的实验对比

View File

@@ -136,13 +136,18 @@
- URL`/api/predict/models` - URL`/api/predict/models`
- 方法:`GET` - 方法:`GET`
- 说明:返回可用模型及其性能指标 - 说明:返回可用模型及其性能指标,包含传统模型与 `LSTM+MLP` 深度学习模型
### 4.4 获取模型信息 ### 4.4 获取模型信息
- URL`/api/predict/model-info` - URL`/api/predict/model-info`
- 方法:`GET` - 方法:`GET`
- 说明:返回训练样本量、特征数量训练日期 - 说明:返回训练样本量、特征数量训练日期以及深度学习窗口信息
新增返回字段示例:
- `sequence_window_size`
- `deep_learning_available`
## 5. 员工画像接口 ## 5. 员工画像接口

View File

@@ -74,6 +74,10 @@
- 星期几 - 星期几
- 是否节假日前后 - 是否节假日前后
- 季节 - 季节
- 事件日期
- 事件日期索引
- 事件序号
- 员工历史事件数
- 请假申请渠道 - 请假申请渠道
- 请假类型 - 请假类型
- 请假原因大类 - 请假原因大类
@@ -129,6 +133,23 @@
- 慢性病史和健康异常会提升缺勤时长 - 慢性病史和健康异常会提升缺勤时长
- 年假和调休通常对应较短缺勤时长 - 年假和调休通常对应较短缺勤时长
### 6.3 时序样本构造
为支持 LSTM+MLP 深度学习模型,数据集在事件层面额外补充了时序字段:
- `事件日期`:缺勤事件发生日期
- `事件日期索引`:便于排序和窗口切片的数值型时间索引
- `事件序号`:同一员工内部的事件顺序
- `员工历史事件数`:该员工在数据集中对应的事件总数
深度学习样本构造规则如下:
- 以员工为单位按 `事件日期索引``事件序号` 排序
- 取最近 `5` 次缺勤事件作为时间窗口输入
- 序列不足时使用前向零填充
- 当前事件作为窗口最后一个时间步
- 静态特征单独输入 MLP 分支,与 LSTM 输出融合后进行回归预测
## 7. 数据质量要求 ## 7. 数据质量要求
- 无大量缺失值 - 无大量缺失值

View File

@@ -4,7 +4,7 @@
随着企业管理数字化水平的提升,员工缺勤行为分析逐渐成为人力资源管理中的重要研究内容。针对传统缺勤管理方式依赖人工统计、分析效率较低、风险预警能力不足等问题,本文设计并实现了一套基于中国企业员工缺勤事件分析与预测系统。系统围绕缺勤事件数据,构建了数据概览、影响因素分析、缺勤风险预测和员工群体画像四个核心模块,实现了缺勤时长统计分析、关键因素挖掘、多模型预测与聚类画像展示等功能。 随着企业管理数字化水平的提升,员工缺勤行为分析逐渐成为人力资源管理中的重要研究内容。针对传统缺勤管理方式依赖人工统计、分析效率较低、风险预警能力不足等问题,本文设计并实现了一套基于中国企业员工缺勤事件分析与预测系统。系统围绕缺勤事件数据,构建了数据概览、影响因素分析、缺勤风险预测和员工群体画像四个核心模块,实现了缺勤时长统计分析、关键因素挖掘、多模型预测与聚类画像展示等功能。
在系统实现过程中,后端采用 Flask 框架构建接口服务,结合 PandasScikit-learn 完成数据处理、特征工程、模型训练与预测;前端采用 Vue 3、Element Plus 与 ECharts 实现交互式可视化界面。针对毕业设计场景,系统构建了一套符合中国企业特征的员工缺勤事件数据集,并设计了请假类型、医院证明、加班通勤压力、健康风险等关键影响因素。实验结果表明,系统能够较好地完成缺勤时长预测任务,并通过可视化方式直观展现缺勤趋势、影响因素和员工群体特征。 在系统实现过程中,后端采用 Flask 框架构建接口服务,结合 PandasScikit-learn 与 PyTorch 完成数据处理、特征工程、模型训练与预测;前端采用 Vue 3、Element Plus 与 ECharts 实现交互式可视化界面。针对毕业设计场景,系统构建了一套符合中国企业特征的员工缺勤事件数据集,并设计了请假类型、医院证明、加班通勤压力、健康风险等关键影响因素。同时,为增强论文的算法研究内容,系统引入了 LSTM+MLP 深度学习模型,将员工历史缺勤事件序列与静态属性特征进行融合建模。实验结果表明,系统能够较好地完成缺勤时长预测任务,并通过可视化方式直观展现缺勤趋势、影响因素和员工群体特征。
本文的研究工作对企业缺勤行为分析与管理辅助决策具有一定参考价值,同时也为后续扩展员工行为分析、离职预警和绩效管理等方向提供了基础。 本文的研究工作对企业缺勤行为分析与管理辅助决策具有一定参考价值,同时也为后续扩展员工行为分析、离职预警和绩效管理等方向提供了基础。
@@ -14,6 +14,7 @@
- 风险预测 - 风险预测
- 特征挖掘 - 特征挖掘
- 机器学习 - 机器学习
- 深度学习
- 可视化系统 - 可视化系统
- Vue - Vue
- Flask - Flask

View File

@@ -19,7 +19,8 @@
- 2.2 Vue 3 前端框架 - 2.2 Vue 3 前端框架
- 2.3 ECharts 可视化技术 - 2.3 ECharts 可视化技术
- 2.4 机器学习相关算法 - 2.4 机器学习相关算法
- 2.5 K-Means 聚类方 - 2.5 深度学习相关算
- 2.6 K-Means 聚类方法
### 第3章 系统需求分析 ### 第3章 系统需求分析
@@ -41,15 +42,16 @@
- 5.1 数据概览模块实现 - 5.1 数据概览模块实现
- 5.2 影响因素分析模块实现 - 5.2 影响因素分析模块实现
- 5.3 缺勤预测模块实现 - 5.3 缺勤预测模块实现
- 5.4 员工画像模块实现 - 5.4 LSTM+MLP 深度学习模型实现
- 5.5 前端界面实现 - 5.5 员工画像模块实现
- 5.6 前端界面实现
### 第6章 系统测试与结果分析 ### 第6章 系统测试与结果分析
- 6.1 测试环境 - 6.1 测试环境
- 6.2 功能测试 - 6.2 功能测试
- 6.3 接口测试 - 6.3 接口测试
- 6.4 模型效果分析 - 6.4 传统模型与深度学习模型对比
- 6.5 系统展示效果分析 - 6.5 系统展示效果分析
### 第7章 总结与展望 ### 第7章 总结与展望

View File

@@ -27,6 +27,8 @@
- Vue 3 的组件化优势 - Vue 3 的组件化优势
- Element Plus 和 ECharts 的可视化能力 - Element Plus 和 ECharts 的可视化能力
- 随机森林、GBDT、Extra Trees 的基本原理 - 随机森林、GBDT、Extra Trees 的基本原理
- LSTM 与 MLP 的基本原理
- 时序序列建模与多输入融合思想
- K-Means 聚类思想 - K-Means 聚类思想
## 第3章 系统需求分析 ## 第3章 系统需求分析
@@ -71,6 +73,7 @@
- 数据生成与预处理实现 - 数据生成与预处理实现
- 特征工程实现 - 特征工程实现
- 模型训练与保存实现 - 模型训练与保存实现
- LSTM+MLP 深度学习训练流程
- 后端接口实现 - 后端接口实现
- 前端页面实现 - 前端页面实现
- 预测页卡片布局与交互实现 - 预测页卡片布局与交互实现
@@ -89,6 +92,7 @@
- 预测功能测试 - 预测功能测试
- 聚类与分析结果测试 - 聚类与分析结果测试
- 模型性能指标分析 - 模型性能指标分析
- 传统模型与深度学习模型对比分析
## 第7章 总结与展望 ## 第7章 总结与展望

View File

@@ -45,6 +45,7 @@
- 前后端分离结构清晰 - 前后端分离结构清晰
- 采用多模型训练与比较 - 采用多模型训练与比较
- 引入 LSTM+MLP 深度学习模型,支持时序行为建模
- 融合特征工程与聚类分析 - 融合特征工程与聚类分析
- 前端页面采用卡片式可视化布局,适合展示 - 前端页面采用卡片式可视化布局,适合展示

View File

@@ -0,0 +1,193 @@
# 环境配置与安装说明
## 1. 推荐环境
为保证传统机器学习模型和 `LSTM+MLP` 深度学习模型均可正常训练,推荐使用 **conda 虚拟环境** 管理本项目依赖。
推荐环境:
- 操作系统Windows 10 / Windows 11
- Python3.11
- CondaAnaconda 或 Miniconda
- Node.js16+
- pnpm8+
- CUDA建议与 PyTorch GPU 轮子版本匹配
## 2. 创建 conda 虚拟环境
```powershell
conda create -n forsetenv python=3.11 -y
conda activate forsetenv
```
说明:
- 后续所有 Python 依赖安装、数据生成、模型训练和后端启动,均建议在 `forsetenv` 环境中进行。
## 3. 推荐安装顺序
推荐严格按下面顺序执行:
1. 创建并激活 `conda` 虚拟环境
2. 单独安装 `PyTorch GPU`
3. 安装其余后端依赖
4. 安装前端依赖
说明:
- `backend/requirements.txt` 中包含 `torch==2.6.0`
- 如果在 Windows 下先直接执行 `pip install -r backend/requirements.txt`,可能安装成非预期构建
- 因此深度学习环境建议先执行官方 `cu124` 安装命令,再补齐其余依赖
## 4. 安装 PyTorch GPU 版
本项目的 hybrid 深度学习模型要求:
- `torch >= 2.6`
推荐安装方式:
- 使用 **pip 官方 cu124 轮子**
- 避免在 Windows 上由 conda 自动解析成 `cpu_mkl` 构建
安装命令如下:
```powershell
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124
```
## 5. 安装其余后端依赖
如果你已经按上一步安装了 GPU 版 `torch`,推荐补装其余后端依赖:
```powershell
pip install Flask==2.3.3 Flask-CORS==4.0.0 python-dotenv==1.0.0
pip install pandas==2.0.3 numpy==1.24.3 scikit-learn==1.3.0 joblib==1.3.1
pip install xgboost==1.7.6 lightgbm==4.1.0
```
如果你仍然希望直接使用依赖文件,可以在完成 GPU 版 `torch` 安装后执行:
```powershell
pip install -r backend/requirements.txt
```
这一步通常不会影响已经安装好的 `cu124` 版本;如有覆盖风险,可在执行后再次运行上一节的 GPU 安装命令。
## 6. 安装前端依赖
```powershell
cd frontend
pnpm install
```
## 7. 一键执行示例
下面是一套推荐的 `conda` 环境安装流程:
```powershell
conda create -n forsetenv python=3.11 -y
conda activate forsetenv
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124
pip install Flask==2.3.3 Flask-CORS==4.0.0 python-dotenv==1.0.0
pip install pandas==2.0.3 numpy==1.24.3 scikit-learn==1.3.0 joblib==1.3.1
pip install xgboost==1.7.6 lightgbm==4.1.0
cd frontend
pnpm install
```
## 8. 验证安装
### 8.1 验证基础依赖
```powershell
python -c "import pandas,numpy,sklearn,flask;print('base ok')"
```
### 8.2 验证传统模型依赖
```powershell
python -c "import xgboost,lightgbm;print('ml ok')"
```
### 8.3 验证 PyTorch GPU
```powershell
python -c "import torch;print(torch.__version__);print(torch.cuda.is_available())"
```
如果输出为 `True`,说明 GPU 版本 PyTorch 可正常使用。
## 9. 项目启动顺序
### 9.1 生成数据集
```powershell
cd backend
python core/generate_dataset.py
```
### 9.2 训练模型
```powershell
python core/train_model.py
```
### 9.3 启动后端
```powershell
python app.py
```
### 9.4 启动前端
```powershell
cd ..\frontend
pnpm dev
```
## 10. 常见问题
### 10.1 PyTorch 被安装成 CPU 版
原因:
- 使用了默认 `pip install torch`
- 或使用 conda 在 Windows 上自动解析成 CPU 构建
建议:
- 直接使用本文提供的官方 `cu124` 安装命令
### 10.2 训练过程中无法加载深度学习模型
检查项:
- 当前是否处于 `forsetenv` conda 环境
- `torch` 是否成功安装
- `torch.cuda.is_available()` 是否为 `True`
### 10.3 xgboost / lightgbm 缺失
可执行:
```powershell
pip install xgboost==1.7.6 lightgbm==4.1.0
```
### 10.4 如何确认当前使用的是 conda 环境
可执行:
```powershell
conda info --envs
where python
```
如果当前环境为 `forsetenv`,且 `python` 指向对应环境目录,说明切换成功。
## 11. 建议
- 毕设演示或论文实验时,统一使用 `conda activate forsetenv`
- 深度学习模型训练时优先使用 GPU 环境
- 若仅进行页面展示,可先训练传统模型,再补充深度学习实验结果

View File

@@ -0,0 +1,23 @@
# 题目名称、主要技术路线或方法、预期结果
## 1. 题目名称
基于中国企业员工缺勤事件的分析与预测系统设计与实现
## 2. 论文(设计)采取的主要技术路线或方法
本课题围绕企业员工缺勤管理场景,采用前后端分离的系统设计思路开展研究与实现。前端基于 `Vue 3``Element Plus``ECharts` 构建可视化展示界面,实现缺勤趋势、影响因素、预测结果和员工画像等内容的交互式展示;后端基于 `Flask` 搭建接口服务,负责数据处理、分析计算、模型推理和聚类结果组织。
在数据处理方面,首先结合项目内部构建的中国企业员工缺勤事件数据集,使用 `Pandas``NumPy` 完成数据清洗、字段转换、统计分析与特征整理。随后围绕员工属性、岗位信息、班次安排、健康风险、请假原因、通勤压力和加班情况等因素进行特征工程,形成适用于分析与预测的结构化数据。
在算法研究方面,课题采用传统机器学习与深度学习相结合的技术路线。传统模型依托 `scikit-learn``XGBoost``LightGBM` 完成缺勤时长预测与模型对比分析,并通过特征重要性排序和相关性分析挖掘关键影响因素;深度学习部分基于 `PyTorch` 构建 `LSTM+MLP` 融合模型,将员工历史缺勤事件序列与静态属性特征结合,用于提升预测研究的完整性和论文的技术深度。
在员工画像分析方面,课题采用 `K-Means` 聚类方法对员工缺勤行为进行分群,结合散点图、雷达图和群体说明完成群体画像展示,从而辅助企业识别不同类型的缺勤风险群体。最终通过系统集成与前后端联调,实现缺勤数据概览、影响因素分析、单次缺勤预测和员工画像分析四个核心功能模块。
## 3. 论文(设计)预期结果
本课题预期完成一个可运行、可展示、可支撑论文撰写的员工缺勤分析与预测系统。系统能够实现缺勤事件统计展示、趋势分析、原因分布分析、关键因素挖掘、缺勤时长预测、风险等级评估和员工群体画像展示等功能,满足本科毕业设计对系统实现和功能展示的要求。
在研究结果方面,预期能够形成一套较完整的员工缺勤分析方法流程,包括数据预处理、特征工程、相关性分析、特征重要性评估、预测建模和聚类画像分析。系统应能够根据输入的关键业务字段输出缺勤时长预测结果、风险等级和多模型对比结果,并通过可视化图表直观展示分析结论,为企业人力资源管理提供辅助决策依据。
在论文成果方面,预期形成与项目实现一致的毕业设计文档与论文材料,包括需求分析、系统架构设计、接口设计、数据设计、系统实现、实验分析和总结展望等内容,并能够支撑后续开题、中期检查、论文提交和答辩展示工作。

View File

@@ -16,9 +16,16 @@
- [06_毕业论文目录与章节设计.md](D:/VScodeProject/forsetsystem/docs/06_毕业论文目录与章节设计.md) - [06_毕业论文目录与章节设计.md](D:/VScodeProject/forsetsystem/docs/06_毕业论文目录与章节设计.md)
- [07_毕业论文写作提纲.md](D:/VScodeProject/forsetsystem/docs/07_毕业论文写作提纲.md) - [07_毕业论文写作提纲.md](D:/VScodeProject/forsetsystem/docs/07_毕业论文写作提纲.md)
- [08_答辩汇报提纲.md](D:/VScodeProject/forsetsystem/docs/08_答辩汇报提纲.md) - [08_答辩汇报提纲.md](D:/VScodeProject/forsetsystem/docs/08_答辩汇报提纲.md)
- [10_题目名称_技术路线_预期结果.md](D:/VScodeProject/forsetsystem/docs/10_题目名称_技术路线_预期结果.md)
## 环境配置文档
- [09_环境配置与安装说明.md](D:/VScodeProject/forsetsystem/docs/09_环境配置与安装说明.md)
## 说明 ## 说明
- 系统文档以当前项目实现为准,围绕中国企业员工缺勤分析、风险预测与群体画像展开。 - 系统文档以当前项目实现为准,围绕中国企业员工缺勤分析、风险预测与群体画像展开。
- 论文文档采用本科毕业设计常用结构,便于后续继续扩写为正式论文。 - 论文文档采用本科毕业设计常用结构,便于后续继续扩写为正式论文。
- 若后续系统功能或字段发生变化,应同步更新本目录下相关文档。 - 若后续系统功能或字段发生变化,应同步更新本目录下相关文档。
- 深度学习部分推荐使用 `conda` 虚拟环境配合 `pip` 安装 PyTorch GPU 版。
- 推荐安装顺序为:创建 `conda` 环境、安装官方 `cu124` 的 PyTorch、再补充其余后端依赖。