def logistic_warp(alpha, nu, q, y, deltaO=.1, deltag=.05, max_itr=8000, tol=1e-4, display=0, method=1): """ calculates optimal warping for function logistic regression :param alpha: scalar :param nu: numpy ndarray of shape (M,N) of M functions with N samples :param q: numpy ndarray of shape (M,N) of M functions with N samples :param y: numpy ndarray of shape (1,N) of M functions with N samples responses :rtype: numpy array :return gamma: warping function """ if method == 1: tau = 0 # q, scale = cf.scale_curve(q) q = q / norm(q) # nu, scale = cf.scale_curve(nu) # alpha = alpha/scale gam_old, O_old = lw.oclogit_warp( np.ascontiguousarray(alpha), np.ascontiguousarray(nu), np.ascontiguousarray(q), np.ascontiguousarray(y, dtype=np.int32), max_itr, tol, deltaO, deltag, display) elif method == 2: betanu = cf.q_to_curve(nu) beta = cf.q_to_curve(q) T = beta.shape[1] if y == 1: beta1, O_old, tau = cf.find_rotation_and_seed_coord(betanu, beta) q = cf.curve_to_q(beta1)[0] gam_old = cf.optimum_reparam_curve(nu, q) elif y == -1: beta1, O_old, tau = cf.find_rotation_and_seed_coord( -1 * betanu, beta) q = cf.curve_to_q(beta1)[0] gam_old = cf.optimum_reparam_curve(-1 * nu, q) return (gam_old, O_old, tau)
def regression_warp(nu, beta, y, alpha): """ calculates optimal warping for function linear regression :param nu: numpy ndarray of shape (M,N) of M functions with N samples :param beta: numpy ndarray of shape (M,N) of M functions with N samples :param y: numpy ndarray of shape (1,N) of M functions with N samples responses :param alpha: numpy scalar :rtype: numpy array :return gamma_new: warping function """ T = beta.shape[1] betanu = cf.q_to_curve(nu) betaM, O_M, tauM = cf.find_rotation_and_seed_coord(betanu, beta) q = cf.curve_to_q(betaM) gam_M = cf.optimum_reparam_curve(nu, q) betaM = cf.group_action_by_gamma_coord(betaM, gam_M) qM = cf.curve_to_q(betaM) y_M = cf.innerprod_q2(qM, nu) betam, O_m, taum = cf.find_rotation_and_seed_coord(-1 * betanu, beta) q = cf.curve_to_q(betam) gam_m = cf.optimum_reparam_curve(-1 * nu, q) betam = cf.group_action_by_gamma_coord(betam, gam_m) qm = cf.curve_to_q(betam) y_m = cf.innerprod_q2(qm, nu) if y > alpha + y_M: O_hat = O_M gamma_new = gam_M tau = tauM elif y < alpha + y_m: O_hat = O_m gamma_new = gam_m tau = taum else: gamma_new, O_hat, tau = cf.curve_zero_crossing(y - alpha, beta, nu, y_M, y_m, gam_M, gam_m) return(gamma_new, O_hat, tau)
def logistic_warp(alpha, nu, q, y, deltaO=.1, deltag=.05, max_itr=8000, tol=1e-4, display=0, method=1): """ calculates optimal warping for function logistic regression :param alpha: scalar :param nu: numpy ndarray of shape (M,N) of M functions with N samples :param q: numpy ndarray of shape (M,N) of M functions with N samples :param y: numpy ndarray of shape (1,N) of M functions with N samples responses :rtype: numpy array :return gamma: warping function """ if method == 1: tau = 0 # q, scale = cf.scale_curve(q) q = q/norm(q) # nu, scale = cf.scale_curve(nu) # alpha = alpha/scale gam_old, O_old = lw.oclogit_warp(np.ascontiguousarray(alpha), np.ascontiguousarray(nu), np.ascontiguousarray(q), np.ascontiguousarray(y, dtype=np.int32), max_itr, tol, deltaO, deltag, display) elif method == 2: betanu = cf.q_to_curve(nu) beta = cf.q_to_curve(q) T = beta.shape[1] if y == 1: beta1, O_old, tau = cf.find_rotation_and_seed_coord(betanu, beta) q = cf.curve_to_q(beta1) gam_old = cf.optimum_reparam_curve(nu, q) elif y == -1: beta1, O_old, tau = cf.find_rotation_and_seed_coord(-1 * betanu, beta) q = cf.curve_to_q(beta1) gam_old = cf.optimum_reparam_curve(-1 * nu, q) return (gam_old, O_old, tau)
def oc_srvf_align(beta, mode='O'): """ This claculates the mean of a set of curves and aligns them :param beta: numpy ndarray of shape (n, M, N) describing N curves in R^M :param mode: Open ('O') or closed curve ('C') (default 'O') :rtype: tuple of numpy array :return betan: aligned curves :return qn: aligned srvf :return betamean: mean curve :return mu: mean srvf """ n, T, N = beta.shape # find mean mu, betamean, v, q = curve_karcher_mean(beta, mode=mode) qn = zeros((n, T, N)) betan = zeros((n, T, N)) centroid2 = cf.calculatecentroid(betamean) betamean = betamean - tile(centroid2, [T, 1]).T q_mu = cf.curve_to_q(betamean) # align to mean for ii in range(0, N): beta1 = beta[:, :, ii] centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - tile(centroid1, [T, 1]).T # Iteratively optimize over SO(n) x Gamma for i in range(0, 1): # Optimize over SO(n) beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean, beta1) q1 = cf.curve_to_q(beta1) # Optimize over Gamma gam = cf.optimum_reparam_curve(q1, q_mu, 0.0) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta1 = cf.group_action_by_gamma_coord(beta1, gamI) # Optimize over SO(n) beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean, beta1) qn[:, :, ii] = cf.curve_to_q(beta1) betan[:, :, ii] = beta1 align_results = collections.namedtuple('align', ['betan', 'qn', 'betamean', 'mu']) out = align_results(betan, qn, betamean, q_mu) return out
def align_sub(beta_mean, q_mu, beta1): # Iteratively optimize over SO(n) x Gamma for i in range(0, 1): # Optimize over SO(n) beta1, O_hat, tau = cf.find_rotation_and_seed_coord(beta_mean, beta1) q1 = cf.curve_to_q(beta1) # Optimize over Gamma gam = cf.optimum_reparam_curve(q1, q_mu, 0.0) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta1 = cf.group_action_by_gamma_coord(beta1, gamI) # Optimize over SO(n) beta1, O_hat, tau = cf.find_rotation_and_seed_coord(beta_mean, beta1) return (beta1, q1, gamI)
def init_path_rand(beta1, beta_mid, beta2, T=100, k=5): r""" Initializes a path in :math:`\cal{C}`. beta1, beta_mid beta2 are already standardized curves. Creates a path from beta1 to beta_mid to beta2 in shape space, then projects to the closed shape manifold. :param beta1: numpy ndarray of shape (2,M) of M samples (first curve) :param betamid: numpy ndarray of shape (2,M) of M samples (mid curve) :param beta2: numpy ndarray of shape (2,M) of M samples (end curve) :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return alpha: a path between two q-functions :return beta: a path between two curves :return O: rotation matrix """ alpha = zeros((2, T, k)) beta = zeros((2, T, k)) q1 = cf.curve_to_q(beta1) q_mid = cf.curve_to_q(beta_mid) # find optimal rotation of q2 beta2, O1, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) # find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1) gamI = uf.invertGamma(gam) # apply optimal reparametrization beta2n = cf.group_action_by_gamma_coord(beta2, gamI) # find optimal rotation of q2 beta2n, O2, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) # Initialize a path as a geodesic through q1 --- q_mid --- q2 theta1 = arccos(cf.innerprod_q2(q1, q_mid)) theta2 = arccos(cf.innerprod_q2(q_mid, q2n)) tmp = arange(2, int((k-1)/2)+1) t = zeros(tmp.size) alpha[:, :, 0] = q1 beta[:, :, 0] = beta1 i = 0 for tau in range(2, int((k-1)/2)+1): t[i] = (tau-1.)/((k-1)/2.) qnew = (1/sin(theta1))*(sin((1-t[i])*theta1)*q1+sin(t[i]*theta1)*q_mid) alpha[:, :, tau-1] = cf.project_curve(qnew) x = cf.q_to_curve(alpha[:, :, tau-1]) a = -1*cf.calculatecentroid(x) beta[:, :, tau-1] = x + tile(a, [T, 1]).T i += 1 alpha[:, :, int((k-1)/2)] = q_mid beta[:, :, int((k-1)/2)] = beta_mid i = 0 for tau in range(int((k-1)/2)+1, k-1): qnew = (1/sin(theta2))*(sin((1-t[i])*theta2)*q_mid + sin(t[i]*theta2)*q2n) alpha[:, :, tau] = cf.project_curve(qnew) x = cf.q_to_curve(alpha[:, :, tau]) a = -1*cf.calculatecentroid(x) beta[:, :, tau] = x + tile(a, [T, 1]).T i += 1 alpha[:, :, k-1] = q2n beta[:, :, k-1] = beta2n return(alpha, beta, O)
def geod_sphere(beta1, beta2, k=5): """ This function calculates the geodesics between open curves beta1 and beta2 with k steps along path :param beta1: numpy ndarray of shape (2,M) of M samples :param beta2: numpy ndarray of shape (2,M) of M samples :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return dist: geodesic distance :return path: geodesic path :return O: rotation matrix """ lam = 0.0 elastic = 1 rotation = 1 returnpath = 1 n, T = beta1.shape beta1 = cf.resamplecurve(beta1, T) beta2 = cf.resamplecurve(beta2, T) centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - tile(centroid1, [T, 1]).T centroid2 = cf.calculatecentroid(beta2) beta2 = beta2 - tile(centroid2, [T, 1]).T q1 = cf.curve_to_q(beta1) if rotation: beta2, O1, tau = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) else: O1 = eye(2) q2 = cf.curve_to_q(beta2) if elastic: # Find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1, lam) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta2n = cf.group_action_by_gamma_coord(beta2, gamI) q2n = cf.curve_to_q(beta2n) if rotation: beta2n, O2, tau = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) else: q2n = q2 O = O1 # Forming geodesic between the registered curves dist = arccos(cf.innerprod_q2(q1, q2n)) if returnpath: PsiQ = zeros((n, T, k)) PsiX = zeros((n, T, k)) for tau in range(0, k): s = dist * tau / (k - 1.) PsiQ[:, :, tau] = (sin(dist-s)*q1+sin(s)*q2n)/sin(dist) PsiX[:, :, tau] = cf.q_to_curve(PsiQ[:, :, tau]) path = PsiQ else: path = 0 return(dist, path, O)
def init_path_rand(beta1, beta_mid, beta2, T=100, k=5): """ Initializes a path in \cal{C}. beta1, beta_mid beta2 are already standardized curves. Creates a path from beta1 to beta_mid to beta2 in shape space, then projects to the closed shape manifold. :param beta1: numpy ndarray of shape (2,M) of M samples (first curve) :param betamid: numpy ndarray of shape (2,M) of M samples (mid curve) :param beta2: numpy ndarray of shape (2,M) of M samples (end curve) :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return alpha: a path between two q-functions :return beta: a path between two curves :return O: rotation matrix """ alpha = zeros((2, T, k)) beta = zeros((2, T, k)) q1 = cf.curve_to_q(beta1) q_mid = cf.curve_to_q(beta_mid) # find optimal rotation of q2 beta2, O1, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) # find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1) gamI = uf.invertGamma(gam) # apply optimal reparametrization beta2n = cf.group_action_by_gamma_coord(beta2, gamI) # find optimal rotation of q2 beta2n, O2, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) # Initialize a path as a geodesic through q1 --- q_mid --- q2 theta1 = arccos(cf.innerprod_q2(q1, q_mid)) theta2 = arccos(cf.innerprod_q2(q_mid, q2n)) tmp = arange(2, int((k - 1) / 2) + 1) t = zeros(tmp.size) alpha[:, :, 0] = q1 beta[:, :, 0] = beta1 i = 0 for tau in range(2, int((k - 1) / 2) + 1): t[i] = (tau - 1.0) / ((k - 1) / 2.0) qnew = (1 / sin(theta1)) * (sin((1 - t[i]) * theta1) * q1 + sin(t[i] * theta1) * q_mid) alpha[:, :, tau - 1] = cf.project_curve(qnew) x = cf.q_to_curve(alpha[:, :, tau - 1]) a = -1 * cf.calculatecentroid(x) beta[:, :, tau - 1] = x + tile(a, [T, 1]).T i += 1 alpha[:, :, int((k - 1) / 2)] = q_mid beta[:, :, int((k - 1) / 2)] = beta_mid i = 0 for tau in range(int((k - 1) / 2) + 1, k - 1): qnew = (1 / sin(theta2)) * (sin((1 - t[i]) * theta2) * q_mid + sin(t[i] * theta2) * q2n) alpha[:, :, tau] = cf.project_curve(qnew) x = cf.q_to_curve(alpha[:, :, tau]) a = -1 * cf.calculatecentroid(x) beta[:, :, tau] = x + tile(a, [T, 1]).T i += 1 alpha[:, :, k - 1] = q2n beta[:, :, k - 1] = beta2n return (alpha, beta, O)
def geod_sphere(beta1, beta2, k=5): """ This function caluclates the geodecis between open curves beta1 and beta2 with k steps along path :param beta1: numpy ndarray of shape (2,M) of M samples :param beta2: numpy ndarray of shape (2,M) of M samples :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return dist: geodesic distance :return path: geodesic path :return O: rotation matrix """ lam = 0.0 elastic = 1 rotation = 1 returnpath = 1 n, T = beta1.shape beta1 = cf.resamplecurve(beta1, T) beta2 = cf.resamplecurve(beta2, T) centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - tile(centroid1, [T, 1]).T centroid2 = cf.calculatecentroid(beta2) beta2 = beta2 - tile(centroid2, [T, 1]).T q1 = cf.curve_to_q(beta1) if rotation: beta2, O1, tau = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) else: O1 = eye(2) q2 = cf.curve_to_q(beta2) if elastic: # Find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1, lam) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta2n = cf.group_action_by_gamma_coord(beta2, gamI) q2n = cf.curve_to_q(beta2n) if rotation: beta2n, O2, tau = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) else: q2n = q2 O = O1 # Forming geodesic between the registered curves dist = arccos(cf.innerprod_q2(q1, q2n)) if returnpath: PsiQ = zeros((n, T, k)) PsiX = zeros((n, T, k)) for tau in range(0, k): s = dist * tau / (k - 1.0) PsiQ[:, :, tau] = (sin(dist - s) * q1 + sin(s) * q2n) / sin(dist) PsiX[:, :, tau] = cf.q_to_curve(PsiQ[:, :, tau]) path = PsiQ else: path = 0 return (dist, path, O)