Paper: GENOME: Generative Neuro-Symbolic Visual Reasoning by Growing and Reusing Modules (ICLR-2024)

Reviewer comment (Experiments):
Is there anything to prevent overfitting to the small train set of a given task, and only creating specific modules tailored for that domain? I can imagine that these overfitted modules may not be very useful in new tasks.

Author response:
**Q1-Q2. About overfitting VS training number.**
Thanks for concerns on the overfitting issue of train examples. Our GNSVR pipeline do have overfitting issue when the number of the training examples is too small (10), which could be reflected in the ablation study in table 5 of the revised paper. However, as the number of training examples goes up (50 and 100), the performance becomes stable, which is unlikely that the GNSVR framework creates a broad function signature overfitting the training examples. We believe that one reason for the strong few-shot performance of GNSVR is that all our pre-defined APIs are general APIs that work well for vision tasks in the wild. We also provide the performance VS test cases in the following tables for different tasks. As shown in the tables, as the training number is larger than a small number, our GNSVR framework becomes effective and relieve the overfitting issue. 

**Number of Sampling Examples**

Table 1: Number of Sampling Examples on GQA.
| # of samples | GQA |
| ------- | -------- |
| 60     | 44.5   |
| 120    | 45.3   |
| 300    | 45.9   |

Table 2: Number of Sampling Examples on RefCOCO.
| # of samples | RefCOCO |
| ------- | -------- |
| 10     | 49.4   |
| 50     | 67.0   |
| 100    | 67.1   |

Table 3: Number of Sampling Examples on RAVEN.
| # of samples | Center | L-R  | U-D  |
| ------------ | ------ | ---- | ---- |
| 5     | 46.5   | 37.2 | 39.8 |
| 10    | 80.1   | 67.6 | 69.1 |
| 20    | 80.1   | 67.6 | 69.1 |

Table 4: Number of Sampling Examples on MEWL.
| # of samples | shape | color |  material  |
| ------------ | -------- | -------- | --- |
| 5     | 38.9   | 39.6 | 37.9 |
| 10    | 43.7   | 45.3 | 41.0 |
| 20    | 43.7   | 45.3 | 41.0 |

Reviewer comment (Experiments):
Isn’t it possible that the method creates a broad function signature, but during stage 2 verification with the small set of train examples, it overfits to a bad implementation that only works for those examples, and therefore actually harms performance from there on out? I’m mainly concerned about the above two overfitting challenges.

Author response:
**Q1-Q2. About overfitting VS training number.**
Thanks for concerns on the overfitting issue of train examples. Our GNSVR pipeline do have overfitting issue when the number of the training examples is too small (10), which could be reflected in the ablation study in table 5 of the revised paper. However, as the number of training examples goes up (50 and 100), the performance becomes stable, which is unlikely that the GNSVR framework creates a broad function signature overfitting the training examples. We believe that one reason for the strong few-shot performance of GNSVR is that all our pre-defined APIs are general APIs that work well for vision tasks in the wild. We also provide the performance VS test cases in the following tables for different tasks. As shown in the tables, as the training number is larger than a small number, our GNSVR framework becomes effective and relieve the overfitting issue. 

**Number of Sampling Examples**

Table 1: Number of Sampling Examples on GQA.
| # of samples | GQA |
| ------- | -------- |
| 60     | 44.5   |
| 120    | 45.3   |
| 300    | 45.9   |

Table 2: Number of Sampling Examples on RefCOCO.
| # of samples | RefCOCO |
| ------- | -------- |
| 10     | 49.4   |
| 50     | 67.0   |
| 100    | 67.1   |

Table 3: Number of Sampling Examples on RAVEN.
| # of samples | Center | L-R  | U-D  |
| ------------ | ------ | ---- | ---- |
| 5     | 46.5   | 37.2 | 39.8 |
| 10    | 80.1   | 67.6 | 69.1 |
| 20    | 80.1   | 67.6 | 69.1 |

Table 4: Number of Sampling Examples on MEWL.
| # of samples | shape | color |  material  |
| ------------ | -------- | -------- | --- |
| 5     | 38.9   | 39.6 | 37.9 |
| 10    | 43.7   | 45.3 | 41.0 |
| 20    | 43.7   | 45.3 | 41.0 |

