Project Icon

simglucose

Python实现的1型糖尿病模拟器助力强化学习研究

simglucose 是一个基于 FDA 批准的 UVa/Padova Simulator 实现的开源 1 型糖尿病模拟器。它包含 30 个虚拟患者模型,兼容 OpenAI Gym 和 rllab API,支持自定义奖励函数和控制器。该项目支持并行计算,能生成多种性能分析图表。研究人员可利用 simglucose 开发和测试糖尿病管理的强化学习算法,为相关研究提供了便利。

simglucose

下载量 月下载量 周下载量

一个用Python实现的1型糖尿病模拟器,用于强化学习目的

这个模拟器是FDA批准的UVa/Padova模拟器(2008版)的Python实现,仅供研究使用。模拟器包含30个虚拟患者,10名青少年,10名成人,10名儿童。

如何引用: Jinyu Xie. Simglucose v0.2.1 (2018) [在线]. 可用: https://github.com/jxx123/simglucose. 访问日期: 月-日-年.

注意: simglucose不再支持Python 3.7和3.8版本,请更新至3.9或更高版本。谢谢!

公告 (2023年8月20日): simglucose现已支持gymnasium! 查看examples/run_gymnasium.py了解使用方法。

动画CVGA图血糖追踪图风险指数统计
动画截图CVGA血糖追踪图风险指数统计

主要特性

  • 模拟环境遵循OpenAI gymrllab API。每一步都返回观察、奖励、是否结束和信息,这意味着模拟器已经"准备好用于强化学习"。
  • 支持自定义奖励函数。奖励函数是过去一小时内血糖测量值的函数。默认情况下,每一步的奖励是risk[t-1] - risk[t]risk[t]是时间t的风险指数,定义见这篇论文
  • 支持并行计算。模拟器使用pathos多进程包并行模拟多个患者(您可以通过设置parallel=False关闭并行)。
  • 模拟器提供随机场景生成器(from simglucose.simulation.scenario_gen import RandomScenario)和自定义场景生成器(from simglucose.simulation.scenario import CustomScenario)。命令行用户界面将指导您完成场景设置。
  • 模拟器目前提供最基本的基础-大剂量控制器。它提供了非常简单的语法来实现您自己的控制器,如模型预测控制、PID控制、强化学习控制等。
  • 您可以指定随机种子,以便重复实验。
  • 模拟后,模拟器将生成几个性能分析图。这些图包括血糖追踪图、控制变异性网格分析(CVGA)图、不同区域血糖统计图、风险指数统计图。
  • 注意:在macOS中,animateparallel不能同时设置为True。macOS中大多数matplotlib后端都不是线程安全的。Windows尚未测试。如果有人测试过,请告知结果。

安装

强烈建议使用pip安装simglucose,请点击此链接安装pip。

自动安装:

pip install simglucose

手动安装:

git clone https://github.com/jxx123/simglucose.git
cd simglucose

如果您已安装pip,则:

pip install -e .

如果您没有安装pip,则:

python setup.py install

如果安装了rllab(可选),该包将利用rllab中的一些功能。

注意:自动安装版本和手动安装版本之间可能存在一些细微差异。使用git clone和手动安装以获取最新版本。

快速开始

将simglucose用作模拟器并测试控制器

运行模拟器用户界面

from simglucose.simulation.user_interface import simulate
simulate()

您可以自由实现自己的控制器,并在模拟器中测试。例如:

from simglucose.simulation.user_interface import simulate
from simglucose.controller.base import Controller, Action


class MyController(Controller):
    def __init__(self, init_state):
        self.init_state = init_state
        self.state = init_state

    def policy(self, observation, reward, done, **info):
        '''
        每个控制器必须实现此方法!
        ----
        输入:
        observation - 在simglucose.simulation.env中定义的命名元组。目前
                      它只有一个条目:CGM传感器测量的血糖水平。
        reward      - 环境返回的当前奖励
        done        - True,游戏结束。False,游戏继续
        info        - 额外信息作为关键字参数,
                      simglucose.simulation.env.T1DSimEnv返回patient_name
                      和sample_time
        ----
        输出:
        action - 在此文件开头定义的命名元组。控制器
                 动作包含两个条目:basal,bolus
        '''
        self.state = observation
        action = Action(basal=0, bolus=0)
        return action

    def reset(self):
        '''
        将控制器状态重置为初始状态,必须实现
        '''
        self.state = self.init_state


ctrller = MyController(0)
simulate(controller=ctrller)

这两个示例也可以在examples\文件夹中找到。

实际上,您可以通过simulation指定更多的模拟参数:

simulate(sim_time=my_sim_time,
         scenario=my_scenario,
         controller=my_controller,
         start_time=my_start_time,
         save_path=my_save_path,
         animate=False,
         parallel=True)

