Normalize a matrix of row vectors to unit length. Contains a shortcut if there are no zero vectors in the matrix. If there are zero vectors, we do some indexing tricks to avoid dividing by 0. :param vectors: The vectors to normalize. :param norms: Precomputed norms. If thi
(vectors: npt.NDArray, norms: npt.NDArray | None = None)
| 7 | |
| 8 | |
| 9 | def normalize(vectors: npt.NDArray, norms: npt.NDArray | None = None) -> npt.NDArray: |
| 10 | """ |
| 11 | Normalize a matrix of row vectors to unit length. |
| 12 | |
| 13 | Contains a shortcut if there are no zero vectors in the matrix. |
| 14 | If there are zero vectors, we do some indexing tricks to avoid |
| 15 | dividing by 0. |
| 16 | |
| 17 | :param vectors: The vectors to normalize. |
| 18 | :param norms: Precomputed norms. If this is None, the norms are computed. |
| 19 | :return: The input vectors, normalized to unit length. |
| 20 | """ |
| 21 | if np.ndim(vectors) == 1: |
| 22 | norm_float = np.linalg.norm(vectors) |
| 23 | if np.isclose(norm_float, 0): |
| 24 | return np.zeros_like(vectors) |
| 25 | return vectors / norm_float |
| 26 | |
| 27 | if norms is None: |
| 28 | norm: npt.NDArray = np.linalg.norm(vectors, axis=1) |
| 29 | else: |
| 30 | norm = norms |
| 31 | |
| 32 | if np.any(np.isclose(norm, 0.0)): |
| 33 | vectors = np.copy(vectors) |
| 34 | nonzero = norm > 0.0 |
| 35 | result = np.zeros_like(vectors) |
| 36 | masked_norm = norm[nonzero] |
| 37 | masked_vectors = vectors[nonzero] |
| 38 | result[nonzero] = masked_vectors / masked_norm[:, None] |
| 39 | |
| 40 | return result |
| 41 | else: |
| 42 | return vectors / norm[:, None] |
| 43 | |
| 44 | |
| 45 | def normalize_or_copy(vectors: npt.NDArray) -> npt.NDArray: |
no outgoing calls
searching dependent graphs…