mealpy icon indicating copy to clipboard operation
mealpy copied to clipboard

[BUG]: TypeError: Problem.init() missing 1 required positional argument: 'bounds'

Open Fa20 opened this issue 1 year ago • 9 comments

Description of the bug


TypeError Traceback (most recent call last) Cell In[34], line 48 41 bounds = [ 42
43 FloatVar(lb=0., ub=1.0, name="learning-rate")] 47 gwo= OriginalGWO(epoch, pop_size) ---> 48 best_position, best_fitness = gwo.solve(svr_problem) 49 print(f"Solution: {best_position}, Fitness: {best_fitness}")

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:223, in Optimizer.solve(self, problem, mode, n_workers, termination, starting_solutions, seed) 202 def solve(self, problem: Union[Dict, Problem] = None, mode: str = 'single', n_workers: int = None, 203 termination: Union[Dict, Termination] = None, starting_solutions: Union[List, np.ndarray, Tuple] = None, 204 seed: int = None) -> Agent: 205 """ 206 Args: 207 problem: an instance of Problem class or a dictionary (...) 221 g_best: g_best, the best found agent, that hold the best solution and the best target. Access by: .g_best.solution, .g_best.target 222 """ --> 223 self.check_problem(problem, seed) 224 self.check_mode_and_workers(mode, n_workers) 225 self.check_termination("start", termination, None)

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:157, in Optimizer.check_problem(self, problem, seed) 155 elif type(problem) == dict: 156 problem["seed"] = seed --> 157 self.problem = Problem(**problem) 158 else: 159 raise ValueError("problem needs to be a dict or an instance of Problem class.")

TypeError: Problem.init() missing 1 required positional argument: 'bounds'

Steps To Reproduce

  1. Define the model

def create_model(learning_rate, num_neurons): base_model = keras.applications.VGG16( weights='imagenet', input_shape=(224, 224, 3), include_top=False)

base_model.trainable = False
inputs = keras.Input(shape=(224, 224, 3))
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(num_neurons, activation='relu')(x)
outputs = keras.layers.Dense(6, activation='softmax')(x)
model = keras.Model(inputs, outputs)

model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=learning_rate),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
return model

2.# Fitness function for optimization def fitness_function(solution): learning_rate= 0.01 num_neurons= solution

model = create_model(learning_rate, int(num_neurons))

# Assuming train_it and valid_it are already defined
history = model.fit(train_it, validation_data=valid_it, 
                    steps_per_epoch=train_it.samples/train_it.batch_size, 
                    validation_steps=valid_it.samples/valid_it.batch_size, 
                    epochs=1, verbose=0)
val_accuracy = history.history['val_accuracy'][-1]

return history.history['val_accuracy'][-1] #1 - val_accuracy  # Minimize the inverse of accuracy

3.# number of neurons problem_size = 2 lb = [10] # lower bounds: num_neurons ub = [ 512] # upper bounds: num_neurons epoch = 1
pop_size = 5 # Size of the population in each generation pc = 0.95 # Crossover probability pm = 0.05 # Mutation probability

svr_problem = { "fit_func": fitness_function, 'lb':[1], # Lower bound of our parameters 'ub':[6], # upper bound of our parameters "minmax": "min" }

gwo= OriginalGWO(epoch, pop_size) best_position, best_fitness = gwo.solve(svr_problem) print(f"Solution: {best_position}, Fitness: {best_fitness}")

Additional Information

Here is my code to use meaply with pretrained model to find best values of hyperpramters: from mealpy.evolutionary_based.GA import BaseGA from mealpy.evolutionary_based.GA import BaseGA from mealpy.utils.problem import Problem from mealpy.utils.space import FloatVar, IntegerVar from mealpy.swarm_based.GWO import OriginalGWO from tensorflow.keras.optimizers import Adam

from tensorflow import keras from mealpy.evolutionary_based import GA

Define the model as a function

def create_model(learning_rate, num_neurons): base_model = keras.applications.VGG16( weights='imagenet', input_shape=(224, 224, 3), include_top=False)

base_model.trainable = False
inputs = keras.Input(shape=(224, 224, 3))
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(num_neurons, activation='relu')(x)
outputs = keras.layers.Dense(6, activation='softmax')(x)
model = keras.Model(inputs, outputs)

model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=learning_rate),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
return model

Fitness function for optimization

