SIR model - Solver to fit pre-existing data possible? If so, how would one do that?

5 次查看(过去 30 天)
Hello. For a school project, I am tasked with fitting a SIR model to some pre-existing data of cases. The suggested process to accomplish this, as described by my instructor, is to tweak the transmission rate, recovery rate, and starting percentage manually until the curve fits the values.
Figure 1
I am asking if it is instead possible to create a solver that fits this pre-existing data. Importantly, the data provided does not have a model that would fit it perfectly.
Here is the code provided by my instructor:
%% SIR base model, calibrate -- United States data
% This script models the spread and recovery of a disease using the SIR
% model. It also plots real data to help calibrate the parameters.
%
% Model inspired by this video: https://www.youtube.com/watch?v=k6nLfCbAzgo
% Data from: https://ourworldindata.org/coronavirus-data
%
% Real-world data is passed in to figure 2. User can then tweak transm and
% recov to try to match the real data
%% Parameters
% tweak these three to calibrate
transm = 13.00; % transmission rate
recov = 12.825; % recovery rate
start_scale = 15; % fudge factor to account for many early cases not being reported
% Real-world data
r_days = 1:7:36;
r_cases = [34,287,2988,13963,27103,30613]; % Pre-existing data
r_Pop = 33.05E7; % Actual population
% adjusted for model
Pop = 1; % read numbers as a fraction. Total Population = 100%
I_start = r_cases(1)/r_Pop*start_scale; % the starting percentage of infected people
n_days = 180; % # of days to simulate
%% Pre-allocate variables
% in each category, there is one index for each day
I = zeros(n_days,1);
S = I;
R = I;
% fill in starting value
I(1) = I_start;
S(1) = Pop - I_start;
R(1) = 0;
%% Run simulation, day-by-day
for day = 2:n_days
% compute changes
del_S = -transm * S(day-1) * I(day-1);
del_R = recov * I(day-1);
del_I = -del_S - del_R;
% update values
S(day) = S(day-1) + del_S;
I(day) = I(day-1) + del_I;
R(day) = R(day-1) + del_R;
end
%% Plot results
x = 1:n_days;
% time series of just I and the real-world data -- zoomed in
figure(3)
hold on
plot(x,I,'b-','LineWidth',3)
plot(r_days,r_scaled,'ro','MarkerSize',15)
xlim([0,max(r_days)]) % zoom in to known data domain
xlabel('Day','FontSize',16)
ylabel('New cases','FontSize',16)
title(words,'FontSize',18)
Thank you!

回答(1 个)

Neelanshu
Neelanshu 2023-10-5
Hi Zach,
I understand that you are facing an issue in creating a solver to fit preexisting data, given that no optimal SIR model fits the data.
You can try “fminsearch” function which is a nonlinear programming solver that find the minimum of a problem. Please refer to the below documentation to know more about “fminsearch” function:
I have implemented the following and obtained transm, recov and start_scale as 13.6021, 12.6324 and 15.0049 respectively. I have assumed that real world cases will be normalized by population.
var = [ I S R];
initialParams = [transm recov start_scale];
data = r_cases/r_Pop;
objectiveFunction = @(params) myObjectiveFunction(params, data, var);
% Set the options for the solver
options = optimset('Display', 'iter', 'MaxIter', 1000, 'TolFun', 1e-6);
% Run the solver to fit the data
fittedParams = fminsearch(objectiveFunction, initialParams, options);
% Display the fitted parameters
disp('Fitted Parameters:');
disp(fittedParams);
% Define the objective function
function error = myObjectiveFunction(params, data, var)
% Extract the parameters
param1 = params(1);
param2 = params(2);
param3 = params(3);
% Generate the model predictions using the parameters
% Modify this part according to your model
modelPredictions = myModelFunction(param1, param2, param3,var);
% Calculate the error between the model predictions and the observed data
error = sum((modelPredictions([1 8 15 22 29 36],1) - data').^2);
end
% Define your model function
function modelPredictions = myModelFunction(transm, recov, start_scale, var)
% Modify this function according to your model
% Use the provided parameters to generate the model predictions
% For example:
I = var(1);
S = var(2);
R = var(3);
for day = 2:180
% compute changes
del_S = -transm * S(day-1) * I(day-1);
del_R = recov * I(day-1);
del_I = -del_S - del_R;
% update values
S(day) = S(day-1) + del_S;
I(day) = I(day-1) + del_I;
R(day) = R(day-1) + del_R;
end
modelPredictions = [I' S' R'];
end
Hope it helps,
Regards,
Neelanshu

产品


版本

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by