OpenAI Gym 用法

  • 使用默认奖励
import gym
# 注册gym环境。通过指定kwargs,
# 你可以选择模拟哪个或哪些患者。
# patient_name必须是'adolescent#001'到'adolescent#010',
# 或'adult#001'到'adult#010',或'child#001'到'child#010'
# 它也可以是患者名称列表
# 你还可以指定自定义场景或自定义场景列表
# 如果你选择了患者名称列表或自定义场景列表,
# 每次环境重置时,都会从列表中随机选择一个患者和场景

from gym.envs.registration import register
from simglucose.simulation.scenario import CustomScenario
from datetime import datetime

start_time = datetime(2018, 1, 1, 0, 0, 0)
meal_scenario = CustomScenario(start_time=start_time, scenario=[(1,20)])


register(
    id='simglucose-adolescent2-v0',
    entry_point='simglucose.envs:T1DSimEnv',
    kwargs={'patient_name': 'adolescent#002',
            'custom_scenario': meal_scenario}
)

env = gym.make('simglucose-adolescent2-v0')

observation = env.reset()
for t in range(100):
    env.render(mode='human')
    print(observation)
    # gym环境中的动作是一个标量
    # 代表基础胰岛素,这与
    # gym环境外的常规控制器动作不同
    # (一个元组(basal, bolus))。
    # 在理想情况下,代理应该能够
    # 仅通过基础胰岛素控制血糖,而不是
    # 要求患者注射大剂量胰岛素
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)
    if done:
        print("在{}个时间步后,回合结束".format(t + 1))
        break
  • 自定义奖励函数
import gym
from gym.envs.registration import register


def custom_reward(BG_last_hour):
    if BG_last_hour[-1] > 180:
        return -1
    elif BG_last_hour[-1] < 70:
        return -2
    else:
        return 1


register(
    id='simglucose-adolescent2-v0',
    entry_point='simglucose.envs:T1DSimEnv',
    kwargs={'patient_name': 'adolescent#002',
            'reward_fun': custom_reward}
)

env = gym.make('simglucose-adolescent2-v0')

reward = 1
done = False

observation = env.reset()
for t in range(200):
    env.render(mode='human')
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)
    print(observation)
    print("奖励 = {}".format(reward))
    if done:
        print("在{}个时间步后,回合结束".format(t + 1))
        break

rllab用法

from rllab.algos.ddpg import DDPG
from rllab.envs.normalized_env import normalize
from rllab.exploration_strategies.ou_strategy import OUStrategy
from rllab.policies.deterministic_mlp_policy import DeterministicMLPPolicy
from rllab.q_functions.continuous_mlp_q_function import ContinuousMLPQFunction
from rllab.envs.gym_env import GymEnv
from gym.envs.registration import register

register(
    id='simglucose-adolescent2-v0',
    entry_point='simglucose.envs:T1DSimEnv',
    kwargs={'patient_name': 'adolescent#002'}
)

env = GymEnv('simglucose-adolescent2-v0')
env = normalize(env)

policy = DeterministicMLPPolicy(
    env_spec=env.spec,
    # 神经网络策略应该有两个隐藏层,每层32个隐藏单元。
    hidden_sizes=(32, 32)
)

es = OUStrategy(env_spec=env.spec)

qf = ContinuousMLPQFunction(env_spec=env.spec)

algo = DDPG(
    env=env,
    policy=policy,
    es=es,
    qf=qf,
    batch_size=32,
    max_path_length=100,
    epoch_length=1000,
    min_pool_size=10000,
    n_epochs=1000,
    discount=0.99,
    scale_reward=0.01,
    qf_learning_rate=1e-3,
    policy_learning_rate=1e-4
)
algo.train()

高级用法

你可以创建模拟对象,并运行批量模拟。例如,

from simglucose.simulation.env import T1DSimEnv
from simglucose.controller.basal_bolus_ctrller import BBController
from simglucose.sensor.cgm import CGMSensor
from simglucose.actuator.pump import InsulinPump
from simglucose.patient.t1dpatient import T1DPatient
from simglucose.simulation.scenario_gen import RandomScenario
from simglucose.simulation.scenario import CustomScenario
from simglucose.simulation.sim_engine import SimObj, sim, batch_sim
from datetime import timedelta
from datetime import datetime

# 将start_time指定为今天的开始
now = datetime.now()
start_time = datetime.combine(now.date(), datetime.min.time())

# --------- 创建随机场景 --------------
# 指定结果保存路径
path = './results'

