i think i've done this shit RMSE: 0.64 !!!!

This commit is contained in:
2025-11-07 01:44:59 +03:00
parent cfae423f11
commit 74e02df205
3 changed files with 38 additions and 125 deletions

View File

@@ -77,32 +77,6 @@ class MAEFitness(BaseFitness):
return float(np.mean(np.abs(predicted - true_values)))
class HuberFitness(BaseFitness):
"""Huber Loss (компромисс между MSE и MAE)"""
def __init__(
self,
target_fn: TargetFunction,
test_points_fn: TestPointsFn,
delta: float = 1.0,
):
super().__init__(target_fn, test_points_fn)
self.delta = delta
def fitness_fn(
self,
chromosome: Chromosome,
predicted: NDArray[np.float64],
true_values: NDArray[np.float64],
) -> float:
error = predicted - true_values
mask = np.abs(error) <= self.delta
squared = 0.5 * (error[mask] ** 2)
linear = self.delta * (np.abs(error[~mask]) - 0.5 * self.delta)
huber = np.concatenate([squared, linear])
return float(np.mean(huber))
class NRMSEFitness(BaseFitness):
"""Нормализованный RMSE (масштаб-инвариантен)"""
@@ -128,12 +102,18 @@ class PenalizedFitness(BaseFitness):
base_fitness: BaseFitness,
lambda_: float = 0.001,
depth_weight: float = 0.2,
scale_penalty: bool | None = None,
):
super().__init__(target_fn, test_points_fn)
self.base_fitness = base_fitness
self.lambda_ = lambda_
self.depth_weight = depth_weight
# Масштабировать штраф необязательно, если функция фитнеса нормализована
if scale_penalty is None:
scale_penalty = not isinstance(base_fitness, NRMSEFitness)
self.scale_penalty = scale_penalty
def fitness_fn(
self,
chromosome: Chromosome,
@@ -146,4 +126,8 @@ class PenalizedFitness(BaseFitness):
depth = chromosome.root.get_depth()
penalty = self.lambda_ * (size + self.depth_weight * depth)
if self.scale_penalty:
penalty *= base
return float(base + penalty)

View File

@@ -42,29 +42,25 @@ def grow_mutation(chromosome: Chromosome, max_depth: int) -> Chromosome:
def node_replacement_mutation(chromosome: Chromosome) -> Chromosome:
"""Мутация замены операции (Node Replacement Mutation).
Выбирает случайный узел с операцией (arity > 0) и заменяет его
на случайную другую операцию той же арности, сохраняя поддеревья.
Выбирает случайный узел и заменяет его
на случайную другую операцию той же арности или терминал, сохраняя поддеревья.
Если подходящей альтернативы нет — возвращает копию без изменений.
"""
chromosome = chromosome.copy()
operation_nodes = [n for n in chromosome.root.list_nodes() if n.value.arity > 0]
if not operation_nodes:
return chromosome
target_node = random.choice(operation_nodes)
target_node = random.choice(chromosome.root.list_nodes())
current_arity = target_node.value.arity
same_arity_ops = [
same_arity = [
op
for op in chromosome.operations
for op in list(chromosome.operations) + list(chromosome.terminals)
if op.arity == current_arity and op != target_node.value
]
if not same_arity_ops:
if not same_arity:
return chromosome
new_operation = random.choice(same_arity_ops)
new_operation = random.choice(same_arity)
target_node.value = new_operation