Reviewer comment (Experiments):
There seems to be an assumption that the queries in the train set actually all require similar modules, for example, to verify the new modules, the selected set of test cases from the train set must actually use those modules. I’m not sure if this is a reasonable assumption, and also, how is this sampling of train examples (both in stage 1 and stage 2) done?

Author response:
The training samples in stage 1 and stage 2 are the same samples, randomly sampled by question categories. Specially, we first sample N examples to perform stage 1 to get the new module signatures and a set of corresponding test cases. The module signatures contain the standard input and output formats of the new modules. A test case is generated by parsing the corresponding sample query into a high-level program. We consider a new generated module passes a test case if the execution of the high-level program generates the correct answer. We also group the training examples according to the same new module signature, and use them to generate a set of test cases that would be used to test the correctness of the new modules.

Reviewer comment (Experiments):
In the experiments, are Visprog/Viper also given the same few-shot training set? For example, I believe you can use the same method of error correction and correct both Visprog/Viper when it is incorrect. In this way, you can include Visprog/Viper comparison in Tables 3 and 4. Would be great to better disentangle what drives this improvement of performance -- modularity in the proposed modules, or the training examples given in the loop, etc.

Author response:
**Q4. Variants of VisProg and ViperGPT.** Thanks for your suggestion on implementing variants of VisProg and ViperGPT for Raven and MEWL. Note that both VisProg and ViperGPT have no training phase that **generates** new modules for **reusage** in the test phase. Thus, there is no easy way for VisProg and ViperGPT to perform error correction with test cases. During the rebuttal, we have implemented the new variants in the following way to make use of training examples for VisProg and ViperGPT. 
For VisProg, it requires a manual implementation of all modules by making use of the provided APIs. Thus, to enable VisProg handle Raven and MEWL tasks, we manually implement and debug new hand-crafted modules for VisProg to recognize and discover patterns to handle the task. We call this baseline **VisProg variant**. We also put the training examples in GNSVR' stage 1 into the prompt of **VisProg variant** for better performance. For ViperGPT, it has no manual modules and ask the LLMs to make use of the APIs to handle the instances. Thus, we manually write solutions for the training examples into the prompt of the ViperGPT to teach ViperGPT to handle the task. We call this approach **ViperGPT variant**. We have added such analysis into the revised paper. VisProg by itself needs a handcrafted solver module to find the target solution and it would be extremely difficult for ViperGPT to generate a solver from scratch. Thus, we add the solver module learnt from our GNSVR model to pre-defined API pool of VisProg and ViperGPT. As shown in table 5 and table 6 below, our GNSVR model achieves better performance than these two baselines, showing the great value of module learning for handling new tasks from only a few examples.

Table 5: Compare our GNSVR model with baselines, VisProg and ViperGPT on RAVEN.
| Methods | Center | L-R  | U-D  |
| ------- | ------ | ---- | ---- |
| VisProg variant  | 36.8   | 26.1 | 27.8 |
| ViperGPT variant | 40.6   | 30.7 | 32.4 |
| Ours    | 80.1   | 67.6 | 69.1 |

Table 6: Compare our GNSVR model with baselines, VisProg and ViperGPT on MEWL.
| Methods | shape | color |  material  |
| ------- | -------- | -------- | --- |
| VisProg variant | 35.2   | 35.9 | 34.9 |
| ViperGPT variant | 37.8   | 38.2 | 36.7 |
| Ours    | 43.7   | 45.3 | 41.0 |

Reviewer comment (Experiments):
Please clarify the selection of training examples used in stage 1 and 2.

Author response:
The training samples in stage 1 and stage 2 are the same samples, randomly sampled by question categories. Specially, we first sample N examples to perform stage 1 to get the new module signatures and a set of corresponding test cases. The module signatures contain the standard input and output formats of the new modules. A test case is generated by parsing the corresponding sample query into a high-level program. We consider a new generated module passes a test case if the execution of the high-level program generates the correct answer. We also group the training examples according to the same new module signature, and use them to generate a set of test cases that would be used to test the correctness of the new modules.

