Log likelihood of (marked) Hawkes Process - matlab

I need to calculate the log likelihood of a Hawkes Process and also of a Marked Hawkes Process, where the jump in intensity is not the same for every event.
More specifically, I have some datasets consisting of around 100 events spread over 1 million years (each event happens in one of the years, no fractions) and I want to use likelihood maximization to estimate the parameters of the process.
I tried coding myself using Matlab's fmincon, but it doesn't seem to be working properly. It is too sensitive to the initial guess and to the dataset. Sometimes it throws the 'close to singular or badly scaled matrix' warning. If I change the initial guess for the first parameter I eventually find one that makes it work. I guess this happens because the values of the parameters are on the scale of 10^(-4)?
Here is the code I used for the Hawkes Process. 'times' stores the the year of each event and 'T' is the total length of the process.
Any thoughts on how to deal with this issue?
Thanks
func = #(x)hawkes_likelihood(times, T, x(1), x(2), x(3));
options = optimoptions(#fmincon,'Display','off');
[params, likelihood] = fmincon(func, [length(times)/T 0.001 0.001], ...
[], [], [], [0 0 0], [], [],options);
function likelihood = hawkes_likelihood(times, T, c, alpha, beta)
% Compute the negative log-likelihood of the Hawkes Process
% Integral of the intensity function
likelihood = c*T + sum(alpha.*(1-exp(-beta*(T-times)))/beta);
for i = 1:length(times)
% Intensity function at i-th event
lambda_t = c + sum(alpha*exp(-beta*(times(i)-times(1:i-1))));
likelihood = likelihood - log(lambda_t);
end
end

Related

How do I implement multiple sub-intervals onto this code?

I am trying to optimize the function under the mathematical assumption given below (it essentially breaks down the current interval in the code into multiple subintervals but how do I even implement it?):
[the mathematical theory]- It is well known that the Trapezoid rule gives a more accurate approximation if the intervals are broken up into smaller intervals so that: I1 = [a; b1], I2 = [b1; b2], I3 = [b2; b3],...,I n-1 = [b n-1, bn] where bn = b. Write a program that implements this strategy using your NC.m code from above. It should be able to complete the task for an arbitrary n. How many sub-intervals must be created to get an "accurate" integral approximation of the function listed below on the interval [-3:0]?
%For this problem write a script file called NC.m that implements
%the Newton-Cotes method of integration for an arbitrary function f(x). It
%should takes as inputs the function and the limits of integration [a: b] and
%output the value of the definite integral. Specifically, you should use the
%Trapezoid rule as presented in Equation (11.73)
function [f]= NC(a,b,fun) %newton-cotes
%a and b are limits of integration
%setting it up
fa= fun(a); %y value for lower limit
fb= fun(b); %y value for upper limit
%the actual function
f= (b-a)*(fa+fb)/2;
end
%Result from estimation
%fun= #(x) normpdf(x)
%[f]= NC(-3,0,fun)- 0.6051
%not accurate when compared to results from actual calculation
%syms x
%f= normpdf(x);
%a= -3;- lower limit
%b= 0;- higher limit
%int(f, a, b)- 0.4897
Please help. It would be greatly appreciated!

Solving a simple system of differential equations

How would I numerically solve for the following simple system of differential equations using Octave?
Note:
I use the qualifier "simple" as, from my understanding, the system is
first order and is not coupled.
I have tried every
method and script online to try solve this including here,
here and here. In all options, I either get a hanging,
non-responsive Octave, a prompt stating "repeated convergence
failures", an error with recommendation that I manually adjust
the initial and maximum step size (which I did try and do, to no
avail), or something that initially seems like a solution on account of no errors but plotting the solution shows a blank graph
Where Octave provided for equivalent Matlab routines, I tried the various routines ode45, ode23, ode113, ode15s, ode23s, ode23t, ode23tb, ode15i and of course, Octaves own lsode command, all giving the same errors described above.
Let's first replicate the vanilla solution
% z = [x,y]
f = #(t,z) [ z(1).^2+t; z(1).*z(2)-2 ];
z0 = [ 2; 1];
[ T, Z ] = ode45(f, [0, 10], z0);
plot(T,Z); legend(["x";"y"]);
The integrator fails as reported with the warning
warning: Solving was not successful. The iterative integration loop exited at time t = 0.494898 before the endpoint at tend = 10.000000 was reached. This may happen if the stepsize becomes too small. Try to reduce the value of 'InitialStep' and/or 'MaxStep' with the command 'odeset'.
Repeating the integration up to shortly before the critical time
opt = odeset('MaxStep',0.01);
[ T, Z ] = ode45(f, [0, 0.49], z0, opt);
clf; plot(T,Z); legend(["x";"y"]);
results in the graph
where one can see that the quadratic term in the first equation leads to run-away growth. For some reason the solver does only recognize the ever reducing step size, but not the run-away values of the solution.
Indeed the first is a Riccati equation which are known to have poles at finite times. Using the typical parametrization x(t)=-u'(t)/u(t) has by the product/quotient rule the derivative
x' = -u''(t)/u(t) - u'(t)* (-u'(t)/u(t)^2) = -u''(t)/u(t) + x(t)^2
which then results in the ODE for u
u''(t)+t*u(t)=0, u(0)=-1, u'(0)=x(0)=2,
which is an Airy equation with the oscillating branch for t>0. The first root of u is a pole for x, there is no way to extend the solution beyond this point.
g=#(t,u) [u(2); -t.*u(1)]
u0 = [ 1; -2];
function [val,term, dir] = event(t,u)
val = u(1);
term = 0;
dir = 0;
end
opt = odeset('MaxStep',0.1, 'Events', #(t,u) event(t,u));
[T,U,Te,Ue,Ie] = ode45(g,[0,4],u0,opt);
disp(Te)
clf; plot(T,U); legend(["u";"u'"]);
which lists the zeros of u as 0.4949319379979706, 2.886092605590324, again confirming the reason for the warning, and gives the plot

A moving average with different functions and varying time-frames

I have a matrix time-series data for 8 variables with about 2500 points (~10 years of mon-fri) and would like to calculate the mean, variance, skewness and kurtosis on a 'moving average' basis.
Lets say frames = [100 252 504 756] - I would like calculate the four functions above on over each of the (time-)frames, on a daily basis - so the return for day 300 in the case with 100 day-frame, would be [mean variance skewness kurtosis] from the period day201-day300 (100 days in total)... and so on.
I know this means I would get an array output, and the the first frame number of days would be NaNs, but I can't figure out the required indexing to get this done...
This is an interesting question because I think the optimal solution is different for the mean than it is for the other sample statistics.
I've provided a simulation example below that you can work through.
First, choose some arbitrary parameters and simulate some data:
%#Set some arbitrary parameters
T = 100; N = 5;
WindowLength = 10;
%#Simulate some data
X = randn(T, N);
For the mean, use filter to obtain a moving average:
MeanMA = filter(ones(1, WindowLength) / WindowLength, 1, X);
MeanMA(1:WindowLength-1, :) = nan;
I had originally thought to solve this problem using conv as follows:
MeanMA = nan(T, N);
for n = 1:N
MeanMA(WindowLength:T, n) = conv(X(:, n), ones(WindowLength, 1), 'valid');
end
MeanMA = (1/WindowLength) * MeanMA;
But as #PhilGoddard pointed out in the comments, the filter approach avoids the need for the loop.
Also note that I've chosen to make the dates in the output matrix correspond to the dates in X so in later work you can use the same subscripts for both. Thus, the first WindowLength-1 observations in MeanMA will be nan.
For the variance, I can't see how to use either filter or conv or even a running sum to make things more efficient, so instead I perform the calculation manually at each iteration:
VarianceMA = nan(T, N);
for t = WindowLength:T
VarianceMA(t, :) = var(X(t-WindowLength+1:t, :));
end
We could speed things up slightly by exploiting the fact that we have already calculated the mean moving average. Simply replace the within loop line in the above with:
VarianceMA(t, :) = (1/(WindowLength-1)) * sum((bsxfun(#minus, X(t-WindowLength+1:t, :), MeanMA(t, :))).^2);
However, I doubt this will make much difference.
If anyone else can see a clever way to use filter or conv to get the moving window variance I'd be very interested to see it.
I leave the case of skewness and kurtosis to the OP, since they are essentially just the same as the variance example, but with the appropriate function.
A final point: if you were converting the above into a general function, you could pass in an anonymous function as one of the arguments, then you would have a moving average routine that works for arbitrary choice of transformations.
Final, final point: For a sequence of window lengths, simply loop over the entire code block for each window length.
I have managed to produce a solution, which only uses basic functions within MATLAB and can also be expanded to include other functions, (for finance: e.g. a moving Sharpe Ratio, or a moving Sortino Ratio). The code below shows this and contains hopefully sufficient commentary.
I am using a time series of Hedge Fund data, with ca. 10 years worth of daily returns (which were checked to be stationary - not shown in the code). Unfortunately I haven't got the corresponding dates in the example so the x-axis in the plots would be 'no. of days'.
% start by importing the data you need - here it is a selection out of an
% excel spreadsheet
returnsHF = xlsread('HFRXIndices_Final.xlsx','EquityHedgeMarketNeutral','D1:D2742');
% two years to be used for the moving average. (250 business days in one year)
window = 500;
% create zero-matrices to fill with the MA values at each point in time.
mean_avg = zeros(length(returnsHF)-window,1);
st_dev = zeros(length(returnsHF)-window,1);
skew = zeros(length(returnsHF)-window,1);
kurt = zeros(length(returnsHF)-window,1);
% Now work through the time-series with each of the functions (one can add
% any other functions required), assinging the values to the zero-matrices
for count = window:length(returnsHF)
% This is the most tricky part of the script, the indexing in this section
% The TwoYearReturn is what is shifted along one period at a time with the
% for-loop.
TwoYearReturn = returnsHF(count-window+1:count);
mean_avg(count-window+1) = mean(TwoYearReturn);
st_dev(count-window+1) = std(TwoYearReturn);
skew(count-window+1) = skewness(TwoYearReturn);
kurt(count-window +1) = kurtosis(TwoYearReturn);
end
% Plot the MAs
subplot(4,1,1), plot(mean_avg)
title('2yr mean')
subplot(4,1,2), plot(st_dev)
title('2yr stdv')
subplot(4,1,3), plot(skew)
title('2yr skewness')
subplot(4,1,4), plot(kurt)
title('2yr kurtosis')

MATLAB Optimization Error

My Genetic Algorithm optimization script on Matlab runs, but at the end produces the following message: "Optimization terminated: average change in the penalty fitness value less than options.TolFun but constraints are not satisfied."
Why would it say that? I replaced my fitness function with one that does nothing but returns a constant number, and nothing changed. It may be the case that my constraints are not defined correctly, though I can't find the mistake. Here is the relevant part of the code:
nGenerators = 9;
monthlyHours = 24*daysInJanuary;
(some irrelevant code here)
steamCapacities = [31.46*ones(1,2) 5.5*ones(1,3) 4*ones(1,4)];
nVars = xSize;
IntCon = 1:nVars;
LB = zeros(1, nVars);
UB = ones(1, nVars);
b = -1*steamLoad; % Ax <= b
A = zeros(monthlyHours, xSize);
for p = 1:monthlyHours
A(p, 9*p-8:9*p) = -1*steamCapacities;
% disp(p);
end
(some more code here)
anonFitness = #(x)mosb_test(x, fitnessData);
gaOptions = gaoptimset('Vectorized', 'off', 'UseParallel', 'always', ...
'Display', 'diagnose', 'PlotFcn', #gaplotbestf, 'Generations', 300, ...
'TolFun', 1e-15, 'StallGenLimit', 200);
[x, fval, exitFlag] = ga(anonFitness, nVars, A, b,[],[], LB, UB, [], IntCon, gaOptions);
Here, x represents the on/off states for a set of 9 generators for each hour of the month. Their steam production capacities are as in the variable steamCapacities, and there is a constant steam load that has to be met at every hour. This is represented by the inequality constraint.
Any help appreciated.
Interesting problem! Too bad it can't be solved deterministically. :-( Anyway, your TolFun is defined by the mathworks as being:
Positive scalar. The algorithm stops if the weighted average relative
change in the best fitness function value over StallGenLimit
generations is less than or equal to TolFun
and StallGenLimit has the same description. It makes perfect sense that a constant will give you the same error. It appears to me that the GA is unable to converge to a solution in the StallGenLimit, here 200, generations. You could try making the TolFun more restrictive, like 1e-12, or try and develop a far simpler model for the GA, one that will just allow you to find a solution. Then build complexity on this model until it matches your real system. Likely, it will fail at some point and you will be able to see why the problem can't be solved like too many degrees of freedom, too tight of constraints, etc. HTH!

Getting unexpected results while using ode45

I am trying to solve a system of differential equations by writing code in Matlab. I am posting on this forum, hoping that someone might be able to help me in some way.
I have a system of 10 coupled differential equations. It is a vector-host epidemic model, which captures the transmission of a disease between human population and insect population. Since it is a simple system of differential equations, I am using solvers (ode45) for non-stiff problem type.
There are 10 differential equations, each representing 10 different state variables. There are two functions which have the same system of 10 coupled ODEs. One is called NoEffects_derivative_6_15_2012.m which contains the original system of ODEs. The other function is called OnlyLethal_derivative_6_15_2012.m which contains the same system of ODEs with an increased withdrawal rate starting at time, gamma=32 %days and that withdrawal rate decays exponentially with time.
I use ode45 to solve both the systems, using the same initial conditions. Time vector is also the same for both systems, going from t0 to tfinal. The vector tspan contains the time values going from t0 to tfinal, each with a increment of 0.25 days, making a total of 157 time values.
The solution values are stored in matrices ye0 and yeL. Both these matrices contain 157 rows and 10 columns (for the 10 state variable values). When I compare the value of the 10th state variable, for the time=tfinal, in the matrix ye0 and yeL by plotting the difference, I find it to be becoming negative for some time values. (using the command: plot(te0,ye0(:,10)-yeL(:,10))). This is not expected. For all time values from t0 till tfinal, the value of the 10 state variable, should be greater, as it is the solution obtained from a system of ODEs which did not have an increased withdrawal rate applied to it.
I am told that there is a bug in my matlab code. I am not sure how to find out that bug. Or maybe the solver in matlab I am using (ode45) is not efficient and does give this kind of problem. Can anyone help.
I have tried ode23 and ode113 as well, and yet get the same problem. The figure (2), shows a curve which becomes negative for time values 32 and 34 and this is showing a result which is not expected. This curve should have a positive value throughout, for all time values. Is there any other forum anyone can suggest ?
Here is the main script file:
clear memory; clear all;
global Nc capitalambda muh lambdah del1 del2 p eta alpha1 alpha2 muv lambdav global dims Q t0 tfinal gamma Ct0 b1 b2 Ct0r b3 H C m_tilda betaHV bitesPERlanding IC global tspan Hs Cs betaVH k landingARRAY muARRAY
Nhh=33898857; Nvv=2*Nhh; Nc=21571585; g=354; % number of public health centers in Bihar state %Fix human parameters capitalambda= 1547.02; muh=0.000046142; lambdah= 0.07; del1=0.001331871263014; del2=0.000288658; p=0.24; eta=0.0083; alpha1=0.044; alpha2=0.0217; %Fix vector parameters muv=0.071428; % UNIT:2.13 SANDFLIES DEAD/SAND FLY/MONTH, SOURCE: MUBAYI ET AL., 2010 lambdav=0.05; % UNIT:1.5 TRANSMISSIONS/MONTH, SOURCE: MUBAYI ET AL., 2010
Ct0=0.054;b1=0.0260;b2=0.0610; Ct0r=0.63;b3=0.0130;
dimsH=6; % AS THERE ARE FIVE HUMAN COMPARTMENTS dimsV=3; % AS THERE ARE TWO VECTOR COMPARTMENTS dims=dimsH+dimsV; % THE TOTAL NUMBER OF COMPARTMENTS OR DIFFERENTIAL EQUATIONS
gamma=32; % spraying is done of 1st feb of the year
Q=0.2554; H=7933615; C=5392890;
m_tilda=100000; % assumed value 6.5, later I will have to get it for sand flies or mosquitoes betaHV=66.67/1000000; % estimated value from the short technical report sent by Anuj bitesPERlanding=lambdah/(m_tilda*betaHV); betaVH=lambdav/bitesPERlanding; IC=zeros(dims+1,1); % CREATES A MATRIX WITH DIMS+1 ROWS AND 1 COLUMN WITH ALL ELEMENTS AS ZEROES
t0=1; tfinal=40; for j=t0:1:(tfinal*4-4) tspan(1)= t0; tspan(j+1)= tspan(j)+0.25; end clear j;
% INITIAL CONDITION OF HUMAN COMPARTMENTS q1=0.8; q2=0.02; q3=0.0005; q4=0.0015; IC(1,1) = q1*Nhh; IC(2,1) = q2*Nhh; IC(3,1) = q3*Nhh; IC(4,1) = q4*Nhh; IC(5,1) = (1-q1-q2-q3-q4)*Nhh; IC(6,1) = Nhh; % INTIAL CONDITIONS OF THE VECTOR COMPARTMENTS IC(7,1) = 0.95*Nvv; %80 PERCENT OF TOTAL ARE ASSUMED AS SUSCEPTIBLE VECTORS IC(8,1) = 0.05*Nvv; %20 PRECENT OF TOTAL ARE ASSUMED AS INFECTED VECTORS IC(9,1) = Nvv; IC(10,1)=0;
Hs=2000000; Cs=3000000; k=1; landingARRAY=zeros(tfinal*50,2); muARRAY=zeros(tfinal*50,2);
[te0 ye0]=ode45(#NoEffects_derivative_6_15_2012,tspan,IC); [teL yeL]=ode45(#OnlyLethal_derivative_6_15_2012,tspan,IC);
figure(1) subplot(4,3,1); plot(te0,ye0(:,1),'b-',teL,yeL(:,1),'r-'); xlabel('time'); ylabel('S'); legend('susceptible humans'); subplot(4,3,2); plot(te0,ye0(:,2),'b-',teL,yeL(:,2),'r-'); xlabel('time'); ylabel('I'); legend('Infectious Cases'); subplot(4,3,3); plot(te0,ye0(:,3),'b-',teL,yeL(:,3),'r-'); xlabel('time'); ylabel('G'); legend('Cases in Govt. Clinics'); subplot(4,3,4); plot(te0,ye0(:,4),'b-',teL,yeL(:,4),'r-'); xlabel('time'); ylabel('T'); legend('Cases in Private Clinics'); subplot(4,3,5); plot(te0,ye0(:,5),'b-',teL,yeL(:,5),'r-'); xlabel('time'); ylabel('R'); legend('Recovered Cases');
subplot(4,3,6);plot(te0,ye0(:,6),'b-',teL,yeL(:,6),'r-'); hold on; plot(teL,capitalambda/muh); xlabel('time'); ylabel('Nh'); legend('Nh versus time');hold off;
subplot(4,3,7); plot(te0,ye0(:,7),'b-',teL,yeL(:,7),'r-'); xlabel('time'); ylabel('X'); legend('Susceptible Vectors');
subplot(4,3,8); plot(te0,ye0(:,8),'b-',teL,yeL(:,8),'r-'); xlabel('time'); ylabel('Z'); legend('Infected Vectors');
subplot(4,3,9); plot(te0,ye0(:,9),'b-',teL,yeL(:,9),'r-'); xlabel('time'); ylabel('Nv'); legend('Nv versus time');
subplot(4,3,10);plot(te0,ye0(:,10),'b-',teL,yeL(:,10),'r-'); xlabel('time'); ylabel('FS'); legend('Total number of human infections');
figure(2) plot(te0,ye0(:,10)-yeL(:,10)); xlabel('time'); ylabel('FS(without intervention)-FS(with lethal effect)'); legend('Diff. bet. VL cases with and w/o intervention:ode45');
The function file: NoEffects_derivative_6_15_2012
function dx = NoEffects_derivative_6_15_2012( t , x )
global Nc capitalambda muh del1 del2 p eta alpha1 alpha2 muv global dims m_tilda betaHV bitesPERlanding betaVH
dx = zeros(dims+1,1); % t % dx
dx(1,1) = capitalambda-(m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-muh*x(1,1);
dx(2,1) = (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-(del1+eta+muh)*x(2,1);
dx(3,1) = p*eta*x(2,1)-(del2+alpha1+muh)*x(3,1);
dx(4,1) = (1-p)*eta*x(2,1)-(del2+alpha2+muh)*x(4,1);
dx(5,1) = alpha1*x(3,1)+alpha2*x(4,1)-muh*x(5,1);
dx(6,1) = capitalambda -del1*x(2,1)-del2*x(3,1)-del2*x(4,1)-muh*x(6,1);
dx(7,1) = muv*(x(7,1)+x(8,1))-bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-muv*x(7,1);
%dx(8,1) = lambdav*x(7,1)*x(2,1)/(x(6,1)+Nc)-muvIOFt(t)*x(8,1);
dx(8,1) = bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-muv*x(8,1);
dx(9,1) = (muv-muv)*x(9,1);
dx(10,1) = (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/x(9,1);
The function file: OnlyLethal_derivative_6_15_2012
function dx=OnlyLethal_derivative_6_15_2012(t,x)
global Nc capitalambda muh del1 del2 p eta alpha1 alpha2 muv global dims m_tilda betaHV bitesPERlanding betaVH k muARRAY
dx=zeros(dims+1,1);
% the below code saves some values into the second column of the two arrays % t muARRAY(k,1)=t; muARRAY(k,2)=artificialdeathrate1(t); k=k+1;
dx(1,1)= capitalambda-(m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-muh*x(1,1);
dx(2,1)= (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-(del1+eta+muh)*x(2,1);
dx(3,1)=p*eta*x(2,1)-(del2+alpha1+muh)*x(3,1);
dx(4,1)=(1-p)*eta*x(2,1)-(del2+alpha2+muh)*x(4,1);
dx(5,1)=alpha1*x(3,1)+alpha2*x(4,1)-muh*x(5,1);
dx(6,1)=capitalambda -del1*x(2,1)-del2*( x(3,1)+x(4,1) ) - muh*x(6,1);
dx(7,1)=muv*( x(7,1)+x(8,1) )- bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc) - (artificialdeathrate1(t) + muv)*x(7,1);
dx(8,1)= bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-(artificialdeathrate1(t) + muv)*x(8,1);
dx(9,1)= -artificialdeathrate1(t) * x(9,1);
dx(10,1)= (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/x(9,1);
The function file: artificialdeathrate1
function art1=artificialdeathrate1(t)
global Q Hs H Cs C
art1= Q*Hs*iOFt(t)/H + (1-Q)*Cs*oOFt(t)/C ;
The function file: iOFt
function i = iOFt(t)
global gamma tfinal Ct0 b1
if t>=gamma && t<=tfinal
i = Ct0*exp(-b1*(t-gamma));
else
i =0;
end
The function file: oOFt
function o = oOFt(t)
global gamma Ct0 b2 tfinal
if (t>=gamma && t<=tfinal)
o = Ct0*exp(-b2*(t-gamma));
else
o = 0;
end
If your working code is even remotely as messy as the code you posted, then that should IMHO the first thing you should address.
I cleaned up iOFt, oOFt a bit for you, since those were quite easy to handle. I tried my best at NoEffects_derivative_6_15_2012. What I'd personally change to your code is using decent indexes. You have 10 variables, there is no way that if you let your code rest for a few weeks or months, that you will remember what state 7 is for example. So instead of using (7,1), you might want to rewrite your ODE either using verbose names and then retrieving/storing them in the x and dx vectors. Or use indexes that make it clear what is happening.
E.g.
function ODE(t,x)
insectsInfected = x(1);
humansInfected = x(2);
%etc
dInsectsInfected = %some function of the rest
dHumansInfected = %some function of the rest
% etc
dx = [dInsectsInfected; dHumansInfected; ...];
or
function ODE(t,x)
iInsectsInfected = 1;
iHumansInfected = 2;
%etc
dx(iInsectsInfected) = %some function of x(i...)
dx(iHumansInfected) = %some function of x(i...)
%etc
When you don't do such things, you might end up using x(6,1) instead of e.g. x(3,1) in some formulas and it might take you hours to spot such a thing. If you use verbose names, it takes a bit longer to type, but it makes debugging a lot easier and if you understand your equations, it should be more obvious when such an error happens.
Also, don't hesitate to put spaces inside your formulas, it makes reading much easier. If you have some sub-expressions that are meaningful (e.g. if (1-p)*eta*x(2,1) is the number of insects that are dying of the disease, just put it in a variable dyingInsects and use that everywhere it occurs). If you align your assignments (as I've done above), this might add to code that is easier to read and understand.
With regard to the ODE solver, if you are sure your implementation is correct, I'd also try a solver for stiff problems (unless you are absolutely sure you don't have a stiff system).