def fitness_function(solution): learning_rate= 0.01 num_neurons= solution

model = create_model(learning_rate, int(num_neurons))

# Assuming train_it and valid_it are already defined
history = model.fit(train_it, validation_data=valid_it, 
                    steps_per_epoch=train_it.samples/train_it.batch_size, 
                    validation_steps=valid_it.samples/valid_it.batch_size, 
                    epochs=1, verbose=0)
val_accuracy = history.history['val_accuracy'][-1]

return history.history['val_accuracy'][-1] #1 - val_accuracy  # Minimize the inverse of accuracy

Define boundaries for learning rate and number of neurons

problem_size = 2 lb = [10] # lower bounds: num_neurons ub = [ 512] # upper bounds: num_neurons epoch = 1
pop_size = 5 # Size of the population in each generation pc = 0.95 # Crossover probability pm = 0.05 # Mutation probability param_bounds = {

"num_neurons": list(range(10, 50))

} svr_problem = { "fit_func": fitness_function, 'lb':[1], # Lower bound of our parameters 'ub':[6], # upper bound of our parameters "minmax": "min" } bounds = [

FloatVar(lb=0., ub=1.0, name="learning-rate")]

gwo= OriginalGWO(epoch, pop_size) best_position, best_fitness = gwo.solve(svr_problem) print(f"Solution: {best_position}, Fitness: {best_fitness}")

Fa20 avatar Sep 28 '24 09:09 Fa20

@Fa20 Could you please put your code into a good format of "coding style". I can help you but with this format I don't know what are you doing with this code.

thieu1995 avatar Sep 28 '24 15:09 thieu1995

from tensorflow.keras.preprocessing.image import ImageDataGenerator
from mealpy.utils.problem import Problem
from mealpy.utils.space import IntegerVar
from mealpy.swarm_based.GWO import OriginalGWO
from tensorflow import keras
import numpy as np

# Create the data generators with validation split
datagen_train = ImageDataGenerator(
    samplewise_center=True,
    rotation_range=10,
    zoom_range=0.1,
    width_shift_range=0.1,
    height_shift_range=0.1,
    horizontal_flip=True,
    validation_split=0.2
)

# Load the training data and split into train and validation sets
train_it = datagen_train.flow_from_directory(
    "data/train/",
    target_size=(224, 224),
    color_mode="rgb",
    class_mode="categorical",
    subset='training'
)

valid_it = datagen_train.flow_from_directory(
    "data/train/",
    target_size=(224, 224),
    color_mode="rgb",
    class_mode="categorical",
    subset='validation'
)

# Define the model as a function
def create_model(learning_rate, num_neurons):
    base_model = keras.applications.VGG16(
        weights='imagenet',
        input_shape=(224, 224, 3),
        include_top=False)

    base_model.trainable = False
    inputs = keras.Input(shape=(224, 224, 3))
    x = base_model(inputs, training=False)
    x = keras.layers.GlobalAveragePooling2D()(x)
    x = keras.layers.Dense(num_neurons, activation='relu')(x)
    outputs = keras.layers.Dense(6, activation='softmax')(x)
    model = keras.Model(inputs, outputs)

    model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=learning_rate),
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model

# Define the objective (fitness) function
class NeuronOptimization(Problem):
    def __init__(self, bounds=None, minmax="max", name=None, **kwargs):
        super().__init__(bounds, minmax, **kwargs)
    
    def obj_func(self, solution):
        learning_rate = 0.01
        num_neurons = int(solution[0])  # We assume one-dimensional solution (neurons)
        
        # Create and train the model
        model = create_model(learning_rate, num_neurons)
        history = model.fit(train_it, validation_data=valid_it,
                            steps_per_epoch=train_it.samples // train_it.batch_size,
                            validation_steps=valid_it.samples // valid_it.batch_size,
                            epochs=1, verbose=1)
        
        # Return the validation accuracy as fitness
        val_accuracy = history.history['val_accuracy'][-1]
        return val_accuracy  # Maximizing accuracy, so returning as-is

# Define the search space for neurons
bounds = [IntegerVar(lb=10, ub=11, name='num_neurons')]

# Create the optimization problem instance
problem = NeuronOptimization(bounds=bounds, minmax="max", name="Neurons_Optimization")

# Set up the GWO optimizer
gwo = OriginalGWO(problem=problem, epoch=1, pop_size=5)

