def fit(self, vecs, pq_iter=<NUM_LIT:20>, rotation_iter=<NUM_LIT:10>, seed=<NUM_LIT>):
assert vecs.dtype == np.float32<EOL>assert vecs.ndim == <NUM_LIT:2><EOL>_, D = vecs.shape<EOL>self.R = np.eye(D, dtype=np.float32)<EOL>for i in range(rotation_iter):<EOL><INDENT>print("<STR_LIT>".format(i, rotation_iter))<EOL>X = vecs @ self.R<EOL>pq_tmp = PQ(M=self.M, Ks=self.Ks, verbose=self.verbose)<EOL>if i == rotation_iter - <NUM_LIT:1>:<EOL><INDENT>pq_tmp.fit(X, iter=pq_iter, seed=seed)<EOL><DEDENT>else:<EOL><INDENT>pq_tmp.fit(X, iter=<NUM_LIT:1>, seed=seed)<EOL><DEDENT>X_ = pq_tmp.decode(pq_tmp.encode(X))<EOL>U, s, V = np.linalg.svd(vecs.T @ X_)<EOL>print("<STR_LIT>", np.linalg.norm(X - X_, '<STR_LIT>'), "<STR_LIT>")<EOL>if i == rotation_iter - <NUM_LIT:1>:<EOL><INDENT>self.pq = pq_tmp<EOL>break<EOL><DEDENT>else:<EOL><INDENT>self.R = U @ V<EOL><DEDENT><DEDENT>return self<EOL>
Given training vectors, this function alternatively trains
        (a) codewords and (b) a rotation matrix.
        The procedure of training codewords is same as :func:`PQ.fit`.
        The rotation matrix is computed so as to minimize the quantization error
        given codewords (Orthogonal Procrustes problem)

        This function is a translation from the original MATLAB implementation to that of python
        http://kaiminghe.com/cvpr13/index.html

        If you find the error message is messy, please turn off the verbose flag, then
        you can see the reduction of error for each iteration clearly

        Args:
            vecs: (np.ndarray): Training vectors with shape=(N, D) and dtype=np.float32.
            pq_iter (int): The number of iteration for k-means
            rotation_iter (int): The number of iteration for leraning rotation
            seed (int): The seed for random process

        Returns:
            object: self