| from .linalg import Matrix, Vector, identity, invert_matrix, matmul, matvec, np, scale_matrix, transpose |
|
|
|
|
| def _empty_matrix(matrix: Matrix) -> bool: |
| if np is not None and hasattr(matrix, "size"): |
| return int(matrix.size) == 0 |
| return not matrix |
|
|
|
|
| def ridge_regression_readout( |
| states: list[Vector], |
| targets: list[Vector], |
| *, |
| regularization: float, |
| ) -> Matrix: |
| if not states or not targets: |
| raise ValueError("States and targets must be non-empty for ridge readout.") |
| if np is not None: |
| state_matrix = np.asarray(states, dtype=np.float64).T |
| target_matrix = np.asarray(targets, dtype=np.float64).T |
| gram = state_matrix @ state_matrix.T |
| regularized = gram + (regularization * np.eye(gram.shape[0], dtype=np.float64)) |
| cross_covariance = target_matrix @ state_matrix.T |
| return np.linalg.solve(regularized.T, cross_covariance.T).T.tolist() |
|
|
| state_matrix = transpose(states) |
| target_matrix = transpose(targets) |
| gram = matmul(state_matrix, transpose(state_matrix)) |
| regularized = [ |
| [ |
| gram[row][col] + (regularization if row == col else 0.0) |
| for col in range(len(gram[row])) |
| ] |
| for row in range(len(gram)) |
| ] |
| inverse = invert_matrix(regularized) |
| cross_covariance = matmul(target_matrix, transpose(state_matrix)) |
| return matmul(cross_covariance, inverse) |
|
|
|
|
| def ridge_regression_readout_from_moments( |
| gram: Matrix, |
| cross_covariance: Matrix, |
| *, |
| regularization: float, |
| ) -> Matrix: |
| if _empty_matrix(gram) or _empty_matrix(cross_covariance): |
| raise ValueError("Gram and cross-covariance moments must be non-empty for ridge readout.") |
| if np is not None: |
| gram_array = np.asarray(gram, dtype=np.float64) |
| regularized = gram_array + (regularization * np.eye(gram_array.shape[0], dtype=np.float64)) |
| cross_covariance_array = np.asarray(cross_covariance, dtype=np.float64) |
| return np.linalg.solve(regularized.T, cross_covariance_array.T).T |
|
|
| regularized = [ |
| [ |
| gram[row][col] + (regularization if row == col else 0.0) |
| for col in range(len(gram[row])) |
| ] |
| for row in range(len(gram)) |
| ] |
| inverse = invert_matrix(regularized) |
| return matmul(cross_covariance, inverse) |
|
|
|
|
| def ridge_regression_readout_from_diagonal_moments( |
| feature_second_moment: Vector, |
| cross_covariance: Matrix, |
| *, |
| regularization: float, |
| ) -> Matrix: |
| if _empty_matrix(feature_second_moment) or _empty_matrix(cross_covariance): |
| raise ValueError("Diagonal moments and cross-covariance must be non-empty for ridge readout.") |
| if np is not None: |
| denominator = np.asarray(feature_second_moment, dtype=np.float64) + regularization |
| denominator = np.where(np.abs(denominator) > 1e-12, denominator, regularization) |
| cross_covariance_array = np.asarray(cross_covariance, dtype=np.float64) |
| return cross_covariance_array / denominator[None, :] |
|
|
| denominator = [ |
| value + regularization if abs(value + regularization) > 1e-12 else regularization |
| for value in feature_second_moment |
| ] |
| return [ |
| [ |
| value / denominator[col] |
| for col, value in enumerate(row) |
| ] |
| for row in cross_covariance |
| ] |
|
|
|
|
| def apply_readout(weights: Matrix, state: Vector) -> Vector: |
| return matvec(weights, state) |
|
|