В моей предыдущей карьере написания торговых алгоритмов я бы посмотрел на этот график и увидел потенциал для зарабатывания денег. Теперь, как родитель маленького ребенка с диабетом 1 типа, я смотрю на эту таблицу и меня тошнит. Этот график показывает уровень сахара в крови моего сына за два дня на прошлой неделе - уровень сахара в крови маленького ребенка с диабетом 1 типа может быть сумасшедшим!

В течение последних нескольких лет я исследовал способы уменьшить бремя диабета в его жизни и страх, с которым живет моя семья каждый день (первое решение, чтобы помочь моей семье). В моем исследовании использовались новейшие и самые лучшие модели машинного обучения, например Рекуррентные нейронные сети, Seq2Seq, Seq2Seq с вниманием, Convnets и т. Д. Все эти усилия были направлены на создание идеального долгосрочного прогноза уровня сахара в крови.

Так было до недавнего времени, когда я осознал тот факт, что этим моделям будет очень трудно приблизиться к совершенству, особенно в моменты, когда требуется немедленное вмешательство в определение уровня глюкозы в крови (ГК). Что наиболее важно, я не думаю, что эти типы моделей будут решать проблемы, с которыми ежедневно сталкиваются лица, осуществляющие уход за детьми с типом 1.

Большинство моделей машинного обучения могут понять физиологические процессы, представленные в данных о диабете, но очень сложно уловить поведение человека, которое влияет на bg. Особенно в моменты повышенной тревожности поведение человека играет очень важную роль в управлении диабетом. Например, воспитатель может решить дать ребенку еду без предупреждения, чтобы предотвратить уныние, ошибиться при подсчете углеводов или в панике дать ребенку большое количество сахара - решения, принятые в условиях стресса, создают совершенно новое измерение, которое модельер должен учитывать . При таких вмешательствах как исследователю, так и пользователю может быть очень трудно чувствовать себя комфортно, давая точечные прогнозы.

Я искал способы смоделировать эту неопределенность в bg как результат несовершенных измерений и поведения человека. Этот желаемый результат - очень хороший кандидат для байесовской модели. Байесовское моделирование предлагает систематическую основу для рассуждений о неопределенности модели. Итак, вместо того, чтобы просто изучать точечные оценки, мы собираемся изучить распределение по переменным, которое согласуется с наблюдаемыми данными, прежде чем делать вывод о прогнозируемом распределении. Это распределение по параметрам (апостериорное распределение) является применением правила Байеса и представлено следующим образом:

Затем мы можем использовать это апостериорное распределение для прогнозов. Эти прогнозы (апостериорное прогнозирующее распределение) можно записать как:

К счастью, у нас есть инструменты, которые делают этот тип вычислений возможным, так как знаменатель апостериорного вычисления трудноизлечим. Используя PyTorch и Pyro, мы создаем три основных компонента для запуска нашей модели. Первый компонент - это модель или функция, которая будет делать прогноз bg. Мы определяем нашу модель (трехуровневую нейронную сеть), как любую нейронную сеть PyTorch.

class RegressionModel(nn.Module):
def __init__(self, num_feature,num_hidden,num_output,dropout=0.0): super().__init__()
self.linear_1 = nn.Linear(num_feature, num_hidden)
self.linear_2 = nn.Linear(num_hidden, num_hidden)
self.linear_out = nn.Linear(num_hidden, num_output)
self.drop_layer = nn.Dropout(p=dropout)
def forward(self, x):
x=self.linear_1(x)
x=F.relu(self.drop_layer(x))
x=self.linear_2(x)
x=F.relu(self.drop_layer(x))
out=self.linear_out(x)
return out
num_hidden=32 #hidden units
num_feature=5  #num input dimensions
num_rank=1 #regression so output =1 
regression_model = RegressionModel(num_feature,num_hidden,num_rank)

Относительно упрощенная модель на самом деле довольно эффективна (RMSE ~ 20) при оценке сахара в крови до 30 минут с учетом изменчивости зависимой переменной. Однако я должен подчеркнуть, что необходимо очень внимательно рассмотреть вопрос о том, как преобразовать входящие данные (глюкоза, углеводы, инсулин) в эффективный набор функций. Я преобразовал входные данные в 5 функций, включая 1) сглаженное bg, 2) скользящее среднее сглаженного bg, 3) импульс сглаженного bg, 4) поглощенные углеводы и 5) поглощенный инсулин. Авторы Loop и OpenAPS проделали потрясающую работу по моделированию углеводов и инсулина, и с незначительной настройкой нескольких параметров у меня есть процесс абсорбции углеводов / инсулина, в котором я уверен.

Следующим шагом является определение модели и направляющей в Pyro. Модель Pyro будет использовать нейронную сеть, определенную выше, и переназначить ее для байесовской настройки.