Reviewer comment (Experiments):
From my perspective, the biggest current weakness of the paper is that from the experimental design it’s hard to parse out exactly how the discovered modules affect the system's performance. Ostensibly, this can be gleaned from comparisons between GNSVR and VisProg/ViperGPT, but there are more differences between these systems beyond merging in discovered modules. Specifically, GNSVR uses a "base API" that is a combination of VisProg and ViperGPT, so the "fair" comparison would be against an ablated version of GNSVR that removes steps 1 and 2, and just tries to solve test-problems with the original API functions. This condition is considered in the ablation experiment (GNSVR w/o ML), but only a subset of the RefCOCO test-set. To solidify the claim that the improvement GNSVR observes stems from its discovered modules, this base condition should be added to all of the experimental set-ups (tables 1-5). For example, from Table 2 it’s unclear how much of the delta improvement between VisProg and GNSVR can be attributed to improvements in the base API versus improvements to the API from the new modules.

Author response:
**Q1. More ablation study on Performance**

Thanks for the insightful suggestions. We add more baseline experiments for comparison.

For the GQA and RefCOCO baseline's comparison, please refer to **Q2** below.

In Table 2 of the main paper, we showcase the capability of GNSVR's transfer learning. That is to say, the new modules learned from GQA and RefCOCO can be applied to the image editing and knowledge tagging task. Therefore, in the two tasks involved in Table 2, we did not learn any new modules but instead transferred and used new modules learned from other tasks. In Table 2, we can see that in all metrics, we surpassed VisProg. This performance improvement actually stems from the new modules generated from GQA and RefCOCO. It is these new modules that enabled functions that the inherent modules of VisProg couldn't achieve, thus leading to the improved performance of our system.

As for RAVEN and MEWL, we have implemented the ViperGPT and VisProg baseline experiments in the following way. 
For VisProg, it requires a manual implementation of all modules by making use of the provided APIs. Thus, to enable VisProg handle Raven and MEWL tasks, we manually implement and debug new hand-crafted modules for VisProg to recognize and discover patterns to handle the task. We call this baseline **VisProg variant**. We also put the training examples in GNSVR' stage 1 into the prompt of **VisProg variant** for better performance. For ViperGPT, it has no manual modules and ask the LLMs to make use of the APIs to handle the instances. Thus, we manually write solutions for the training examples into the prompt of the ViperGPT to teach ViperGPT to handle the task. We call this approach **ViperGPT variant**. We have added such analysis into the revised paper. VisProg by itself needs a handcrafted solver module to find the target solution and it would be extremely difficult for ViperGPT to generate a solver from scratch. Thus, we add the solver module learnt from our GNSVR model to pre-defined API pool of VisProg and ViperGPT. As shown in table 1 and table 2, our GNSVR model achieves better performance than these two baselines, showing the great value of module learning for handling new tasks from only a few examples.

Table 1: Compare our GNSVR model with baselines, VisProg and ViperGPT on RAVEN.
| Methods | Center | L-R  | U-D  |
| ------- | ------ | ---- | ---- |
| VisProg variant  | 36.8   | 26.1 | 27.8 |
| ViperGPT variant | 40.6   | 30.7 | 32.4 |
| Ours    | 80.1   | 67.6 | 69.1 |

Table 2: Compare our GNSVR model with baselines, VisProg and ViperGPT on MEWL.
| Methods | shape | color |  material  |
| ------- | -------- | -------- | --- |
| VisProg variant | 35.2   | 35.9 | 34.9 |
| ViperGPT variant | 37.8   | 38.2 | 36.7 |
| Ours    | 43.7   | 45.3 | 41.0 |

Reviewer comment (Experiments):
I’m slightly concerned about the design of the GNSVR w/o ML baseline. At inference time, is this baseline allowed to invoke arbitrary Python logic in the style of ViperGPT (e.g., standard control flow constructs), or is it restricted to *only* using API function calls in the style of VisProg? I would imagine that the first condition would be more fair to evaluate GNSVR. Solving some tasks might require simple logic that the LLM knows how to express in Python, but might not be directly expressible with a series of API calls. In GNSVR, this logic is incorporated into modules, but in the baseline the LLM should still have the opportunity to invoke similar logic in its test-time solutions; otherwise it’s impossible to properly evaluate the usefulness of the discovered modules. Please clarify which of these modes the baseline is operating in.

