Reframr-RFM-v2-Base / reframr /reservoir.py
OkeyMeta's picture
Add Reframr-RFM-v2-Base release files
52da7b7 verified
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)