def model(x_data, y_data):
# weight and bias priors
w1_prior=Normal(loc=torch.zeros_like(regression_model.linear_1.weight),scale=torch.ones_like(regression_model.linear_1.weight)).independent(2)
b1_prior=Normal(loc=torch.zeros_like(regression_model.linear_1.bias,scale=torch.ones_like(regression_model.linear_1.bias)).independent(1)
w2_prior=Normal(loc=torch.zeros_like(regression_model.linear_2.weight),scale=torch.ones_like(regression_model.linear_2.weight)).independent(2)
b2_prior=Normal(loc=torch.zeros_like(regression_model.linear_2.bias),scale=torch.ones_like(regression_model.linear_2.bias)).independent(1)
wout_prior=Normal(loc=torch.zeros_like(regression_model.linear_out.weight),scale=torch.ones_like(regression_model.linear_out.weight)).independent(2)
bout_prior=Normal(loc=torch.zeros_like(regression_model.linear_out.bias),scale=torch.ones_like(regression_model.linear_out.bias)).independent(1)
scale = torch.ones(1, 1)scale = pyro.sample("sigma", Uniform(0., 10.))
priors = {'linear_1.weight':w1_prior,'linear_1.bias':b1_prior,'linear_2.weight':w2_prior,'linear_2.bias':b2_prior,'linear_out.weight':wout_prior,'linear_out.bias':bout_prior}
# lift module parameters from neural net
lifted_module = pyro.random_module("module", regression_model, priors)
lifted_reg_model = lifted_module()
with pyro.plate("map", len(x_data)):
#run forward on regression_model
prediction_mean = lifted_reg_model(x_data)
prediction_mean=prediction_mean.squeeze(-1)
# condition on the observed data
pyro.sample("obs",Normal(prediction_mean, scale),obs=y_data)
return prediction_mean

Руководство определяется во многом так же, как и модель, с обучаемыми параметрами, соответствующими каждому образцу () в режиме, и идентичной сигнатурой функции. Основная идея руководства заключается в том, что мы вводим параметризованное распределение qϕ (z), где ϕ известны как вариационные параметры. Руководство будет служить приближением к апостериорной оценке, где мы минимизируем разницу, используя ELBO, нижнюю границу свидетельства.

Имея наше руководство и модель, мы теперь можем аппроксимировать апостериорное распределение, используя стохастический вариационный вывод.

optim = Adam({"lr": 1e-2})
svi = SVI(model, guide, optim, loss=Trace_ELBO(),num_samples=1000)
num_iterations=1500
def train():
pyro.clear_param_store()
for j in range(num_iterations):
for xb,yb in train_dl:
# calculate the loss and take a gradient step
loss = svi.step(xb, yb.squeeze(-1))
if j % 50== 0:
print("[iteration %04d] loss: %.4f" % (j + 1, loss / len(xb)))

Поскольку наше вариационное распределение полностью параметризовано, мы можем просто запустить расширенную модель. Используя некоторые вспомогательные функции, предоставляемые Pyro, мы делаем прогнозы со следующим:

get_marginal = lambda traces, sites:EmpiricalMarginal(traces, sites)._get_samples_and_weights()[0].detach().cpu().numpy()
def summary(traces, sites):
marginal = get_marginal(traces, sites)
site_stats = {}
for i in range(marginal.shape[1]):
site_name = sites[i]
marginal_site = pd.DataFrame(marginal[:, i]).transpose()
describe = partial(pd.Series.describe, percentiles=[.05, 0.25, 0.5, 0.75, 0.95])
site_stats[site_name] = marginal_site.apply(describe, axis=1) \[["mean", "std", "5%", "25%", "50%", "75%", "95%"]]
return site_stats
def wrapped_model(x_data, y_data):
pyro.sample("prediction", Delta(model(x_data, y_data)))
#posterior = svi.run(X, Y)
x_data=x[-1000:]
y_data=y[-1000:]
posterior = svi.run(x_data, y_data)
trace_pred = TracePredictive(wrapped_model,posterior,num_samples=1000)
post_pred = trace_pred.run(x_data, None)
post_summary = summary(post_pred, sites= ['prediction', 'obs'])
mu = post_summary["prediction"]
y_o = post_summary["obs"]
predictions = pd.DataFrame({"bg": x_data[:, 0],"mu_mean": mu["mean"],"mu_perc_5": mu["5%"],"mu_perc_95": mu["95%"],"y_mean": y_o["mean"],"y_perc_5": y_o["5%"],"y_perc_95": y_o["95%"],"true_y": y_data,})

Как показано на рис. 2, теперь у нас есть границы для наших прогнозов. Имейте в виду, что мы не так озабочены точечной оценкой (средним распределением) будущего уровня сахара в крови, как мы используем неопределенность, чтобы чувствовать себя более комфортно при принятии решений по лечению диабета. Например, осознание того, что bgs выходит за предсказанные границы, может быть очень полезной информацией, чтобы знать, что что-то может быть не так. В большинстве случаев, когда я вижу, что уровень глюкозы крови (около часов приема пищи) выходит за эти пределы, это происходит из-за неправильного или несвоевременного болюса, что не представляет большого труда и быстро возвращается в норму. Однако, когда вы постоянно видите реализации за пределами интервалов прогноза, вы понимаете, что в текущих методах лечения может потребоваться существенная корректировка. Это то, что я испытал на прошлой неделе, когда последовательные выводы, выходящие за рамки установленных границ, привели нас к выводу, что чувствительность к инсулину необходимо изменить.

Эта модель помогла мне обрести душевное равновесие в моей повседневной жизни, и я думаю, что это лишь верхушка возможного. Теперь я могу чувствовать себя более уверенно в решениях, которые принимаю, и зная, что мне не всегда нужно быть начеку. В большинстве случаев достаточно иметь спокойствие, зная, что вы делаете хорошую работу и можете жить нормальной жизнью. Когда дело доходит до диабета, не бывает совершенства, так зачем же ожидать того же от себя.

Мы рады поделиться своими успехами, поскольку мы продолжаем совершенствовать наши решения, чтобы помочь людям, живущим с диабетом. Мы поделимся своей работой на предстоящей Конференции по диабетической технологии в Вашингтоне, округ Колумбия, 14 ноября, и на ATTD в Мадриде, Испания, в феврале. Хотел бы пообщаться с людьми с похожими интересами в этом пространстве.