Author response:
**Q2. the detailed implementation of (GNSVR w/o ML baseline)**
Thanks for the concerns about the baseline's implementation. Our current implementation of the GNSVR w/o ML baseline is restricted to only using API function calls in the style of VisProg. To make it fair, we have wrapped the APIs in ViperGPT into **the same style** as VisProg and our GNSVR.
We highly value the reviewer's opinion and develop a new baseline variant, **GNSVR w/o ML v2**, where the LLM is allowed to invoke arbitrary python logic. s shown in table 3, our GNSVR performs better than both
two baselines across tasks, showing the effectiveness of the module learning.

Table 3: Comparison of GNSVR and baselines on RefCOCO and GQA.
| Model               | GQA     | RefCOCO|
| -------- |-------- | -------- | 
| **GNSVR w/o ML**    | 43.3    |  62.3  |
| **GNSVR w/o ML v2** | 40.9    |  65.5  | 
| **GNSVR**           | 45.9    |  67.1  |

Reviewer comment (Experiments):
Compared to VisProg and ViperGPT, this system seems to require more training data, as the I/O pairs are not only used to populate in-context examples, but also impact (i) what module concepts are proposed and (ii) how the correctness of each module concept is evaluated. This point about reliance on training data is touched on in the ablation section, but it would be good to make this distinction explicit when comparing the pros/cons of the proposed system against past work.

Author response:
**Q3. Discussion on the pros/cons of the proposed system against past work** Thanks for the suggestion to make the reliance on training examples distinct and explicit. Compared with existing methods, our GNSVR framework can leveraging LLMs to create new neural models or general code snippets for specific functions. Moreover, these newly generated modules in GNSVR can cooperate and be reused for various tasks, enhancing overall performance and adaptability. However, compared with existing frameworks VisProg and ViperGPT, we also need a few training examples to serve as test cases to learn new modules. We have also added the pros/cons of the proposed system in the related work section highlighted in the blue color in the revised version.

Reviewer comment (Reproducibility):
Can new modules be hierarchical (e.g., can one proposed module reference a previously proposed module), or can they only call out to the original API functions?

Author response:
**Q4. About hierarchical module generation.** We do **not** explicitly restrict the LLM to only use the original API functions. However, as we examine the generated modules one by one. We found that all the modules use the original APIs functions. The reasons are that we have provided examples in the prompt that make use of original APIs for new modules. However, we do believe that it is an interesting direction to include hierarchical module generation in the future work.

Reviewer comment (Reproducibility):
The error-correction and pass-rate logic for the module generation step are not clear. What is the "pass-rate" at which a function is accepted as a new module? From the listed examples it seems like a single input/output pair is used, so is the pass rate 1?

Author response:
**Q5. More Details about Pass Rate Definition.** Since we have been using multiple training examples for our module initialization. Thus, each initialized new module should be paired with multiple test cases (*i.e.* multiple instances of the visual reasoning tasks) and we only accept the modules that whose pass rate is larger than a threshold (0.5 in our implementation). We have added such explanation for pass rate in the revised paper.

Reviewer comment (Experiments):
What exactly is the error-correcting mechanism when one of the authored functions produces an error — is it sent back through the LLM with a modified prompt? How many times? What constitutes an error? This seems like a potentially important part of the contribution, so I would encourage the authors to even consider adding an ablation condition demonstrating this is helpful for the performance of the system.

Author response:
**Q6. Ablation on Debug mechanism.**

Table 4: Ablation on Debug mechanism.
| Method GNSVR | GQA |
| -------- | -------- |
|  Baseline | 45.9 |
|  w/o debug | 44.9 |

The error-correction prompt contains the error message from Python interpreter and wrong code snippet. We prompt the LLM to correct the wrong code based on the error message from Python interpreter.
We heuristically set the maximal number of debug iterations as 5. If the wrong code can be corrected within 5 iterations, we will keep it. Otherwise, it will be abandoned. (Details can be found in Module Generation section of Fig. 2)
The errors mainly stem from two sources: one is basic syntax errors in Python code, such as indentation and variable name errors. The other source is some fundamental logical errors, such as mistakes made when setting variable types, like treating a variable that should be of the bool type as the string type.
By observing the table above, we can conclude that the debug process can assist GNSVR with generating more useful modules to elevate performance and prevent elementary programming mistakes.

