Open nbro opened 3 years ago
Good questions. It seems like you have some questions about PushGP in general and some questions about the specific implementation of pyshgp
. I'll break down my answer into sections.
1. Just a clarification of terminology.
GP/GAs are a family of methods, while supervised/unsupervised are a family of tasks/problems. It is possible to have supervised and unsupervised evolutionary systems. Typically, GP systems are supervised. The most popular kind of GP is symbolic regression/classification which is inherently supervised.
Based on my reading of your questions, it seems like you define "supervised" as: requires a dataset of know labels. If we configure our evolutionary systems with a fitness function, is that any less supervised? I would say no, but perhaps that is merely semantics.
2. Is PushGP always driven by input-output datasets?
No, PushGP can be driven by an error/fitness function. That said, in the PushGP literature it is almost always the case that we evaluate Push programs based on input-output pairs and thus the natural framing of the problem is usually with datasets. If you have a different way of evaluating programs, it is perfectly reasonable to supply your own error function.
3. How can custom error functions be used in pyshgp
?
There are 2 "public" APIs in pyshgp
: the Estimator
and the SearchAlgorithm
. The Estimator
API is meant to mirror the scikit-learn API, which is driven by datasets. As you have noticed in #150, pyshgp
will eventually open up Estimators
to support custom loss functions (still dataset driven) and custom evaluators (not dataset driven).
The SearchAlgorithm
API is less commonly used, but it is meant to handle what you are looking for. First you must instantiate a SearchConfiguration
, which includes an Evaluator
parameter. Then you instantiate a GeneticAlgorithm
with the config and call .run()
.
I recommend looking into using a FunctionEvaluator
for your evaluator.
4. How does the API of pyshgp
compare with the API of CPushPush?
I have never looked into either implementation of CPushPush. Maarten was the original author, and the fork you linked is maintained by Kwaku Yeboah-Antwi. Based on the GitHub issues of Kwaku's fork, it seems like there is no GP system built in and thus there would be no corresponding code construct.
Hopefully those answers have helped. Let me know if you have any other questions.
@erp12 Thanks! That clarifies a few things, especially about the estimator.
I am very familiar with SL, UL, RL, GA, etc., but I never thought of GA as supervised. In the past, I only used and implemented GA by thinking of the evaluation with a fitness function, which is more similar to a reward function in RL, so I would almost say that GP/GA is more similar to RL than SL or UL, but, yes, it's true, the supervisory signal could act as the fitness (which is the case of most of your examples, if I understood them).
Regarding SearchAlgorithm
, do you have examples? For example, could I solve the ant problem (a typical problem that GP is usually applied to) using SearchAlgorithm
? If you could provide a simple example of how to use this API, that would be nice. Meanwhile, I will see what I can do with SearchAlgorithm
.
Given that I wasn't yet familiar with the details of Push and PushGP when I wrote the comment above, I didn't really think about the difference between Push and PushGP, which seems to be just a simple implementation of GP in Push, which, as you say, is apparently not implemented in CPushPush
. I was probably confused because I was also looking at another codebase that uses CPushPush
that implements some form of GP.
I am still not very familiar with either Push/PushGP (implemented in other languages) and PyshGP. In all examples I've seen in this repo, it seems that you need to pass the inputs, denoted by X, and the targets/outputs, y. It's not clear to me why is this strictly necessary. If you're performing supervised learning, yes, sure you need a labeled dataset, but, in our case, we are performing GP, i.e. in general, in GP/GAs, you don't have to specify any target/label, you just need a way to evaluate the fitness. So, is this target what would be the fitness?
This does not seem right, because how can we evolve programs in case we don't have the target? We first need to execute the programs to evaluate them and then compute the targets (i.e. the evaluation of the programs), which would imply that the estimator assumes that you already executed and evaluated the programs, so how can you use PyshGP to evolve programs (i.e. GP)? So, what would the estimator actually do here?
What would this API (estimator that needs inputs and targets) correspond to (in terms of code constructs) in other implementations of Push and PushGP, in particular, I am interested in this C++ implementation by Maarten Keijzer?
I am trying to convert a GP program written with that C++ implementation to PyshGP, but it's not clear why you have targets in PyshGP, so what do they map to in that C++ implementation.