Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/demo1.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def main():
os.chdir(script_dir)

# Filepath
file_path = os.path.join("datasets", "corners_3clusters.csv")
file_path = os.path.join("datasets", "corners_5clusters.csv")

# Generate data with corners distribution and save it to a CSV file
data_with_labels = DataGenerator.generate_data_corners(
Expand Down
3 changes: 3 additions & 0 deletions src/gaufs/data_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,9 @@ def _generate_cluster_centered(
# significant dimensions
# Generate random direction vector
denom = 0.0
# avoid division by zero in case the random vector is zero
denom = 1.0 if denom == 0.0 else denom

for j in range(num_dims_sig):
vector_aux[j] = random.uniform(-1, 1)
denom = denom + vector_aux[j] ** 2
Expand Down
30 changes: 17 additions & 13 deletions src/gaufs/gaufs.py
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ def run(self):
f"Optimal number of clusters: {self._optimal_variable_selection_and_num_of_clusters[1]}\n"
)
f.write(
f"Fitness: {self._optimal_variable_selection_and_num_of_clusters}\n\n"
f"Fitness: {self._fitness_of_optimal_variable_selection_and_num_of_clusters}\n\n"
)
f.write("Selected Variables:\n")
f.write(
Expand Down Expand Up @@ -888,7 +888,7 @@ def run(self):

return (
self._optimal_variable_selection_and_num_of_clusters,
self._optimal_variable_selection_and_num_of_clusters,
self._fitness_of_optimal_variable_selection_and_num_of_clusters,
)

def run_genetic_searches(self):
Expand Down Expand Up @@ -1002,7 +1002,7 @@ def analyze_variable_weights(self):
"Variable significances not computed. Please run genetic searches with `run_genetic_searches` before analyzing variable weights."
)

thresholds = sorted(self._variable_significance, reverse=True)
thresholds = sorted(set(self._variable_significance), reverse=True)

# list of the considered selections
possible_variable_selections = []
Expand Down Expand Up @@ -1228,7 +1228,9 @@ def plot_dictionaries(self):
_plot_discontinuous(ax1, x1, y1, marker="o", color="black")
ax1.set_xlabel("Number of Selected Variables")
ax1.set_ylabel("Number of Clusters")
ax1.set_title("Number of Clusters for Each Selection")
ax1.set_title(
r"Number of Clusters for Each Selection $\Psi_{\text{num\_clusters}}$"
)
ax1.grid(True, alpha=0.3)
ax1.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax1.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
Expand All @@ -1239,7 +1241,7 @@ def plot_dictionaries(self):
ax2.plot(x2, y2, marker="o", color="tab:blue")
ax2.set_xlabel("Number of Selected Variables")
ax2.set_ylabel("Fitness")
ax2.set_title("Fitness for Each Selection")
ax2.set_title(r"Fitness for Each Selection $\tilde{\Psi}_{\text{fitness}}$")
ax2.grid(True, alpha=0.3)
ax2.xaxis.set_major_locator(plt.MaxNLocator(integer=True))

Expand All @@ -1249,15 +1251,19 @@ def plot_dictionaries(self):
ax3.plot(x3, y3, marker="o", color="tab:blue")
ax3.set_xlabel("Number of Selected Variables")
ax3.set_ylabel("Threshold")
ax3.set_title("Threshold for Each Selection")
ax3.set_title(r"Threshold for Each Selection $\tilde{\Psi}_{\text{weight}}$")
ax3.grid(True, alpha=0.3)
ax3.xaxis.set_major_locator(plt.MaxNLocator(integer=True))

# Plot 4: Importance (continuous line) and Delta Importance (red crosses)
ax4 = axes[1, 1]
x4, y4 = zip(*sorted(self._dict_num_var_selected_importance.items()))
ax4.plot(
x4, y4, marker="o", label="Selected Variables' Importance", color="navy"
x4,
y4,
marker="o",
label=r"Selected Variables' Importance $\Phi_{\text{average}}$",
color="navy",
)

x5, y5 = zip(
Expand All @@ -1271,15 +1277,15 @@ def plot_dictionaries(self):
marker="x",
s=50,
color="red",
label="Delta Importance with Exp Decay",
label=r"Delta Importance with Exp Decay $\tilde{\delta}_i$",
)

x_argmax = sum(self._optimal_variable_selection_and_num_of_clusters[0])
ax4.axvline(
x=x_argmax,
color="black",
linestyle="--",
label=f"Automatic solution with {x_argmax} variables achieving a fitness of: {self._dict_num_var_selected_fitness[x_argmax]:.3f}",
label=rf"Automatic solution: {x_argmax} = $\hat{{i}}$ variables and fitness of: {self._dict_num_var_selected_fitness[x_argmax]:.3f}",
)

ax4.set_xlabel("Number of Selected Variables")
Expand Down Expand Up @@ -1462,7 +1468,6 @@ def get_plot_comparing_solution_with_another_metric(
label=f"Automatic solution with {x_argmax} variables achieving a fitness of: {self._dict_num_var_selected_fitness[x_argmax]:.3f}",
)
ax1.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax1.legend()

# Right plot: Variables vs External Metric
# plot with discontinuities
Expand All @@ -1487,7 +1492,6 @@ def get_plot_comparing_solution_with_another_metric(
label=f"Automatic solution with {x_argmax} variables achieving a metric of: {external_metrics[num_vars.index(x_argmax)]:.3f}",
)
ax2.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax2.legend()

# Add baseline scores for true number of labels
if true_number_of_labels is not None:
Expand All @@ -1511,8 +1515,8 @@ def get_plot_comparing_solution_with_another_metric(
color="red",
label="Metric for each selection with True Number of Labels",
)
ax1.legend()
ax2.legend()
ax1.legend()
ax2.legend()

plt.tight_layout()

Expand Down
3 changes: 1 addition & 2 deletions src/gaufs/genetic_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def __init__(
self.num_clusters_and_its_max_fitness = dict()
# dictionary={variable_selection:(maximum fitness found for that selection (regardeless of the cluster number), number of times a chromosome with this selection entered in the hof)}
self.hof_counter = dict()
self.hof_weighted = dict()

# logbook to store statistics
self.logbook = tools.Logbook()
Expand Down Expand Up @@ -336,7 +335,7 @@ def run(self):
self.hof_counter[variables_selection] = (
max(old[0], ind.fitness.values[0]),
old[1] + 1,
) # maximo fitness y cuento las veces que ha entrado
) # max fitness and times it entered in the hof
else:
self.hof_counter[variables_selection] = (ind.fitness.values[0], 1)

Expand Down
11 changes: 9 additions & 2 deletions src/gaufs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,22 @@ def _clear_directory(directory_path):
# Helper function to plot with discontinuities
def _plot_discontinuous(ax, x_vals, y_vals, **kwargs):
"""Plot lines only between consecutive x values"""
# Extract label from kwargs
label = kwargs.pop("label", None)
i = 0
while i < len(x_vals):
# Find the end of the consecutive sequence
j = i
while j < len(x_vals) - 1 and x_vals[j + 1] == x_vals[j] + 1:
j += 1

# Plot this consecutive segment
ax.plot(x_vals[i : j + 1], y_vals[i : j + 1], **kwargs)
# Plot this consecutive segment: only the first segment carries the label
ax.plot(
x_vals[i : j + 1],
y_vals[i : j + 1],
label=label if i == 0 else None,
**kwargs,
)

# Move to next segment
i = j + 1
Expand Down
Loading