Reviewer comment (Evaluation):
It would be informative to provide additional details on the generated modules for each task: how many are created for each task? How often does each one get used in solving test-cases? Do they each capture distinct concepts, or are some modules duplicates?

Author response:
**Q7. how many modules are generated for each tasks**

**GQA** (13 modules)
VERIFY_COLOR, VERIFY_ACTION, VERIFY_ATTRIBUTE, VERIFY_MATERIAL, VERIFY_OBJECT, COMPARE_ATTRIBUTE, COMPARE_COLOR, COMPARE_MATERIAL, CHOOSE_ATTRIBUTE, CHOOSE_COLOR, CHOOSE_MATERIAL, CHOOSE_DEPTH, CHOOSE_ACTION.

**RefCOCO** (5 modules)
FILTER_COLOR, FILTER_SHAPE, VERIFY_RELATION, FILTER_RELATION, SORT_SPATIAL

**RAVEN** (4 modules) 
DETECT_COLOR, DETECT_SIZE, DETECT_SHAPE, SOLVER.

**MEWL** (4 modules)
DETECT_COLOR, DETECT_MATERIAL, DETECT_SHAPE, SOLVER.

We further take GQA as an example to exhibit the percentage of top-5 most-used new modules in GQA in table 5.

Table 5: Percentage of top-5 most-used new modules in GQA.
|Task|VERIFY_ATTRIBUTE |CHOOSE_ATTRIBUTE|VERIFY_COLOR|COMPARE_ATTRIBUTE|VERIFY_MATERIAL|
| -------  |  -------  | -------- | -------- | --- | --- |
| GQA      | 14.1 | 10.8  | 6.9 | 5.9 | 3.6 |

The data in the above table shows the proportion of the five most common new modules appearing in the generated high-level programs. Overall, 38.7% of all generated high-level programs use the newly generated modules (this 38.7% calculation includes other less common modules and excludes duplicate samples, such as a single high-level program containing multiple new modules). From these results, it can be seen that these newly learned modules can be widely applied to GQA, thereby helping GNSVR achieve good results on GQA.

Reviewer comment (Experiments):
For the inference in-context examples, are these chosen randomly from the training tasks that found a successful program?

Author response:
**Q9. inference context examples.** Yes. They are randomly chosen from training samples which generated successful programs. These examples utilize various newly generated modules. Each new module is assigned at least three successful training examples.

Reviewer comment (Reproducibility):
For the Raven task, my understanding is that the input is just a series of images. If this understanding is correct, how do you turn these images into a question? I am also quite curious to see the internals of the SOLVER generated module — is this module shared between Raven and MEWL, or does it employ distinct logic?

Author response:
**Q10. Details on Raven and MEWL.** Note that a visual reasoning task does **not** necessarily to use language as input. All we need is to prompt the LLMs to generate modules that recognize the patterns and solve the problem. In RAVEN, by prompting LLM, we can obtain DETECT_COLOR, DETECT_SHAPE, and DETECT_SIZE. The image is fed into these modules and the output is the color, shape, and size of the image. In this way, the input image is converted into a (color, shape, size) triplet. We provide LLM with ten examples from RAVEN train split to demonstrate how to deduce the pattern of these triplets. By observing few-shot demonstrations, we let LLM generate the SOLVER() module, which detects the pattern of input triplets from Problem Matrix and choose the most appropriate answer from the Answer Set. Therefore, the internal of the SOLVER() module is primarily based on judgment, used to identify the patterns of the input triples in the Problem Matrix, thereby finding the answer in the Answer Set. The workflow of RAVEN is shown in Fig. 5. As for MEWL, we employ a similar approach to handle it. One example is provided Fig. 6. Since MEWL and RAVEN have different patterns, the SOLVER() module is not shared between RAVEN and MEWL. Thus, it utilizes distinct logics.

