{
  "id": 551688,
  "title": "1st Place Detailed Solution",
  "content": "<p>I would like to thank Kaggle and EEDI for hosting this interesting competition! It was challenging and provided many opportunities to learn/apply new techniques. As always, I'm grateful to the Kaggle community for innovative ideas and engaging discussions. I'm excited to share my detailed solution and hope others will find it helpful!</p>\n<h2>1 Task</h2>\n<p>Given a diagnostic math MCQ, together with the correct answer and an incorrect answer, the task was to recommend top 25 misconceptions (sorted by their affinity to the incorrect answer) from a pool of 2.5k+ misconceptions. \nEven though the standard retrieve-rerank framework was a natural fit, it came with a few challenges:</p>\n<ul>\n<li>Current LLMs often struggle to mimic either (1) a <code>Novice Learner</code> i.e. generating the incorrect answer stemming from a specific misconception or (2) an <code>Expert Tutor</code> i.e. identifying the misconception that explains a given incorrect answer. LLMs excel at solving math problems, but they are not so great at counterfactual reasoning.</li>\n<li>The misconception pool ties together closely related conceptual and computational mistakes, demanding high discriminative power to spot subtle differences with precision. This is highlighted in the competition overview:</li>\n</ul>\n<blockquote>\n  <p>Initial efforts to use pre-trained language models have not been successful, likely due to the complexity of the mathematical content in the questions.</p>\n</blockquote>\n<ul>\n<li>The task setup requires the model to not only do well on known misconceptions but also generalize to new misconceptions.</li>\n</ul>\n<h2>2 Meta Thoughts</h2>\n<p>At the start of the competition, I had the following hypotheses on what could be important for a good solution:</p>\n<ul>\n<li>Synthetic data should help with out-of-distribution generalization</li>\n<li>High quality synthetic data generation should be feasible since Math domain can be verified and curated objectively</li>\n<li>Distillation from a good teacher(s) should be very powerful, as Large LLMs are significantly better at reasoning</li>\n<li>Distilling Chain of Thoughts (CoT) from top LLMs (e.g. Claude 3.5 Sonnet) should help to tackle difficult examples</li>\n<li>Quantization method and the calibration datasets could be important. We may need to add recovery adapters to the quantized models for maintaining top 1 accuracy.</li>\n<li>Full training might be better than LoRA</li>\n</ul>\n<p>These hypotheses guided me to design my experiments throughout the competition and helped me to stick to an idea even though the initial attempts were not successful.</p>\n<h2>3 Pipeline</h2>\n<p>I implemented a retrieve-and-rerank system that involved a sequence of four steps:</p>\n<ul>\n<li><strong>Retrieval</strong>: Identify top misconception candidates for each of the MCQ-Incorrect answer combinations. Specifically, I retained the top 32 retrieved candidates and included up to 32 additional candidates based on a dynamic threshold. The dynamic threshold is computed as the <code>top candidate similarity score - constant</code>. Candidates with similarity scores higher than the dynamic threshold are kept. </li>\n<li><strong>14B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-14B</code> ranker to process all retrieved candidates and shortlist top 8.</li>\n<li><strong>32B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-32B</code> ranker to process top 8 candidates and narrow them down to top 5.</li>\n<li><strong>72B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-72B</code> ranker to finalize the ranking of top 5 candidates.</li>\n</ul>\n<p>A schematic diagram of the pipeline and the leaderboard scores from each stages are shown below:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F3b2245b7c0baaab58b9d9232c6ff9bae%2Finference_pipeline.png?generation=1734198970117751&amp;alt=media\" alt=\"Inference Pipeline\"></p>\n<p>The final 25 misconception predictions comprised of:</p>\n<ul>\n<li>1st to 5th candidate from the 72B ranker</li>\n<li>6th to 8th candidate from the 32B ranker</li>\n<li>9th to 25th candidate from the 14B ranker.</li>\n</ul>\n<h2>4 Data</h2>\n<p>The training data mix for both the retriever and ranker models included competition data (1.8k examples) and synthetic data (10k examples). The synthetic data played a crucial role in improving both raw performance and generalization capability with respect to unseen misconceptions.</p>\n<h3>4.1 Synthetic Data</h3>\n<p>In an ideal scenario, synthetic MCQs should have the following properties:</p>\n<ul>\n<li>The designated correct answers are indeed the correct answers (high accuracy).</li>\n<li>The incorrect answers directly stem from the target misconception (high diagnostic power).</li>\n<li>Among all misconceptions in the misconception pool (2.5k+), the indicated misconception should provide the most precise explanation for a given incorrect answer (high resolution).</li>\n<li>The generated MCQs should cover a broad range of subjects and constructs (high diversity).</li>\n</ul>\n<p>I started generating diagnostic MCQs with a simple prompt that specified the expected format and a misconception of interest. However, it resulted in a dataset that violated almost all the properties to varying degrees. It was expected since</p>\n<ul>\n<li>The simple prompt only included information about a single misconception. Hence, the data-generating LLM was completely unaware of closely related misconceptions within the misconception pool.</li>\n<li>Lack of few shot examples meant lack of reference on the expected quality, difficulty level, tone, and language.</li>\n<li>Even the advanced LLMs struggle with handling misconceptions and counterfactual reasoning effectively.</li>\n<li>No curation was performed.</li>\n</ul>\n<p>I experimented with several strategies to address the issues and managed to create a high quality synthetic dataset with a <code>grouped synthetic data generation</code> approach and incorporating LLM based filtering. Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data. <a href=\"https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d\" target=\"_blank\">This notebook</a> demonstrates the clustering process. Here is an example of a misconception cluster:</p>\n<pre><code>- Thinks x^2 - a^2x is a valid form of difference of two squares\n- When factorising a quadratic without a non variable term, tries to double bracket factorise\n- Incorrectly factorises a quadratic\n- Believes the constant in an expanded quadratic comes from adding the two numbers in the brackets\n- Believes the coefficent of x in an expanded quadratic comes from multiplying the two numbers in the brackets\n- Does not recognise difference of two squares\n- Does not realise a quadratic must be in the form ax^2+bx+c=0 to be factorised\n- Does not know how to identify common factors from algebraic terms\n- Believes the difference of 2 squares method of factorising also works for the addition of 2 squares\n- When factorising, believes they can choose different factors for each term\n- Believes they can factorise a difference of two squares by placing the constant in both brackets without square rooting\n</code></pre>\n<p>I next generated 5 new MCQs for each cluster using <code>Claude 3.5 Sonnet</code> with a refined prompt that included 4-5 reference examples on misconceptions from the cluster. I used the <a href=\"https://github.com/anthropics/anthropic-cookbook/blob/main/misc/metaprompt.ipynb\" target=\"_blank\">metaprompt</a> tool from Anthropic cookbook for prompt engineering. Here is the final prompt used for data generation:</p>\n<pre><code>You will be generating Multiple Choice Questions (MCQs) that diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n&lt;misconceptions&gt;\n{cluster_misconceptions}\n&lt;/misconceptions&gt;\n\nHere are reference MCQs that demonstrate how to effectively diagnose these misconceptions:\n\n&lt;reference_mcqs&gt;\n{reference_mcqs}\n&lt;/reference_mcqs&gt;\n\nYour task is to generate {num_mcqs} new MCQs that diagnose misconceptions not already covered by the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n1. For each reference MCQ, identify in your &lt;analysis&gt; tags:\n   - Which misconception it targets\n   - How the incorrect answers map to specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n2. Note the style, difficulty level, and precision of language used\n\nThen, in your &lt;planning&gt; tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where it commonly appears\n- Design questions where the misconception leads naturally to specific wrong answers\n- Take notes on how you can craft new MCQs that adheres to the reference MCQs' style, difficulty level, and precision of language\n\nFinally, generate new MCQs following these important guidelines:\n- Make sure each incorrect answer maps clearly to exactly one misconception\n- Use precise mathematical language matching the style of reference MCQs\n- Make questions challenging enough that students must demonstrate real understanding\n- Ensure wrong answers are plausible and stem from genuine misconceptions, not careless errors\n- Use the exact wording of misconceptions as given in the misconceptions list\n- Pay careful attention to subtle differences between the misconceptions and observe which one is the most appropriate for a given incorrect answer\n- Keep the construct name and subject name as short as possible hiding the details of the misconception\n- Questions should be of higher difficulty level than reference MCQs\n</code></pre>\n<h3>4.1.1 Curation</h3>\n<p>I used LLM-as-a-judge to filter out low quality synthetic MCQs. I prompted <code>GPT-4o</code> to rate the quality of the synthetic MCQs as below:</p>\n<pre><code>You will analyze how well an incorrect answer reflects a suspected misconception in a mathematics problem. Your goal is to determine whether there is a clear, logical connection between the misconception and the wrong answer.\n\nHere is the problem with both correct and incorrect answers. The suspected misconception is also provided:\n&lt;problem&gt;\n{PROBLEM_DATA}\n&lt;/problem&gt;\n\nFirst, analyze the problem in your scratchpad:\n&lt;scratchpad&gt;\n1. Solve the problem independently to verify the correct answer\n2. Examine how someone holding the suspected misconception would approach the problem\n3. Trace the logical path from misconception to incorrect answer\n4. Identify any gaps or inconsistencies in this connection\n&lt;/scratchpad&gt;\n\nThen provide your evaluation using this format:\n&lt;evaluation&gt;\n1. Brief explanation of how the misconception could lead to the wrong answer\n2. Score from 0-10 based on these criteria:\n   - 10: Perfect alignment - wrong answer is direct result of misconception\n   - 8-9: Strong alignment - clear logical path from misconception to answer\n   - 5-7: Moderate alignment - connection exists but has some gaps\n   - 1-4: Weak alignment - connection is unclear or requires assumptions\n   - 0: No alignment - misconception does not explain wrong answer\n&lt;/evaluation&gt;\n\nImportant guidelines:\n- Focus solely on the logical connection between misconception and wrong answer\n- Do not speculate about other possible misconceptions\n- Be specific about how the misconception leads to the error\n- Flag and deduct scores if any assumptions are required to connect misconception to answer\n- Consider whether a student with this misconception would consistently arrive at this wrong answer\n</code></pre>\n<p>I selected <code>GPT-4o</code> as judge based on vibe test as it felt more sensitive to the scoring scheme and as consistent as Claude 3.5 Sonnet.</p>\n<h3>4.1.2 Incorporating Additional Misconceptions</h3>\n<p>While creating synthetic data, LLM produced many misconceptions (4k+) that were not part of the host provided misconception pool. I decided to keep the external misconceptions to improve generalization capability of the retriever and ranker models. </p>\n<p>Naively merging the external misconceptions with existing ones would have introduced conflicts and noise, since many of them were just rephrasing of the existing misconceptions. I adopted the following steps to handle this carefully:</p>\n<ul>\n<li>Attempt to match with existing misconceptions using string normalization (lowercasing, removing trailing punctuation, etc.)</li>\n<li>Attempt to match with existing misconceptions using similarity scores from an embedding model (<code>thenlper/gte-base</code>) with very high threshold (0.995)</li>\n<li>Remove new misconceptions that have fairly high similarity (between 0.95 and 0.995) with any of the existing misconceptions</li>\n<li>Keep rest of the remaining external misconceptions</li>\n</ul>\n<h3>4.1.3 Dataset</h3>\n<p>The final dataset is uploaded here: <a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset/\" target=\"_blank\">Eedi - Mining Misconceptions in Mathematics</a>. It contains</p>\n<ul>\n<li>1.8k competition MCQs + 10.6k generated MCQs</li>\n<li>4791 misconceptions\nand follows the same format as the original competition dataset.</li>\n</ul>\n<p>Reference: I'd highly recommend reading the synthetic data generation post from answer.ai: <a href=\"https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html\" target=\"_blank\">How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data</a>.</p>\n<h3>4.2 Chain of Thought (CoT) Generation</h3>\n<p>To distill the reasoning capability of an advanced LLM in my solution pipeline, I first created a dataset containing thought processes generated by <code>Claude 3.5 Sonnet</code>. I provided Claude with: (i) the problem statement, (ii) the correct answer, (iii) an incorrect answer, (iv) the ground truth misconception, and (v) several closely related misconceptions. Using this information, I prompted Claude to generate the likely thought process that led a student to select the incorrect answer. The prompt is shown below:</p>\n<pre><code>You will analyze a student's incorrect answer to identify the specific reasoning flaw that led to their error.\nYour goal is to explain precisely how their misconception caused them to arrive at the wrong answer.\n\nHere is the problem information:\n&lt;problem_data&gt;\n# Question: Simplify the expression: \\[x \\cdot y \\cdot x\\]\n# Correct Answer: \\(x^2y\\)\n# Incorrect Answer: \\(x^2\\)\n# Primary Misconception: Ignores variables without explicit coefficients when multiplying\n&lt;/problem_data&gt;\n\nHere are related misconceptions that are similar but do not explain this specific error as precisely:\n&lt;related_misconceptions&gt;\n- Thinks only like terms can be multiplied\n- Fails to combine all instances of the same variable\n- Incorrectly identifies an incomplete variable factor\n- Does not understand how to multiply algebraic terms\n&lt;/related_misconceptions&gt;\n\nFirst, examine all components of the problem carefully:\n1. The problem statement and question asked\n2. The correct answer and solution method\n3. The student's incorrect answer\n4. The primary misconception given\n5. The related misconceptions that should be distinguished from the primary one\n\nThen, reconstruct the student's likely thought process:\n- Identify the exact point where their reasoning diverged from the correct solution path\n- Note which specific mathematical operations or concepts they misapplied\n- Connect their error directly to the stated primary misconception\n- Verify that this explanation better fits the error than the related misconceptions\n\nWrite your analysis in &lt;evaluation&gt; tags, following this structure:\n- Show the correct calculation first\n- Show the incorrect calculations that demonstrate the error\n- Explain the specific flaw in the student's reasoning\n- Demonstrate how the misconception led to this particular error\n- Distinguish from the related misconceptions\n- Keep your explanation to 5-6 clear, non-repetitive sentences\n- Focus solely on the reasoning that produced this specific error\n\nGuidelines for writing your explanation:\n- Do not restate the problem or name the misconception\n- Be precise about the mathematical concepts involved\n- Show exactly how the misconception led to the error\n- Distinguish from related misconceptions\n- Avoid repetition\n- Stay focused on this specific error\n</code></pre>\n<p>Using this dataset, I fine-tuned three Qwen 2.5 series models (<code>Qwen/Qwen2.5-Math-7B</code>, <code>Qwen/Qwen2.5-14B</code>, and <code>Qwen/Qwen2.5-32B</code>) to act as reasoners. Notably, I omitted the true and related misconceptions from the input for fine-tuning. During inference, these models would see: (i) the problem statement, (ii) the correct answer, and (iii) an incorrect answer. They would then generate the likely thought process of a student behind selecting the incorrect answer. I used <code>vllm</code> for CoT generation during inference with <code>temperature=0.7, top_p=0.8, repetition_penalty=1.0, max_tokens=256</code>.</p>\n<p>The CoT dataset is uploaded here: <a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-sonnet-cot-comp-sharp-dec-09/\" target=\"_blank\">Eedi - CoT Dataset</a>.</p>\n<h2>5 Train-Validation Split</h2>\n<p>I split the competition dataset into 5 folds, initially based on the <code>QuestionId</code> field. However, this produced overly optimistic estimates with a large gap between validation and leaderboard scores. Next, I tried GroupKFold on <code>SubjectId</code>, but this resulted in overly pessimistic estimates. I finally settled on GroupKFold with <code>ConstructId</code>, which yielded a narrow Validation/LB gap and good correlation up to ~0.62 public LB score range.</p>\n<p>During development, I always trained my models on folds 1-4 and validated on fold 0. The synthetic data was marked as fold 99 and was included in the training set. The final models were trained on the entire dataset (full fit) using the same hyper parameters from the development stage.</p>\n<h2>6 Retrievers</h2>\n<p>I used the standard <a href=\"https://sbert.net/docs/package_reference/sentence_transformer/losses.html#multiplenegativesrankingloss\" target=\"_blank\">MultipleNegativesRankingLoss</a> to fine-tune the retrievers, while referencing the <a href=\"https://github.com/FlagOpen/FlagEmbedding/tree/master/FlagEmbedding/finetune/embedder/decoder_only\" target=\"_blank\">FlagEmbedding</a> codebase for developing training scripts. At this stage, I tracked both <code>map@25</code> and <code>recall@32</code> metrics and prioritized optimizing for <code>recall@32</code>, since recall was more important for overall pipeline performance.</p>\n<p>I fine-tuned several retrievers with the following scores:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fee7ac74c895fd5221738bf2ae8f42cee%2Fretriever_scores.png?generation=1734199290617188&amp;alt=media\" alt=\"Retriever Scores\"></p>\n<p>Incorporating hard negatives into training batches and distilling re-ranker scores consistently improved <code>map@25</code> performance, but did not positively impact <code>recall@32</code>. For my final submission selections, I chose the high-recall <code>Qwen/Qwen2.5-14B</code> encoder (Model 3) instead of the best <code>map@25</code> encoder (Model 4). Following the same logic, I also excluded the BGE encoder (Model 2).  Notably, my best encoder-only submission (Model 1 + Model 2 + Model 4) scored 0.524 on public LB and 0.475 on private LB.</p>\n<p>Retrievers were fine-tuned using LoRA with: <code>r=64, alpha=128, learning_rate_lora_a=1e-5, learning_rate_lora_b=5e-5, LoRA on all linear layers, batch_size=128, and epochs=12</code>. A few key factors that improved recall performance were:</p>\n<ul>\n<li>Setting temperature to 0.01, instead of the typically used value of 0.02 in LLM-based encoders</li>\n<li>Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives</li>\n<li>Pretraining the <code>Qwen/Qwen2.5-14B</code> encoder with all available synthetic data (before the curation step in section 4.1.1).</li>\n</ul>\n<p>What didn't work:</p>\n<ul>\n<li>Iterative hard negative mining</li>\n<li>Increasing batch size <a href=\"https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L194\" target=\"_blank\">through cross-device negatives</a></li>\n<li>Custom batching strategies e.g. having (query, misconception) positive pairs from the same SubjectId in the same batch</li>\n<li>My attempts at converting LLM retrievers to bi-directional encoders similar the the strategy used in <a href=\"https://huggingface.co/nvidia/NV-Embed-v2/blob/main/modeling_nvembed.py#L33\" target=\"_blank\">nvidia/NV-Embed-v2</a>.</li>\n</ul>\n<h2>6 Re-rankers</h2>\n<p>The Qwen 14B ranker did most of the heavy lifting by processing all retrieved misconceptions (32-64 candidates) and identifying top 8 candidates. This model was trained with a pointwise approach, where it sees one misconception at a time in the context window. The model input was structured as follows:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fa64d8d1be0b9fd0d27ddc7c8b47b7644%2Fpointwise_ranker.png?generation=1734199367236460&amp;alt=media\" alt=\"Pointwise Ranker\"></p>\n<p>The logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:</p>\n<pre><code>outputs = self.model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=True)\nlogits_yes = outputs.logits[:, -1, self.yes_loc]  # Yes token logit at the last position [bs]\nlogits_no = outputs.logits[:, -1, self.no_loc]  # No token logit at the last position [bs]\nlogits = logits_yes - logits_no  # [bs]\n\nlogits = logits.reshape(-1, self.group_size)\nlabels = labels.to(logits.device).reshape(-1) \nce_loss = self.loss_fn(logits, labels)\n</code></pre>\n<p>Each batch contained 1 positive and <code>batch_size-1</code> negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with <code>r=64, alpha=128, LoRA on all linear layers</code>. The language modelling head (<code>lm_head</code>) of the LLM (<code>Qwen/Qwen2.5-14B</code>) was frozen during fine-tuning.</p>\n<h3>6.1 Ablations</h3>\n<p>I found the following 4 strategies to be particularly significant for boosting the reranker performance and its generalization capability:</p>\n<h3>6.1.1 Few Shot Examples</h3>\n<p>To retain and leverage the LLM's in-context learning capabilities, I optionally included a few reference misconception examples (0 to 2) in the model input context (as shown in the diagram above). Not all training examples contained these few-shot demonstrations. The objective was to encourage the model to use reference examples when available, and otherwise rely on its internal reasoning. During inference, I used 1 or 2 examples from the entire training set as demonstrations. This approach was particularly effective for the 14B ranker's performance boosting private LB score from 0.495 to 0.531 <strong>(+0.036)</strong>. At this point, I was only using the competition data for training.</p>\n<h3>6.1.2 Distillation / Pseudo Labelling</h3>\n<p>Next, I incorporated the synthetic examples (post curation) into the training pipeline through pseudo labeling. I first fine-tuned two pointwise 72B models (<code>Qwen/Qwen2.5-Math-72B</code> and <code>Qwen/Qwen2.5-72B</code>) using only the competition dataset. These models were then used to generate pseudo labels for the synthetic examples. Finally, I used competition + pseudo-labeled data to fine-tune the next iteration of the 14B rerankers. This strategy boosted the 14B reranker's private LB score from 0.531 to 0.575 <strong>(+0.044)</strong>.</p>\n<h3>6.1.3 Negative Ratio</h3>\n<p>Next, I experimented with increasing the number of negative samples per positive. Showing the rankers a large number of negatives during training helped to improve performance. For each positive, I next increased the number of negatives to 24 from earlier 16. At this point, I also added scaled number of synthetic examples 2x. These two modifications boosted the 14B reranker's private LB score from 0.575 to 0.596 <strong>(+0.021)</strong>.</p>\n<h3>6.1.4 Chain of Thought (CoT)</h3>\n<p>I finally added the fine-tuned CoT reasoners (Section 4.2) into training and inference pipeline. During training, CoTs produced from fine-tuned <code>Qwen/Qwen2.5-14B</code> reasoner were optionally added to the model input. 50% of training data used CoTs and 50% did not. This encouraged the model to use external reasoning when available and otherwise rely on its internal reasoning. CoT boosted the 14B reranker's private LB score from 0.596 to 0.615 <strong>(+0.019)</strong>.</p>\n<p>The impact of these strategies is summarized in the following table:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F933a9cbaf89521f3873ce3220955d411%2F14b_ablation_updated.png?generation=1734200026698363&amp;alt=media\" alt=\"Ablation\"></p>\n<p>The live eval during fine-tuning showed consistent improvement in the 14B reranker's performance.\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F32caa0b7b996ea5af12050a4dc23f1c9%2Flive_eval_14b_ranker.png?generation=1734199467358905&amp;alt=media\" alt=\"Live Eval\"></p>\n<h3>6.2 Pointwise Re-Ranker (<code>Qwen/Qwen2.5-32B</code>)</h3>\n<p>I fine-tuned the <code>Qwen/Qwen2.5-32B</code> model in exactly the same way as the 14B reranker (with a different seed). My best 32B model had validation score of <code>0.663</code> vs that of <code>0.646</code> for the 14B reranker. During inference, the 32B reranker was used to process top 8 candidates from the 14B reranker and narrow them down to top 5 candidates. Incorporating the 32B reranker boosted private LB score from <code>0.615</code> to <code>0.625</code> <strong>(+0.010)</strong>.</p>\n<h3>6.3 Listwise Re-Ranker (<code>Qwen/Qwen2.5-72B</code>)</h3>\n<p>The top 5 candidates were finally ranked in a listwise manner using a fine-tuned <code>Qwen/Qwen2.5-72B</code> model. Here, the model sees all of the top 5 candidates at once. An example model input is shown below:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fd044104a02153e758cbeda0b6914a14d%2Flistwise_model_input.png?generation=1734199518083387&amp;alt=media\" alt=\"Listwise\"></p>\n<p>This model had access to the even more information than pointwise re-rankers i.e.</p>\n<ul>\n<li>It sees 3 Chains of Thought (CoT) during inference - one each from the 7B, 14B, and 32B reasoners</li>\n<li>It sees up to 5 reference examples from the training set - 1 for each of the 5 candidate misconceptions</li>\n<li>It sees all of the candidates at once in the context window.</li>\n</ul>\n<p>The model had the best <code>MAP@5</code> among all of the rerankers (validation MAP@5 of <code>0.661</code>). LLM based Listwise rankers typically suffer from candidate position bias. One way to mitigate this is to run multiple inference runs by shuffling the position of the candidate misconceptions (Test time augmentation (TTA) like impact). I was unable to run TTA during inference due to time constraints. Incorporating the 72B reranker boosted private LB score from <code>0.625</code> to <code>0.638</code> <strong>(+0.013)</strong>.</p>\n<h3>6.4 Quantization</h3>\n<p>I quantized the fine-tuned rankers using <a href=\"https://github.com/casper-hansen/AutoAWQ\" target=\"_blank\">AutoAWQ</a>. I used task specific calibration datasets for each model to mitigate performance degradation. I tested the impact of calibration dataset with one of my 32B rerankers. The results are shown below:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F66dae22248f881fdf8a065979695c6e2%2Fcalibration_update.png?generation=1734200937122595&amp;alt=media\" alt=\"\"></p>\n<h3>6.5 What didn't work</h3>\n<ul>\n<li>Merging strategy as described in <a href=\"https://docs.google.com/document/d/1OjbjU5AOz4Ftn9xHQrX3oFQGhQ6RDUuXQipnQ9gn6tU/edit?tab=t.0\" target=\"_blank\">Continuous Fine-tuning Without Loss Using Lora and Mergekit</a></li>\n<li><a href=\"https://huggingface.co/Qwen/QwQ-32B-Preview\" target=\"_blank\">Qwen/QwQ-32B-Preview</a>: I naively fine-tuned it using the same steps as with <code>Qwen/Qwen2.5-32B</code> but got worse results. The QwQ model likely requires additional research to find out its proper usage.</li>\n</ul>\n<h2>7 Links</h2>\n<ul>\n<li><a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">Training code</a></li>\n<li><a href=\"https://www.kaggle.com/code/conjuring92/eedi-a2-pipeline?scriptVersionId=211785645\" target=\"_blank\">Inference Notebook</a></li>\n<li><a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset\" target=\"_blank\">Dataset with Synthetic + Competition MCQ</a></li>\n<li><a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-cot-sonnet-6k\" target=\"_blank\">CoT Dataset</a></li>\n</ul>\n<h2>8 References</h2>\n<ul>\n<li><a href=\"https://arxiv.org/pdf/2310.02439\" target=\"_blank\">Novice Learner and Expert Tutor: Evaluating Math Reasoning Abilities of Large Language Models with Misconceptions</a></li>\n<li><a href=\"https://github.com/vllm-project/vllm\" target=\"_blank\">vllm</a></li>\n<li><a href=\"https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html\" target=\"_blank\">How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data</a></li>\n<li><a href=\"https://github.com/FlagOpen/FlagEmbedding\" target=\"_blank\">FlagEmbedding</a></li>\n<li><a href=\"https://github.com/casper-hansen/AutoAWQ\" target=\"_blank\">AutoAWQ</a></li>\n</ul>",
  "comments": [
    {
      "id": 3072151,
      "author_name": "Nicholas Broad",
      "author_url": "",
      "post_date": "2024-12-14T19:03:56.193000",
      "content": "<p>Detailed is an understatement!</p>\n<p>This is great info to share, Raja. Congrats again!</p>",
      "votes": 5,
      "replies": []
    },
    {
      "id": 3154496,
      "author_name": "Orange",
      "author_url": "",
      "post_date": "2025-03-20T02:42:06.973000",
      "content": "<p>Hi, thanks for sharing such an excellent proposal—it’s a solid RAG framework concept. Here's my understanding of your approach to training the reasoner:</p>\n<ol>\n<li>First, you use a prompt with Claude 3.5 to generate a chain-of-thought (CoT) that might lead to selecting the wrong answer.</li>\n<li>Then, with the same input, you filter out the error causes and near-error causes and combine the resulting text with the generated CoT to form a query-CoT text pair for fine-tuning the student model.</li>\n</ol>\n<p>My question is: How do you ensure that the generated text—the CoT content—is accurate? Do you employ a curation step, similar to the one used in the synthesized data process, to filter for high-quality CoTs?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3155013,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2025-03-20T16:05:37.953000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/youwbpyr\" target=\"_blank\">@youwbpyr</a>, Thanks. Yes, I used the generated query-CoT pairs to distill Claude 3.5's reasoning capability into student models. For this competition, I didn't curate the generated CoTs. However, I think generating multiple CoTs and picking the best one as per a process reward model / llm-as-a-judge could improve student models reasoning abilities. </p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 3077833,
      "author_name": "Geremie Yeo",
      "author_url": "",
      "post_date": "2024-12-21T12:56:21.633000",
      "content": "<p>Hi Raja, thanks for the detailed solution! Congrats for the solo win🥇</p>\n<p>Would you mind if I ask a few questions ?</p>\n<p><strong>Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?</strong></p>\n<p>Context: I rented H100s from RunPod and finetuning using LoRA for a 14B Yes/No reranker took &gt; 5 hours with our team’s external data. For initial experiments I tested various numbers of hard negatives (1,2,4,8,16,24) and easily training these six models can take more than 2 days total (just for one idea!). Towards the end I finetuned 32B and the training on just 4 negatives took &gt; 20 hours for a single experiment (5 hours without external data)! I trained for 2 epochs using the SFTTrainer. Felt that there may be a faster way…</p>\n<p><strong>Do you have tips on selecting experiments?</strong></p>\n<p>Context: From the MCTS and EEDI competitions, I realised that I’m able to think of lots of ideas to solve the problem. However, I felt my ability to decide which one to prioritise needs improvement. For example in EEDI, I spent 3 days customizing TextGrad to optimize prompts for Qwen to hopefully improve the reranking performance (similar to <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/540759\" target=\"_blank\">this</a>). However the improvement is very marginal and possibly not worth 3 full days of effort…Maybe I will get better at this as I gain more experience 😅</p>\n<p>Really inspiring that you got the correct approach from the beginning and have 3 months to get the most out of it 👍</p>",
      "votes": 4,
      "replies": [
        {
          "id": 3078167,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-21T21:54:46.657000",
          "content": "<p>Hi bogoconic1!</p>\n<p>Thanks a lot! You've been on an impressive path and performing well across different types of competitions!</p>\n<blockquote>\n  <p>Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?</p>\n</blockquote>\n<p>I used 2xH100 GPUs from <a href=\"https://cloud.vast.ai/create/\" target=\"_blank\">vast.ai</a>. I trained my models using the HF accelerate with a few basic speed optimizations e.g. using (1)  torch.compile (2) flash-attention (3) LoRA instead of QLoRA (4) padding sequence lengths to multiples of 8. The 14B re-ranker was also taking ~5hrs for a full run in my setup. But, I very rarely did a full run: (a) ~50% of training was giving good indications on the experiment, (b) I primarily experimented with the 7B models. For 32B, I just copied the best settings from 14B. IMO key is to keep experiment setup as lean as possible.</p>\n<blockquote>\n  <p>Do you have tips on selecting experiments?</p>\n</blockquote>\n<p>I often struggle with this too. It's difficult to get the exploration vs exploitation balance right. Although there is no silver bullet, I think the following points help in NLP comps:</p>\n<ol>\n<li>Try to find the best set of backbones to fine-tune from</li>\n<li>Once you find a good backbone &amp; have a decent baseline, focus on data related experiments</li>\n<li>Write down takeaways after each experiment -- include related plots, error analysis etc. This should inform you what to do next</li>\n<li>Techniques like distillation/pseudo labeling almost always help with performance and generalization</li>\n</ol>\n<p>Will add to this list if I can think of other points tomorrow. I'm not sure if these are too obvious or very opinionated…</p>",
          "votes": 10,
          "replies": []
        }
      ]
    },
    {
      "id": 3122439,
      "author_name": "YuhaoWu123",
      "author_url": "",
      "post_date": "2025-02-12T16:21:11.237000",
      "content": "<p>hi～ I would like to ask you another question. In your notebook at <a href=\"https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d\" target=\"_blank\">https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d</a>, you used a file named ranker_oof_df.csv. In your solution, you mentioned, “Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data.” My question is, when you refer to “validation data” here, do you mean the predictions on the validation data obtained by training a model using the training set, which is split from the original entire dataset into training and valid sets? thanks a lot！</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3123110,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2025-02-13T11:41:31.767000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/yuhaowu123\" target=\"_blank\">@yuhaowu123</a>, yes, exactly. Using top retrieved candidates on the validation split.</p>",
          "votes": 0,
          "replies": [
            {
              "id": 3141956,
              "author_name": "",
              "author_url": "",
              "post_date": "2025-03-06T02:04:19.437000",
              "content": "",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3081076,
      "author_name": "CodeCavalier",
      "author_url": "",
      "post_date": "2024-12-26T07:06:16.510000",
      "content": "<p>Superb, good luck in your future ventures!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3078878,
      "author_name": "Miles",
      "author_url": "",
      "post_date": "2024-12-23T00:42:09.683000",
      "content": "<p>Congrats for the winning! Did you try to train the 14b reranker with synthetic data but without distillation from 72b? I wonder how it would perform.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3078984,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-23T04:54:24.810000",
          "content": "<p>Interesting, this should be a good experiment! However, I didn't try this thinking synthetic data misconceptions still may be noisy (lesser quality than competition data) even after curation…</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3078557,
      "author_name": "YuhaoWu123",
      "author_url": "",
      "post_date": "2024-12-22T13:49:41.320000",
      "content": "<p>Thank you very much for your insights! This is a very interesting and solid solution. However, I have a few questions regarding the prompt design that I’d like to clarify:</p>\n<ol>\n<li><p>You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?</p></li>\n<li><p>The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?</p></li>\n<li><p>The prompt mentions that the  tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？</p></li>\n<li><p>Many of my above questions stem from uncertainty about the content within the  tag and the  tag in a complete prompt. Would you be able to provide me with an example of a fully constructed prompt including these tags?Thanks a lot again！~~~</p></li>\n</ol>",
      "votes": 1,
      "replies": [
        {
          "id": 3079014,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-23T06:06:25.877000",
          "content": "<p>Here is an example prompt:</p>\n<pre><code>You will be generating Multiple Choice Questions (MCQs)  diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n&lt;misconceptions&gt;\n- Thinks  the perimeter  a square grid  the number  squares surrounding the rectangle\n- Calculates area  asked  perimeter\n- Counts a side length more than once  counting perimeter due   marking a starting point\n- Thinks  the perimeter  a square grid  the number  squares inside  are touching the perimeter  the shape\n- Calculates perimeter  asked  area\n- When calculating perimeter, only adds two sides\n- Believes lines inside the shape are included  finding perimeter\n- When calculating perimeter, only adds the marked lengths\n- When calculating perimeter, multiplies instead  adds\n- Thinks only labelled dimensions need  be included  calculating the perimeter\n- Confuses perimeter  area\n- Fails  use the properties  simple shapes  work out missing lengths\n- Does  know  we can use the conservation  perimeter  find missing lengths\n- Makes an assumption about line segments being equal within a shape\n- Mixes up width  height  a rectangle\n- Does  know how  find missing lengths  a composite shape\n&lt;/misconceptions&gt;\n\nHere are reference MCQs  demonstrate how  effectively diagnose these misconceptions:\n\n&lt;reference_mcqs&gt;\n[{: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }]\n&lt;/reference_mcqs&gt;\n\nYour task   generate   MCQs  diagnose misconceptions  already covered  the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n For each reference MCQ, identify  your &lt;analysis&gt; tags:\n   - Which misconception  targets\n   - How the incorrect answers   specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n Note the style, difficulty level,  precision  language used\n\nThen,  your &lt;planning&gt; tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where  commonly appears\n- Design questions where the misconception leads naturally  specific wrong answers\n- Take notes  how you can craft  MCQs  adheres  the reference MCQs</code></pre>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 3079020,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-23T06:17:30.400000",
          "content": "<blockquote>\n  <p>You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?</p>\n</blockquote>\n<p>For each MCQ, the LLM would generate</p>\n<pre><code>           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n</code></pre>\n<p>therefore, incorrect answers and misconceptions can be paired properly.</p>\n<blockquote>\n  <p>The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?</p>\n</blockquote>\n<p>Nice spot. Even if we specify the possible misconceptions, LLM still likes to generate additional ones. Before I settled on this prompt, my earlier prompts would generate even more of new misconceptions. </p>\n<blockquote>\n  <p>The prompt mentions that the tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？</p>\n</blockquote>\n<p>I have provided a full prompt example <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/551688#3079014\" target=\"_blank\">here</a>. Hope it helps!</p>",
          "votes": 0,
          "replies": [
            {
              "id": 3140911,
              "author_name": "lixianyan11",
              "author_url": "",
              "post_date": "2025-03-05T03:58:35.747000",
              "content": "<p>Do the misconceptions generated by the LLM, such as misconception_a_name, misconception_b_name, misconception_c_name, and misconception_d_name, tend to choose from the given misconception pool of the cluster?</p>",
              "votes": 0,
              "replies": []
            }
          ]
        },
        {
          "id": 3140906,
          "author_name": "lixianyan11",
          "author_url": "",
          "post_date": "2025-03-05T03:48:03.497000",
          "content": "<p>I would like to ask: If only the misconceptions are provided as clusters, where do the other answers and corresponding misconceptions generated by the LLM for a new question come from? </p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3077562,
      "author_name": "Yannan Chen",
      "author_url": "",
      "post_date": "2024-12-21T05:39:43.933000",
      "content": "<p>Thank you so much for this detailed solution. I'm so impressed with how much attention you've paid to details, and how you fully utilze the limited GPU resources to perform so many rounds of reranking. May I ask:</p>\n<ul>\n<li>you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?</li>\n<li>What are the important tricks to fit 72b model for inference into 2 T4 GPUs?</li>\n<li>What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?</li>\n</ul>\n<p>Thanks again! Congratulations on 1st place! The solution really deserves it.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3077760,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-21T11:19:04.580000",
          "content": "<p>Thanks for the kind words! Congratulations to you too on solo gold! 🎉</p>\n<blockquote>\n  <p>you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?</p>\n</blockquote>\n<p>The idea comes from the <a href=\"https://arxiv.org/pdf/2407.21075\" target=\"_blank\">Apple Intelligence report</a> (Section 5.2). </p>\n<blockquote>\n  <p>… The quantized model often shows a moderate level of quality loss. Therefore, instead of directly passing the quantized model to application teams for feature development, we attach a set of parameter-efficient LoRA adapters for quality recovery. We make sure that these LoRA adapters training recipes are consistent with pre-training and post-training processes.</p>\n</blockquote>\n<p>I didn't get to try this in this competition.</p>\n<blockquote>\n  <p>What are the important tricks to fit 72b model for inference into 2 T4 GPUs?</p>\n</blockquote>\n<p>I mainly followed <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/550223\" target=\"_blank\">this great post</a> from <a href=\"https://www.kaggle.com/jagatkiran\" target=\"_blank\">@jagatkiran</a>! Didn't have any inference tricks for the 72b model. For 14b ranker, prefix caching was key.</p>\n<blockquote>\n  <p>What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?</p>\n</blockquote>\n<p>My best selected submission was ~510mins. I didn't face OOM but had a few out of time near the end…</p>\n<p>Thanks!</p>",
          "votes": 2,
          "replies": [
            {
              "id": 3078220,
              "author_name": "Yannan Chen",
              "author_url": "",
              "post_date": "2024-12-22T00:36:24.273000",
              "content": "<p>Thank you for your explanation! I also noticed that for your retriever, you used different learning rate for lora_a and lora _b, this is an interesting detail. May I ask what is the rationale behind that?</p>",
              "votes": 1,
              "replies": []
            },
            {
              "id": 3078977,
              "author_name": "Raja Biswas",
              "author_url": "",
              "post_date": "2024-12-23T04:48:38.020000",
              "content": "<p>I followed the LoRA+ paper: <a href=\"https://arxiv.org/abs/2402.12354\" target=\"_blank\">LoRA+: Efficient Low Rank Adaptation of Large Models</a> -- which shows faster convergence and better perf with different LRs for LoRA A and B.</p>\n<blockquote>\n  <p>…Low Rank Adaptation (LoRA) as originally introduced in Hu et al. (2021) leads to suboptimal finetuning of models with large width (embedding dimension). This is due to the fact that adapter matrices A and B in LoRA are updated with the same learning rate. Using scaling arguments for large width networks, we demonstrate that using the same learning rate for A and B does not allow efficient feature learning. We then show that this suboptimality of LoRA can be corrected simply by setting different learning rates for the LoRA adapter matrices A and B with a well-chosen ratio. We call this proposed algorithm LoRA+. In our extensive experiments, LoRA+ improves performance (1-2 % improvements) and finetuning speed (up to ∼ 2X SpeedUp), at the same computational cost as LoRA.</p>\n</blockquote>",
              "votes": 1,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3073545,
      "author_name": "xyzlsy",
      "author_url": "",
      "post_date": "2024-12-16T15:42:50.033000",
      "content": "<p>I want to know if your recall model is created by combining model 1, model 2, and model 3, and then concatenating the last token, or if another method is used.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3074399,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-17T16:22:45.953000",
          "content": "<p>I averaged similarity scores from these models.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3073495,
      "author_name": "xyzlsy",
      "author_url": "",
      "post_date": "2024-12-16T14:53:16.193000",
      "content": "<p>Did you merge the training set and the synthetic dataset together and then perform the 5-fold split, or did you perform the 5-fold split on the training set and then directly add the synthetic data to the training set?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3073504,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-16T15:00:42.240000",
          "content": "<p>5-fold split on the training set and then directly add the synthetic data to the training set</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3073391,
      "author_name": "Khairul Islam25",
      "author_url": "",
      "post_date": "2024-12-16T13:18:32.093000",
      "content": "<p>Your explanation is excellent bro, Thanks.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3073360,
      "author_name": "Santiago Mota",
      "author_url": "",
      "post_date": "2024-12-16T11:59:14.937000",
      "content": "<p>Congrats both. Result ans explication. </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3072882,
      "author_name": "MrSimple",
      "author_url": "",
      "post_date": "2024-12-15T18:00:13.827000",
      "content": "<p>This is undoubtedly very insightful! Thank you for sharing this amazing information! <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a></p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3072696,
      "author_name": "Bootstrapping",
      "author_url": "",
      "post_date": "2024-12-15T15:00:31.440000",
      "content": "<p>Thanks for sharing such a detailed solution!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3072550,
      "author_name": "Andrey Galichin",
      "author_url": "",
      "post_date": "2024-12-15T11:36:55.657000",
      "content": "<p>A very insightful and beautiful solution, thank you!</p>\n<p>We have also tried to generate Chain-of-Thought using gpt-4o in the early stage of the competition, but found that we couldn't correctly formalize the way of thinking for the model, and quite often the model explicitly mentioned the misconception in its response (although we've tried to encourage it not to do so).</p>\n<p>Haven't you met this problem during the prompt construction; if yes, can you please tell, what exact prompting modifications helped to solve it?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3073139,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-16T05:10:59.153000",
          "content": "<p>Yes, I too noticed Claude mentioning the misconception name at the start of CoT. I fixed it with prompt engineering by asking LLM to follow this sequence:</p>\n<ul>\n<li>Show the correct calculation first</li>\n<li>Show the incorrect calculations that demonstrate the error</li>\n<li>Explain the specific flaw in the student's reasoning</li>\n<li>Demonstrate how the misconception led to this particular error</li>\n<li>Distinguish from the related misconceptions</li>\n</ul>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3072535,
      "author_name": "Dipam Chakraborty",
      "author_url": "",
      "post_date": "2024-12-15T11:24:21.007000",
      "content": "<p>I see a lot of people used the LM Head with Yes/No probabilities as the binary classifier. Any thoughts on whether that is the best approach when fine tuning, or is it better to add a new classifier head? I tried both and the classifier head worked better for me, but it was also my first time doing any serious comparision between these two approaches. Appreciate if you share your thoughts. Thanks also for such an immensely detailed post, learnt a lot.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3073138,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-16T05:08:13.313000",
          "content": "<p>Thanks Dipam!</p>\n<p>I actually trained most of my models with a new classification head and switched to Yes/No tokens approach in the later stages -- mainly to take advantage of vllm inference + in-built prefix caching. Both Yes/No approach and classifier head gave similar scores here.</p>",
          "votes": 3,
          "replies": [
            {
              "id": 3078523,
              "author_name": "Atharva Ingle",
              "author_url": "",
              "post_date": "2024-12-22T12:32:24.967000",
              "content": "<p>Thanks for the detailed writeup, a lot to learn here. I am a bit confused in this part:</p>\n<p>Question: Since you are finetuning the causal lm to output Yes/No token, why the lm_head was frozen. What was the reasoning behind this ? As we want the lm_head to have high probs for either Yes/No token, freezing it will avoid it to learn this mapping. Can you explain this part ?</p>\n<blockquote>\n  <p>The logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:</p>\n</blockquote>\n<pre><code>outputs = .model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=)\nlogits_yes = outputs.logits[:, -, .yes_loc]  \nlogits_no = outputs.logits[:, -, .no_loc]  \nlogits = logits_yes - logits_no  \nlogits = logits.reshape(-, .group_size)\nlabels = labels.to(logits.device).reshape(-) \nce_loss = .loss_fn(logits, labels)\n</code></pre>\n<blockquote>\n  <p>Each batch contained 1 positive and batch_size-1 negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with r=64, alpha=128, LoRA on all linear layers. The language modelling head (lm_head) of the LLM (Qwen/Qwen2.5-14B) was frozen during fine-tuning.</p>\n</blockquote>",
              "votes": 1,
              "replies": []
            },
            {
              "id": 3079011,
              "author_name": "Raja Biswas",
              "author_url": "",
              "post_date": "2024-12-23T05:59:35.763000",
              "content": "<p>Hey <a href=\"https://www.kaggle.com/atharvaingle\" target=\"_blank\">@atharvaingle</a>, on freezing the <code>lm_head</code>:</p>\n<ul>\n<li><code>logit(y=Yes) = features . W_lm_head_yes</code> : The Yes/No token logits are controlled by both the LM head weights at the location of Yes/No tokens and model hidden states at end of the sequence. Even if we freeze the LM head, the logits can be adjusted by the network by updating other params such that features are moving as per loss during fine-tuning.</li>\n<li>The prompt template would already increase logits for the Yes/No tokens (without fine-tuning the LM head)</li>\n<li>Qwen2.5 tokenizer has 150k+ tokens (out of which we are only concerned with 2 tokens), unfreezing LM Head would increase VRAM requirement significantly</li>\n<li>However, as always, we should test both unfreeze and freeze cases and see the performance diff. Intuitively, I felt difference wouldn't be significant.</li>\n</ul>",
              "votes": 1,
              "replies": []
            },
            {
              "id": 3079086,
              "author_name": "Atharva Ingle",
              "author_url": "",
              "post_date": "2024-12-23T08:15:26.720000",
              "content": "<p>Thanks this helps a lot.</p>",
              "votes": 1,
              "replies": []
            },
            {
              "id": 3086113,
              "author_name": "Chenyu Lin",
              "author_url": "",
              "post_date": "2025-01-02T02:26:49.143000",
              "content": "<p>If possible, could you show me which part of the code freezes the weights for this section? I couldn’t find it. Thank you very much.</p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3072329,
      "author_name": "James owen",
      "author_url": "",
      "post_date": "2024-12-15T03:31:27.977000",
      "content": "<p>Hi raja, I have carefully read the detailed plan you posted. I have truly learned a lot. As a beginner in LLM, your plan involves a lot of knowledge that I have not yet understood. Please allow me to express my sincerest gratitude to you and look forward to your performance in the next competition</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 3074742,
      "author_name": "Lao Xiaodong",
      "author_url": "",
      "post_date": "2024-12-18T02:40:30.673000",
      "content": "<p>Looking forward to the release of your training code.</p>",
      "votes": 2,
      "replies": [
        {
          "id": 3077764,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-21T11:20:42.470000",
          "content": "<p>Currently working on the code release, so sorry for the delay…</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 3080817,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-25T19:16:04.187000",
          "content": "<p>published the code here: <a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">https://github.com/rbiswasfc/eedi-mining-misconceptions</a></p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3073598,
      "author_name": "Nikhil Tumbde",
      "author_url": "",
      "post_date": "2024-12-16T16:30:47.543000",
      "content": "<p>Hi <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a>, thank you so much for the detailed explanation. It is quite a lot to unpack.<br>\nIn my efforts towards learning, I am trying to summarize my understanding of your approach. However, I have a few questions and would really appreciate if you (or anyone on the forum) can help me get more clarity.</p>\n<h1>Questions</h1>\n<ol>\n<li>How many negative samples were used for retriever finetuning?</li>\n<li>Can you elaborate on <em>“Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”</em>. Do you mean 1 misconception won’t appear as true label twice in a batch?</li>\n<li>How were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?</li>\n<li>Can you explain the re-ranker distillation part?</li>\n<li>AWQ - which datasets were used for calibration? </li>\n</ol>\n<blockquote>\n  <h1>Summary</h1>\n  <h2>1.    Data Generation</h2>\n  <p>a.    Create clusters out of similar misconceptions<br>\n  b.    Generate 5 MCQs (using Claude 3.5 sonnet) for each clusters by giving cluster misconceptions and related 4-5 questions as context. (data quality can be questionable)<br>\n  c.    Use GPT-4o to evaluate the quality of generated MCQs on a scale from 0-10 and filter out the bad ones.<br>\n  d.    Step b gave additional misconceptions (not in misconception_mapping). Filtered out the misconceptions similar to the ones in the given mapping to avoid conflicts (using vectors from embedding model).<br>\n  At this point the author has original misc clusters, and generated MCQs with misconceptions mapped to them (both original and generated)</p>\n  <h2>2.    COT Distillation</h2>\n  <p>Overall, the idea here is to distill the knowledge of claude into smaller models. So we get generations from claude and use that to finetune smaller models.<br>\n  a.    Generate COT (on original train dataset) using Claude using the question context, misc and related misc in the prompt. <br>\n  b.    Finetune 3 models (7,14,32B) on the generated text and same prompt but exclude the misconceptions and related misc (as during inference they won’t be present)<br>\n  At this point the author has 3 models (reasoners) with the capability of generating COT reasons for each incorrect answer using only the questions context (no misconception).</p>\n  <h2>3.    Models - retriever</h2>\n  <p>a.    Finetune retrievers using MNR loss for 12 epochs on entire data (except 1 fold) from step 1.d. {some confusion here will update once it is clarified}<br>\n  b.    Pre-training the finetuned qwen-14B on synthetic data from step 1.b gave recall boost. </p>\n  <h2>4.    Model –reranker</h2>\n  <p><em>overall 2 pointwise rerankers (yes/no output for each misconception) and 1 listwise used.</em></p>\n  <h3>a.    Pointwise rerankers (14/32B)</h3>\n  <p>i.    Pseudo labels on synthetic dataset (from 1.d) generated using models (Qwen/Qwen2.5-Math-72B and Qwen/Qwen2.5-72B) finetuned on train dataset.<br>\n  ii.    Entire dataset used for finetuning pointwise reranker. COT was also added to 50% of the training dataset.<br>\n  iii.    Other details-</p>\n  <ol>\n  <li>The prompt contains few shot examples.</li>\n  <li>The re-ranker was trained on logit difference of ‘yes’ and ‘no’ tokens as predictions using cross entropy loss. </li>\n  <li>1 positive and (BS – 1) negative samples taken for each batch. 1:24 positive:negative ratio.</li>\n  <li>LM head was frozen during finetuning.</li>\n  </ol>\n  <h3>b.    Listwise reranker</h3>\n  <p>i.    Predicts 1 out of top 5 choices.<br>\n  ii.    <em>{Training strategy not shared}</em></p>\n  <h2>5.    Quantization</h2>\n  <p>a.    Fp16 finetuning was performed and the models were quantized using AWQ.<br>\n  b.    Calibration dataset used <em>{some confusion here will update once it is clarified.}</em></p>\n</blockquote>",
      "votes": 2,
      "replies": [
        {
          "id": 3074397,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-17T16:22:09.333000",
          "content": "<p>Thanks Nikhil for the questions. Please find below my replies.</p>\n<blockquote>\n  <p>How many negative samples were used for retriever finetuning?</p>\n</blockquote>\n<p>I used the standard <strong>in-batch negatives</strong> setup. Therefore, for a batch_size of 128, there were 127 negatives and 1 positive for each query (question + incorrect answer).</p>\n<blockquote>\n  <p>Can you elaborate on “Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”. Do you mean 1 misconception won’t appear as true label twice in a batch?</p>\n</blockquote>\n<p>Say, In a batch, the positive examples are <code>(q1, m1), (q2, m2)..., (q128, m128)</code>. For the in-batch negatives setup, this means <code>q1</code> will have <code>m1</code> as positive and <code>[m2, m3, ..m128]</code> as negatives. Similarly, for <code>q2</code> you will have <code>m2</code> as positive and <code>[m1, m3, ...m128]</code> as negatives.  During training, we will compute similarity scores between all query and misconception combinations (<code>128x128</code> matrix). The diagonal elements would correspond to the positives and off-diagonals should be negatives. In this competition, we had many-to-one relationship for the query to content mapping. Hence, a random batching strategy would lead to cases where multiple queries belonging to the same misconception would end up in a given batch. In this case, you will have false negatives in the off diagonals -- leading to noisy, sub optimal convergence.</p>\n<blockquote>\n  <p>How were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?</p>\n</blockquote>\n<p>I just used in-batch negatives. I, however, experimented mined hard negatives obtained from fine-tuned retrievers (+ de-noised with re-ranker predictions <a href=\"https://arxiv.org/abs/2407.15831\" target=\"_blank\">Reference</a>), but it was ineffective to improve long tail recall.</p>\n<blockquote>\n  <p>Can you explain the re-ranker distillation part?</p>\n</blockquote>\n<p>You can refer to the <a href=\"https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L280\" target=\"_blank\">distillation loss</a> in the <a href=\"https://github.com/FlagOpen/FlagEmbedding\" target=\"_blank\">FlagEmbedding</a> repo.</p>\n<blockquote>\n  <p>AWQ - which datasets were used for calibration?</p>\n</blockquote>\n<p>I basically used the a subset of re-ranker training dataset as calibration dataset.</p>",
          "votes": 3,
          "replies": [
            {
              "id": 3074759,
              "author_name": "Nikhil Tumbde",
              "author_url": "",
              "post_date": "2024-12-18T03:15:24.390000",
              "content": "<p>Thanks a lot for the response! That helps.</p>",
              "votes": 1,
              "replies": []
            },
            {
              "id": 3182330,
              "author_name": "White_Ink",
              "author_url": "",
              "post_date": "2025-04-19T06:04:40.330000",
              "content": "<p>Thanks a lot for the response! That helps.</p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3072154,
      "author_name": "Saurabh Badole",
      "author_url": "",
      "post_date": "2024-12-14T19:09:44.270000",
      "content": "<p>This is undoubtedly very insightful! Thank you for sharing this amazing information! <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a> </p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 3121905,
      "author_name": "YuhaoWu123",
      "author_url": "",
      "post_date": "2025-02-12T05:06:11.393000",
      "content": "<p>Hello, I’d like to ask another question. The problem ultimately uses the MAP@K of the correct answers, but your code calculates the MAP@K for all the top K answers. I’m curious why the metric in the code is inconsistent with the metric required by the problem. the code i mentioned is ⬇️<br>\n    for i, p in enumerate(predicted):<br>\n        # first condition checks whether it is valid prediction<br>\n        # second condition checks if prediction is not repeated<br>\n        if p in actual and p not in predicted[:i]:<br>\n            num_hits += 1.0<br>\n            score += num_hits / (i + 1.0)</p>\n<pre><code>  / (len(actual), k)\n</code></pre>\n<p>looking forward for your reply，thanks a lot！</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3123112,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2025-02-13T11:42:27.030000",
          "content": "<p>Metric computation looks okay to me. Here is a detailed post on the metric: <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/534077\" target=\"_blank\">https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/534077</a></p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3087919,
      "author_name": "Joaquin Robador",
      "author_url": "",
      "post_date": "2025-01-04T04:38:36",
      "content": "<p>GOAT. Amazing</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3081241,
      "author_name": "未来鸟@",
      "author_url": "",
      "post_date": "2024-12-26T13:46:33.623000",
      "content": "<p>RAJA BISWAS, I am very grateful that you have published the training code！ I would like to know how long it took you to install the flash_attn package. It has been almost an hour since I ran pip install \"flash_attn==2.6.3\" --no-build-isolation, and it still hasn't completed the installation.</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3081264,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-26T14:14:33.623000",
          "content": "<p>that's strange, it was ~3mins iirc, please try: <code>pip install flash-attn --no-build-isolation</code></p>",
          "votes": 0,
          "replies": [
            {
              "id": 3081271,
              "author_name": "未来鸟@",
              "author_url": "",
              "post_date": "2024-12-26T14:29:45.057000",
              "content": "<p>Three minutes is really fast! I'm happy that I finally managed to install it, but it took me almost an hour. This might be because I used a VPN, as I can't directly connect to vast.ai from my country.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3081606,
              "author_name": "未来鸟@",
              "author_url": "",
              "post_date": "2024-12-27T01:52:17.697000",
              "content": "<p>Hello RAJA BISWAS,</p>\n<p>I would like to know if the input_dataset in the configuration file conf_qwen14b_pretrain was named eedi-embed-pretrain-mix-final instead of eedi-embed-pretrain-mix-expanded when you trained Qwen/Qwen2.5-14B on the synthetic dataset. I couldn't find the file eedi-embed-pretrain-mix-expanded on Kaggle.</p>\n<p>Thank you!</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3081692,
              "author_name": "Raja Biswas",
              "author_url": "",
              "post_date": "2024-12-27T04:52:03.260000",
              "content": "<p>Thanks for the catch! It should be <code>conjuring92/eedi-embed-pretrain-mix-final</code>. I just pushed the fix.</p>\n<p>Please feel free to create an issue in the repo if you encounter other issues!</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3133227,
              "author_name": "未来鸟@",
              "author_url": "",
              "post_date": "2025-02-25T06:13:30.100000",
              "content": "<p>I would like to know if you can provide the calibration datasets for quantizing a fine-tuned model using AWQ, such as rbiswasfc/eedi-awq-calibration, rbiswasfc/eedi-awq-calibration-tutor, and rbiswasfc/eedi-awq-calibration-cot</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3133584,
              "author_name": "Raja Biswas",
              "author_url": "",
              "post_date": "2025-02-25T14:07:41.307000",
              "content": "<p>Here are the datasets:</p>\n<ul>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-tutor\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-tutor</a></li>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-cot\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-cot</a></li>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration</a></li>\n</ul>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3134240,
              "author_name": "未来鸟@",
              "author_url": "",
              "post_date": "2025-02-26T06:33:33.733000",
              "content": "<p>Many thanks！</p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3078935,
      "author_name": "Miles",
      "author_url": "",
      "post_date": "2024-12-23T03:09:18.463000",
      "content": "<p>How was it achieved to inference 72b model on 2 T4 GPUs? They are 2*16=32GB Vram. AWQ of 72b takes 36GB vram on parameters only. And if offload to CPU, it would be so slow as not able to complete the inference within time.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3078921,
      "author_name": "yanqiangmiffy",
      "author_url": "",
      "post_date": "2024-12-23T02:40:53.943000",
      "content": "<p>Looking forward to training code</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3080820,
          "author_name": "Raja Biswas",
          "author_url": "",
          "post_date": "2024-12-25T19:17:34.867000",
          "content": "<p>Just pushed the code <a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">here</a>. </p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 3074526,
      "author_name": "Amardeep Singh",
      "author_url": "",
      "post_date": "2024-12-17T18:56:14.323000",
      "content": "<p>Your explanation is excellent bro, Thanks.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3142482,
      "author_name": "",
      "author_url": "",
      "post_date": "2025-03-06T12:36:23.377000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3141983,
      "author_name": "",
      "author_url": "",
      "post_date": "2025-03-06T02:42:58.807000",
      "content": "",
      "votes": 0,
      "replies": [
        {
          "id": 3141984,
          "author_name": "",
          "author_url": "",
          "post_date": "2025-03-06T02:43:33.153000",
          "content": "",
          "votes": 0,
          "replies": []
        },
        {
          "id": 3142013,
          "author_name": "",
          "author_url": "",
          "post_date": "2025-03-06T03:19:58.493000",
          "content": "",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3078331,
      "author_name": "",
      "author_url": "",
      "post_date": "2024-12-22T07:02:24.763000",
      "content": "",
      "votes": 0,
      "replies": [
        {
          "id": 3101726,
          "author_name": "James KJ ",
          "author_url": "",
          "post_date": "2025-01-21T08:15:49.537000",
          "content": "<p>Hi, did you get the csv file ?</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3077461,
      "author_name": "",
      "author_url": "",
      "post_date": "2024-12-21T02:03:29.063000",
      "content": "",
      "votes": 0,
      "replies": []
    }
  ],
  "comment_count": 67,
  "messages": [
    {
      "id": 3072128,
      "postDate": "2024-12-14T18:18:44.017Z",
      "content": "<p>I would like to thank Kaggle and EEDI for hosting this interesting competition! It was challenging and provided many opportunities to learn/apply new techniques. As always, I'm grateful to the Kaggle community for innovative ideas and engaging discussions. I'm excited to share my detailed solution and hope others will find it helpful!</p>\n<h2>1 Task</h2>\n<p>Given a diagnostic math MCQ, together with the correct answer and an incorrect answer, the task was to recommend top 25 misconceptions (sorted by their affinity to the incorrect answer) from a pool of 2.5k+ misconceptions. \nEven though the standard retrieve-rerank framework was a natural fit, it came with a few challenges:</p>\n<ul>\n<li>Current LLMs often struggle to mimic either (1) a <code>Novice Learner</code> i.e. generating the incorrect answer stemming from a specific misconception or (2) an <code>Expert Tutor</code> i.e. identifying the misconception that explains a given incorrect answer. LLMs excel at solving math problems, but they are not so great at counterfactual reasoning.</li>\n<li>The misconception pool ties together closely related conceptual and computational mistakes, demanding high discriminative power to spot subtle differences with precision. This is highlighted in the competition overview:</li>\n</ul>\n<blockquote>\n  <p>Initial efforts to use pre-trained language models have not been successful, likely due to the complexity of the mathematical content in the questions.</p>\n</blockquote>\n<ul>\n<li>The task setup requires the model to not only do well on known misconceptions but also generalize to new misconceptions.</li>\n</ul>\n<h2>2 Meta Thoughts</h2>\n<p>At the start of the competition, I had the following hypotheses on what could be important for a good solution:</p>\n<ul>\n<li>Synthetic data should help with out-of-distribution generalization</li>\n<li>High quality synthetic data generation should be feasible since Math domain can be verified and curated objectively</li>\n<li>Distillation from a good teacher(s) should be very powerful, as Large LLMs are significantly better at reasoning</li>\n<li>Distilling Chain of Thoughts (CoT) from top LLMs (e.g. Claude 3.5 Sonnet) should help to tackle difficult examples</li>\n<li>Quantization method and the calibration datasets could be important. We may need to add recovery adapters to the quantized models for maintaining top 1 accuracy.</li>\n<li>Full training might be better than LoRA</li>\n</ul>\n<p>These hypotheses guided me to design my experiments throughout the competition and helped me to stick to an idea even though the initial attempts were not successful.</p>\n<h2>3 Pipeline</h2>\n<p>I implemented a retrieve-and-rerank system that involved a sequence of four steps:</p>\n<ul>\n<li><strong>Retrieval</strong>: Identify top misconception candidates for each of the MCQ-Incorrect answer combinations. Specifically, I retained the top 32 retrieved candidates and included up to 32 additional candidates based on a dynamic threshold. The dynamic threshold is computed as the <code>top candidate similarity score - constant</code>. Candidates with similarity scores higher than the dynamic threshold are kept. </li>\n<li><strong>14B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-14B</code> ranker to process all retrieved candidates and shortlist top 8.</li>\n<li><strong>32B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-32B</code> ranker to process top 8 candidates and narrow them down to top 5.</li>\n<li><strong>72B Ranker</strong>: Use a fine-tuned <code>Qwen/Qwen2.5-72B</code> ranker to finalize the ranking of top 5 candidates.</li>\n</ul>\n<p>A schematic diagram of the pipeline and the leaderboard scores from each stages are shown below:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F3b2245b7c0baaab58b9d9232c6ff9bae%2Finference_pipeline.png?generation=1734198970117751&amp;alt=media\" alt=\"Inference Pipeline\"></p>\n<p>The final 25 misconception predictions comprised of:</p>\n<ul>\n<li>1st to 5th candidate from the 72B ranker</li>\n<li>6th to 8th candidate from the 32B ranker</li>\n<li>9th to 25th candidate from the 14B ranker.</li>\n</ul>\n<h2>4 Data</h2>\n<p>The training data mix for both the retriever and ranker models included competition data (1.8k examples) and synthetic data (10k examples). The synthetic data played a crucial role in improving both raw performance and generalization capability with respect to unseen misconceptions.</p>\n<h3>4.1 Synthetic Data</h3>\n<p>In an ideal scenario, synthetic MCQs should have the following properties:</p>\n<ul>\n<li>The designated correct answers are indeed the correct answers (high accuracy).</li>\n<li>The incorrect answers directly stem from the target misconception (high diagnostic power).</li>\n<li>Among all misconceptions in the misconception pool (2.5k+), the indicated misconception should provide the most precise explanation for a given incorrect answer (high resolution).</li>\n<li>The generated MCQs should cover a broad range of subjects and constructs (high diversity).</li>\n</ul>\n<p>I started generating diagnostic MCQs with a simple prompt that specified the expected format and a misconception of interest. However, it resulted in a dataset that violated almost all the properties to varying degrees. It was expected since</p>\n<ul>\n<li>The simple prompt only included information about a single misconception. Hence, the data-generating LLM was completely unaware of closely related misconceptions within the misconception pool.</li>\n<li>Lack of few shot examples meant lack of reference on the expected quality, difficulty level, tone, and language.</li>\n<li>Even the advanced LLMs struggle with handling misconceptions and counterfactual reasoning effectively.</li>\n<li>No curation was performed.</li>\n</ul>\n<p>I experimented with several strategies to address the issues and managed to create a high quality synthetic dataset with a <code>grouped synthetic data generation</code> approach and incorporating LLM based filtering. Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data. <a href=\"https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d\" target=\"_blank\">This notebook</a> demonstrates the clustering process. Here is an example of a misconception cluster:</p>\n<pre><code>- Thinks x^2 - a^2x is a valid form of difference of two squares\n- When factorising a quadratic without a non variable term, tries to double bracket factorise\n- Incorrectly factorises a quadratic\n- Believes the constant in an expanded quadratic comes from adding the two numbers in the brackets\n- Believes the coefficent of x in an expanded quadratic comes from multiplying the two numbers in the brackets\n- Does not recognise difference of two squares\n- Does not realise a quadratic must be in the form ax^2+bx+c=0 to be factorised\n- Does not know how to identify common factors from algebraic terms\n- Believes the difference of 2 squares method of factorising also works for the addition of 2 squares\n- When factorising, believes they can choose different factors for each term\n- Believes they can factorise a difference of two squares by placing the constant in both brackets without square rooting\n</code></pre>\n<p>I next generated 5 new MCQs for each cluster using <code>Claude 3.5 Sonnet</code> with a refined prompt that included 4-5 reference examples on misconceptions from the cluster. I used the <a href=\"https://github.com/anthropics/anthropic-cookbook/blob/main/misc/metaprompt.ipynb\" target=\"_blank\">metaprompt</a> tool from Anthropic cookbook for prompt engineering. Here is the final prompt used for data generation:</p>\n<pre><code>You will be generating Multiple Choice Questions (MCQs) that diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n&lt;misconceptions&gt;\n{cluster_misconceptions}\n&lt;/misconceptions&gt;\n\nHere are reference MCQs that demonstrate how to effectively diagnose these misconceptions:\n\n&lt;reference_mcqs&gt;\n{reference_mcqs}\n&lt;/reference_mcqs&gt;\n\nYour task is to generate {num_mcqs} new MCQs that diagnose misconceptions not already covered by the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n1. For each reference MCQ, identify in your &lt;analysis&gt; tags:\n   - Which misconception it targets\n   - How the incorrect answers map to specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n2. Note the style, difficulty level, and precision of language used\n\nThen, in your &lt;planning&gt; tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where it commonly appears\n- Design questions where the misconception leads naturally to specific wrong answers\n- Take notes on how you can craft new MCQs that adheres to the reference MCQs' style, difficulty level, and precision of language\n\nFinally, generate new MCQs following these important guidelines:\n- Make sure each incorrect answer maps clearly to exactly one misconception\n- Use precise mathematical language matching the style of reference MCQs\n- Make questions challenging enough that students must demonstrate real understanding\n- Ensure wrong answers are plausible and stem from genuine misconceptions, not careless errors\n- Use the exact wording of misconceptions as given in the misconceptions list\n- Pay careful attention to subtle differences between the misconceptions and observe which one is the most appropriate for a given incorrect answer\n- Keep the construct name and subject name as short as possible hiding the details of the misconception\n- Questions should be of higher difficulty level than reference MCQs\n</code></pre>\n<h3>4.1.1 Curation</h3>\n<p>I used LLM-as-a-judge to filter out low quality synthetic MCQs. I prompted <code>GPT-4o</code> to rate the quality of the synthetic MCQs as below:</p>\n<pre><code>You will analyze how well an incorrect answer reflects a suspected misconception in a mathematics problem. Your goal is to determine whether there is a clear, logical connection between the misconception and the wrong answer.\n\nHere is the problem with both correct and incorrect answers. The suspected misconception is also provided:\n&lt;problem&gt;\n{PROBLEM_DATA}\n&lt;/problem&gt;\n\nFirst, analyze the problem in your scratchpad:\n&lt;scratchpad&gt;\n1. Solve the problem independently to verify the correct answer\n2. Examine how someone holding the suspected misconception would approach the problem\n3. Trace the logical path from misconception to incorrect answer\n4. Identify any gaps or inconsistencies in this connection\n&lt;/scratchpad&gt;\n\nThen provide your evaluation using this format:\n&lt;evaluation&gt;\n1. Brief explanation of how the misconception could lead to the wrong answer\n2. Score from 0-10 based on these criteria:\n   - 10: Perfect alignment - wrong answer is direct result of misconception\n   - 8-9: Strong alignment - clear logical path from misconception to answer\n   - 5-7: Moderate alignment - connection exists but has some gaps\n   - 1-4: Weak alignment - connection is unclear or requires assumptions\n   - 0: No alignment - misconception does not explain wrong answer\n&lt;/evaluation&gt;\n\nImportant guidelines:\n- Focus solely on the logical connection between misconception and wrong answer\n- Do not speculate about other possible misconceptions\n- Be specific about how the misconception leads to the error\n- Flag and deduct scores if any assumptions are required to connect misconception to answer\n- Consider whether a student with this misconception would consistently arrive at this wrong answer\n</code></pre>\n<p>I selected <code>GPT-4o</code> as judge based on vibe test as it felt more sensitive to the scoring scheme and as consistent as Claude 3.5 Sonnet.</p>\n<h3>4.1.2 Incorporating Additional Misconceptions</h3>\n<p>While creating synthetic data, LLM produced many misconceptions (4k+) that were not part of the host provided misconception pool. I decided to keep the external misconceptions to improve generalization capability of the retriever and ranker models. </p>\n<p>Naively merging the external misconceptions with existing ones would have introduced conflicts and noise, since many of them were just rephrasing of the existing misconceptions. I adopted the following steps to handle this carefully:</p>\n<ul>\n<li>Attempt to match with existing misconceptions using string normalization (lowercasing, removing trailing punctuation, etc.)</li>\n<li>Attempt to match with existing misconceptions using similarity scores from an embedding model (<code>thenlper/gte-base</code>) with very high threshold (0.995)</li>\n<li>Remove new misconceptions that have fairly high similarity (between 0.95 and 0.995) with any of the existing misconceptions</li>\n<li>Keep rest of the remaining external misconceptions</li>\n</ul>\n<h3>4.1.3 Dataset</h3>\n<p>The final dataset is uploaded here: <a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset/\" target=\"_blank\">Eedi - Mining Misconceptions in Mathematics</a>. It contains</p>\n<ul>\n<li>1.8k competition MCQs + 10.6k generated MCQs</li>\n<li>4791 misconceptions\nand follows the same format as the original competition dataset.</li>\n</ul>\n<p>Reference: I'd highly recommend reading the synthetic data generation post from answer.ai: <a href=\"https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html\" target=\"_blank\">How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data</a>.</p>\n<h3>4.2 Chain of Thought (CoT) Generation</h3>\n<p>To distill the reasoning capability of an advanced LLM in my solution pipeline, I first created a dataset containing thought processes generated by <code>Claude 3.5 Sonnet</code>. I provided Claude with: (i) the problem statement, (ii) the correct answer, (iii) an incorrect answer, (iv) the ground truth misconception, and (v) several closely related misconceptions. Using this information, I prompted Claude to generate the likely thought process that led a student to select the incorrect answer. The prompt is shown below:</p>\n<pre><code>You will analyze a student's incorrect answer to identify the specific reasoning flaw that led to their error.\nYour goal is to explain precisely how their misconception caused them to arrive at the wrong answer.\n\nHere is the problem information:\n&lt;problem_data&gt;\n# Question: Simplify the expression: \\[x \\cdot y \\cdot x\\]\n# Correct Answer: \\(x^2y\\)\n# Incorrect Answer: \\(x^2\\)\n# Primary Misconception: Ignores variables without explicit coefficients when multiplying\n&lt;/problem_data&gt;\n\nHere are related misconceptions that are similar but do not explain this specific error as precisely:\n&lt;related_misconceptions&gt;\n- Thinks only like terms can be multiplied\n- Fails to combine all instances of the same variable\n- Incorrectly identifies an incomplete variable factor\n- Does not understand how to multiply algebraic terms\n&lt;/related_misconceptions&gt;\n\nFirst, examine all components of the problem carefully:\n1. The problem statement and question asked\n2. The correct answer and solution method\n3. The student's incorrect answer\n4. The primary misconception given\n5. The related misconceptions that should be distinguished from the primary one\n\nThen, reconstruct the student's likely thought process:\n- Identify the exact point where their reasoning diverged from the correct solution path\n- Note which specific mathematical operations or concepts they misapplied\n- Connect their error directly to the stated primary misconception\n- Verify that this explanation better fits the error than the related misconceptions\n\nWrite your analysis in &lt;evaluation&gt; tags, following this structure:\n- Show the correct calculation first\n- Show the incorrect calculations that demonstrate the error\n- Explain the specific flaw in the student's reasoning\n- Demonstrate how the misconception led to this particular error\n- Distinguish from the related misconceptions\n- Keep your explanation to 5-6 clear, non-repetitive sentences\n- Focus solely on the reasoning that produced this specific error\n\nGuidelines for writing your explanation:\n- Do not restate the problem or name the misconception\n- Be precise about the mathematical concepts involved\n- Show exactly how the misconception led to the error\n- Distinguish from related misconceptions\n- Avoid repetition\n- Stay focused on this specific error\n</code></pre>\n<p>Using this dataset, I fine-tuned three Qwen 2.5 series models (<code>Qwen/Qwen2.5-Math-7B</code>, <code>Qwen/Qwen2.5-14B</code>, and <code>Qwen/Qwen2.5-32B</code>) to act as reasoners. Notably, I omitted the true and related misconceptions from the input for fine-tuning. During inference, these models would see: (i) the problem statement, (ii) the correct answer, and (iii) an incorrect answer. They would then generate the likely thought process of a student behind selecting the incorrect answer. I used <code>vllm</code> for CoT generation during inference with <code>temperature=0.7, top_p=0.8, repetition_penalty=1.0, max_tokens=256</code>.</p>\n<p>The CoT dataset is uploaded here: <a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-sonnet-cot-comp-sharp-dec-09/\" target=\"_blank\">Eedi - CoT Dataset</a>.</p>\n<h2>5 Train-Validation Split</h2>\n<p>I split the competition dataset into 5 folds, initially based on the <code>QuestionId</code> field. However, this produced overly optimistic estimates with a large gap between validation and leaderboard scores. Next, I tried GroupKFold on <code>SubjectId</code>, but this resulted in overly pessimistic estimates. I finally settled on GroupKFold with <code>ConstructId</code>, which yielded a narrow Validation/LB gap and good correlation up to ~0.62 public LB score range.</p>\n<p>During development, I always trained my models on folds 1-4 and validated on fold 0. The synthetic data was marked as fold 99 and was included in the training set. The final models were trained on the entire dataset (full fit) using the same hyper parameters from the development stage.</p>\n<h2>6 Retrievers</h2>\n<p>I used the standard <a href=\"https://sbert.net/docs/package_reference/sentence_transformer/losses.html#multiplenegativesrankingloss\" target=\"_blank\">MultipleNegativesRankingLoss</a> to fine-tune the retrievers, while referencing the <a href=\"https://github.com/FlagOpen/FlagEmbedding/tree/master/FlagEmbedding/finetune/embedder/decoder_only\" target=\"_blank\">FlagEmbedding</a> codebase for developing training scripts. At this stage, I tracked both <code>map@25</code> and <code>recall@32</code> metrics and prioritized optimizing for <code>recall@32</code>, since recall was more important for overall pipeline performance.</p>\n<p>I fine-tuned several retrievers with the following scores:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fee7ac74c895fd5221738bf2ae8f42cee%2Fretriever_scores.png?generation=1734199290617188&amp;alt=media\" alt=\"Retriever Scores\"></p>\n<p>Incorporating hard negatives into training batches and distilling re-ranker scores consistently improved <code>map@25</code> performance, but did not positively impact <code>recall@32</code>. For my final submission selections, I chose the high-recall <code>Qwen/Qwen2.5-14B</code> encoder (Model 3) instead of the best <code>map@25</code> encoder (Model 4). Following the same logic, I also excluded the BGE encoder (Model 2).  Notably, my best encoder-only submission (Model 1 + Model 2 + Model 4) scored 0.524 on public LB and 0.475 on private LB.</p>\n<p>Retrievers were fine-tuned using LoRA with: <code>r=64, alpha=128, learning_rate_lora_a=1e-5, learning_rate_lora_b=5e-5, LoRA on all linear layers, batch_size=128, and epochs=12</code>. A few key factors that improved recall performance were:</p>\n<ul>\n<li>Setting temperature to 0.01, instead of the typically used value of 0.02 in LLM-based encoders</li>\n<li>Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives</li>\n<li>Pretraining the <code>Qwen/Qwen2.5-14B</code> encoder with all available synthetic data (before the curation step in section 4.1.1).</li>\n</ul>\n<p>What didn't work:</p>\n<ul>\n<li>Iterative hard negative mining</li>\n<li>Increasing batch size <a href=\"https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L194\" target=\"_blank\">through cross-device negatives</a></li>\n<li>Custom batching strategies e.g. having (query, misconception) positive pairs from the same SubjectId in the same batch</li>\n<li>My attempts at converting LLM retrievers to bi-directional encoders similar the the strategy used in <a href=\"https://huggingface.co/nvidia/NV-Embed-v2/blob/main/modeling_nvembed.py#L33\" target=\"_blank\">nvidia/NV-Embed-v2</a>.</li>\n</ul>\n<h2>6 Re-rankers</h2>\n<p>The Qwen 14B ranker did most of the heavy lifting by processing all retrieved misconceptions (32-64 candidates) and identifying top 8 candidates. This model was trained with a pointwise approach, where it sees one misconception at a time in the context window. The model input was structured as follows:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fa64d8d1be0b9fd0d27ddc7c8b47b7644%2Fpointwise_ranker.png?generation=1734199367236460&amp;alt=media\" alt=\"Pointwise Ranker\"></p>\n<p>The logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:</p>\n<pre><code>outputs = self.model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=True)\nlogits_yes = outputs.logits[:, -1, self.yes_loc]  # Yes token logit at the last position [bs]\nlogits_no = outputs.logits[:, -1, self.no_loc]  # No token logit at the last position [bs]\nlogits = logits_yes - logits_no  # [bs]\n\nlogits = logits.reshape(-1, self.group_size)\nlabels = labels.to(logits.device).reshape(-1) \nce_loss = self.loss_fn(logits, labels)\n</code></pre>\n<p>Each batch contained 1 positive and <code>batch_size-1</code> negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with <code>r=64, alpha=128, LoRA on all linear layers</code>. The language modelling head (<code>lm_head</code>) of the LLM (<code>Qwen/Qwen2.5-14B</code>) was frozen during fine-tuning.</p>\n<h3>6.1 Ablations</h3>\n<p>I found the following 4 strategies to be particularly significant for boosting the reranker performance and its generalization capability:</p>\n<h3>6.1.1 Few Shot Examples</h3>\n<p>To retain and leverage the LLM's in-context learning capabilities, I optionally included a few reference misconception examples (0 to 2) in the model input context (as shown in the diagram above). Not all training examples contained these few-shot demonstrations. The objective was to encourage the model to use reference examples when available, and otherwise rely on its internal reasoning. During inference, I used 1 or 2 examples from the entire training set as demonstrations. This approach was particularly effective for the 14B ranker's performance boosting private LB score from 0.495 to 0.531 <strong>(+0.036)</strong>. At this point, I was only using the competition data for training.</p>\n<h3>6.1.2 Distillation / Pseudo Labelling</h3>\n<p>Next, I incorporated the synthetic examples (post curation) into the training pipeline through pseudo labeling. I first fine-tuned two pointwise 72B models (<code>Qwen/Qwen2.5-Math-72B</code> and <code>Qwen/Qwen2.5-72B</code>) using only the competition dataset. These models were then used to generate pseudo labels for the synthetic examples. Finally, I used competition + pseudo-labeled data to fine-tune the next iteration of the 14B rerankers. This strategy boosted the 14B reranker's private LB score from 0.531 to 0.575 <strong>(+0.044)</strong>.</p>\n<h3>6.1.3 Negative Ratio</h3>\n<p>Next, I experimented with increasing the number of negative samples per positive. Showing the rankers a large number of negatives during training helped to improve performance. For each positive, I next increased the number of negatives to 24 from earlier 16. At this point, I also added scaled number of synthetic examples 2x. These two modifications boosted the 14B reranker's private LB score from 0.575 to 0.596 <strong>(+0.021)</strong>.</p>\n<h3>6.1.4 Chain of Thought (CoT)</h3>\n<p>I finally added the fine-tuned CoT reasoners (Section 4.2) into training and inference pipeline. During training, CoTs produced from fine-tuned <code>Qwen/Qwen2.5-14B</code> reasoner were optionally added to the model input. 50% of training data used CoTs and 50% did not. This encouraged the model to use external reasoning when available and otherwise rely on its internal reasoning. CoT boosted the 14B reranker's private LB score from 0.596 to 0.615 <strong>(+0.019)</strong>.</p>\n<p>The impact of these strategies is summarized in the following table:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F933a9cbaf89521f3873ce3220955d411%2F14b_ablation_updated.png?generation=1734200026698363&amp;alt=media\" alt=\"Ablation\"></p>\n<p>The live eval during fine-tuning showed consistent improvement in the 14B reranker's performance.\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F32caa0b7b996ea5af12050a4dc23f1c9%2Flive_eval_14b_ranker.png?generation=1734199467358905&amp;alt=media\" alt=\"Live Eval\"></p>\n<h3>6.2 Pointwise Re-Ranker (<code>Qwen/Qwen2.5-32B</code>)</h3>\n<p>I fine-tuned the <code>Qwen/Qwen2.5-32B</code> model in exactly the same way as the 14B reranker (with a different seed). My best 32B model had validation score of <code>0.663</code> vs that of <code>0.646</code> for the 14B reranker. During inference, the 32B reranker was used to process top 8 candidates from the 14B reranker and narrow them down to top 5 candidates. Incorporating the 32B reranker boosted private LB score from <code>0.615</code> to <code>0.625</code> <strong>(+0.010)</strong>.</p>\n<h3>6.3 Listwise Re-Ranker (<code>Qwen/Qwen2.5-72B</code>)</h3>\n<p>The top 5 candidates were finally ranked in a listwise manner using a fine-tuned <code>Qwen/Qwen2.5-72B</code> model. Here, the model sees all of the top 5 candidates at once. An example model input is shown below:\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fd044104a02153e758cbeda0b6914a14d%2Flistwise_model_input.png?generation=1734199518083387&amp;alt=media\" alt=\"Listwise\"></p>\n<p>This model had access to the even more information than pointwise re-rankers i.e.</p>\n<ul>\n<li>It sees 3 Chains of Thought (CoT) during inference - one each from the 7B, 14B, and 32B reasoners</li>\n<li>It sees up to 5 reference examples from the training set - 1 for each of the 5 candidate misconceptions</li>\n<li>It sees all of the candidates at once in the context window.</li>\n</ul>\n<p>The model had the best <code>MAP@5</code> among all of the rerankers (validation MAP@5 of <code>0.661</code>). LLM based Listwise rankers typically suffer from candidate position bias. One way to mitigate this is to run multiple inference runs by shuffling the position of the candidate misconceptions (Test time augmentation (TTA) like impact). I was unable to run TTA during inference due to time constraints. Incorporating the 72B reranker boosted private LB score from <code>0.625</code> to <code>0.638</code> <strong>(+0.013)</strong>.</p>\n<h3>6.4 Quantization</h3>\n<p>I quantized the fine-tuned rankers using <a href=\"https://github.com/casper-hansen/AutoAWQ\" target=\"_blank\">AutoAWQ</a>. I used task specific calibration datasets for each model to mitigate performance degradation. I tested the impact of calibration dataset with one of my 32B rerankers. The results are shown below:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F66dae22248f881fdf8a065979695c6e2%2Fcalibration_update.png?generation=1734200937122595&amp;alt=media\" alt=\"\"></p>\n<h3>6.5 What didn't work</h3>\n<ul>\n<li>Merging strategy as described in <a href=\"https://docs.google.com/document/d/1OjbjU5AOz4Ftn9xHQrX3oFQGhQ6RDUuXQipnQ9gn6tU/edit?tab=t.0\" target=\"_blank\">Continuous Fine-tuning Without Loss Using Lora and Mergekit</a></li>\n<li><a href=\"https://huggingface.co/Qwen/QwQ-32B-Preview\" target=\"_blank\">Qwen/QwQ-32B-Preview</a>: I naively fine-tuned it using the same steps as with <code>Qwen/Qwen2.5-32B</code> but got worse results. The QwQ model likely requires additional research to find out its proper usage.</li>\n</ul>\n<h2>7 Links</h2>\n<ul>\n<li><a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">Training code</a></li>\n<li><a href=\"https://www.kaggle.com/code/conjuring92/eedi-a2-pipeline?scriptVersionId=211785645\" target=\"_blank\">Inference Notebook</a></li>\n<li><a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset\" target=\"_blank\">Dataset with Synthetic + Competition MCQ</a></li>\n<li><a href=\"https://www.kaggle.com/datasets/conjuring92/eedi-cot-sonnet-6k\" target=\"_blank\">CoT Dataset</a></li>\n</ul>\n<h2>8 References</h2>\n<ul>\n<li><a href=\"https://arxiv.org/pdf/2310.02439\" target=\"_blank\">Novice Learner and Expert Tutor: Evaluating Math Reasoning Abilities of Large Language Models with Misconceptions</a></li>\n<li><a href=\"https://github.com/vllm-project/vllm\" target=\"_blank\">vllm</a></li>\n<li><a href=\"https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html\" target=\"_blank\">How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data</a></li>\n<li><a href=\"https://github.com/FlagOpen/FlagEmbedding\" target=\"_blank\">FlagEmbedding</a></li>\n<li><a href=\"https://github.com/casper-hansen/AutoAWQ\" target=\"_blank\">AutoAWQ</a></li>\n</ul>",
      "rawMarkdown": "I would like to thank Kaggle and EEDI for hosting this interesting competition! It was challenging and provided many opportunities to learn/apply new techniques. As always, I'm grateful to the Kaggle community for innovative ideas and engaging discussions. I'm excited to share my detailed solution and hope others will find it helpful!\n\n## 1 Task\nGiven a diagnostic math MCQ, together with the correct answer and an incorrect answer, the task was to recommend top 25 misconceptions (sorted by their affinity to the incorrect answer) from a pool of 2.5k+ misconceptions. \nEven though the standard retrieve-rerank framework was a natural fit, it came with a few challenges:\n- Current LLMs often struggle to mimic either (1) a `Novice Learner` i.e. generating the incorrect answer stemming from a specific misconception or (2) an `Expert Tutor` i.e. identifying the misconception that explains a given incorrect answer. LLMs excel at solving math problems, but they are not so great at counterfactual reasoning.\n- The misconception pool ties together closely related conceptual and computational mistakes, demanding high discriminative power to spot subtle differences with precision. This is highlighted in the competition overview:\n>Initial efforts to use pre-trained language models have not been successful, likely due to the complexity of the mathematical content in the questions.\n\n- The task setup requires the model to not only do well on known misconceptions but also generalize to new misconceptions.\n\n## 2 Meta Thoughts\nAt the start of the competition, I had the following hypotheses on what could be important for a good solution:\n- Synthetic data should help with out-of-distribution generalization\n- High quality synthetic data generation should be feasible since Math domain can be verified and curated objectively\n- Distillation from a good teacher(s) should be very powerful, as Large LLMs are significantly better at reasoning\n- Distilling Chain of Thoughts (CoT) from top LLMs (e.g. Claude 3.5 Sonnet) should help to tackle difficult examples\n- Quantization method and the calibration datasets could be important. We may need to add recovery adapters to the quantized models for maintaining top 1 accuracy.\n- Full training might be better than LoRA\n\nThese hypotheses guided me to design my experiments throughout the competition and helped me to stick to an idea even though the initial attempts were not successful.\n\n## 3 Pipeline\nI implemented a retrieve-and-rerank system that involved a sequence of four steps:\n- **Retrieval**: Identify top misconception candidates for each of the MCQ-Incorrect answer combinations. Specifically, I retained the top 32 retrieved candidates and included up to 32 additional candidates based on a dynamic threshold. The dynamic threshold is computed as the `top candidate similarity score - constant`. Candidates with similarity scores higher than the dynamic threshold are kept. \n- **14B Ranker**: Use a fine-tuned `Qwen/Qwen2.5-14B` ranker to process all retrieved candidates and shortlist top 8.\n- **32B Ranker**: Use a fine-tuned `Qwen/Qwen2.5-32B` ranker to process top 8 candidates and narrow them down to top 5.\n- **72B Ranker**: Use a fine-tuned `Qwen/Qwen2.5-72B` ranker to finalize the ranking of top 5 candidates.\n\nA schematic diagram of the pipeline and the leaderboard scores from each stages are shown below:\n![Inference Pipeline](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F3b2245b7c0baaab58b9d9232c6ff9bae%2Finference_pipeline.png?generation=1734198970117751&alt=media)\n\nThe final 25 misconception predictions comprised of:\n- 1st to 5th candidate from the 72B ranker\n- 6th to 8th candidate from the 32B ranker\n- 9th to 25th candidate from the 14B ranker.\n\n## 4 Data\nThe training data mix for both the retriever and ranker models included competition data (1.8k examples) and synthetic data (10k examples). The synthetic data played a crucial role in improving both raw performance and generalization capability with respect to unseen misconceptions.\n\n### 4.1 Synthetic Data\nIn an ideal scenario, synthetic MCQs should have the following properties:\n- The designated correct answers are indeed the correct answers (high accuracy).\n- The incorrect answers directly stem from the target misconception (high diagnostic power).\n- Among all misconceptions in the misconception pool (2.5k+), the indicated misconception should provide the most precise explanation for a given incorrect answer (high resolution).\n- The generated MCQs should cover a broad range of subjects and constructs (high diversity).\n\nI started generating diagnostic MCQs with a simple prompt that specified the expected format and a misconception of interest. However, it resulted in a dataset that violated almost all the properties to varying degrees. It was expected since\n- The simple prompt only included information about a single misconception. Hence, the data-generating LLM was completely unaware of closely related misconceptions within the misconception pool.\n- Lack of few shot examples meant lack of reference on the expected quality, difficulty level, tone, and language.\n- Even the advanced LLMs struggle with handling misconceptions and counterfactual reasoning effectively.\n- No curation was performed.\n\nI experimented with several strategies to address the issues and managed to create a high quality synthetic dataset with a `grouped synthetic data generation` approach and incorporating LLM based filtering. Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data. [This notebook](https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d) demonstrates the clustering process. Here is an example of a misconception cluster:\n```\n- Thinks x^2 - a^2x is a valid form of difference of two squares\n- When factorising a quadratic without a non variable term, tries to double bracket factorise\n- Incorrectly factorises a quadratic\n- Believes the constant in an expanded quadratic comes from adding the two numbers in the brackets\n- Believes the coefficent of x in an expanded quadratic comes from multiplying the two numbers in the brackets\n- Does not recognise difference of two squares\n- Does not realise a quadratic must be in the form ax^2+bx+c=0 to be factorised\n- Does not know how to identify common factors from algebraic terms\n- Believes the difference of 2 squares method of factorising also works for the addition of 2 squares\n- When factorising, believes they can choose different factors for each term\n- Believes they can factorise a difference of two squares by placing the constant in both brackets without square rooting\n```\n\nI next generated 5 new MCQs for each cluster using `Claude 3.5 Sonnet` with a refined prompt that included 4-5 reference examples on misconceptions from the cluster. I used the [metaprompt](https://github.com/anthropics/anthropic-cookbook/blob/main/misc/metaprompt.ipynb) tool from Anthropic cookbook for prompt engineering. Here is the final prompt used for data generation:\n\n```\nYou will be generating Multiple Choice Questions (MCQs) that diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n<misconceptions>\n{cluster_misconceptions}\n</misconceptions>\n\nHere are reference MCQs that demonstrate how to effectively diagnose these misconceptions:\n\n<reference_mcqs>\n{reference_mcqs}\n</reference_mcqs>\n\nYour task is to generate {num_mcqs} new MCQs that diagnose misconceptions not already covered by the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n1. For each reference MCQ, identify in your <analysis> tags:\n   - Which misconception it targets\n   - How the incorrect answers map to specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n2. Note the style, difficulty level, and precision of language used\n\nThen, in your <planning> tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where it commonly appears\n- Design questions where the misconception leads naturally to specific wrong answers\n- Take notes on how you can craft new MCQs that adheres to the reference MCQs' style, difficulty level, and precision of language\n\nFinally, generate new MCQs following these important guidelines:\n- Make sure each incorrect answer maps clearly to exactly one misconception\n- Use precise mathematical language matching the style of reference MCQs\n- Make questions challenging enough that students must demonstrate real understanding\n- Ensure wrong answers are plausible and stem from genuine misconceptions, not careless errors\n- Use the exact wording of misconceptions as given in the misconceptions list\n- Pay careful attention to subtle differences between the misconceptions and observe which one is the most appropriate for a given incorrect answer\n- Keep the construct name and subject name as short as possible hiding the details of the misconception\n- Questions should be of higher difficulty level than reference MCQs\n```\n\n### 4.1.1 Curation\nI used LLM-as-a-judge to filter out low quality synthetic MCQs. I prompted `GPT-4o` to rate the quality of the synthetic MCQs as below:\n\n```\nYou will analyze how well an incorrect answer reflects a suspected misconception in a mathematics problem. Your goal is to determine whether there is a clear, logical connection between the misconception and the wrong answer.\n\nHere is the problem with both correct and incorrect answers. The suspected misconception is also provided:\n<problem>\n{PROBLEM_DATA}\n</problem>\n\nFirst, analyze the problem in your scratchpad:\n<scratchpad>\n1. Solve the problem independently to verify the correct answer\n2. Examine how someone holding the suspected misconception would approach the problem\n3. Trace the logical path from misconception to incorrect answer\n4. Identify any gaps or inconsistencies in this connection\n</scratchpad>\n\nThen provide your evaluation using this format:\n<evaluation>\n1. Brief explanation of how the misconception could lead to the wrong answer\n2. Score from 0-10 based on these criteria:\n   - 10: Perfect alignment - wrong answer is direct result of misconception\n   - 8-9: Strong alignment - clear logical path from misconception to answer\n   - 5-7: Moderate alignment - connection exists but has some gaps\n   - 1-4: Weak alignment - connection is unclear or requires assumptions\n   - 0: No alignment - misconception does not explain wrong answer\n</evaluation>\n\nImportant guidelines:\n- Focus solely on the logical connection between misconception and wrong answer\n- Do not speculate about other possible misconceptions\n- Be specific about how the misconception leads to the error\n- Flag and deduct scores if any assumptions are required to connect misconception to answer\n- Consider whether a student with this misconception would consistently arrive at this wrong answer\n```\n\nI selected `GPT-4o` as judge based on vibe test as it felt more sensitive to the scoring scheme and as consistent as Claude 3.5 Sonnet.\n\n### 4.1.2 Incorporating Additional Misconceptions\nWhile creating synthetic data, LLM produced many misconceptions (4k+) that were not part of the host provided misconception pool. I decided to keep the external misconceptions to improve generalization capability of the retriever and ranker models. \n\nNaively merging the external misconceptions with existing ones would have introduced conflicts and noise, since many of them were just rephrasing of the existing misconceptions. I adopted the following steps to handle this carefully:\n- Attempt to match with existing misconceptions using string normalization (lowercasing, removing trailing punctuation, etc.)\n- Attempt to match with existing misconceptions using similarity scores from an embedding model (`thenlper/gte-base`) with very high threshold (0.995)\n- Remove new misconceptions that have fairly high similarity (between 0.95 and 0.995) with any of the existing misconceptions\n- Keep rest of the remaining external misconceptions\n\n### 4.1.3 Dataset\nThe final dataset is uploaded here: [Eedi - Mining Misconceptions in Mathematics](https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset/). It contains\n- 1.8k competition MCQs + 10.6k generated MCQs\n- 4791 misconceptions\nand follows the same format as the original competition dataset.\n\nReference: I'd highly recommend reading the synthetic data generation post from answer.ai: [How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data](https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html).\n\n\n### 4.2 Chain of Thought (CoT) Generation\nTo distill the reasoning capability of an advanced LLM in my solution pipeline, I first created a dataset containing thought processes generated by `Claude 3.5 Sonnet`. I provided Claude with: (i) the problem statement, (ii) the correct answer, (iii) an incorrect answer, (iv) the ground truth misconception, and (v) several closely related misconceptions. Using this information, I prompted Claude to generate the likely thought process that led a student to select the incorrect answer. The prompt is shown below:\n\n```\nYou will analyze a student's incorrect answer to identify the specific reasoning flaw that led to their error.\nYour goal is to explain precisely how their misconception caused them to arrive at the wrong answer.\n\nHere is the problem information:\n<problem_data>\n# Question: Simplify the expression: \\[x \\cdot y \\cdot x\\]\n# Correct Answer: \\(x^2y\\)\n# Incorrect Answer: \\(x^2\\)\n# Primary Misconception: Ignores variables without explicit coefficients when multiplying\n</problem_data>\n\nHere are related misconceptions that are similar but do not explain this specific error as precisely:\n<related_misconceptions>\n- Thinks only like terms can be multiplied\n- Fails to combine all instances of the same variable\n- Incorrectly identifies an incomplete variable factor\n- Does not understand how to multiply algebraic terms\n</related_misconceptions>\n\nFirst, examine all components of the problem carefully:\n1. The problem statement and question asked\n2. The correct answer and solution method\n3. The student's incorrect answer\n4. The primary misconception given\n5. The related misconceptions that should be distinguished from the primary one\n\nThen, reconstruct the student's likely thought process:\n- Identify the exact point where their reasoning diverged from the correct solution path\n- Note which specific mathematical operations or concepts they misapplied\n- Connect their error directly to the stated primary misconception\n- Verify that this explanation better fits the error than the related misconceptions\n\nWrite your analysis in <evaluation> tags, following this structure:\n- Show the correct calculation first\n- Show the incorrect calculations that demonstrate the error\n- Explain the specific flaw in the student's reasoning\n- Demonstrate how the misconception led to this particular error\n- Distinguish from the related misconceptions\n- Keep your explanation to 5-6 clear, non-repetitive sentences\n- Focus solely on the reasoning that produced this specific error\n\nGuidelines for writing your explanation:\n- Do not restate the problem or name the misconception\n- Be precise about the mathematical concepts involved\n- Show exactly how the misconception led to the error\n- Distinguish from related misconceptions\n- Avoid repetition\n- Stay focused on this specific error\n```\n\nUsing this dataset, I fine-tuned three Qwen 2.5 series models (`Qwen/Qwen2.5-Math-7B`, `Qwen/Qwen2.5-14B`, and `Qwen/Qwen2.5-32B`) to act as reasoners. Notably, I omitted the true and related misconceptions from the input for fine-tuning. During inference, these models would see: (i) the problem statement, (ii) the correct answer, and (iii) an incorrect answer. They would then generate the likely thought process of a student behind selecting the incorrect answer. I used `vllm` for CoT generation during inference with `temperature=0.7, top_p=0.8, repetition_penalty=1.0, max_tokens=256`.\n\nThe CoT dataset is uploaded here: [Eedi - CoT Dataset](https://www.kaggle.com/datasets/conjuring92/eedi-sonnet-cot-comp-sharp-dec-09/).\n\n## 5 Train-Validation Split\nI split the competition dataset into 5 folds, initially based on the `QuestionId` field. However, this produced overly optimistic estimates with a large gap between validation and leaderboard scores. Next, I tried GroupKFold on `SubjectId`, but this resulted in overly pessimistic estimates. I finally settled on GroupKFold with `ConstructId`, which yielded a narrow Validation/LB gap and good correlation up to ~0.62 public LB score range.\n\nDuring development, I always trained my models on folds 1-4 and validated on fold 0. The synthetic data was marked as fold 99 and was included in the training set. The final models were trained on the entire dataset (full fit) using the same hyper parameters from the development stage.\n\n\n## 6 Retrievers\nI used the standard [MultipleNegativesRankingLoss](https://sbert.net/docs/package_reference/sentence_transformer/losses.html#multiplenegativesrankingloss) to fine-tune the retrievers, while referencing the [FlagEmbedding](https://github.com/FlagOpen/FlagEmbedding/tree/master/FlagEmbedding/finetune/embedder/decoder_only) codebase for developing training scripts. At this stage, I tracked both `map@25` and `recall@32` metrics and prioritized optimizing for `recall@32`, since recall was more important for overall pipeline performance.\n\nI fine-tuned several retrievers with the following scores:\n![Retriever Scores](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fee7ac74c895fd5221738bf2ae8f42cee%2Fretriever_scores.png?generation=1734199290617188&alt=media)\n\nIncorporating hard negatives into training batches and distilling re-ranker scores consistently improved `map@25` performance, but did not positively impact `recall@32`. For my final submission selections, I chose the high-recall `Qwen/Qwen2.5-14B` encoder (Model 3) instead of the best `map@25` encoder (Model 4). Following the same logic, I also excluded the BGE encoder (Model 2).  Notably, my best encoder-only submission (Model 1 + Model 2 + Model 4) scored 0.524 on public LB and 0.475 on private LB.\n\nRetrievers were fine-tuned using LoRA with: `r=64, alpha=128, learning_rate_lora_a=1e-5, learning_rate_lora_b=5e-5, LoRA on all linear layers, batch_size=128, and epochs=12`. A few key factors that improved recall performance were:\n- Setting temperature to 0.01, instead of the typically used value of 0.02 in LLM-based encoders\n- Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives\n- Pretraining the `Qwen/Qwen2.5-14B` encoder with all available synthetic data (before the curation step in section 4.1.1).\n\nWhat didn't work:\n- Iterative hard negative mining\n- Increasing batch size [through cross-device negatives](https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L194)\n- Custom batching strategies e.g. having (query, misconception) positive pairs from the same SubjectId in the same batch\n- My attempts at converting LLM retrievers to bi-directional encoders similar the the strategy used in [nvidia/NV-Embed-v2](https://huggingface.co/nvidia/NV-Embed-v2/blob/main/modeling_nvembed.py#L33).\n\n## 6 Re-rankers\nThe Qwen 14B ranker did most of the heavy lifting by processing all retrieved misconceptions (32-64 candidates) and identifying top 8 candidates. This model was trained with a pointwise approach, where it sees one misconception at a time in the context window. The model input was structured as follows:\n![Pointwise Ranker](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fa64d8d1be0b9fd0d27ddc7c8b47b7644%2Fpointwise_ranker.png?generation=1734199367236460&alt=media)\n\nThe logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:\n\n```python\noutputs = self.model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=True)\nlogits_yes = outputs.logits[:, -1, self.yes_loc]  # Yes token logit at the last position [bs]\nlogits_no = outputs.logits[:, -1, self.no_loc]  # No token logit at the last position [bs]\nlogits = logits_yes - logits_no  # [bs]\n\nlogits = logits.reshape(-1, self.group_size)\nlabels = labels.to(logits.device).reshape(-1) \nce_loss = self.loss_fn(logits, labels)\n```\n\nEach batch contained 1 positive and `batch_size-1` negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with `r=64, alpha=128, LoRA on all linear layers`. The language modelling head (`lm_head`) of the LLM (`Qwen/Qwen2.5-14B`) was frozen during fine-tuning.\n\n\n### 6.1 Ablations\nI found the following 4 strategies to be particularly significant for boosting the reranker performance and its generalization capability:\n\n### 6.1.1 Few Shot Examples\nTo retain and leverage the LLM's in-context learning capabilities, I optionally included a few reference misconception examples (0 to 2) in the model input context (as shown in the diagram above). Not all training examples contained these few-shot demonstrations. The objective was to encourage the model to use reference examples when available, and otherwise rely on its internal reasoning. During inference, I used 1 or 2 examples from the entire training set as demonstrations. This approach was particularly effective for the 14B ranker's performance boosting private LB score from 0.495 to 0.531 **(+0.036)**. At this point, I was only using the competition data for training.\n\n### 6.1.2 Distillation / Pseudo Labelling\nNext, I incorporated the synthetic examples (post curation) into the training pipeline through pseudo labeling. I first fine-tuned two pointwise 72B models (`Qwen/Qwen2.5-Math-72B` and `Qwen/Qwen2.5-72B`) using only the competition dataset. These models were then used to generate pseudo labels for the synthetic examples. Finally, I used competition + pseudo-labeled data to fine-tune the next iteration of the 14B rerankers. This strategy boosted the 14B reranker's private LB score from 0.531 to 0.575 **(+0.044)**.\n\n### 6.1.3 Negative Ratio\nNext, I experimented with increasing the number of negative samples per positive. Showing the rankers a large number of negatives during training helped to improve performance. For each positive, I next increased the number of negatives to 24 from earlier 16. At this point, I also added scaled number of synthetic examples 2x. These two modifications boosted the 14B reranker's private LB score from 0.575 to 0.596 **(+0.021)**.\n\n### 6.1.4 Chain of Thought (CoT)\nI finally added the fine-tuned CoT reasoners (Section 4.2) into training and inference pipeline. During training, CoTs produced from fine-tuned `Qwen/Qwen2.5-14B` reasoner were optionally added to the model input. 50% of training data used CoTs and 50% did not. This encouraged the model to use external reasoning when available and otherwise rely on its internal reasoning. CoT boosted the 14B reranker's private LB score from 0.596 to 0.615 **(+0.019)**.\n\nThe impact of these strategies is summarized in the following table:\n![Ablation](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F933a9cbaf89521f3873ce3220955d411%2F14b_ablation_updated.png?generation=1734200026698363&alt=media)\n\nThe live eval during fine-tuning showed consistent improvement in the 14B reranker's performance.\n![Live Eval](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F32caa0b7b996ea5af12050a4dc23f1c9%2Flive_eval_14b_ranker.png?generation=1734199467358905&alt=media)\n\n### 6.2 Pointwise Re-Ranker (`Qwen/Qwen2.5-32B`)\nI fine-tuned the `Qwen/Qwen2.5-32B` model in exactly the same way as the 14B reranker (with a different seed). My best 32B model had validation score of `0.663` vs that of `0.646` for the 14B reranker. During inference, the 32B reranker was used to process top 8 candidates from the 14B reranker and narrow them down to top 5 candidates. Incorporating the 32B reranker boosted private LB score from `0.615` to `0.625` **(+0.010)**.\n\n### 6.3 Listwise Re-Ranker (`Qwen/Qwen2.5-72B`)\nThe top 5 candidates were finally ranked in a listwise manner using a fine-tuned `Qwen/Qwen2.5-72B` model. Here, the model sees all of the top 5 candidates at once. An example model input is shown below:\n![Listwise](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2Fd044104a02153e758cbeda0b6914a14d%2Flistwise_model_input.png?generation=1734199518083387&alt=media)\n\n\nThis model had access to the even more information than pointwise re-rankers i.e.\n- It sees 3 Chains of Thought (CoT) during inference - one each from the 7B, 14B, and 32B reasoners\n- It sees up to 5 reference examples from the training set - 1 for each of the 5 candidate misconceptions\n- It sees all of the candidates at once in the context window.\n\nThe model had the best `MAP@5` among all of the rerankers (validation MAP@5 of `0.661`). LLM based Listwise rankers typically suffer from candidate position bias. One way to mitigate this is to run multiple inference runs by shuffling the position of the candidate misconceptions (Test time augmentation (TTA) like impact). I was unable to run TTA during inference due to time constraints. Incorporating the 72B reranker boosted private LB score from `0.625` to `0.638` **(+0.013)**.\n\n### 6.4 Quantization\nI quantized the fine-tuned rankers using [AutoAWQ](https://github.com/casper-hansen/AutoAWQ). I used task specific calibration datasets for each model to mitigate performance degradation. I tested the impact of calibration dataset with one of my 32B rerankers. The results are shown below:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F2125251%2F66dae22248f881fdf8a065979695c6e2%2Fcalibration_update.png?generation=1734200937122595&alt=media)\n\n### 6.5 What didn't work\n- Merging strategy as described in [Continuous Fine-tuning Without Loss Using Lora and Mergekit](https://docs.google.com/document/d/1OjbjU5AOz4Ftn9xHQrX3oFQGhQ6RDUuXQipnQ9gn6tU/edit?tab=t.0)\n- [Qwen/QwQ-32B-Preview](https://huggingface.co/Qwen/QwQ-32B-Preview): I naively fine-tuned it using the same steps as with `Qwen/Qwen2.5-32B` but got worse results. The QwQ model likely requires additional research to find out its proper usage.\n\n## 7 Links\n- [Training code](https://github.com/rbiswasfc/eedi-mining-misconceptions)\n- [Inference Notebook](https://www.kaggle.com/code/conjuring92/eedi-a2-pipeline?scriptVersionId=211785645)\n- [Dataset with Synthetic + Competition MCQ](https://www.kaggle.com/datasets/conjuring92/eedi-mcq-dataset)\n- [CoT Dataset](https://www.kaggle.com/datasets/conjuring92/eedi-cot-sonnet-6k)\n\n## 8 References\n- [Novice Learner and Expert Tutor: Evaluating Math Reasoning Abilities of Large Language Models with Misconceptions](https://arxiv.org/pdf/2310.02439)\n- [vllm](https://github.com/vllm-project/vllm)\n- [How To T̶r̶a̶i̶n̶ Synthesize Your D̶r̶a̶g̶o̶n̶ Data](https://www.answer.ai/posts/2024-10-15-how-to-synthesize-data.html)\n- [FlagEmbedding](https://github.com/FlagOpen/FlagEmbedding)\n- [AutoAWQ](https://github.com/casper-hansen/AutoAWQ)",
      "votes": 179
    },
    {
      "id": 3072151,
      "postDate": "2024-12-14T19:03:56.193Z",
      "content": "<p>Detailed is an understatement!</p>\n<p>This is great info to share, Raja. Congrats again!</p>",
      "rawMarkdown": "Detailed is an understatement!\n\nThis is great info to share, Raja. Congrats again!",
      "votes": 5
    },
    {
      "id": 3154496,
      "postDate": "2025-03-20T02:42:06.973Z",
      "content": "<p>Hi, thanks for sharing such an excellent proposal—it’s a solid RAG framework concept. Here's my understanding of your approach to training the reasoner:</p>\n<ol>\n<li>First, you use a prompt with Claude 3.5 to generate a chain-of-thought (CoT) that might lead to selecting the wrong answer.</li>\n<li>Then, with the same input, you filter out the error causes and near-error causes and combine the resulting text with the generated CoT to form a query-CoT text pair for fine-tuning the student model.</li>\n</ol>\n<p>My question is: How do you ensure that the generated text—the CoT content—is accurate? Do you employ a curation step, similar to the one used in the synthesized data process, to filter for high-quality CoTs?</p>",
      "rawMarkdown": "Hi, thanks for sharing such an excellent proposal—it’s a solid RAG framework concept. Here's my understanding of your approach to training the reasoner:\n\n1. First, you use a prompt with Claude 3.5 to generate a chain-of-thought (CoT) that might lead to selecting the wrong answer.\n2. Then, with the same input, you filter out the error causes and near-error causes and combine the resulting text with the generated CoT to form a query-CoT text pair for fine-tuning the student model.\n\nMy question is: How do you ensure that the generated text—the CoT content—is accurate? Do you employ a curation step, similar to the one used in the synthesized data process, to filter for high-quality CoTs?",
      "votes": 1,
      "replies": [
        {
          "id": 3155013,
          "postDate": "2025-03-20T16:05:37.953Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/youwbpyr\" target=\"_blank\">@youwbpyr</a>, Thanks. Yes, I used the generated query-CoT pairs to distill Claude 3.5's reasoning capability into student models. For this competition, I didn't curate the generated CoTs. However, I think generating multiple CoTs and picking the best one as per a process reward model / llm-as-a-judge could improve student models reasoning abilities. </p>",
          "rawMarkdown": "Hi @youwbpyr, Thanks. Yes, I used the generated query-CoT pairs to distill Claude 3.5's reasoning capability into student models. For this competition, I didn't curate the generated CoTs. However, I think generating multiple CoTs and picking the best one as per a process reward model / llm-as-a-judge could improve student models reasoning abilities. ",
          "votes": 2
        }
      ]
    },
    {
      "id": 3077833,
      "postDate": "2024-12-21T12:56:21.633Z",
      "content": "<p>Hi Raja, thanks for the detailed solution! Congrats for the solo win🥇</p>\n<p>Would you mind if I ask a few questions ?</p>\n<p><strong>Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?</strong></p>\n<p>Context: I rented H100s from RunPod and finetuning using LoRA for a 14B Yes/No reranker took &gt; 5 hours with our team’s external data. For initial experiments I tested various numbers of hard negatives (1,2,4,8,16,24) and easily training these six models can take more than 2 days total (just for one idea!). Towards the end I finetuned 32B and the training on just 4 negatives took &gt; 20 hours for a single experiment (5 hours without external data)! I trained for 2 epochs using the SFTTrainer. Felt that there may be a faster way…</p>\n<p><strong>Do you have tips on selecting experiments?</strong></p>\n<p>Context: From the MCTS and EEDI competitions, I realised that I’m able to think of lots of ideas to solve the problem. However, I felt my ability to decide which one to prioritise needs improvement. For example in EEDI, I spent 3 days customizing TextGrad to optimize prompts for Qwen to hopefully improve the reranking performance (similar to <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/540759\" target=\"_blank\">this</a>). However the improvement is very marginal and possibly not worth 3 full days of effort…Maybe I will get better at this as I gain more experience 😅</p>\n<p>Really inspiring that you got the correct approach from the beginning and have 3 months to get the most out of it 👍</p>",
      "rawMarkdown": "Hi Raja, thanks for the detailed solution! Congrats for the solo win🥇\n\nWould you mind if I ask a few questions ?\n\n**Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?**\n\nContext: I rented H100s from RunPod and finetuning using LoRA for a 14B Yes/No reranker took > 5 hours with our team’s external data. For initial experiments I tested various numbers of hard negatives (1,2,4,8,16,24) and easily training these six models can take more than 2 days total (just for one idea!). Towards the end I finetuned 32B and the training on just 4 negatives took > 20 hours for a single experiment (5 hours without external data)! I trained for 2 epochs using the SFTTrainer. Felt that there may be a faster way…\n\n**Do you have tips on selecting experiments?**\n\nContext: From the MCTS and EEDI competitions, I realised that I’m able to think of lots of ideas to solve the problem. However, I felt my ability to decide which one to prioritise needs improvement. For example in EEDI, I spent 3 days customizing TextGrad to optimize prompts for Qwen to hopefully improve the reranking performance (similar to [this](https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/540759)). However the improvement is very marginal and possibly not worth 3 full days of effort…Maybe I will get better at this as I gain more experience 😅\n\nReally inspiring that you got the correct approach from the beginning and have 3 months to get the most out of it 👍\n\n\n\n",
      "votes": 4,
      "replies": [
        {
          "id": 3078167,
          "postDate": "2024-12-21T21:54:46.657Z",
          "content": "<p>Hi bogoconic1!</p>\n<p>Thanks a lot! You've been on an impressive path and performing well across different types of competitions!</p>\n<blockquote>\n  <p>Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?</p>\n</blockquote>\n<p>I used 2xH100 GPUs from <a href=\"https://cloud.vast.ai/create/\" target=\"_blank\">vast.ai</a>. I trained my models using the HF accelerate with a few basic speed optimizations e.g. using (1)  torch.compile (2) flash-attention (3) LoRA instead of QLoRA (4) padding sequence lengths to multiples of 8. The 14B re-ranker was also taking ~5hrs for a full run in my setup. But, I very rarely did a full run: (a) ~50% of training was giving good indications on the experiment, (b) I primarily experimented with the 7B models. For 32B, I just copied the best settings from 14B. IMO key is to keep experiment setup as lean as possible.</p>\n<blockquote>\n  <p>Do you have tips on selecting experiments?</p>\n</blockquote>\n<p>I often struggle with this too. It's difficult to get the exploration vs exploitation balance right. Although there is no silver bullet, I think the following points help in NLP comps:</p>\n<ol>\n<li>Try to find the best set of backbones to fine-tune from</li>\n<li>Once you find a good backbone &amp; have a decent baseline, focus on data related experiments</li>\n<li>Write down takeaways after each experiment -- include related plots, error analysis etc. This should inform you what to do next</li>\n<li>Techniques like distillation/pseudo labeling almost always help with performance and generalization</li>\n</ol>\n<p>Will add to this list if I can think of other points tomorrow. I'm not sure if these are too obvious or very opinionated…</p>",
          "rawMarkdown": "Hi bogoconic1!\n\nThanks a lot! You've been on an impressive path and performing well across different types of competitions!\n\n>Great job on trying out lots of experiments within a short period of three months. What GPU specifications/clusters did you use to fine tune the models ?\n\nI used 2xH100 GPUs from [vast.ai](https://cloud.vast.ai/create/). I trained my models using the HF accelerate with a few basic speed optimizations e.g. using (1)  torch.compile (2) flash-attention (3) LoRA instead of QLoRA (4) padding sequence lengths to multiples of 8. The 14B re-ranker was also taking ~5hrs for a full run in my setup. But, I very rarely did a full run: (a) ~50% of training was giving good indications on the experiment, (b) I primarily experimented with the 7B models. For 32B, I just copied the best settings from 14B. IMO key is to keep experiment setup as lean as possible.\n\n> Do you have tips on selecting experiments?\n\nI often struggle with this too. It's difficult to get the exploration vs exploitation balance right. Although there is no silver bullet, I think the following points help in NLP comps:\n1. Try to find the best set of backbones to fine-tune from\n2. Once you find a good backbone & have a decent baseline, focus on data related experiments\n3. Write down takeaways after each experiment -- include related plots, error analysis etc. This should inform you what to do next\n4. Techniques like distillation/pseudo labeling almost always help with performance and generalization\n\nWill add to this list if I can think of other points tomorrow. I'm not sure if these are too obvious or very opinionated...",
          "votes": 10
        }
      ]
    },
    {
      "id": 3122439,
      "postDate": "2025-02-12T16:21:11.237Z",
      "content": "<p>hi～ I would like to ask you another question. In your notebook at <a href=\"https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d\" target=\"_blank\">https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d</a>, you used a file named ranker_oof_df.csv. In your solution, you mentioned, “Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data.” My question is, when you refer to “validation data” here, do you mean the predictions on the validation data obtained by training a model using the training set, which is split from the original entire dataset into training and valid sets? thanks a lot！</p>",
      "rawMarkdown": "hi～ I would like to ask you another question. In your notebook at https://gist.github.com/rbiswasfc/8d2bfec5c2a358e8beeb2df390111f9d, you used a file named ranker_oof_df.csv. In your solution, you mentioned, “Specifically, I first created clusters of closely related misconceptions leveraging co-occurrence statistics of misconceptions in retriever/ranker predictions on validation data.” My question is, when you refer to “validation data” here, do you mean the predictions on the validation data obtained by training a model using the training set, which is split from the original entire dataset into training and valid sets? thanks a lot！",
      "votes": 1,
      "replies": [
        {
          "id": 3123110,
          "postDate": "2025-02-13T11:41:31.767Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/yuhaowu123\" target=\"_blank\">@yuhaowu123</a>, yes, exactly. Using top retrieved candidates on the validation split.</p>",
          "rawMarkdown": "Hi @yuhaowu123, yes, exactly. Using top retrieved candidates on the validation split.",
          "replies": [
            {
              "id": 3141956,
              "postDate": "2025-03-06T02:04:19.437Z",
              "rawMarkdown": "",
              "isDeleted": true
            }
          ]
        }
      ]
    },
    {
      "id": 3081076,
      "postDate": "2024-12-26T07:06:16.510Z",
      "content": "<p>Superb, good luck in your future ventures!</p>",
      "rawMarkdown": "Superb, good luck in your future ventures!",
      "votes": 1
    },
    {
      "id": 3078878,
      "postDate": "2024-12-23T00:42:09.683Z",
      "content": "<p>Congrats for the winning! Did you try to train the 14b reranker with synthetic data but without distillation from 72b? I wonder how it would perform.</p>",
      "rawMarkdown": "Congrats for the winning! Did you try to train the 14b reranker with synthetic data but without distillation from 72b? I wonder how it would perform.",
      "votes": 1,
      "replies": [
        {
          "id": 3078984,
          "postDate": "2024-12-23T04:54:24.810Z",
          "content": "<p>Interesting, this should be a good experiment! However, I didn't try this thinking synthetic data misconceptions still may be noisy (lesser quality than competition data) even after curation…</p>",
          "rawMarkdown": "Interesting, this should be a good experiment! However, I didn't try this thinking synthetic data misconceptions still may be noisy (lesser quality than competition data) even after curation..."
        }
      ]
    },
    {
      "id": 3078557,
      "postDate": "2024-12-22T13:49:41.320Z",
      "content": "<p>Thank you very much for your insights! This is a very interesting and solid solution. However, I have a few questions regarding the prompt design that I’d like to clarify:</p>\n<ol>\n<li><p>You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?</p></li>\n<li><p>The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?</p></li>\n<li><p>The prompt mentions that the  tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？</p></li>\n<li><p>Many of my above questions stem from uncertainty about the content within the  tag and the  tag in a complete prompt. Would you be able to provide me with an example of a fully constructed prompt including these tags?Thanks a lot again！~~~</p></li>\n</ol>",
      "rawMarkdown": "Thank you very much for your insights! This is a very interesting and solid solution. However, I have a few questions regarding the prompt design that I’d like to clarify:\n\n1. You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?\n\n2. The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?\n\n3. The prompt mentions that the <analysis> tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？\n\n4. Many of my above questions stem from uncertainty about the content within the <misconceptions> tag and the <reference_mcqs> tag in a complete prompt. Would you be able to provide me with an example of a fully constructed prompt including these tags?Thanks a lot again！~~~",
      "votes": 1,
      "replies": [
        {
          "id": 3079014,
          "postDate": "2024-12-23T06:06:25.877Z",
          "content": "<p>Here is an example prompt:</p>\n<pre><code>You will be generating Multiple Choice Questions (MCQs)  diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n&lt;misconceptions&gt;\n- Thinks  the perimeter  a square grid  the number  squares surrounding the rectangle\n- Calculates area  asked  perimeter\n- Counts a side length more than once  counting perimeter due   marking a starting point\n- Thinks  the perimeter  a square grid  the number  squares inside  are touching the perimeter  the shape\n- Calculates perimeter  asked  area\n- When calculating perimeter, only adds two sides\n- Believes lines inside the shape are included  finding perimeter\n- When calculating perimeter, only adds the marked lengths\n- When calculating perimeter, multiplies instead  adds\n- Thinks only labelled dimensions need  be included  calculating the perimeter\n- Confuses perimeter  area\n- Fails  use the properties  simple shapes  work out missing lengths\n- Does  know  we can use the conservation  perimeter  find missing lengths\n- Makes an assumption about line segments being equal within a shape\n- Mixes up width  height  a rectangle\n- Does  know how  find missing lengths  a composite shape\n&lt;/misconceptions&gt;\n\nHere are reference MCQs  demonstrate how  effectively diagnose these misconceptions:\n\n&lt;reference_mcqs&gt;\n[{: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }, {: , : , : , : , : , : , : , : , : , : , : , : }]\n&lt;/reference_mcqs&gt;\n\nYour task   generate   MCQs  diagnose misconceptions  already covered  the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n For each reference MCQ, identify  your &lt;analysis&gt; tags:\n   - Which misconception  targets\n   - How the incorrect answers   specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n Note the style, difficulty level,  precision  language used\n\nThen,  your &lt;planning&gt; tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where  commonly appears\n- Design questions where the misconception leads naturally  specific wrong answers\n- Take notes  how you can craft  MCQs  adheres  the reference MCQs</code></pre>",
          "rawMarkdown": "Here is an example prompt:\n\n```\nYou will be generating Multiple Choice Questions (MCQs) that diagnose specific mathematical misconceptions. Here are the misconceptions you should focus on:\n\n<misconceptions>\n- Thinks that the perimeter on a square grid is the number of squares surrounding the rectangle\n- Calculates area when asked for perimeter\n- Counts a side length more than once when counting perimeter due to not marking a starting point\n- Thinks that the perimeter on a square grid is the number of squares inside that are touching the perimeter of the shape\n- Calculates perimeter when asked for area\n- When calculating perimeter, only adds two sides\n- Believes lines inside the shape are included when finding perimeter\n- When calculating perimeter, only adds the marked lengths\n- When calculating perimeter, multiplies instead of adds\n- Thinks only labelled dimensions need to be included when calculating the perimeter\n- Confuses perimeter and area\n- Fails to use the properties of simple shapes to work out missing lengths\n- Does not know that we can use the conservation of perimeter to find missing lengths\n- Makes an assumption about line segments being equal within a shape\n- Mixes up width and height of a rectangle\n- Does not know how to find missing lengths in a composite shape\n</misconceptions>\n\nHere are reference MCQs that demonstrate how to effectively diagnose these misconceptions:\n\n<reference_mcqs>\n[{'SubjectName': 'Volume and Capacity Units', 'ConstructName': 'Given the perimeter, work out a missing length requiring knowledge of the geometrical properties of the shape', 'QuestionText': 'The perimeter of this rectangle is \\\\( 5.6 \\\\mathrm{~cm} \\\\).\\n\\nWhat is the length of the side marked with a star? ![Rectangle with base length labelled 1.02 cm and side length labelled with a gold star]()', 'AnswerAText': '\\\\( 4.58 \\\\mathrm{~cm} \\\\)', 'AnswerBText': '\\\\( 1.6 \\\\mathrm{~cm} \\\\)', 'AnswerCText': '\\\\( 1.78 \\\\mathrm{~cm} \\\\)', 'AnswerDText': '\\\\( 4.4 \\\\mathrm{~cm} \\\\)', 'CorrectAnswer': 'C', 'MisconceptionAName': 'When calculating perimeter, only adds the marked lengths', 'MisconceptionBName': '', 'MisconceptionCName': '', 'MisconceptionDName': ''}, {'SubjectName': 'Missing Lengths', 'ConstructName': 'Calculate missing lengths of shapes by geometrical inference, where the lengths given are in the same units', 'QuestionText': 'What is value of \\\\( p \\\\) in this compound shape made with rectangles? ![Compound shape made of two rectangles with the sides labelled p (in red) cm, 15 cm, 12 cm, 7 cm and 7 cm. One side is unlabelled]()', 'AnswerAText': '\\\\( 5 \\\\mathrm{~cm} \\\\)', 'AnswerBText': '\\\\( 6 \\\\mathrm{~cm} \\\\)', 'AnswerCText': '\\\\( 7 \\\\mathrm{~cm} \\\\)', 'AnswerDText': 'Not enough information', 'CorrectAnswer': 'A', 'MisconceptionAName': '', 'MisconceptionBName': 'Makes an assumption about line segments being equal within a shape', 'MisconceptionCName': 'Makes an assumption about line segments being equal within a shape', 'MisconceptionDName': 'Does not know that we can use the conservation of perimeter to find missing lengths'}, {'SubjectName': 'Distance Between Two Co-ordinates', 'ConstructName': 'Calculate the length of horizontal and vertical line segments', 'QuestionText': '![A rectangle drawn on a coordinate grid. Three of the vertices are labelled (3,12) (10,12) and (10,7). There is a red arrow between (3,12) and (10,12) indicating the width.]() What is the width of this rectangle as indicated by the arrow?', 'AnswerAText': '\\\\( 12 \\\\)', 'AnswerBText': '\\\\( 7 \\\\)', 'AnswerCText': '\\\\( 5 \\\\)', 'AnswerDText': '\\\\( 13 \\\\)', 'CorrectAnswer': 'B', 'MisconceptionAName': '', 'MisconceptionBName': '', 'MisconceptionCName': 'Mixes up width and height of a rectangle', 'MisconceptionDName': ''}, {'SubjectName': 'Writing Formula', 'ConstructName': 'Use perimeter to write algebraic expressions', 'QuestionText': 'What is the perimeter of this rectangle? ![A rectangle. The length of a short side is labelled x, and the length of a long side is labelled y.]()', 'AnswerAText': '\\\\( x+y \\\\)', 'AnswerBText': '\\\\( 2 x y \\\\)', 'AnswerCText': '\\\\( 2 x+2 y \\\\)', 'AnswerDText': '\\\\( x y \\\\)', 'CorrectAnswer': 'C', 'MisconceptionAName': 'Thinks only labelled dimensions need to be included when calculating the perimeter', 'MisconceptionBName': '', 'MisconceptionCName': '', 'MisconceptionDName': 'Calculates area when asked for perimeter'}, {'SubjectName': 'Perimeter', 'ConstructName': 'Given the area of a square, calculate a missing dimension', 'QuestionText': 'A shape is made up a square and regular pentagon.\\nThe area of the square is \\\\( 196 \\\\mathrm{~cm}^{2} \\\\).\\n\\nWhat is the perimeter of the compound shape? ![A regular pentagon with a square joined along one edge]()', 'AnswerAText': '\\\\( 14 \\\\mathrm{~cm} \\\\)', 'AnswerBText': '\\\\( 343 \\\\mathrm{~cm} \\\\)', 'AnswerCText': '\\\\( 112 \\\\mathrm{~cm} \\\\)', 'AnswerDText': '\\\\( 98 \\\\mathrm{~cm} \\\\)', 'CorrectAnswer': 'D', 'MisconceptionAName': '', 'MisconceptionBName': '', 'MisconceptionCName': 'Believes lines inside the shape are included when finding perimeter', 'MisconceptionDName': ''}]\n</reference_mcqs>\n\nYour task is to generate 5 new MCQs that diagnose misconceptions not already covered by the reference MCQs.\n\nFirst, analyze the reference MCQs carefully:\n1. For each reference MCQ, identify in your <analysis> tags:\n   - Which misconception it targets\n   - How the incorrect answers map to specific misconceptions\n   - What makes the question effective at diagnosing the misconception\n2. Note the style, difficulty level, and precision of language used\n\nThen, in your <planning> tags:\n- List which misconceptions still need coverage\n- For each needed misconception, brainstorm mathematical contexts where it commonly appears\n- Design questions where the misconception leads naturally to specific wrong answers\n- Take notes on how you can craft new MCQs that adheres to the reference MCQs' style, difficulty level, and precision of language\n\nFinally, generate new MCQs following these important guidelines:\n- Make sure each incorrect answer maps clearly to exactly one misconception\n- Use precise mathematical language matching the style of reference MCQs\n- Make questions challenging enough that students must demonstrate real understanding\n- Ensure wrong answers are plausible and stem from genuine misconceptions, not careless errors\n- Use the exact wording of misconceptions as given in the misconceptions list\n- Pay careful attention to subtle differences between the misconceptions and observe which one is the most appropriate for a given incorrect answer\n- Keep the construct name and subject name as short as possible hiding the details of the misconception\n- Questions should be of higher difficulty level than reference MCQs\n```"
        },
        {
          "id": 3079020,
          "postDate": "2024-12-23T06:17:30.400Z",
          "content": "<blockquote>\n  <p>You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?</p>\n</blockquote>\n<p>For each MCQ, the LLM would generate</p>\n<pre><code>           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n           \n</code></pre>\n<p>therefore, incorrect answers and misconceptions can be paired properly.</p>\n<blockquote>\n  <p>The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?</p>\n</blockquote>\n<p>Nice spot. Even if we specify the possible misconceptions, LLM still likes to generate additional ones. Before I settled on this prompt, my earlier prompts would generate even more of new misconceptions. </p>\n<blockquote>\n  <p>The prompt mentions that the tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？</p>\n</blockquote>\n<p>I have provided a full prompt example <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/551688#3079014\" target=\"_blank\">here</a>. Hope it helps!</p>",
          "rawMarkdown": "> You mentioned that the misconception you provided are very similar, but for a single question (Q), the three incorrect answers (A) might correspond to very different types of misconception. In that case, does each reference correspond to one QA pair, or does one Q correspond to three different A options ?\n\nFor each MCQ, the LLM would generate\n```\n        subject_name: str,  # The subject area of the question\n        construct_name: str,  # The specific mathematical construct being tested\n        question_text: str,  # The text of the question\n        answer_a_text: str,  # Text for answer choice A\n        answer_b_text: str,  # Text for answer choice B\n        answer_c_text: str,  # Text for answer choice C\n        answer_d_text: str,  # Text for answer choice D\n        correct_answer: str,  # The letter (A, B, C, or D) of the correct answer\n        misconception_a_name: str,  # The misconception name targeted by answer A (if any)\n        misconception_b_name: str,  # The misconception name targeted by answer B (if any)\n        misconception_c_name: str,  # The misconception name targeted by answer C (if any)\n        misconception_d_name: str,  # The misconception name targeted by answer D (if any)\n```\ntherefore, incorrect answers and misconceptions can be paired properly.\n\n> The prompt does not explicitly mention that the types of misconception in the generated samples can be new. However, it does state that you need to first identify which misconception need to be leverage, which implies selecting misconception from those provided that were not covered by the reference questions. If this is the case, how can we ensure that new types of misconception will appear in the constructed dataset?\n\nNice spot. Even if we specify the possible misconceptions, LLM still likes to generate additional ones. Before I settled on this prompt, my earlier prompts would generate even more of new misconceptions. \n\n> The prompt mentions that the tag needs to indicate which misconception each incorrect answer corresponds to. Does this mean that the reference questions only provide the incorrect answers without providing the misconception？\n\nI have provided a full prompt example [here](https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/551688#3079014). Hope it helps!",
          "replies": [
            {
              "id": 3140911,
              "postDate": "2025-03-05T03:58:35.747Z",
              "content": "<p>Do the misconceptions generated by the LLM, such as misconception_a_name, misconception_b_name, misconception_c_name, and misconception_d_name, tend to choose from the given misconception pool of the cluster?</p>",
              "rawMarkdown": "Do the misconceptions generated by the LLM, such as misconception_a_name, misconception_b_name, misconception_c_name, and misconception_d_name, tend to choose from the given misconception pool of the cluster?"
            }
          ]
        },
        {
          "id": 3140906,
          "postDate": "2025-03-05T03:48:03.497Z",
          "content": "<p>I would like to ask: If only the misconceptions are provided as clusters, where do the other answers and corresponding misconceptions generated by the LLM for a new question come from? </p>",
          "rawMarkdown": "I would like to ask: If only the misconceptions are provided as clusters, where do the other answers and corresponding misconceptions generated by the LLM for a new question come from? "
        }
      ]
    },
    {
      "id": 3077562,
      "postDate": "2024-12-21T05:39:43.933Z",
      "content": "<p>Thank you so much for this detailed solution. I'm so impressed with how much attention you've paid to details, and how you fully utilze the limited GPU resources to perform so many rounds of reranking. May I ask:</p>\n<ul>\n<li>you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?</li>\n<li>What are the important tricks to fit 72b model for inference into 2 T4 GPUs?</li>\n<li>What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?</li>\n</ul>\n<p>Thanks again! Congratulations on 1st place! The solution really deserves it.</p>",
      "rawMarkdown": "Thank you so much for this detailed solution. I'm so impressed with how much attention you've paid to details, and how you fully utilze the limited GPU resources to perform so many rounds of reranking. May I ask:\n\n- you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?\n- What are the important tricks to fit 72b model for inference into 2 T4 GPUs?\n- What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?\n\nThanks again! Congratulations on 1st place! The solution really deserves it.",
      "votes": 1,
      "replies": [
        {
          "id": 3077760,
          "postDate": "2024-12-21T11:19:04.580Z",
          "content": "<p>Thanks for the kind words! Congratulations to you too on solo gold! 🎉</p>\n<blockquote>\n  <p>you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?</p>\n</blockquote>\n<p>The idea comes from the <a href=\"https://arxiv.org/pdf/2407.21075\" target=\"_blank\">Apple Intelligence report</a> (Section 5.2). </p>\n<blockquote>\n  <p>… The quantized model often shows a moderate level of quality loss. Therefore, instead of directly passing the quantized model to application teams for feature development, we attach a set of parameter-efficient LoRA adapters for quality recovery. We make sure that these LoRA adapters training recipes are consistent with pre-training and post-training processes.</p>\n</blockquote>\n<p>I didn't get to try this in this competition.</p>\n<blockquote>\n  <p>What are the important tricks to fit 72b model for inference into 2 T4 GPUs?</p>\n</blockquote>\n<p>I mainly followed <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/550223\" target=\"_blank\">this great post</a> from <a href=\"https://www.kaggle.com/jagatkiran\" target=\"_blank\">@jagatkiran</a>! Didn't have any inference tricks for the 72b model. For 14b ranker, prefix caching was key.</p>\n<blockquote>\n  <p>What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?</p>\n</blockquote>\n<p>My best selected submission was ~510mins. I didn't face OOM but had a few out of time near the end…</p>\n<p>Thanks!</p>",
          "rawMarkdown": "Thanks for the kind words! Congratulations to you too on solo gold! 🎉\n\n> you mentioned \"add recovery adapters\" to quantization, what is it? did you apply it eventually?\n\nThe idea comes from the [Apple Intelligence report](https://arxiv.org/pdf/2407.21075) (Section 5.2). \n> ... The quantized model often shows a moderate level of quality loss. Therefore, instead of directly passing the quantized model to application teams for feature development, we attach a set of parameter-efficient LoRA adapters for quality recovery. We make sure that these LoRA adapters training recipes are consistent with pre-training and post-training processes.\n\nI didn't get to try this in this competition.\n\n> What are the important tricks to fit 72b model for inference into 2 T4 GPUs?\n\nI mainly followed [this great post](https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/550223) from @jagatkiran! Didn't have any inference tricks for the 72b model. For 14b ranker, prefix caching was key.\n\n>What total running time did you manange to achieve during competition? Any out of time or out of memory experienced near the end of the competition?\n\nMy best selected submission was ~510mins. I didn't face OOM but had a few out of time near the end...\n\nThanks!",
          "votes": 2,
          "replies": [
            {
              "id": 3078220,
              "postDate": "2024-12-22T00:36:24.273Z",
              "content": "<p>Thank you for your explanation! I also noticed that for your retriever, you used different learning rate for lora_a and lora _b, this is an interesting detail. May I ask what is the rationale behind that?</p>",
              "rawMarkdown": "Thank you for your explanation! I also noticed that for your retriever, you used different learning rate for lora_a and lora _b, this is an interesting detail. May I ask what is the rationale behind that?",
              "votes": 1
            },
            {
              "id": 3078977,
              "postDate": "2024-12-23T04:48:38.020Z",
              "content": "<p>I followed the LoRA+ paper: <a href=\"https://arxiv.org/abs/2402.12354\" target=\"_blank\">LoRA+: Efficient Low Rank Adaptation of Large Models</a> -- which shows faster convergence and better perf with different LRs for LoRA A and B.</p>\n<blockquote>\n  <p>…Low Rank Adaptation (LoRA) as originally introduced in Hu et al. (2021) leads to suboptimal finetuning of models with large width (embedding dimension). This is due to the fact that adapter matrices A and B in LoRA are updated with the same learning rate. Using scaling arguments for large width networks, we demonstrate that using the same learning rate for A and B does not allow efficient feature learning. We then show that this suboptimality of LoRA can be corrected simply by setting different learning rates for the LoRA adapter matrices A and B with a well-chosen ratio. We call this proposed algorithm LoRA+. In our extensive experiments, LoRA+ improves performance (1-2 % improvements) and finetuning speed (up to ∼ 2X SpeedUp), at the same computational cost as LoRA.</p>\n</blockquote>",
              "rawMarkdown": "I followed the LoRA+ paper: [LoRA+: Efficient Low Rank Adaptation of Large Models](https://arxiv.org/abs/2402.12354) -- which shows faster convergence and better perf with different LRs for LoRA A and B.\n\n>...Low Rank Adaptation (LoRA) as originally introduced in Hu et al. (2021) leads to suboptimal finetuning of models with large width (embedding dimension). This is due to the fact that adapter matrices A and B in LoRA are updated with the same learning rate. Using scaling arguments for large width networks, we demonstrate that using the same learning rate for A and B does not allow efficient feature learning. We then show that this suboptimality of LoRA can be corrected simply by setting different learning rates for the LoRA adapter matrices A and B with a well-chosen ratio. We call this proposed algorithm LoRA+. In our extensive experiments, LoRA+ improves performance (1-2 % improvements) and finetuning speed (up to ∼ 2X SpeedUp), at the same computational cost as LoRA.",
              "votes": 1
            }
          ]
        }
      ]
    },
    {
      "id": 3073545,
      "postDate": "2024-12-16T15:42:50.033Z",
      "content": "<p>I want to know if your recall model is created by combining model 1, model 2, and model 3, and then concatenating the last token, or if another method is used.</p>",
      "rawMarkdown": "I want to know if your recall model is created by combining model 1, model 2, and model 3, and then concatenating the last token, or if another method is used.",
      "votes": 1,
      "replies": [
        {
          "id": 3074399,
          "postDate": "2024-12-17T16:22:45.953Z",
          "content": "<p>I averaged similarity scores from these models.</p>",
          "rawMarkdown": "I averaged similarity scores from these models."
        }
      ]
    },
    {
      "id": 3073495,
      "postDate": "2024-12-16T14:53:16.193Z",
      "content": "<p>Did you merge the training set and the synthetic dataset together and then perform the 5-fold split, or did you perform the 5-fold split on the training set and then directly add the synthetic data to the training set?</p>",
      "rawMarkdown": "Did you merge the training set and the synthetic dataset together and then perform the 5-fold split, or did you perform the 5-fold split on the training set and then directly add the synthetic data to the training set?",
      "votes": 1,
      "replies": [
        {
          "id": 3073504,
          "postDate": "2024-12-16T15:00:42.240Z",
          "content": "<p>5-fold split on the training set and then directly add the synthetic data to the training set</p>",
          "rawMarkdown": "5-fold split on the training set and then directly add the synthetic data to the training set",
          "votes": 1
        }
      ]
    },
    {
      "id": 3073391,
      "postDate": "2024-12-16T13:18:32.093Z",
      "content": "<p>Your explanation is excellent bro, Thanks.</p>",
      "rawMarkdown": "Your explanation is excellent bro, Thanks.",
      "votes": 1
    },
    {
      "id": 3073360,
      "postDate": "2024-12-16T11:59:14.937Z",
      "content": "<p>Congrats both. Result ans explication. </p>",
      "rawMarkdown": "Congrats both. Result ans explication. ",
      "votes": 1
    },
    {
      "id": 3072882,
      "postDate": "2024-12-15T18:00:13.827Z",
      "content": "<p>This is undoubtedly very insightful! Thank you for sharing this amazing information! <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a></p>",
      "rawMarkdown": "This is undoubtedly very insightful! Thank you for sharing this amazing information! @conjuring92\n\n\n",
      "votes": 1
    },
    {
      "id": 3072696,
      "postDate": "2024-12-15T15:00:31.440Z",
      "content": "<p>Thanks for sharing such a detailed solution!</p>",
      "rawMarkdown": "Thanks for sharing such a detailed solution!",
      "votes": 1
    },
    {
      "id": 3072550,
      "postDate": "2024-12-15T11:36:55.657Z",
      "content": "<p>A very insightful and beautiful solution, thank you!</p>\n<p>We have also tried to generate Chain-of-Thought using gpt-4o in the early stage of the competition, but found that we couldn't correctly formalize the way of thinking for the model, and quite often the model explicitly mentioned the misconception in its response (although we've tried to encourage it not to do so).</p>\n<p>Haven't you met this problem during the prompt construction; if yes, can you please tell, what exact prompting modifications helped to solve it?</p>",
      "rawMarkdown": "A very insightful and beautiful solution, thank you!\n\nWe have also tried to generate Chain-of-Thought using gpt-4o in the early stage of the competition, but found that we couldn't correctly formalize the way of thinking for the model, and quite often the model explicitly mentioned the misconception in its response (although we've tried to encourage it not to do so).\n\nHaven't you met this problem during the prompt construction; if yes, can you please tell, what exact prompting modifications helped to solve it?",
      "votes": 1,
      "replies": [
        {
          "id": 3073139,
          "postDate": "2024-12-16T05:10:59.153Z",
          "content": "<p>Yes, I too noticed Claude mentioning the misconception name at the start of CoT. I fixed it with prompt engineering by asking LLM to follow this sequence:</p>\n<ul>\n<li>Show the correct calculation first</li>\n<li>Show the incorrect calculations that demonstrate the error</li>\n<li>Explain the specific flaw in the student's reasoning</li>\n<li>Demonstrate how the misconception led to this particular error</li>\n<li>Distinguish from the related misconceptions</li>\n</ul>",
          "rawMarkdown": "Yes, I too noticed Claude mentioning the misconception name at the start of CoT. I fixed it with prompt engineering by asking LLM to follow this sequence:\n- Show the correct calculation first\n- Show the incorrect calculations that demonstrate the error\n- Explain the specific flaw in the student's reasoning\n- Demonstrate how the misconception led to this particular error\n- Distinguish from the related misconceptions",
          "votes": 1
        }
      ]
    },
    {
      "id": 3072535,
      "postDate": "2024-12-15T11:24:21.007Z",
      "content": "<p>I see a lot of people used the LM Head with Yes/No probabilities as the binary classifier. Any thoughts on whether that is the best approach when fine tuning, or is it better to add a new classifier head? I tried both and the classifier head worked better for me, but it was also my first time doing any serious comparision between these two approaches. Appreciate if you share your thoughts. Thanks also for such an immensely detailed post, learnt a lot.</p>",
      "rawMarkdown": "I see a lot of people used the LM Head with Yes/No probabilities as the binary classifier. Any thoughts on whether that is the best approach when fine tuning, or is it better to add a new classifier head? I tried both and the classifier head worked better for me, but it was also my first time doing any serious comparision between these two approaches. Appreciate if you share your thoughts. Thanks also for such an immensely detailed post, learnt a lot.",
      "votes": 1,
      "replies": [
        {
          "id": 3073138,
          "postDate": "2024-12-16T05:08:13.313Z",
          "content": "<p>Thanks Dipam!</p>\n<p>I actually trained most of my models with a new classification head and switched to Yes/No tokens approach in the later stages -- mainly to take advantage of vllm inference + in-built prefix caching. Both Yes/No approach and classifier head gave similar scores here.</p>",
          "rawMarkdown": "Thanks Dipam!\n\nI actually trained most of my models with a new classification head and switched to Yes/No tokens approach in the later stages -- mainly to take advantage of vllm inference + in-built prefix caching. Both Yes/No approach and classifier head gave similar scores here.",
          "votes": 3,
          "replies": [
            {
              "id": 3078523,
              "postDate": "2024-12-22T12:32:24.967Z",
              "content": "<p>Thanks for the detailed writeup, a lot to learn here. I am a bit confused in this part:</p>\n<p>Question: Since you are finetuning the causal lm to output Yes/No token, why the lm_head was frozen. What was the reasoning behind this ? As we want the lm_head to have high probs for either Yes/No token, freezing it will avoid it to learn this mapping. Can you explain this part ?</p>\n<blockquote>\n  <p>The logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:</p>\n</blockquote>\n<pre><code>outputs = .model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=)\nlogits_yes = outputs.logits[:, -, .yes_loc]  \nlogits_no = outputs.logits[:, -, .no_loc]  \nlogits = logits_yes - logits_no  \nlogits = logits.reshape(-, .group_size)\nlabels = labels.to(logits.device).reshape(-) \nce_loss = .loss_fn(logits, labels)\n</code></pre>\n<blockquote>\n  <p>Each batch contained 1 positive and batch_size-1 negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with r=64, alpha=128, LoRA on all linear layers. The language modelling head (lm_head) of the LLM (Qwen/Qwen2.5-14B) was frozen during fine-tuning.</p>\n</blockquote>",
              "rawMarkdown": "Thanks for the detailed writeup, a lot to learn here. I am a bit confused in this part:\n\nQuestion: Since you are finetuning the causal lm to output Yes/No token, why the lm_head was frozen. What was the reasoning behind this ? As we want the lm_head to have high probs for either Yes/No token, freezing it will avoid it to learn this mapping. Can you explain this part ?\n\n\n>The logits were computed by taking the difference between the 'Yes' and 'No' token scores, as below:\n```python\noutputs = self.model(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=True)\nlogits_yes = outputs.logits[:, -1, self.yes_loc]  # Yes token logit at the last position [bs]\nlogits_no = outputs.logits[:, -1, self.no_loc]  # No token logit at the last position [bs]\nlogits = logits_yes - logits_no  # [bs]\nlogits = logits.reshape(-1, self.group_size)\nlabels = labels.to(logits.device).reshape(-1) \nce_loss = self.loss_fn(logits, labels)\n```\n>Each batch contained 1 positive and batch_size-1 negative misconceptions for a given Question-Incorrect Answer combination. The label was set to the index of the positive misconception and cross entropy loss was used for training. The models was trained with LoRA with r=64, alpha=128, LoRA on all linear layers. The language modelling head (lm_head) of the LLM (Qwen/Qwen2.5-14B) was frozen during fine-tuning.",
              "votes": 1
            },
            {
              "id": 3079011,
              "postDate": "2024-12-23T05:59:35.763Z",
              "content": "<p>Hey <a href=\"https://www.kaggle.com/atharvaingle\" target=\"_blank\">@atharvaingle</a>, on freezing the <code>lm_head</code>:</p>\n<ul>\n<li><code>logit(y=Yes) = features . W_lm_head_yes</code> : The Yes/No token logits are controlled by both the LM head weights at the location of Yes/No tokens and model hidden states at end of the sequence. Even if we freeze the LM head, the logits can be adjusted by the network by updating other params such that features are moving as per loss during fine-tuning.</li>\n<li>The prompt template would already increase logits for the Yes/No tokens (without fine-tuning the LM head)</li>\n<li>Qwen2.5 tokenizer has 150k+ tokens (out of which we are only concerned with 2 tokens), unfreezing LM Head would increase VRAM requirement significantly</li>\n<li>However, as always, we should test both unfreeze and freeze cases and see the performance diff. Intuitively, I felt difference wouldn't be significant.</li>\n</ul>",
              "rawMarkdown": "Hey @atharvaingle, on freezing the `lm_head`:\n- `logit(y=Yes) = features . W_lm_head_yes` : The Yes/No token logits are controlled by both the LM head weights at the location of Yes/No tokens and model hidden states at end of the sequence. Even if we freeze the LM head, the logits can be adjusted by the network by updating other params such that features are moving as per loss during fine-tuning.\n- The prompt template would already increase logits for the Yes/No tokens (without fine-tuning the LM head)\n- Qwen2.5 tokenizer has 150k+ tokens (out of which we are only concerned with 2 tokens), unfreezing LM Head would increase VRAM requirement significantly\n- However, as always, we should test both unfreeze and freeze cases and see the performance diff. Intuitively, I felt difference wouldn't be significant.",
              "votes": 1
            },
            {
              "id": 3079086,
              "postDate": "2024-12-23T08:15:26.720Z",
              "content": "<p>Thanks this helps a lot.</p>",
              "rawMarkdown": "Thanks this helps a lot.",
              "votes": 1
            },
            {
              "id": 3086113,
              "postDate": "2025-01-02T02:26:49.143Z",
              "content": "<p>If possible, could you show me which part of the code freezes the weights for this section? I couldn’t find it. Thank you very much.</p>",
              "rawMarkdown": "If possible, could you show me which part of the code freezes the weights for this section? I couldn’t find it. Thank you very much."
            }
          ]
        }
      ]
    },
    {
      "id": 3072329,
      "postDate": "2024-12-15T03:31:27.977Z",
      "content": "<p>Hi raja, I have carefully read the detailed plan you posted. I have truly learned a lot. As a beginner in LLM, your plan involves a lot of knowledge that I have not yet understood. Please allow me to express my sincerest gratitude to you and look forward to your performance in the next competition</p>",
      "rawMarkdown": "Hi raja, I have carefully read the detailed plan you posted. I have truly learned a lot. As a beginner in LLM, your plan involves a lot of knowledge that I have not yet understood. Please allow me to express my sincerest gratitude to you and look forward to your performance in the next competition",
      "votes": 1
    },
    {
      "id": 3074742,
      "postDate": "2024-12-18T02:40:30.673Z",
      "content": "<p>Looking forward to the release of your training code.</p>",
      "rawMarkdown": "Looking forward to the release of your training code.",
      "votes": 2,
      "replies": [
        {
          "id": 3077764,
          "postDate": "2024-12-21T11:20:42.470Z",
          "content": "<p>Currently working on the code release, so sorry for the delay…</p>",
          "rawMarkdown": "Currently working on the code release, so sorry for the delay..."
        },
        {
          "id": 3080817,
          "postDate": "2024-12-25T19:16:04.187Z",
          "content": "<p>published the code here: <a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">https://github.com/rbiswasfc/eedi-mining-misconceptions</a></p>",
          "rawMarkdown": "published the code here: https://github.com/rbiswasfc/eedi-mining-misconceptions",
          "votes": 1
        }
      ]
    },
    {
      "id": 3073598,
      "postDate": "2024-12-16T16:30:47.543Z",
      "content": "<p>Hi <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a>, thank you so much for the detailed explanation. It is quite a lot to unpack.<br>\nIn my efforts towards learning, I am trying to summarize my understanding of your approach. However, I have a few questions and would really appreciate if you (or anyone on the forum) can help me get more clarity.</p>\n<h1>Questions</h1>\n<ol>\n<li>How many negative samples were used for retriever finetuning?</li>\n<li>Can you elaborate on <em>“Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”</em>. Do you mean 1 misconception won’t appear as true label twice in a batch?</li>\n<li>How were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?</li>\n<li>Can you explain the re-ranker distillation part?</li>\n<li>AWQ - which datasets were used for calibration? </li>\n</ol>\n<blockquote>\n  <h1>Summary</h1>\n  <h2>1.    Data Generation</h2>\n  <p>a.    Create clusters out of similar misconceptions<br>\n  b.    Generate 5 MCQs (using Claude 3.5 sonnet) for each clusters by giving cluster misconceptions and related 4-5 questions as context. (data quality can be questionable)<br>\n  c.    Use GPT-4o to evaluate the quality of generated MCQs on a scale from 0-10 and filter out the bad ones.<br>\n  d.    Step b gave additional misconceptions (not in misconception_mapping). Filtered out the misconceptions similar to the ones in the given mapping to avoid conflicts (using vectors from embedding model).<br>\n  At this point the author has original misc clusters, and generated MCQs with misconceptions mapped to them (both original and generated)</p>\n  <h2>2.    COT Distillation</h2>\n  <p>Overall, the idea here is to distill the knowledge of claude into smaller models. So we get generations from claude and use that to finetune smaller models.<br>\n  a.    Generate COT (on original train dataset) using Claude using the question context, misc and related misc in the prompt. <br>\n  b.    Finetune 3 models (7,14,32B) on the generated text and same prompt but exclude the misconceptions and related misc (as during inference they won’t be present)<br>\n  At this point the author has 3 models (reasoners) with the capability of generating COT reasons for each incorrect answer using only the questions context (no misconception).</p>\n  <h2>3.    Models - retriever</h2>\n  <p>a.    Finetune retrievers using MNR loss for 12 epochs on entire data (except 1 fold) from step 1.d. {some confusion here will update once it is clarified}<br>\n  b.    Pre-training the finetuned qwen-14B on synthetic data from step 1.b gave recall boost. </p>\n  <h2>4.    Model –reranker</h2>\n  <p><em>overall 2 pointwise rerankers (yes/no output for each misconception) and 1 listwise used.</em></p>\n  <h3>a.    Pointwise rerankers (14/32B)</h3>\n  <p>i.    Pseudo labels on synthetic dataset (from 1.d) generated using models (Qwen/Qwen2.5-Math-72B and Qwen/Qwen2.5-72B) finetuned on train dataset.<br>\n  ii.    Entire dataset used for finetuning pointwise reranker. COT was also added to 50% of the training dataset.<br>\n  iii.    Other details-</p>\n  <ol>\n  <li>The prompt contains few shot examples.</li>\n  <li>The re-ranker was trained on logit difference of ‘yes’ and ‘no’ tokens as predictions using cross entropy loss. </li>\n  <li>1 positive and (BS – 1) negative samples taken for each batch. 1:24 positive:negative ratio.</li>\n  <li>LM head was frozen during finetuning.</li>\n  </ol>\n  <h3>b.    Listwise reranker</h3>\n  <p>i.    Predicts 1 out of top 5 choices.<br>\n  ii.    <em>{Training strategy not shared}</em></p>\n  <h2>5.    Quantization</h2>\n  <p>a.    Fp16 finetuning was performed and the models were quantized using AWQ.<br>\n  b.    Calibration dataset used <em>{some confusion here will update once it is clarified.}</em></p>\n</blockquote>",
      "rawMarkdown": "Hi @conjuring92, thank you so much for the detailed explanation. It is quite a lot to unpack.\nIn my efforts towards learning, I am trying to summarize my understanding of your approach. However, I have a few questions and would really appreciate if you (or anyone on the forum) can help me get more clarity.\n\n# Questions\n1.\tHow many negative samples were used for retriever finetuning?\n2.\tCan you elaborate on *“Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”*. Do you mean 1 misconception won’t appear as true label twice in a batch?\n3.\tHow were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?\n4.\tCan you explain the re-ranker distillation part?\n5.\tAWQ - which datasets were used for calibration? \n\n\n># Summary\n## 1.\tData Generation\na.\tCreate clusters out of similar misconceptions\nb.\tGenerate 5 MCQs (using Claude 3.5 sonnet) for each clusters by giving cluster misconceptions and related 4-5 questions as context. (data quality can be questionable)\nc.\tUse GPT-4o to evaluate the quality of generated MCQs on a scale from 0-10 and filter out the bad ones.\nd.\tStep b gave additional misconceptions (not in misconception_mapping). Filtered out the misconceptions similar to the ones in the given mapping to avoid conflicts (using vectors from embedding model).\nAt this point the author has original misc clusters, and generated MCQs with misconceptions mapped to them (both original and generated)\n## 2.\tCOT Distillation\nOverall, the idea here is to distill the knowledge of claude into smaller models. So we get generations from claude and use that to finetune smaller models.\na.\tGenerate COT (on original train dataset) using Claude using the question context, misc and related misc in the prompt. \nb.\tFinetune 3 models (7,14,32B) on the generated text and same prompt but exclude the misconceptions and related misc (as during inference they won’t be present)\nAt this point the author has 3 models (reasoners) with the capability of generating COT reasons for each incorrect answer using only the questions context (no misconception).\n## 3.\tModels - retriever\na.\tFinetune retrievers using MNR loss for 12 epochs on entire data (except 1 fold) from step 1.d. {some confusion here will update once it is clarified}\nb.\tPre-training the finetuned qwen-14B on synthetic data from step 1.b gave recall boost. \n## 4.\tModel –reranker\n*overall 2 pointwise rerankers (yes/no output for each misconception) and 1 listwise used.*\n### a.\tPointwise rerankers (14/32B)\ni.\tPseudo labels on synthetic dataset (from 1.d) generated using models (Qwen/Qwen2.5-Math-72B and Qwen/Qwen2.5-72B) finetuned on train dataset.\nii.\tEntire dataset used for finetuning pointwise reranker. COT was also added to 50% of the training dataset.\niii.\tOther details-\n1.\tThe prompt contains few shot examples.\n2.\tThe re-ranker was trained on logit difference of ‘yes’ and ‘no’ tokens as predictions using cross entropy loss. \n3.\t1 positive and (BS – 1) negative samples taken for each batch. 1:24 positive:negative ratio.\n4.\tLM head was frozen during finetuning.\n### b.\tListwise reranker\ni.\tPredicts 1 out of top 5 choices.\nii.\t*{Training strategy not shared}*\n## 5.\tQuantization\na.\tFp16 finetuning was performed and the models were quantized using AWQ.\nb.\tCalibration dataset used *{some confusion here will update once it is clarified.}*\n\n",
      "votes": 2,
      "replies": [
        {
          "id": 3074397,
          "postDate": "2024-12-17T16:22:09.333Z",
          "content": "<p>Thanks Nikhil for the questions. Please find below my replies.</p>\n<blockquote>\n  <p>How many negative samples were used for retriever finetuning?</p>\n</blockquote>\n<p>I used the standard <strong>in-batch negatives</strong> setup. Therefore, for a batch_size of 128, there were 127 negatives and 1 positive for each query (question + incorrect answer).</p>\n<blockquote>\n  <p>Can you elaborate on “Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”. Do you mean 1 misconception won’t appear as true label twice in a batch?</p>\n</blockquote>\n<p>Say, In a batch, the positive examples are <code>(q1, m1), (q2, m2)..., (q128, m128)</code>. For the in-batch negatives setup, this means <code>q1</code> will have <code>m1</code> as positive and <code>[m2, m3, ..m128]</code> as negatives. Similarly, for <code>q2</code> you will have <code>m2</code> as positive and <code>[m1, m3, ...m128]</code> as negatives.  During training, we will compute similarity scores between all query and misconception combinations (<code>128x128</code> matrix). The diagonal elements would correspond to the positives and off-diagonals should be negatives. In this competition, we had many-to-one relationship for the query to content mapping. Hence, a random batching strategy would lead to cases where multiple queries belonging to the same misconception would end up in a given batch. In this case, you will have false negatives in the off diagonals -- leading to noisy, sub optimal convergence.</p>\n<blockquote>\n  <p>How were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?</p>\n</blockquote>\n<p>I just used in-batch negatives. I, however, experimented mined hard negatives obtained from fine-tuned retrievers (+ de-noised with re-ranker predictions <a href=\"https://arxiv.org/abs/2407.15831\" target=\"_blank\">Reference</a>), but it was ineffective to improve long tail recall.</p>\n<blockquote>\n  <p>Can you explain the re-ranker distillation part?</p>\n</blockquote>\n<p>You can refer to the <a href=\"https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L280\" target=\"_blank\">distillation loss</a> in the <a href=\"https://github.com/FlagOpen/FlagEmbedding\" target=\"_blank\">FlagEmbedding</a> repo.</p>\n<blockquote>\n  <p>AWQ - which datasets were used for calibration?</p>\n</blockquote>\n<p>I basically used the a subset of re-ranker training dataset as calibration dataset.</p>",
          "rawMarkdown": "Thanks Nikhil for the questions. Please find below my replies.\n\n> How many negative samples were used for retriever finetuning?\n\nI used the standard **in-batch negatives** setup. Therefore, for a batch_size of 128, there were 127 negatives and 1 positive for each query (question + incorrect answer).\n\n> Can you elaborate on “Ensuring only one demonstration per misconception appeared in each training batch, as multiple demonstrations would introduce label noise through in-batch negatives”. Do you mean 1 misconception won’t appear as true label twice in a batch?\n\nSay, In a batch, the positive examples are `(q1, m1), (q2, m2)..., (q128, m128)`. For the in-batch negatives setup, this means `q1` will have `m1` as positive and `[m2, m3, ..m128]` as negatives. Similarly, for `q2` you will have `m2` as positive and `[m1, m3, ...m128]` as negatives.  During training, we will compute similarity scores between all query and misconception combinations (`128x128` matrix). The diagonal elements would correspond to the positives and off-diagonals should be negatives. In this competition, we had many-to-one relationship for the query to content mapping. Hence, a random batching strategy would lead to cases where multiple queries belonging to the same misconception would end up in a given batch. In this case, you will have false negatives in the off diagonals -- leading to noisy, sub optimal convergence.\n\n> How were the negative samples obtained for retriever models 4/ 3? Using a pretrained embedding model?\n\nI just used in-batch negatives. I, however, experimented mined hard negatives obtained from fine-tuned retrievers (+ de-noised with re-ranker predictions [Reference](https://arxiv.org/abs/2407.15831)), but it was ineffective to improve long tail recall.\n\n> Can you explain the re-ranker distillation part?\n\nYou can refer to the [distillation loss](https://github.com/FlagOpen/FlagEmbedding/blob/master/FlagEmbedding/abc/finetune/embedder/AbsModeling.py#L280) in the [FlagEmbedding](https://github.com/FlagOpen/FlagEmbedding) repo.\n\n\n> AWQ - which datasets were used for calibration?\n\nI basically used the a subset of re-ranker training dataset as calibration dataset.",
          "votes": 3,
          "replies": [
            {
              "id": 3074759,
              "postDate": "2024-12-18T03:15:24.390Z",
              "content": "<p>Thanks a lot for the response! That helps.</p>",
              "rawMarkdown": "Thanks a lot for the response! That helps.",
              "votes": 1
            },
            {
              "id": 3182330,
              "postDate": "2025-04-19T06:04:40.330Z",
              "content": "<p>Thanks a lot for the response! That helps.</p>",
              "rawMarkdown": "Thanks a lot for the response! That helps."
            }
          ]
        }
      ]
    },
    {
      "id": 3072154,
      "postDate": "2024-12-14T19:09:44.270Z",
      "content": "<p>This is undoubtedly very insightful! Thank you for sharing this amazing information! <a href=\"https://www.kaggle.com/conjuring92\" target=\"_blank\">@conjuring92</a> </p>",
      "rawMarkdown": "This is undoubtedly very insightful! Thank you for sharing this amazing information! @conjuring92 ",
      "votes": 2
    },
    {
      "id": 3121905,
      "postDate": "2025-02-12T05:06:11.393Z",
      "content": "<p>Hello, I’d like to ask another question. The problem ultimately uses the MAP@K of the correct answers, but your code calculates the MAP@K for all the top K answers. I’m curious why the metric in the code is inconsistent with the metric required by the problem. the code i mentioned is ⬇️<br>\n    for i, p in enumerate(predicted):<br>\n        # first condition checks whether it is valid prediction<br>\n        # second condition checks if prediction is not repeated<br>\n        if p in actual and p not in predicted[:i]:<br>\n            num_hits += 1.0<br>\n            score += num_hits / (i + 1.0)</p>\n<pre><code>  / (len(actual), k)\n</code></pre>\n<p>looking forward for your reply，thanks a lot！</p>",
      "rawMarkdown": "Hello, I’d like to ask another question. The problem ultimately uses the MAP@K of the correct answers, but your code calculates the MAP@K for all the top K answers. I’m curious why the metric in the code is inconsistent with the metric required by the problem. the code i mentioned is ⬇️\n    for i, p in enumerate(predicted):\n        # first condition checks whether it is valid prediction\n        # second condition checks if prediction is not repeated\n        if p in actual and p not in predicted[:i]:\n            num_hits += 1.0\n            score += num_hits / (i + 1.0)\n\n    return score / min(len(actual), k)\nlooking forward for your reply，thanks a lot！",
      "replies": [
        {
          "id": 3123112,
          "postDate": "2025-02-13T11:42:27.030Z",
          "content": "<p>Metric computation looks okay to me. Here is a detailed post on the metric: <a href=\"https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/534077\" target=\"_blank\">https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/534077</a></p>",
          "rawMarkdown": "Metric computation looks okay to me. Here is a detailed post on the metric: https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics/discussion/534077"
        }
      ]
    },
    {
      "id": 3087919,
      "postDate": "2025-01-04T04:38:36Z",
      "content": "<p>GOAT. Amazing</p>",
      "rawMarkdown": "GOAT. Amazing"
    },
    {
      "id": 3081241,
      "postDate": "2024-12-26T13:46:33.623Z",
      "content": "<p>RAJA BISWAS, I am very grateful that you have published the training code！ I would like to know how long it took you to install the flash_attn package. It has been almost an hour since I ran pip install \"flash_attn==2.6.3\" --no-build-isolation, and it still hasn't completed the installation.</p>",
      "rawMarkdown": "RAJA BISWAS, I am very grateful that you have published the training code！ I would like to know how long it took you to install the flash_attn package. It has been almost an hour since I ran pip install \"flash_attn==2.6.3\" --no-build-isolation, and it still hasn't completed the installation.",
      "replies": [
        {
          "id": 3081264,
          "postDate": "2024-12-26T14:14:33.623Z",
          "content": "<p>that's strange, it was ~3mins iirc, please try: <code>pip install flash-attn --no-build-isolation</code></p>",
          "rawMarkdown": "that's strange, it was ~3mins iirc, please try: `pip install flash-attn --no-build-isolation`",
          "replies": [
            {
              "id": 3081271,
              "postDate": "2024-12-26T14:29:45.057Z",
              "content": "<p>Three minutes is really fast! I'm happy that I finally managed to install it, but it took me almost an hour. This might be because I used a VPN, as I can't directly connect to vast.ai from my country.</p>",
              "rawMarkdown": "Three minutes is really fast! I'm happy that I finally managed to install it, but it took me almost an hour. This might be because I used a VPN, as I can't directly connect to vast.ai from my country."
            },
            {
              "id": 3081606,
              "postDate": "2024-12-27T01:52:17.697Z",
              "content": "<p>Hello RAJA BISWAS,</p>\n<p>I would like to know if the input_dataset in the configuration file conf_qwen14b_pretrain was named eedi-embed-pretrain-mix-final instead of eedi-embed-pretrain-mix-expanded when you trained Qwen/Qwen2.5-14B on the synthetic dataset. I couldn't find the file eedi-embed-pretrain-mix-expanded on Kaggle.</p>\n<p>Thank you!</p>",
              "rawMarkdown": "Hello RAJA BISWAS,\n\nI would like to know if the input_dataset in the configuration file conf_qwen14b_pretrain was named eedi-embed-pretrain-mix-final instead of eedi-embed-pretrain-mix-expanded when you trained Qwen/Qwen2.5-14B on the synthetic dataset. I couldn't find the file eedi-embed-pretrain-mix-expanded on Kaggle.\n\nThank you!"
            },
            {
              "id": 3081692,
              "postDate": "2024-12-27T04:52:03.260Z",
              "content": "<p>Thanks for the catch! It should be <code>conjuring92/eedi-embed-pretrain-mix-final</code>. I just pushed the fix.</p>\n<p>Please feel free to create an issue in the repo if you encounter other issues!</p>",
              "rawMarkdown": "Thanks for the catch! It should be `conjuring92/eedi-embed-pretrain-mix-final`. I just pushed the fix.\n\nPlease feel free to create an issue in the repo if you encounter other issues!"
            },
            {
              "id": 3133227,
              "postDate": "2025-02-25T06:13:30.100Z",
              "content": "<p>I would like to know if you can provide the calibration datasets for quantizing a fine-tuned model using AWQ, such as rbiswasfc/eedi-awq-calibration, rbiswasfc/eedi-awq-calibration-tutor, and rbiswasfc/eedi-awq-calibration-cot</p>",
              "rawMarkdown": "I would like to know if you can provide the calibration datasets for quantizing a fine-tuned model using AWQ, such as rbiswasfc/eedi-awq-calibration, rbiswasfc/eedi-awq-calibration-tutor, and rbiswasfc/eedi-awq-calibration-cot"
            },
            {
              "id": 3133584,
              "postDate": "2025-02-25T14:07:41.307Z",
              "content": "<p>Here are the datasets:</p>\n<ul>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-tutor\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-tutor</a></li>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-cot\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-cot</a></li>\n<li><a href=\"https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration\" target=\"_blank\">https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration</a></li>\n</ul>",
              "rawMarkdown": "Here are the datasets:\n- https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-tutor\n- https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration-cot\n- https://huggingface.co/datasets/rbiswasfc/eedi-awq-calibration"
            },
            {
              "id": 3134240,
              "postDate": "2025-02-26T06:33:33.733Z",
              "content": "<p>Many thanks！</p>",
              "rawMarkdown": "Many thanks！"
            }
          ]
        }
      ]
    },
    {
      "id": 3078935,
      "postDate": "2024-12-23T03:09:18.463Z",
      "content": "<p>How was it achieved to inference 72b model on 2 T4 GPUs? They are 2*16=32GB Vram. AWQ of 72b takes 36GB vram on parameters only. And if offload to CPU, it would be so slow as not able to complete the inference within time.</p>",
      "rawMarkdown": "How was it achieved to inference 72b model on 2 T4 GPUs? They are 2*16=32GB Vram. AWQ of 72b takes 36GB vram on parameters only. And if offload to CPU, it would be so slow as not able to complete the inference within time."
    },
    {
      "id": 3078921,
      "postDate": "2024-12-23T02:40:53.943Z",
      "content": "<p>Looking forward to training code</p>",
      "rawMarkdown": "Looking forward to training code",
      "replies": [
        {
          "id": 3080820,
          "postDate": "2024-12-25T19:17:34.867Z",
          "content": "<p>Just pushed the code <a href=\"https://github.com/rbiswasfc/eedi-mining-misconceptions\" target=\"_blank\">here</a>. </p>",
          "rawMarkdown": "Just pushed the code [here](https://github.com/rbiswasfc/eedi-mining-misconceptions). ",
          "votes": 2
        }
      ]
    },
    {
      "id": 3074526,
      "postDate": "2024-12-17T18:56:14.323Z",
      "content": "<p>Your explanation is excellent bro, Thanks.</p>",
      "rawMarkdown": "Your explanation is excellent bro, Thanks."
    },
    {
      "id": 3142482,
      "postDate": "2025-03-06T12:36:23.377Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 3141983,
      "postDate": "2025-03-06T02:42:58.807Z",
      "rawMarkdown": "",
      "isDeleted": true,
      "replies": [
        {
          "id": 3141984,
          "postDate": "2025-03-06T02:43:33.153Z",
          "rawMarkdown": "",
          "isDeleted": true
        },
        {
          "id": 3142013,
          "postDate": "2025-03-06T03:19:58.493Z",
          "rawMarkdown": "",
          "isDeleted": true
        }
      ]
    },
    {
      "id": 3078331,
      "postDate": "2024-12-22T07:02:24.763Z",
      "rawMarkdown": "",
      "isDeleted": true,
      "replies": [
        {
          "id": 3101726,
          "postDate": "2025-01-21T08:15:49.537Z",
          "content": "<p>Hi, did you get the csv file ?</p>",
          "rawMarkdown": "Hi, did you get the csv file ?",
          "votes": 1
        }
      ]
    },
    {
      "id": 3077461,
      "postDate": "2024-12-21T02:03:29.063Z",
      "rawMarkdown": "",
      "isDeleted": true
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T03:47:50Z",
  "competition_id": 82695,
  "competition_slug": "eedi-mining-misconceptions-in-mathematics",
  "team_id": 12601869,
  "solution_url": "/competitions/eedi-mining-misconceptions-in-mathematics/writeups/mth-101-1st-place-detailed-solution"
}