def cf(X, kappa = 0): row, col = X.shape N = np.ones((col, col)) - np.eye(col) M = np.ones((row, row)) - np.eye(row) X2 = X ** 2 f1 = (1 - kappa) * np.sum(np.diag(cross_product(X2, X2.dot(N))) / 4) f2 = kappa * np.sum(np.diag(cross_product(X2, M.dot(X2))) / 4) return (1 - kappa) * X * (X2.dot(N)) + kappa * X * (M.dot(X2)), \ f1 + f2, 'Crawford-Ferguson kappa = ' + kappa
def bentler(X): X2 = X ** 2 M = cross_product(X2, X2) D = np.diag(np.diag(M)) return -L * (L2.dot(la.inv(M) - la.inv(D))), \ -(np.log(la.det(M)) - np.log(la.det(D))) / 4, \ 'Bentler\'s criterion'
def tandemII(X): XX = X.dot(X.T) XX2 = XX ** 2 f = np.sum(np.diag(cross_product(X ** 2, (1 - XX2).dot(X ** 2)))) Gq1 = 4 * X * ((1 - XX2).dot(X ** 2)) Gq2 = 4 * (XX * (X ** 2).dot((X ** 2).T)).dot(X) Gq = Gq1 - Gq2 return Gq, f, 'Tandem II'
def tandemI(X): XX = X.dot(X) XX2 = XX ** 2 Gq1 = 4 * X * (XX2.dot(X ** 2)) Gp2 = 4 * (XX * (X ** 2).dot((X ** 2).T)).dot(X) Gq = -Gq1 - Gq2 return Gq, -np.sum(np.diag(cross_product(X ** 2, XX2.dot(X ** 2)))), \ 'Tandem I'
def orthogonal_rotation(X, normalize = False, eps = 1e-5, max_iter = 1000, method = None): """ Parameters ---------- X : gamma : (default 0) normalize : (default False) eps : (default 1e-5) max_iter : (default 1000) """ if normalize: W = normalize_weight(X) X /= W al = 1 Tmat = np.eye(X.shape[1]) # diff L = X.dot(Tmat) # end obli_mat, obli_sum, method_name = method(L) # diff inter = cross_product(X, obli_mat) # end obli_mat2 = obli_mat.copy() obli_sum2 = obli_sum table = None row_ones = np.ones((1, inter.shape[0])) for i in range(max_iter + 1): # diff M = cross_product(Tmat, inter) inter2 = inter - Tmat.dot((M + M.T) / 2) sqrt_inter = np.sqrt(np.sum(np.diag(inter2.T.dot(inter2)))) # end record = np.array([i, obli_sum, np.log10(sqrt_inter), al]) if table is None: table = record else: table = np.vstack([table, record]) if sqrt_inter < eps: break al *= 2 for j in range(11): A = Tmat - al * inter2 # diff U, D, Vt = la.svd(A) Tmat2 = U.dot(Vt) L = X.dot(Tmat2) # end obli_mat2, obli_sum2, _ = method(L) # diff if obli_sum2 < (obli_sum - .5 * sqrt_inter ** 2 * al): break # end al /= 2 Tmat = Tmat2 obli_sum = obli_sum2 # diff inter = cross_product(X, obli_mat2) # end convergence = sqrt_inter < eps if i == max_iter and not convergence: print('Convergence not obtained in {}. {} iterations used.' .format(method_name, max_iter)) if normalize: L *= W Result = collections.namedtuple('Result', ['loadings', 'Phi', 'Th', 'table', 'method', 'orthogonal', 'convergence', 'Gq']) return Result(loadings = L, Phi = None, Th = Tmat, table = table, method = method_name, orthogonal = True, convergence = convergence, Gq = obli_mat2)
def varimax(X): """Varimax rotation. (Orthogonal)""" QL = (X ** 2) - np.mean(X ** 2, axis = 0) return -X * QL, -np.sqrt(np.sum(np.diag(cross_product(QL, QL)))) ** 2 / 4, \ 'Varimax'
def quartimax(X): return -X ** 3, -np.sum(np.diag(cross_product(X ** 2, X ** 2))) / 4, \ 'Quartimax'