Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions ml-backends/temperature_annotation/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 温度标注ML Backend的Docker配置
# 基于Python 3.9构建

FROM python:3.9-slim

WORKDIR /app

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PORT=9090 \
WORKERS=1 \
THREADS=8

# 安装系统依赖
RUN apt-get update && apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/*

# 复制依赖文件
COPY requirements.txt .
COPY requirements-base.txt .

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 9090

# 启动命令
CMD ["python", "_wsgi.py", "--host", "0.0.0.0", "--port", "9090"]
197 changes: 197 additions & 0 deletions ml-backends/temperature_annotation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Temperature Annotation ML Backend

这是一个专门用于托卡马克等离子体温度数据标注的ML Backend,支持温度特征识别、异常检测和智能标注。

## 功能特性

- **温度特征识别**: 自动检测温度上升、下降、峰值等关键阶段
- **异常事件检测**: 识别温度突变、骤降等异常情况
- **多通道支持**: 支持多个温度测量通道的并行分析
- **自适应阈值**: 基于人工标注自动优化检测阈值
- **实时预测**: 基于Label Studio ML Backend架构的实时预测服务

## 核心算法

### 温度阶段检测
- **上升阶段**: 检测温度超过阈值的持续上升区间
- **峰值时刻**: 基于梯度变化检测温度峰值点
- **下降阶段**: 识别温度低于阈值的下降区间
- **平台期**: 检测温度相对稳定的平台阶段

### 异常检测
- **温度突变**: 基于滑动窗口统计检测异常温度变化
- **温度骤降**: 识别温度快速下降的异常事件

### 阈值优化
- 支持基于人工标注的自适应阈值调整
- 动态学习不同实验条件下的最佳参数

## 快速开始

### 使用Docker运行 (推荐)

1. 启动ML Backend服务:

```bash
docker-compose up
```

2. 验证服务运行状态:

```bash
curl http://localhost:9090/health
# 返回: {"status":"healthy","model_version":"temperature_v1.0",...}
```

3. 在Label Studio中连接后端:
进入项目设置 -> Machine Learning -> Add Model,指定URL为 `http://localhost:9090`

### 从源码构建

```bash
docker-compose build
```

### 不使用Docker运行

```bash
python -m venv temperature-ml-backend
source temperature-ml-backend/bin/activate # Windows: temperature-ml-backend\Scripts\activate
pip install -r requirements.txt
python _wsgi.py
```

## 配置参数

在 `config.json` 中可以设置以下参数:

### 温度阈值设置
- `temp_rise_threshold`: 温度上升阈值 (默认1000.0 eV)
- `temp_fall_threshold`: 温度下降阈值 (默认500.0 eV)
- `gradient_threshold`: 梯度阈值 (默认100.0 eV/ms)
- `anomaly_threshold`: 异常检测阈值 (默认3.0)
- `min_peak_height`: 最小峰值高度 (默认800.0 eV)

### 数据处理设置
- `remove_outliers`: 是否移除异常值
- `outlier_threshold`: 异常值检测阈值
- `interpolate_missing`: 是否插值缺失值
- `normalize_data`: 是否标准化数据

### 预测设置
- `detect_rise_phases`: 是否检测上升阶段
- `detect_peak_moments`: 是否检测峰值时刻
- `detect_fall_phases`: 是否检测下降阶段
- `detect_anomalies`: 是否检测异常事件
- `detect_plateau_phases`: 是否检测平台期

## Label Studio配置

在Label Studio中使用以下XML配置来支持温度标注:

```xml
<View>
<TimeSeries name="ts" value="$ts">
<TimeSeriesLabels name="temperature_events" toName="ts">
<Label value="Te_1_上升阶段" background="#FF6B6B"/>
<Label value="Te_1_峰值时刻" background="#4ECDC4"/>
<Label value="Te_1_下降阶段" background="#45B7D1"/>
<Label value="Te_1_异常事件" background="#96CEB4"/>
<Label value="Te_1_平台期" background="#FFEAA7"/>
</TimeSeriesLabels>
</TimeSeries>
</View>
```

## 数据格式要求

### 输入数据格式
- CSV文件,包含时间列和温度通道列
- 时间列名必须为 `time`
- 温度通道列名应包含 `Te`、`temp`、`Ti` 等关键词
- 支持多通道温度数据

### 示例数据
```csv
time,Te_1,Te_2,Te_3
0.0,100,150,200
0.001,120,170,220
0.002,140,190,240
...
```

## 部署到Kubernetes

```bash
kubectl apply -f temperature-annotation.yaml
```

## 自定义模型

可以通过修改 `temperature_predictor.py` 中的算法来自定义温度处理逻辑:

- 调整阈值检测算法
- 添加新的温度特征识别方法
- 自定义异常检测规则
- 优化梯度计算方法

## 测试

运行测试确保功能正常:

```bash
pytest test_temperature_backend.py -v
```

## API接口

### 健康检查
```
GET /health
```

### 模型信息
```
GET /model/info
```

### 预测接口
```
POST /predict
```

### 训练接口
```
POST /fit
```

## 故障排除

### 常见问题

1. **模型加载失败**: 检查依赖包安装和配置文件
2. **预测结果为空**: 确认输入数据格式和温度通道识别
3. **阈值设置不当**: 根据实际数据调整阈值参数
4. **内存不足**: 调整Docker容器的内存限制

### 日志查看

```bash
# Docker日志
docker logs temperature-annotation-ml-backend

# 查看模型日志
docker exec -it temperature-annotation-ml-backend tail -f /app/logs/model.log
```

## 性能优化

### 数据处理优化
- 使用并发加载多个炮号数据
- 支持数据预处理和缓存
- 优化异常值检测算法

### 预测性能优化
- 批量处理多个温度通道
- 并行计算不同特征检测
- 支持增量学习和模型更新
132 changes: 132 additions & 0 deletions ml-backends/temperature_annotation/_wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
"""
温度标注ML Backend的WSGI应用入口

基于Label Studio ML Backend的标准模式实现
"""

import os
import argparse
import json
import logging
import logging.config

# 设置默认日志级别
log_level = os.getenv("LOG_LEVEL", "INFO")

logging.config.dictConfig({
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "[%(asctime)s] [%(levelname)s] [%(name)s::%(funcName)s::%(lineno)d] %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": log_level,
"stream": "ext://sys.stdout",
"formatter": "standard"
}
},
"root": {
"level": log_level,
"handlers": ["console"],
"propagate": True
}
})

from label_studio_ml.api import init_app
from model import TemperatureModel

_DEFAULT_CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.json')


def get_kwargs_from_config(config_path=_DEFAULT_CONFIG_PATH):
"""从配置文件获取初始化参数"""
if not os.path.exists(config_path):
return dict()
with open(config_path) as f:
config = json.load(f)
assert isinstance(config, dict)
return config


if __name__ == "__main__":
parser = argparse.ArgumentParser(description='温度标注ML Backend')
parser.add_argument(
'-p', '--port', dest='port', type=int, default=9090,
help='Server port')
parser.add_argument(
'--host', dest='host', type=str, default='0.0.0.0',
help='Server host')
parser.add_argument(
'--kwargs', '--with', dest='kwargs', metavar='KEY=VAL', nargs='+',
type=lambda kv: kv.split('='),
help='Additional TemperatureModel initialization kwargs')
parser.add_argument(
'-d', '--debug', dest='debug', action='store_true',
help='Switch debug mode')
parser.add_argument(
'--log-level', dest='log_level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=log_level,
help='Logging level')
parser.add_argument(
'--model-dir', dest='model_dir', default=os.path.dirname(__file__),
help='Directory where models are stored')
parser.add_argument(
'--check', dest='check', action='store_true',
help='Validate model instance before launching server')
parser.add_argument('--basic-auth-user',
default=os.environ.get('ML_SERVER_BASIC_AUTH_USER', None),
help='Basic auth user')
parser.add_argument('--basic-auth-pass',
default=os.environ.get('ML_SERVER_BASIC_AUTH_PASS', None),
help='Basic auth pass')

args = parser.parse_args()

if args.log_level:
logging.root.setLevel(args.log_level)

def isfloat(value):
try:
float(value)
return True
except ValueError:
return False

def parse_kwargs():
param = dict()
if args.kwargs:
for k, v in args.kwargs:
if v.isdigit():
param[k] = int(v)
elif v == 'True' or v == 'true':
param[k] = True
elif v == 'False' or v == 'false':
param[k] = False
elif isfloat(v):
param[k] = float(v)
else:
param[k] = v
return param

kwargs = get_kwargs_from_config()
if args.kwargs:
kwargs.update(parse_kwargs())

if args.check:
print('Check "' + TemperatureModel.__name__ + '" instance creation..')
model = TemperatureModel(**kwargs)

app = init_app(
model_class=TemperatureModel,
basic_auth_user=args.basic_auth_user,
basic_auth_pass=args.basic_auth_pass
)
app.run(host=args.host, port=args.port, debug=args.debug)

else:
# 用于uWSGI
app = init_app(model_class=TemperatureModel)
28 changes: 28 additions & 0 deletions ml-backends/temperature_annotation/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"model_version": "temperature_v1.0",
"temperature_thresholds": {
"temp_rise_threshold": 1000.0,
"temp_fall_threshold": 500.0,
"gradient_threshold": 100.0,
"anomaly_threshold": 3.0,
"min_peak_height": 800.0
},
"data_processing": {
"remove_outliers": true,
"outlier_threshold": 3.0,
"interpolate_missing": true,
"normalize_data": false
},
"prediction_settings": {
"detect_rise_phases": true,
"detect_peak_moments": true,
"detect_fall_phases": true,
"detect_anomalies": true,
"detect_plateau_phases": true
},
"model_optimization": {
"enable_adaptive_thresholds": true,
"learning_rate": 0.05,
"min_training_samples": 10
}
}
Loading