function results = switch_em(y,x1,x2,x3,b1,b2,b3,crit,maxit) % PURPOSE: Switching Regime regression (EM-estimation) % y1 = x1*b1 + e1 % y2 = x2*b2 + e2 % y3 = x3*b3 + e3; e3 =N(0,1) % y = y1 if y3 <= 0, y = y2 if y3 > 0 %--------------------------------------------------- % USAGE: results = switch_em(y,x1,x2,x3,crit) % where: y = dependent variable vector (nobs x 1) % x1 = independent variables matrix (nobs x k1) % x2 = independent variables matrix (nobs x k2) % x3 = independent variables matrix (nobs x k3) % b1 = (optional) initial values for b1 % b2 = (optional) initial values for b2 % b3 = (optional) initial values for b3 % crit = (optional) convergence criteria (default = 0.001) % maxit = maximum # of iterations (default = 1000) %--------------------------------------------------- % RETURNS: a structure % results.meth = 'switch_em' % results.beta1 = bhat1 % results.beta2 = bhat2 % results.beta3 = bhat3 % results.t1 = t-stats for bhat1 % results.t2 = t-stats for bhat2 % results.t3 = t-stats for bhat3 % results.y1 = predicted values regime 1 % results.y2 = predicted values regime 2 % results.yhat = yhat based on probs > 0.5 % results.r1 = residuals regime 1 % results.r2 = residuals regime 2 % results.resid = residuals based on probs > 0.5 % results.sig1 = e1'*e1/(n1-k1) % results.sig2 = e2'*e2/(n2-k2) % results.rsqr1 = rsquared, regime 1 % results.rsqr2 = rsquared, regime 2 % results.nobs = nobs % results.k1 = k1, variables in x1 % results.k2 = k2, variables in x2 % results.k3 = k3, variables in x3 % results.nvar = k1+k2+k3 % results.y = y data vector % results.prob1 = probability of regime 1 % results.prob2 = probability of regime 2 % results.iter = # of iterations in EM-algorithm % results.crit = convergence criterion % results.like = likelihood function value % -------------------------------------------------- % SEE ALSO: prt,plt switchm_em %--------------------------------------------------- % written by: % James P. LeSage, Dept of Economics % University of Toledo % 2801 W. Bancroft St, % Toledo, OH 43606 % jpl@jpl.econ.utoledo.edu if nargin == 4 bflag = 0; crit = 0.001; maxit = 1000; elseif nargin == 7 bflag = 1; crit = 0.001; maxit = 1000; elseif nargin == 8 bflag = 1; maxit = 1000; elseif nargin == 9 bflag = 1; else error('Wrong # of arguments to switch_em'); end; [n1 k1] = size(x1); [n2 k2] = size(x2); [n3 k3] = size(x3); if n1 ~= n2 error('switch_em: x1, x2 have different nobs'); elseif n2 ~= n3 error('switch_em: x2, x3 have different nobs'); end; nobs = n1; % start EM-loop converge = 1.0; iter = 0; if bflag == 0 % user supplied NO initial values % get starting values using postiive and negative y's ypos = find(y > 0); yneg = find(y <= 0); res = ols(y(ypos,1),x1(ypos,:)); sig1 = res.sige; b1 = res.beta; res = ols(y(yneg,1),x2(yneg,:)); sig2 = res.sige; b2 = res.beta; % b3 starting values using ad-hockery res = ols(y,x3); b3 = res.beta; else % user supplied b1,b2,b3 we need to find sig1,sig2 sig1 = (y - x1*b1)'*(y - x1*b1)/nobs; sig2 = (y - x2*b2)'*(y - x2*b2)/nobs; end; while converge > crit f1=norm_pdf(((y-x1*b1)/sig1)/sig1); f2=norm_pdf(((y-x2*b2)/sig2)/sig2); lamda=norm_cdf(-x3*b3); h=(lamda.*f1)+((1-lamda).*f2); chk = find(h == 0); if length(chk > 0) h(chk) = 0.01; end; w1=lamda.*f1./h; w2=ones(nobs,1)-w1; epsilon=x3*b3+(f2-f1).*norm_pdf(-x3*b3./h); t1=sum(w1); t2=sum(w2); if t1 <= 1 error('switch_em: regime 1 weights are all near zero'); end; if t2 <= 1 error('switch_em: regime 2 weights are all near zero'); end; w1 = sqrt(w1); w2 = sqrt(w2); xx1=matmul(x1,w1); xx2=matmul(x2,w2); y1=y.*w1; y2=y.*w2; b01 = b1; b02 = b2; b03 = b3; b1=inv(xx1'*xx1)*xx1'*y1; b2=inv(xx2'*xx2)*xx2'*y2; b3=inv(x3'*x3)*x3'*epsilon; sig01 = sig1; sig02 = sig2; sig1=y1-xx1*b1; sig2=y2-xx2*b2; sig1=sqrt(sig1'*sig1/t1); sig2=sqrt(sig2'*sig2/t2); % check for convergence c = max(abs(b1-b01)); c = max(c,max(abs(b2-b02))); c = max(c,max(abs(b3-b03))); c = max(c,max(sig1-sig01)); converge = max(c,max(sig2-sig02)); iter = iter + 1; if iter > maxit warn('switch_em: maximum # of iterations exceeded'); break; end; end; % compute t-statistics tmp = sig1*(inv(xx1'*xx1)); results.t1 = b1./sqrt(diag(tmp)); tmp = sig2*(inv(xx2'*xx2)); results.t2 = b2./sqrt(diag(tmp)); tmp = inv(x3'*x3); % sig3 = 1 results.t3 = b3./sqrt(diag(tmp)); % return results results.meth = 'switch_em'; results.iter = iter; results.crit = converge; results.beta1 = b1; results.beta2 = b2; results.beta3 = b3; results.nobs = nobs; results.k1 = k1; results.k2 = k2; results.k3 = k3; results.nvar = k1+k2+k3; results.y = y; results.prob1 = w1.^2; results.prob2 = w2.^2; results.y1 = xx1*b1; results.y2 = xx2*b2; results.r1 = y-results.y1; results.r2 = y-results.y2; results.sig1 = sig1; results.sig2 = sig2; % compute R-squared based on two regimes sigu1 = 0; sigu2 = 0; y1sum = 0; y2sum = 0; y1s = 0; y2s = 0; prob1 = results.prob1; nobs1 = 0; nobs2 = 0; for i=1:nobs if prob1(i,1) > 0.5 sigu1 = sigu1 + results.r1(i,1)*results.r1(i,1); y1sum = y1sum + y(i,1); y1s = y1s + y1sum*y1sum; nobs1 = nobs1+1; else sigu2 = sigu2 + results.r2(i,1)*results.r2(i,1); y2sum = y2sum + y(i,1); y2s = y2s + y2sum*y2sum; nobs2 = nobs2+1; end; end; % Overall y-hat and R-squared yhat = zeros(nobs,1); resid = zeros(nobs,1); for j=1:2 for i=1:nobs if prob1 >= 0.5 yhat(i,1) = xx1(i,:)*b1; resid(i,1) = y(i,1) - yhat(i,1); else yhat(i,1) = xx2(i,:)*b2; resid(i,1) = y(i,1) - yhat(i,1); end; end; end; results.yhat = yhat; results.resid = resid; results.rsqr1 = 1 - sigu1/y1s; % r-squared results.rsqr2 = 1 - sigu2/y2s; % log likelihood like = log((1-lamda).*f1 + lamda.*f2); results.like = sum(like);