def meshy2_one(x1,x2,y,m,k1=[1],k2=[1],interp=0,mesh1=None,mesh2=None,lnorm=1,tune=50,eps=0.01,cvx_solver=0): # In this bivariate meshy solver, it is assumed that we are taking the same number of cuts per covariate: same m. In general though, can use m_1 cuts for x_1 and m_2 cuts for x_2. # interp = 0 : nearest neighbor # interp = 1 : linear weighting of nearest 2+1=3 neighbors # k1 is the order differences applied on x_1, k2 for x_2 # k1 and k2 can be lists, but they must be the same length such that they are paired at each index # possible solvers to choose from: typically CVXOPT works better for simulations thus far. solvers = [cvx.SCS,cvx.CVXOPT] # 0 is SCS, 1 CVXOPT default_iter = [160000,3200][cvx_solver] # defaults are 2500 and 100 n = x1.size # Create D-matrix: specify n and k if mesh1==None: mesh1 = np.linspace(min(x1)-eps,max(x1)+eps,m) if mesh2==None: mesh2 = np.linspace(min(x2)-eps,max(x2)+eps,m) delta1 = np.diff(mesh1)[0] # Regular grids, but x1 and x2 can have different range delta2 = np.diff(mesh2)[0] # Create O-matrix: specify x and number of desired cuts O = utils2.interpO(x1=x1,x2=x2,mesh1=mesh1,mesh2=mesh2,interp=interp) # Solve convex problem. theta = cvx.Variable(m,m) sobo_like = sobbynorm(k1=k1,k2=k2,lnorm=lnorm,theta=theta,delta1=delta1,delta2=delta2,m=m) obj = cvx.Minimize(0.5 * cvx.sum_squares(y - O*cvx.reshape(theta,m*m,1)) + tune * sobo_like) prob = cvx.Problem(obj) prob.solve(solver=solvers[cvx_solver],verbose=False,max_iters = default_iter) counter = 0 while prob.status != cvx.OPTIMAL: maxit = 2*default_iter prob.solve(solver=solvers[cvx_solver],verbose=False,max_iters=maxit) default_iter = maxit counter = counter +1 if counter>4: raise Exception("Solver did not converge with %s iterations! (N=%s,d=%s,k1=%s,k2=%s)" % (default_iter,n,m,k1,k2) ) output = {'mesh1': mesh1, 'mesh2':mesh2,'theta.hat': np.array(theta.value),'fitted':O.dot(np.reshape(np.array(theta.value),m*m,1)),'x1':x1,'x2':x2,'y':y,'k1':k1,'k2':k2,'interp':interp,'eps':eps,'m':m} return output
def meshy2_predict(meshy2_one_object,x1,x2): O = utils2.interpO(x1=x1,x2=x2,mesh1=meshy2_one_object['mesh1'],mesh2=meshy2_one_object['mesh2'],interp=meshy2_one_object['interp']) m = meshy2_one_object['m'] return O.dot(np.reshape(meshy2_one_object['theta.hat'],m*m,1))