# Solve the optimization problem
best_position, best_fitness = gwo.solve()

# Output the result
print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

@thieu1995 Thank you so much I have updated the code but got differen error which I can not fix it

error I got ```

{ "name": "ValueError", "message": "problem needs to be a dict or an instance of Problem class.", "stack": "--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[65], line 86 83 gwo = OriginalGWO(problem=problem, epoch=1, pop_size=5) 85 # Solve the optimization problem ---> 86 best_position, best_fitness = gwo.solve() 88 # Output the result 89 print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:223, in Optimizer.solve(self, problem, mode, n_workers, termination, starting_solutions, seed) 202 def solve(self, problem: Union[Dict, Problem] = None, mode: str = 'single', n_workers: int = None, 203 termination: Union[Dict, Termination] = None, starting_solutions: Union[List, np.ndarray, Tuple] = None, 204 seed: int = None) -> Agent: 205 """ 206 Args: 207 problem: an instance of Problem class or a dictionary (...) 221 g_best: g_best, the best found agent, that hold the best solution and the best target. Access by: .g_best.solution, .g_best.target 222 """ --> 223 self.check_problem(problem, seed) 224 self.check_mode_and_workers(mode, n_workers) 225 self.check_termination("start", termination, None)

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:159, in Optimizer.check_problem(self, problem, seed) 157 self.problem = Problem(**problem) 158 else: --> 159 raise ValueError("problem needs to be a dict or an instance of Problem class.") 160 self.generator = np.random.default_rng(seed) 161 self.logger = Logger(self.problem.log_to, log_file=self.problem.log_file).create_logger(name=f"{self.module}.{self.class.name}")

ValueError: problem needs to be a dict or an instance of Problem class." }

Fa20 avatar Sep 28 '24 17:09 Fa20

@Fa20 , Hope that helps! There are several places that you messed it up. You need to define at least 2 parameters, if there is only 1 parameter you can use for loop instead of metaheuristics to optimize. When you define the bounds list, and define your own Problem, you need to call the decode_solution() and get parameter by name.

import numpy as np
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from mealpy import Problem, IntegerVar, FloatVar, OriginalGWO

# Create the data generators with validation split
datagen_train = ImageDataGenerator(
    samplewise_center=True,
    rotation_range=10,
    zoom_range=0.1,
    width_shift_range=0.1,
    height_shift_range=0.1,
    horizontal_flip=True,
    validation_split=0.2
)

# Load the training data and split into train and validation sets
train_it = datagen_train.flow_from_directory(
    "data/train/",
    target_size=(224, 224),
    color_mode="rgb",
    class_mode="categorical",
    subset='training'
)

valid_it = datagen_train.flow_from_directory(
    "data/train/",
    target_size=(224, 224),
    color_mode="rgb",
    class_mode="categorical",
    subset='validation'
)


# Define the model as a function
def create_model(learning_rate, num_neurons):
    base_model = keras.applications.VGG16(
        weights='imagenet',
        input_shape=(224, 224, 3),
        include_top=False)

    base_model.trainable = False
    inputs = keras.Input(shape=(224, 224, 3))
    x = base_model(inputs, training=False)
    x = keras.layers.GlobalAveragePooling2D()(x)
    x = keras.layers.Dense(num_neurons, activation='relu')(x)
    outputs = keras.layers.Dense(6, activation='softmax')(x)
    model = keras.Model(inputs, outputs)

    model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=learning_rate),
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model


# Define the objective (fitness) function
class NeuronOptimization(Problem):
    def __init__(self, bounds=None, minmax="max", **kwargs):
        super().__init__(bounds, minmax, **kwargs)

    def obj_func(self, solution):
        x = self.decode_solution(solution)
        lr, n_nodes = x["lr"], x["n_nodes"]

        # Create and train the model
        model = create_model(lr, n_nodes)
        history = model.fit(train_it, validation_data=valid_it,
                            steps_per_epoch=train_it.samples // train_it.batch_size,
                            validation_steps=valid_it.samples // valid_it.batch_size,
                            epochs=1, verbose=1)

        # Return the validation accuracy as fitness
        val_accuracy = history.history['val_accuracy'][-1]
        return val_accuracy  # Maximizing accuracy, so returning as-is


# Define the search space for neurons
bounds = [
    FloatVar(lb=0.0001, ub=0.5, name="lr"),
    IntegerVar(lb=5, ub=100, name="n_nodes")
]

# Create the optimization problem instance
problem = NeuronOptimization(bounds=bounds, minmax="max", name="Neurons_Optimization")

# Set up the GWO optimizer
gwo = OriginalGWO(problem=problem, epoch=10, pop_size=20)

# Solve the optimization problem
best_position, best_fitness = gwo.solve()

# Output the result
print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

thieu1995 avatar Sep 29 '24 00:09 thieu1995

@thieu1995 thanks for your answer . I'm still getting the same error as before .I rung the above code you provied me but I replaced

from mealpy import Problem, IntegerVar, FloatVar, OriginalGWO
by
from mealpy import Problem, IntegerVar, FloatVar
from mealpy.swarm_based.GWO import OriginalGWO ```