Reviewer comment (Experiments):
How big of a role does "good initialization" of the neural module operators play? How important is defining the correct input and output format for a new module? How important is the selection of the few shot samples to evaluate a new module? (the authors say "We extracted 300 examples from GQA, 100 from RefCOCO, 10 from Raven, and 10 from MEWL based on experimental experience." - is the experience here just cherry picking for results or something else?) How important is the LLM capability to learn new modules? What role does the prompt play for the LLM in evaluating existing modules and creating new ones? Without detailed analysis to support answers to all these questions, the paper is limited in terms of explaining the method beyond just presenting a new method and showing empirical results.

Author response:
To explore the impact of sampling strategies on our experiment, we conducted an additional experiment with a random sampling of 300 samples, beyond our initial sampling strategy. In this setting, we randomly sampled 300 examples from the GQA train split. The performance was observed to be 44.3%, a decrease of 1.6% compared to 45.9%. This result suggests that a strategic sampling method can more effectively guide the LLM in generating more efficient modules for a given task. Relatively speaking, our method is robust in the face of choices in sampling strategies.

**Number of Sampling Examples**

Table 3: Number of Sampling Examples on GQA.
| # of samples | GQA |
| ------- | -------- |
| 60     | 44.5   |
| 120    | 45.3   |
| 300    | 45.9   |

Table 4: Number of Sampling Examples on RefCOCO.
| # of samples | RefCOCO |
| ------- | -------- |
| 10     | 49.4   |
| 50     | 67.0   |
| 100    | 67.1   |

Table 5: Number of Sampling Examples on RAVEN.
| # of samples | Center | L-R  | U-D  |
| ------------ | ------ | ---- | ---- |
| 5     | 46.5   | 37.2 | 39.8 |
| 10    | 80.1   | 67.6 | 69.1 |
| 20    | 80.1   | 67.6 | 69.1 |

Table 6: Number of Sampling Examples on MEWL.
| # of samples | shape | color |  material  |
| ------------ | -------- | -------- | --- |
| 5     | 38.9   | 39.6 | 37.9 |
| 10    | 43.7   | 45.3 | 41.0 |
| 20    | 43.7   | 45.3 | 41.0 |

We conduct a series of experiments to illustrate how the number of training samples influence the performance. 

In the GQA and RefCOCO datasets, if a small number of training samples are used, it's possible for the generated modules to overfit to certain samples, thereby reducing the generalization capability of the newly generated modules. Such overfitting in new modules can negatively impact the final results. Therefore, we can observe that when the number of samples is small, the performance of GNSVR is poorer. As the number of samples increases, the effectiveness of GNSVR improves. However, with a further increase in the number of samples, the performance gains of GNSVR tend to saturate.

Regarding RAVEN and MEWL, since their patterns of change are limited, the number of few-shot samples selected is sufficient if it already covers all the variation patterns in RAVEN and MEWL. In other words, if the number of samples exceeds this threshold, there won't be any further improvement in the results; if it's below this threshold, the performance will decline. We selected 10 few-shot samples each in RAVEN and MEWL. As can be seen from the results in the table above, if the number of samples is equal to 5, there is a noticeable decrease in performance. This is because 5 few-shot samples are not enough to cover all the variation patterns of RAVEN or MEWL. If the number of samples is equal to 10 or 20, at this point, the few-shot samples are sufficient to encompass all possible variations. In this case, the same results are obtained.

**Q1-3: Ablation on LLM's capability.**

Table 7: Ablation on LLM's capability.
| GPT | GQA |
| -------- | -------- |
|  gpt-3.5-turbo-instruct | 45.9 |
|  gpt-3.5-turbo | 44.3 |

By using a better LLM, our prompts can be better understood, and the LLM will generate higher quality modules. In this experiment, we compared the results of using gpt-3.5-turbo-instruct and gpt-3.5-turbo. Our experimental results show that better outcomes are achieved when using the more effective gpt-3.5-turbo-instruct. It is evident that the capabilities of the LLM influence the performance of GNSVR. As the abilities of LLMs continue to improve, so will the performance of GNSVR. Thanks to the flexibility of GNSVR, once a better LLM is available, we can easily switch to the latest LLM to achieve better results.