# 创建模拟环境
patient = T1DPatient.withName('adolescent#001')
sensor = CGMSensor.withName('Dexcom', seed=1)
pump = InsulinPump.withName('Insulet')
scenario = RandomScenario(start_time=start_time, seed=1)
env = T1DSimEnv(patient, sensor, pump, scenario)

# 创建控制器
controller = BBController()

# 将它们组合在一起创建模拟对象
s1 = SimObj(env, controller, timedelta(days=1), animate=False, path=path)
results1 = sim(s1)
print(results1)

# --------- 创建自定义场景 --------------
# 创建模拟环境
patient = T1DPatient.withName('adolescent#001')
sensor = CGMSensor.withName('Dexcom', seed=1)
pump = InsulinPump.withName('Insulet')
# 自定义场景是一个元组列表 (时间, 餐量)
scen = [(7, 45), (12, 70), (16, 15), (18, 80), (23, 10)]
scenario = CustomScenario(start_time=start_time, scenario=scen)
env = T1DSimEnv(patient, sensor, pump, scenario)

# 创建控制器
controller = BBController()

# 将它们组合在一起创建模拟对象
s2 = SimObj(env, controller, timedelta(days=1), animate=False, path=path)
results2 = sim(s2)
print(results2)


# --------- 批量模拟 --------------
# 重新初始化模拟对象
s1.reset()
s2.reset()

# 创建SimObj列表,并调用batch_sim
s = [s1, s2]
results = batch_sim(s, parallel=True)
print(results)

离线运行分析(example/offline_analysis.py):

from simglucose.analysis.report import report
import pandas as pd
from pathlib import Path


# 获取example文件夹的路径
exmaple_pth = Path(__file__).parent
# 查找所有符合 *#*.csv 模式的 csv 文件,例如 adolescent#001.csv
result_filenames = list(exmaple_pth.glob(
    'results/2017-12-31_17-46-32/*#*.csv'))
patient_names = [f.stem for f in result_filenames]
df = pd.concat(
        [pd.read_csv(str(f), index_col=0) for f in result_filenames],
        keys=patient_names)
report(df)

发布说明

2023年8月20日

  • 修复了风险指数计算的 numpy 兼容性问题(感谢 @yihuicai)
  • 支持 Gymnasium。
    • 注意:gymnasium 版本中的观察结果不再是带有 CGM 字段的命名元组。它是一个 numpy 数组(与其空间定义保持一致)。
  • 注意:不再支持 Python 3.7 和 3.8 版本。请更新至 3.9 以上版本。

2021年3月10日

  • 修复了一些随机种子问题。

2020年5月27日

  • 在 simglucose/controller/pid_ctrller 中添加了 PIDController。在 examples/run_pid_controller.py 中有一个示例展示如何使用它。

2018年9月10日

  • 控制器的 policy 方法可以通过 info['patient_state'] 访问当前患者的所有状态。

2018年2月26日

  • 支持自定义奖励函数。

2018年1月10日

  • 添加了在创建 gym 环境时选择患者的解决方法:通过传递 patient_name 的 kwargs 来注册 gym 环境。

2018年1月7日

  • 添加了 OpenAI gym 支持,使用 gym.make('simglucose-v0') 来创建环境。
  • 注意问题:目前在 gym.make 中无法使用患者名称选择。患者名称必须在 simglucose.envs.T1DSimEnv 的构造函数中硬编码。

报告问题

通过创建 issues 向我反馈任何 bug、改进建议,甚至是讨论。

如何贡献

以下说明最初来自 sklearn 的贡献指南

贡献 simglucose 的首选工作流程是在 GitHub 上 fork 主仓库,克隆,并在分支上开发。步骤如下:

  1. 点击页面右上角附近的 "Fork" 按钮,fork 项目仓库。这会在你的 GitHub 账户下创建代码的副本。有关如何 fork 仓库的更多详细信息,请参阅此指南

  2. 将你 fork 的 simglucose 仓库从你的 GitHub 账户克隆到本地磁盘:

    $ git clone git@github.com:你的登录名/simglucose.git
    $ cd simglucose
    
  3. 创建一个 feature 分支来保存你的开发更改:

    $ git checkout -b my-feature
    

    始终使用 feature 分支。永远不要在 master 分支上工作是一个好习惯!

  4. 在你的 feature 分支上开发功能。使用 git add 添加更改的文件,然后 git commit 提交文件:

    $ git add 修改的文件
    $ git commit
    

    在 Git 中记录你的更改,然后使用以下命令将更改推送到你的 GitHub 账户:

    $ git push -u origin my-feature
    
  5. 按照这些说明从你的 fork 创建一个拉取请求。这将通知贡献者。

(如果以上任何内容对你来说像魔法一样,请查阅网上的 Git 文档,或向朋友或其他贡献者寻求帮助。)

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号