and still have same error as before


ValueError Traceback (most recent call last) Cell In[67], line 91 88 gwo = OriginalGWO(problem=problem, epoch=1, pop_size=5) 90 # Solve the optimization problem ---> 91 best_position, best_fitness = gwo.solve() 93 # Output the result 94 print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:223, in Optimizer.solve(self, problem, mode, n_workers, termination, starting_solutions, seed) 202 def solve(self, problem: Union[Dict, Problem] = None, mode: str = 'single', n_workers: int = None, 203 termination: Union[Dict, Termination] = None, starting_solutions: Union[List, np.ndarray, Tuple] = None, 204 seed: int = None) -> Agent: 205 """ 206 Args: 207 problem: an instance of Problem class or a dictionary (...) 221 g_best: g_best, the best found agent, that hold the best solution and the best target. Access by: .g_best.solution, .g_best.target 222 """ --> 223 self.check_problem(problem, seed) 224 self.check_mode_and_workers(mode, n_workers) 225 self.check_termination("start", termination, None)

File c:\Users\FI\AppData\Local\Programs\Python\Python310\lib\site-packages\mealpy\optimizer.py:159, in Optimizer.check_problem(self, problem, seed) 157 self.problem = Problem(**problem) ... --> 159 raise ValueError("problem needs to be a dict or an instance of Problem class.") 160 self.generator = np.random.default_rng(seed) 161 self.logger = Logger(self.problem.log_to, log_file=self.problem.log_file).create_logger(name=f"{self.module}.{self.class.name}")

ValueError: problem needs to be a dict or an instance of Problem class.```

Fa20 avatar Sep 29 '24 00:09 Fa20

@Fa20 , OMG. My bad. I got so much attention to your code that I also forgot the syntax. lol. You need to put the Problem into the solve function. Not in the algorithm itself.

# Set up the GWO optimizer
gwo = OriginalGWO(epoch=10, pop_size=20)

# Solve the optimization problem
best_position, best_fitness = gwo.solve(problem=problem)

# Output the result
print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

thieu1995 avatar Sep 29 '24 07:09 thieu1995

@Fa20, again. Look like your code is from previous version. I correct it again.

# Solve the optimization problem
best_agent = gwo.solve(problem=problem)

# Output the result
print(f"Best agent: {model.g_best}")                    
print(f"Best solution: {model.g_best.solution}")        
print(f"Best fitness: {model.g_best.target.fitness}")
print(f"Best real parameter: {model.problem.decode_solution(best_agent.solution)}")

thieu1995 avatar Sep 29 '24 11:09 thieu1995

@thieu1995 Thank you very much . what is model. ? print(f"Best agent: {model.g_best}")

Fa20 avatar Sep 29 '24 11:09 Fa20

@Fa20 , model is best_agent. My bad copy paste habit.

thieu1995 avatar Oct 08 '24 17:10 thieu1995

@thieu1995 still the code give me error : TypeError Traceback (most recent call last) Cell In[4], line 89 86 gwo = CSA.OriginalCSA(epoch=1, pop_size=5) 88 # Solve the optimization problem ---> 89 best_position, best_fitness = gwo.solve(problem=problem) 91 # Output the result 92 print(f"Best number of neurons: {int(best_position[0])}, Best validation accuracy: {best_fitness}")

TypeError: cannot unpack non-iterable Agent object

Fa20 avatar Oct 13 '24 19:10 Fa20

@Fa20,

You are using older version, please check out the documentation for the latest version 3.0.1 It should be: best_agent = gwo.solve(problem=problem)

thieu1995 avatar Jan 05 '25 12:01 thieu1995