{
  "id": 518964,
  "title": "2nd place solution (All code and datasets released) - CMU_MATH",
  "content": "<h1>2nd place solution: SFT + ORM</h1>\n<h2>All the code and dataset, please check our <a href=\"https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO\" target=\"_blank\"><strong>Github repository</strong></a>.</h2>\n<p><a href=\"https://www.kaggle.com/code/edwardsun0909/aimo-2nd-place-solution\" target=\"_blank\">The notebook of the solution can be found here</a></p>\n<p><a href=\"https://huggingface.co/AIMO-CMU-MATH/policy-model\" target=\"_blank\">policy model</a></p>\n<p><a href=\"https://huggingface.co/AIMO-CMU-MATH/reward-model\" target=\"_blank\">reward model</a></p>\n<h2>Model Details</h2>\n<p>We fine-tuned two DeepSeek-Math-7B-RL models, one is used as policy model (to generate solutions), one as reward model (to score the solutions for weighted majority voting). The training infra is adopted from (Sun et al., 2024), bibtex is in the end.</p>\n<h3>Policy Model</h3>\n<p>Our dataset is a combination of AMC, AIME, and Odyssey-Math. We only select those problems of integer answers since the answer of the test problems will be integers. We also delete the choices of the multiple choice problem in AMC.</p>\n<ul>\n<li><p><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-prize/discussion/492945\" target=\"_blank\">AMC, AIME datasets can be found here</a>. Thanks  <a href=\"https://www.kaggle.com/alexryzhkov\" target=\"_blank\">@alexryzhkov</a> !</p></li>\n<li><p><a href=\"https://github.com/protagolabs/odyssey-math\" target=\"_blank\">Odyssey-Math dataset can be found here</a></p></li>\n</ul>\n<p>We prompt GPT4 to sample code to solutions to the problems in our dataset using few-shot examples, and select the correct solutions as our training dataset for our policy model.</p>\n<p>The datasets can be found at our github <a href=\"https://github.com/AIMO-CMU-MATH/AIMO-2nd-Solution\" target=\"_blank\">AIMO-CMU-MATH</a>.</p>\n<p>We finetune the model for 3 epochs with learning rate 2e-5.</p>\n<h3>Reward Model</h3>\n<h4>Problem Set</h4>\n<p>We use the problems in <a href=\"https://github.com/hendrycks/math/\" target=\"_blank\">MATH</a>, AIME, AMC and Odyssey-Math with nonnegative integer answers as our problem set for training the reward model.</p>\n<h4>Reward Dataset Collection</h4>\n<h5>Observation</h5>\n<p>On MATH dataset, if we sample solutions with DeepSeek-MATH-7B RL, we will only get correct solutions for some problems, and those solutions can be similar. On the other hand, sampling solutions with DeepSeek-MATH-7B Base fails to output any correct solutions on some problems.</p>\n<p>On AMC, AIME and Odyssey, the observation is similar. When using DeepSeek-Math-7B-RL to sample solutions, most of the results are wrong; When using our fine-tuned policy model, the accuracy is high. </p>\n<p>We believe that in order to train a good reward model, the dataset should satisfies:</p>\n<ul>\n<li><p>Diversity: The solutions for each question are quite different.</p></li>\n<li><p>Label balance: The dataset contains both correct solutions (positive examples) and incorrect ones (negative examples) for each question.</p></li>\n</ul>\n<p>Therefore, we adopt the following sample strategies.</p>\n<h5>1. Interpolation</h5>\n<p>For MATH dataset, we interpolate the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base to get models with different level of capabilities. Denote the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base as $M_{RL}$ and $M_{Base}$, respectively. The interpolated model parameter $M_{\\alpha}$ is a linear combination of $M_{RL}$ and $M_{Base}$.<br>\n$$<br>\nM_{\\alpha}=\\alpha M_{RL} + (1-\\alpha)M_{Base}<br>\n$$<br>\nWe choose 8 different models with $\\alpha=0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0$. Each model generates two solutions for each question. The larger $\\alpha$ is, the more correct answers the model samples.</p>\n<p>By interpolation, we can get different models which yield diverse solutions, and the proportion of positive labels and negative labels are much more balanced compare to sampling with only one model.</p>\n<h5>2. Fine-tuning</h5>\n<p>For AMC, AIME, Odyssey, we use the training dataset we collect for the policy model, and train the DeepSeek-Math-RL 7B with 0, 1, 2, and 3 epoch(s) to get 4 different models. Each model generates 12 solutions for each problem.</p>\n<p>In this way, we obtain different solutions and each problems are more likely to have both correct solutions and wrong solutions.</p>\n<h5>Filtering</h5>\n<p>Once we collected all the solutions with labels, we do the filtering below:</p>\n<ul>\n<li>We remove those wrong solutions with non-integer answer, since only solutions with integer answer will be scored as a candidate answer in our weighted majority voting method.</li>\n<li>We keep the number of positive labels v.s. negative labels as 1:1 for each problem. </li>\n</ul>\n<h4>What else we tried for fine-tuning reward model and policy model</h4>\n<ul>\n<li>De-duplicate similar solutions in policy model training dataset.</li>\n<li>Include those gpt's wrong solutions in the policy model training dataset.</li>\n<li>Keep all the sampled solutions with labels in the reward training dataset.</li>\n<li>Not keep the proportion of positive and negative labels for each question in the reward dataset as 1:1, instead  a range of  1:2 to 2:1.</li>\n</ul>\n<p>We find that the above methods don't result in models that perform better on our validation dataset. Therefore we use the methods described before.</p>\n<h2>Solution</h2>\n<h3>vLLM</h3>\n<p>For the policy model, we use <a href=\"https://github.com/vllm-project/vllm\" target=\"_blank\">vLLM</a> to speed up sampling and  huggingface transformer for reward model. Scoring a solution is just a forward pass and doesn't take much time. Each model uses one GPU (T4).</p>\n<h3>Generation</h3>\n<p>We sample 42 solutions for each problem, the policy model is asked to write code. Prompt is simply problem + tool_instruction.</p>\n<p><code>tool_instruction = '\\nPlease integrate natural language reasoning with programs to solve the problem above, and put your final answer within \\\\boxed{}.'</code></p>\n<hr>\n<p>If the result of code execution is not an integer, we give feedback and ask policy model to do it again, the code is below:</p>\n<pre><code> ():\n    prompt = problem + tool_instruction\n    texts = [prompt  _  (num_sequences)]\n    results = []\n    result_texts = []\n     i  (rounds):\n        sampling_params = SamplingParams(temperature=T, top_p=, n=, max_tokens=, stop=)\n        generated_texts = llm.generate(texts, sampling_params)\n        next_round_texts = []\n        completed = []\n        ((generated_texts))\n         j, (text, generated_text)  ((texts, generated_texts)):\n            new_text = generated_text.outputs[].text\n            completed = \n               new_text:\n                :\n                    code_text = new_text.split()[-].split()[]\n                    code_result, CODE_STATUS = process_code(code_text, return_shell_output=)\n                    :\n                        result = ((code_result.strip()))\n                         result &gt;= :\n                            results.append(result % )\n                            result_texts.append((prompt +  + new_text.split()[-]).split()[])\n                        completed = \n                     Exception  e:\n                       code_result += \n                 Exception  e:\n                    code_result = \n                    \n                 completed == :\n                    next_round_texts.append(text + new_text +  + code_result + )\n\n        texts = next_round_texts\n        (, (texts))\n         texts == []:\n            \n     results, result_texts\n</code></pre>\n<p>Where num_sequences was set to be 42, T=0.9, rounds=2.</p>\n<h3>Weighted Majority voting</h3>\n<p>The outcome reward model (ORM) assigns a score to each solution. The input of the ORM is problem + code instead of problem + solution. We let the ORM to score the code generated by the policy model since the final candidate answers are simply execution results of the code.</p>\n<pre><code>def (reward_model, tokenizer, text):\n    input_id = torch.([tokenizer.(text)]).(reward_model.device)\n    with torch.():\n        logits = (input_id).logits\n        score = logits[].(dim=-).().().()[-]\n    return score\n</code></pre>\n<hr>\n<p>To calculate the total weight of one answer, we calculate it as the geometric mean times $N$, i.e. if $N$ solutions lead to the same answer $a$, the $i$-th solution has a score of $S_i$, the weight of answer a is:<br>\n$$<br>\nN(\\prod_{i=1}^n S_i)^{\\frac{1}{N}}.<br>\n$$<br>\nWe choose geometric mean times $N$ instead of the sum the weights because it prevents over-optimization. For example, in our experiment, the answer of the question \"There exists a unique increasing geometric sequence of five 2-digit positive integers. What is their sum?\" is 211. ORM gives score 0.75 to one solution with 211, but 0.85, 0.03, 0.15 to answer 50. The 0.85 can be a false positive of reward model and geometric mean prevents us from choosing such answer.</p>\n<p>We also note that there is a tendency for the policy model to generate solutions with wrong answer 0, so we add some penalty for answer 0. Below is the code of weighted majority voting.</p>\n<pre><code> ():\n     math\n    max_weight = -\n    number_weight_dict = {}\n    max_weight_answer = \n     answer, score  (answers, scores):\n         answer == :\n            score /= \n         answer   number_weight_dict:\n            number_weight_dict[answer] = [score]\n        :\n            number_weight_dict[answer].append(score)\n     answer  number_weight_dict.keys():\n        score_list = number_weight_dict[answer]\n        weight = (score_list) * math.prod(score_list) ** ( / (score_list))\n         weight &gt; max_weight:\n            max_weight = weight\n            max_weight_answer = answer\n     max_weight_answer\n</code></pre>\n<h3>Summary</h3>\n<p>We attribute the high performance of our notebook to the two points below:</p>\n<ul>\n<li>Stronger fine-tuned policy model</li>\n<li>A powerful reward model that selects the true answers from multiple candidate answers.</li>\n</ul>\n<p>In the AIMO train set of 10 problems, with the fine-tuned policy model, the accuracy improves from 1/10 to 2/10, and the reward model further improves it from 2/10 to 4/10.</p>\n<h3>Citation</h3>\n<p>The fine-tuning <a href=\"https://github.com/Edward-Sun/gpt-accelera\" target=\"_blank\">code base</a> is adopted from the code of the paper below:</p>\n<pre><code>@article{sun2024easy,\n  title={Easy-to-Hard Generalization: Alignment Human Supervision},\n  author={Sun, Zhiqing Yu, Longhui Yikang Liu, Weiyang Yang, Yiming Welleck, Sean Gan, Chuang},\n  preprint arXiv:.},\n  year={}\n}\n</code></pre>",
  "comments": [
    {
      "id": 2916257,
      "author_name": "Zhiqing SUN",
      "author_url": "",
      "post_date": "2024-07-10T20:51:48.873000",
      "content": "<p>Update: We are pleased to share the code and datasets used in our solution, including scripts for fine-tuning, dataset collection, and the complete training and validation datasets. With this repository, you can fully reproduce our solution. We hope it is helpful for your research and for the next round of AIMO.</p>\n<p>Please check the materials in our <a href=\"https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO\" target=\"_blank\"><strong>GitHub repository</strong></a>.</p>\n<p>Thanks to Kaggle and XTX Markets for organizing this wonderful competition!</p>",
      "votes": 13,
      "replies": []
    },
    {
      "id": 2913001,
      "author_name": "JM",
      "author_url": "",
      "post_date": "2024-07-09T07:00:12.110000",
      "content": "<p>I had a similar ORM solution too but did not select it, what was your public LB score with this?</p>\n<p>Congratulations on 2nd place!</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 2914134,
      "author_name": "Gcdelgado",
      "author_url": "",
      "post_date": "2024-07-09T18:27:23.593000",
      "content": "<p>Nice! Very good job my friend, thanks for sharing!</p>",
      "votes": 4,
      "replies": []
    },
    {
      "id": 2913074,
      "author_name": "Gusti Winata",
      "author_url": "",
      "post_date": "2024-07-09T08:22:57.927000",
      "content": "<p>Can we have the scripts to train the reward and policy model?</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 2919247,
      "author_name": "Ahmed Arham",
      "author_url": "",
      "post_date": "2024-07-12T18:53:19.480000",
      "content": "<p>Nice! Very good job my friend, thanks for sharing!</p>\n<p>Also checkout my notebook!!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 2913049,
      "author_name": "Sparsh Tewatia",
      "author_url": "",
      "post_date": "2024-07-09T07:44:12.993000",
      "content": "<p>Training scripts for reward model and validation sets if can be made public. Also did you find local cv and leaderboard correlation in your testing.</p>",
      "votes": 0,
      "replies": [
        {
          "id": 2913586,
          "author_name": "Sparsh Tewatia",
          "author_url": "",
          "post_date": "2024-07-09T15:05:01.013000",
          "content": "<p>Don't know the reason for downvote , it was stated in the competition that all details should be open sourced as to replicate the solution and which can help in research for next round of competition.</p>",
          "votes": 1,
          "replies": [
            {
              "id": 2913628,
              "author_name": "Zhiqing SUN",
              "author_url": "",
              "post_date": "2024-07-09T15:29:38.953000",
              "content": "<p>Thank you for your interest in our work! It was not downvoted by me. You can see the codebase of fine-tuning from the link in the citation part.</p>",
              "votes": 2,
              "replies": []
            },
            {
              "id": 2913884,
              "author_name": "Sparsh Tewatia",
              "author_url": "",
              "post_date": "2024-07-09T17:00:47.013000",
              "content": "<p>Thanks , also if the validation sets can be released.</p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3107197,
      "author_name": "harrywh",
      "author_url": "",
      "post_date": "2025-01-26T06:03:04.797000",
      "content": "<p>Nice sharing, follow you here from the bilibili webniar and it helpe me on the prize 2</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3025009,
      "author_name": "SegFault",
      "author_url": "",
      "post_date": "2024-10-22T08:58:16.957000",
      "content": "<p>Can I run the NoteBook using Kaggle GPU T4x2? I am facing out of memory error </p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 2937578,
      "author_name": "Lady Gaga",
      "author_url": "",
      "post_date": "2024-07-27T08:10:32.587000",
      "content": "<p>I want to ask why the labels during fine-tuning are the code of the solutions, rather than just the text of the solutions.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 2913739,
      "author_name": "Chew Kok Wah",
      "author_url": "",
      "post_date": "2024-07-09T16:08:14.727000",
      "content": "<p>Please share the full working finetuning code for this competition, you had not yet share your Full finetuning code for both the policy and reward model .</p>",
      "votes": 0,
      "replies": [
        {
          "id": 2913790,
          "author_name": "Zhiqing SUN",
          "author_url": "",
          "post_date": "2024-07-09T16:24:01.153000",
          "content": "<p>Thanks for your interest. Please be patient, we are still working on cleaning the code, we will push the code to our github soon.</p>",
          "votes": 6,
          "replies": [
            {
              "id": 2913910,
              "author_name": "Chew Kok Wah",
              "author_url": "",
              "post_date": "2024-07-09T17:22:58.553000",
              "content": "<p>Thanks, please also share: </p>\n<ol>\n<li>Your GPT4 prompt &amp; API code used to sample code solutions 2. Your methodology of filtering out wrongly generated solutions for your policy train set.</li>\n<li>The validation sets for both finetuning and local CV</li>\n<li>Type of GPU used for Finetuning and the environment details</li>\n<li>GPU hour or total training time required for final models.</li>\n</ol>",
              "votes": 1,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 2921556,
      "author_name": "",
      "author_url": "",
      "post_date": "2024-07-14T13:31:32.133000",
      "content": "",
      "votes": 2,
      "replies": []
    }
  ],
  "comment_count": 16,
  "messages": [
    {
      "id": 2912822,
      "postDate": "2024-07-09T05:04:34.870Z",
      "content": "<h1>2nd place solution: SFT + ORM</h1>\n<h2>All the code and dataset, please check our <a href=\"https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO\" target=\"_blank\"><strong>Github repository</strong></a>.</h2>\n<p><a href=\"https://www.kaggle.com/code/edwardsun0909/aimo-2nd-place-solution\" target=\"_blank\">The notebook of the solution can be found here</a></p>\n<p><a href=\"https://huggingface.co/AIMO-CMU-MATH/policy-model\" target=\"_blank\">policy model</a></p>\n<p><a href=\"https://huggingface.co/AIMO-CMU-MATH/reward-model\" target=\"_blank\">reward model</a></p>\n<h2>Model Details</h2>\n<p>We fine-tuned two DeepSeek-Math-7B-RL models, one is used as policy model (to generate solutions), one as reward model (to score the solutions for weighted majority voting). The training infra is adopted from (Sun et al., 2024), bibtex is in the end.</p>\n<h3>Policy Model</h3>\n<p>Our dataset is a combination of AMC, AIME, and Odyssey-Math. We only select those problems of integer answers since the answer of the test problems will be integers. We also delete the choices of the multiple choice problem in AMC.</p>\n<ul>\n<li><p><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-prize/discussion/492945\" target=\"_blank\">AMC, AIME datasets can be found here</a>. Thanks  <a href=\"https://www.kaggle.com/alexryzhkov\" target=\"_blank\">@alexryzhkov</a> !</p></li>\n<li><p><a href=\"https://github.com/protagolabs/odyssey-math\" target=\"_blank\">Odyssey-Math dataset can be found here</a></p></li>\n</ul>\n<p>We prompt GPT4 to sample code to solutions to the problems in our dataset using few-shot examples, and select the correct solutions as our training dataset for our policy model.</p>\n<p>The datasets can be found at our github <a href=\"https://github.com/AIMO-CMU-MATH/AIMO-2nd-Solution\" target=\"_blank\">AIMO-CMU-MATH</a>.</p>\n<p>We finetune the model for 3 epochs with learning rate 2e-5.</p>\n<h3>Reward Model</h3>\n<h4>Problem Set</h4>\n<p>We use the problems in <a href=\"https://github.com/hendrycks/math/\" target=\"_blank\">MATH</a>, AIME, AMC and Odyssey-Math with nonnegative integer answers as our problem set for training the reward model.</p>\n<h4>Reward Dataset Collection</h4>\n<h5>Observation</h5>\n<p>On MATH dataset, if we sample solutions with DeepSeek-MATH-7B RL, we will only get correct solutions for some problems, and those solutions can be similar. On the other hand, sampling solutions with DeepSeek-MATH-7B Base fails to output any correct solutions on some problems.</p>\n<p>On AMC, AIME and Odyssey, the observation is similar. When using DeepSeek-Math-7B-RL to sample solutions, most of the results are wrong; When using our fine-tuned policy model, the accuracy is high. </p>\n<p>We believe that in order to train a good reward model, the dataset should satisfies:</p>\n<ul>\n<li><p>Diversity: The solutions for each question are quite different.</p></li>\n<li><p>Label balance: The dataset contains both correct solutions (positive examples) and incorrect ones (negative examples) for each question.</p></li>\n</ul>\n<p>Therefore, we adopt the following sample strategies.</p>\n<h5>1. Interpolation</h5>\n<p>For MATH dataset, we interpolate the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base to get models with different level of capabilities. Denote the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base as $M_{RL}$ and $M_{Base}$, respectively. The interpolated model parameter $M_{\\alpha}$ is a linear combination of $M_{RL}$ and $M_{Base}$.<br>\n$$<br>\nM_{\\alpha}=\\alpha M_{RL} + (1-\\alpha)M_{Base}<br>\n$$<br>\nWe choose 8 different models with $\\alpha=0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0$. Each model generates two solutions for each question. The larger $\\alpha$ is, the more correct answers the model samples.</p>\n<p>By interpolation, we can get different models which yield diverse solutions, and the proportion of positive labels and negative labels are much more balanced compare to sampling with only one model.</p>\n<h5>2. Fine-tuning</h5>\n<p>For AMC, AIME, Odyssey, we use the training dataset we collect for the policy model, and train the DeepSeek-Math-RL 7B with 0, 1, 2, and 3 epoch(s) to get 4 different models. Each model generates 12 solutions for each problem.</p>\n<p>In this way, we obtain different solutions and each problems are more likely to have both correct solutions and wrong solutions.</p>\n<h5>Filtering</h5>\n<p>Once we collected all the solutions with labels, we do the filtering below:</p>\n<ul>\n<li>We remove those wrong solutions with non-integer answer, since only solutions with integer answer will be scored as a candidate answer in our weighted majority voting method.</li>\n<li>We keep the number of positive labels v.s. negative labels as 1:1 for each problem. </li>\n</ul>\n<h4>What else we tried for fine-tuning reward model and policy model</h4>\n<ul>\n<li>De-duplicate similar solutions in policy model training dataset.</li>\n<li>Include those gpt's wrong solutions in the policy model training dataset.</li>\n<li>Keep all the sampled solutions with labels in the reward training dataset.</li>\n<li>Not keep the proportion of positive and negative labels for each question in the reward dataset as 1:1, instead  a range of  1:2 to 2:1.</li>\n</ul>\n<p>We find that the above methods don't result in models that perform better on our validation dataset. Therefore we use the methods described before.</p>\n<h2>Solution</h2>\n<h3>vLLM</h3>\n<p>For the policy model, we use <a href=\"https://github.com/vllm-project/vllm\" target=\"_blank\">vLLM</a> to speed up sampling and  huggingface transformer for reward model. Scoring a solution is just a forward pass and doesn't take much time. Each model uses one GPU (T4).</p>\n<h3>Generation</h3>\n<p>We sample 42 solutions for each problem, the policy model is asked to write code. Prompt is simply problem + tool_instruction.</p>\n<p><code>tool_instruction = '\\nPlease integrate natural language reasoning with programs to solve the problem above, and put your final answer within \\\\boxed{}.'</code></p>\n<hr>\n<p>If the result of code execution is not an integer, we give feedback and ask policy model to do it again, the code is below:</p>\n<pre><code> ():\n    prompt = problem + tool_instruction\n    texts = [prompt  _  (num_sequences)]\n    results = []\n    result_texts = []\n     i  (rounds):\n        sampling_params = SamplingParams(temperature=T, top_p=, n=, max_tokens=, stop=)\n        generated_texts = llm.generate(texts, sampling_params)\n        next_round_texts = []\n        completed = []\n        ((generated_texts))\n         j, (text, generated_text)  ((texts, generated_texts)):\n            new_text = generated_text.outputs[].text\n            completed = \n               new_text:\n                :\n                    code_text = new_text.split()[-].split()[]\n                    code_result, CODE_STATUS = process_code(code_text, return_shell_output=)\n                    :\n                        result = ((code_result.strip()))\n                         result &gt;= :\n                            results.append(result % )\n                            result_texts.append((prompt +  + new_text.split()[-]).split()[])\n                        completed = \n                     Exception  e:\n                       code_result += \n                 Exception  e:\n                    code_result = \n                    \n                 completed == :\n                    next_round_texts.append(text + new_text +  + code_result + )\n\n        texts = next_round_texts\n        (, (texts))\n         texts == []:\n            \n     results, result_texts\n</code></pre>\n<p>Where num_sequences was set to be 42, T=0.9, rounds=2.</p>\n<h3>Weighted Majority voting</h3>\n<p>The outcome reward model (ORM) assigns a score to each solution. The input of the ORM is problem + code instead of problem + solution. We let the ORM to score the code generated by the policy model since the final candidate answers are simply execution results of the code.</p>\n<pre><code>def (reward_model, tokenizer, text):\n    input_id = torch.([tokenizer.(text)]).(reward_model.device)\n    with torch.():\n        logits = (input_id).logits\n        score = logits[].(dim=-).().().()[-]\n    return score\n</code></pre>\n<hr>\n<p>To calculate the total weight of one answer, we calculate it as the geometric mean times $N$, i.e. if $N$ solutions lead to the same answer $a$, the $i$-th solution has a score of $S_i$, the weight of answer a is:<br>\n$$<br>\nN(\\prod_{i=1}^n S_i)^{\\frac{1}{N}}.<br>\n$$<br>\nWe choose geometric mean times $N$ instead of the sum the weights because it prevents over-optimization. For example, in our experiment, the answer of the question \"There exists a unique increasing geometric sequence of five 2-digit positive integers. What is their sum?\" is 211. ORM gives score 0.75 to one solution with 211, but 0.85, 0.03, 0.15 to answer 50. The 0.85 can be a false positive of reward model and geometric mean prevents us from choosing such answer.</p>\n<p>We also note that there is a tendency for the policy model to generate solutions with wrong answer 0, so we add some penalty for answer 0. Below is the code of weighted majority voting.</p>\n<pre><code> ():\n     math\n    max_weight = -\n    number_weight_dict = {}\n    max_weight_answer = \n     answer, score  (answers, scores):\n         answer == :\n            score /= \n         answer   number_weight_dict:\n            number_weight_dict[answer] = [score]\n        :\n            number_weight_dict[answer].append(score)\n     answer  number_weight_dict.keys():\n        score_list = number_weight_dict[answer]\n        weight = (score_list) * math.prod(score_list) ** ( / (score_list))\n         weight &gt; max_weight:\n            max_weight = weight\n            max_weight_answer = answer\n     max_weight_answer\n</code></pre>\n<h3>Summary</h3>\n<p>We attribute the high performance of our notebook to the two points below:</p>\n<ul>\n<li>Stronger fine-tuned policy model</li>\n<li>A powerful reward model that selects the true answers from multiple candidate answers.</li>\n</ul>\n<p>In the AIMO train set of 10 problems, with the fine-tuned policy model, the accuracy improves from 1/10 to 2/10, and the reward model further improves it from 2/10 to 4/10.</p>\n<h3>Citation</h3>\n<p>The fine-tuning <a href=\"https://github.com/Edward-Sun/gpt-accelera\" target=\"_blank\">code base</a> is adopted from the code of the paper below:</p>\n<pre><code>@article{sun2024easy,\n  title={Easy-to-Hard Generalization: Alignment Human Supervision},\n  author={Sun, Zhiqing Yu, Longhui Yikang Liu, Weiyang Yang, Yiming Welleck, Sean Gan, Chuang},\n  preprint arXiv:.},\n  year={}\n}\n</code></pre>",
      "rawMarkdown": "# 2nd place solution: SFT + ORM\n\n## All the code and dataset, please check our [**Github repository**](https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO).\n\n[The notebook of the solution can be found here](https://www.kaggle.com/code/edwardsun0909/aimo-2nd-place-solution)\n\n[policy model](https://huggingface.co/AIMO-CMU-MATH/policy-model)\n\n[reward model](https://huggingface.co/AIMO-CMU-MATH/reward-model)\n\n## Model Details\n\nWe fine-tuned two DeepSeek-Math-7B-RL models, one is used as policy model (to generate solutions), one as reward model (to score the solutions for weighted majority voting). The training infra is adopted from (Sun et al., 2024), bibtex is in the end.\n\n### Policy Model\n\nOur dataset is a combination of AMC, AIME, and Odyssey-Math. We only select those problems of integer answers since the answer of the test problems will be integers. We also delete the choices of the multiple choice problem in AMC.\n\n- [AMC, AIME datasets can be found here](https://www.kaggle.com/competitions/ai-mathematical-olympiad-prize/discussion/492945). Thanks  [@alexryzhkov](https://www.kaggle.com/alexryzhkov) !\n\n- [Odyssey-Math dataset can be found here](https://github.com/protagolabs/odyssey-math)\n\nWe prompt GPT4 to sample code to solutions to the problems in our dataset using few-shot examples, and select the correct solutions as our training dataset for our policy model.\n\nThe datasets can be found at our github [AIMO-CMU-MATH](https://github.com/AIMO-CMU-MATH/AIMO-2nd-Solution).\n\nWe finetune the model for 3 epochs with learning rate 2e-5.\n\n### Reward Model\n\n#### Problem Set\n\nWe use the problems in [MATH](https://github.com/hendrycks/math/), AIME, AMC and Odyssey-Math with nonnegative integer answers as our problem set for training the reward model.\n\n#### Reward Dataset Collection\n\n##### Observation\n\nOn MATH dataset, if we sample solutions with DeepSeek-MATH-7B RL, we will only get correct solutions for some problems, and those solutions can be similar. On the other hand, sampling solutions with DeepSeek-MATH-7B Base fails to output any correct solutions on some problems.\n\nOn AMC, AIME and Odyssey, the observation is similar. When using DeepSeek-Math-7B-RL to sample solutions, most of the results are wrong; When using our fine-tuned policy model, the accuracy is high. \n\nWe believe that in order to train a good reward model, the dataset should satisfies:\n\n- Diversity: The solutions for each question are quite different.\n\n- Label balance: The dataset contains both correct solutions (positive examples) and incorrect ones (negative examples) for each question.\n\nTherefore, we adopt the following sample strategies.\n\n##### 1. Interpolation\n\nFor MATH dataset, we interpolate the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base to get models with different level of capabilities. Denote the model parameters of DeepSeek-Math-7B RL and DeepSeek-Math-7B Base as $M_{RL}$ and $M_{Base}$, respectively. The interpolated model parameter $M_{\\alpha}$ is a linear combination of $M_{RL}$ and $M_{Base}$.\n$$\nM_{\\alpha}=\\alpha M_{RL} + (1-\\alpha)M_{Base}\n$$\nWe choose 8 different models with $\\alpha=0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0$. Each model generates two solutions for each question. The larger $\\alpha$ is, the more correct answers the model samples.\n\nBy interpolation, we can get different models which yield diverse solutions, and the proportion of positive labels and negative labels are much more balanced compare to sampling with only one model.\n\n##### 2. Fine-tuning\n\nFor AMC, AIME, Odyssey, we use the training dataset we collect for the policy model, and train the DeepSeek-Math-RL 7B with 0, 1, 2, and 3 epoch(s) to get 4 different models. Each model generates 12 solutions for each problem.\n\nIn this way, we obtain different solutions and each problems are more likely to have both correct solutions and wrong solutions.\n\n##### Filtering\n\nOnce we collected all the solutions with labels, we do the filtering below:\n\n- We remove those wrong solutions with non-integer answer, since only solutions with integer answer will be scored as a candidate answer in our weighted majority voting method.\n- We keep the number of positive labels v.s. negative labels as 1:1 for each problem. \n\n#### What else we tried for fine-tuning reward model and policy model\n\n- De-duplicate similar solutions in policy model training dataset.\n- Include those gpt's wrong solutions in the policy model training dataset.\n- Keep all the sampled solutions with labels in the reward training dataset.\n- Not keep the proportion of positive and negative labels for each question in the reward dataset as 1:1, instead  a range of  1:2 to 2:1.\n\nWe find that the above methods don't result in models that perform better on our validation dataset. Therefore we use the methods described before.\n\n\n\n## Solution\n\n### vLLM\n\nFor the policy model, we use [vLLM](https://github.com/vllm-project/vllm) to speed up sampling and  huggingface transformer for reward model. Scoring a solution is just a forward pass and doesn't take much time. Each model uses one GPU (T4).\n\n### Generation\n\nWe sample 42 solutions for each problem, the policy model is asked to write code. Prompt is simply problem + tool_instruction.\n\n`tool_instruction = '\\nPlease integrate natural language reasoning with programs to solve the problem above, and put your final answer within \\\\boxed{}.'`\n\n---\n\nIf the result of code execution is not an integer, we give feedback and ask policy model to do it again, the code is below:\n\n```\ndef vllm_round_inference(problem, num_sequences, T, rounds):\n    prompt = problem + tool_instruction\n    texts = [prompt for _ in range(num_sequences)]\n    results = []\n    result_texts = []\n    for i in range(rounds):\n        sampling_params = SamplingParams(temperature=T, top_p=1.0, n=1, max_tokens=1024, stop=\"```output\")\n        generated_texts = llm.generate(texts, sampling_params)\n        next_round_texts = []\n        completed = []\n        print(len(generated_texts))\n        for j, (text, generated_text) in enumerate(zip(texts, generated_texts)):\n            new_text = generated_text.outputs[0].text\n            completed = False\n            if '```python' in new_text:\n                try:\n                    code_text = new_text.split('```python')[-1].split(\"```\")[0]\n                    code_result, CODE_STATUS = process_code(code_text, return_shell_output=True)\n                    try:\n                        result = int(float(code_result.strip()))\n                        if result >= 0:\n                            results.append(result % 1000)\n                            result_texts.append((prompt + \"```python\" + new_text.split('```python')[-1]).split(\"```output\")[0])\n                        completed = True\n                    except Exception as e:\n                       code_result += \"The code output is not an integer, final answer should be an integer.\"\n                except Exception as e:\n                    code_result = \"Code execution fail\"\n                    pass\n                if completed == False:\n                    next_round_texts.append(text + new_text + \"```output\\n\" + code_result + \"\\n```\")\n\n        texts = next_round_texts\n        print(\"remaining text:\", len(texts))\n        if texts == []:\n            break\n    return results, result_texts\n```\n\n\n\nWhere num_sequences was set to be 42, T=0.9, rounds=2.\n\n### Weighted Majority voting\n\nThe outcome reward model (ORM) assigns a score to each solution. The input of the ORM is problem + code instead of problem + solution. We let the ORM to score the code generated by the policy model since the final candidate answers are simply execution results of the code.\n\n```\ndef orm_score(reward_model, tokenizer, text):\n    input_id = torch.tensor([tokenizer.encode(text)]).to(reward_model.device)\n    with torch.no_grad():\n        logits = reward_model(input_id).logits\n        score = logits[0].mean(dim=-1).sigmoid().cpu().tolist()[-1]\n    return score\n```\n\n\n\n---\n\nTo calculate the total weight of one answer, we calculate it as the geometric mean times $N$, i.e. if $N$ solutions lead to the same answer $a$, the $i$-th solution has a score of $S_i$, the weight of answer a is:\n$$\nN(\\prod_{i=1}^n S_i)^{\\frac{1}{N}}.\n$$\nWe choose geometric mean times $N$ instead of the sum the weights because it prevents over-optimization. For example, in our experiment, the answer of the question \"There exists a unique increasing geometric sequence of five 2-digit positive integers. What is their sum?\" is 211. ORM gives score 0.75 to one solution with 211, but 0.85, 0.03, 0.15 to answer 50. The 0.85 can be a false positive of reward model and geometric mean prevents us from choosing such answer.\n\nWe also note that there is a tendency for the policy model to generate solutions with wrong answer 0, so we add some penalty for answer 0. Below is the code of weighted majority voting.\n\n```\ndef weighted_geometric_mean_times_num(answers, scores):\n    import math\n    max_weight = -1\n    number_weight_dict = {}\n    max_weight_answer = None\n    for answer, score in zip(answers, scores):\n        if answer == 0:\n            score /= 10\n        if answer not in number_weight_dict:\n            number_weight_dict[answer] = [score]\n        else:\n            number_weight_dict[answer].append(score)\n    for answer in number_weight_dict.keys():\n        score_list = number_weight_dict[answer]\n        weight = len(score_list) * math.prod(score_list) ** (1 / len(score_list))\n        if weight > max_weight:\n            max_weight = weight\n            max_weight_answer = answer\n    return max_weight_answer\n```\n\n\n\n### Summary\n\nWe attribute the high performance of our notebook to the two points below:\n\n- Stronger fine-tuned policy model\n- A powerful reward model that selects the true answers from multiple candidate answers.\n\nIn the AIMO train set of 10 problems, with the fine-tuned policy model, the accuracy improves from 1/10 to 2/10, and the reward model further improves it from 2/10 to 4/10.\n### Citation\nThe fine-tuning [code base](https://github.com/Edward-Sun/gpt-accelera) is adopted from the code of the paper below:\n```\n@article{sun2024easy,\n  title={Easy-to-Hard Generalization: Scalable Alignment Beyond Human Supervision},\n  author={Sun, Zhiqing and Yu, Longhui and Shen, Yikang and Liu, Weiyang and Yang, Yiming and Welleck, Sean and Gan, Chuang},\n  journal={arXiv preprint arXiv:2403.09472},\n  year={2024}\n}\n```\n\n\n\n\n\n\n\n\n\n",
      "votes": 62
    },
    {
      "id": 2916257,
      "postDate": "2024-07-10T20:51:48.873Z",
      "content": "<p>Update: We are pleased to share the code and datasets used in our solution, including scripts for fine-tuning, dataset collection, and the complete training and validation datasets. With this repository, you can fully reproduce our solution. We hope it is helpful for your research and for the next round of AIMO.</p>\n<p>Please check the materials in our <a href=\"https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO\" target=\"_blank\"><strong>GitHub repository</strong></a>.</p>\n<p>Thanks to Kaggle and XTX Markets for organizing this wonderful competition!</p>",
      "rawMarkdown": "Update: We are pleased to share the code and datasets used in our solution, including scripts for fine-tuning, dataset collection, and the complete training and validation datasets. With this repository, you can fully reproduce our solution. We hope it is helpful for your research and for the next round of AIMO.\n\nPlease check the materials in our [**GitHub repository**](https://github.com/AIMO-CMU-MATH/CMU_MATH-AIMO).\n\nThanks to Kaggle and XTX Markets for organizing this wonderful competition!",
      "votes": 13
    },
    {
      "id": 2913001,
      "postDate": "2024-07-09T07:00:12.110Z",
      "content": "<p>I had a similar ORM solution too but did not select it, what was your public LB score with this?</p>\n<p>Congratulations on 2nd place!</p>",
      "rawMarkdown": "I had a similar ORM solution too but did not select it, what was your public LB score with this?\n\nCongratulations on 2nd place!",
      "votes": 3
    },
    {
      "id": 2914134,
      "postDate": "2024-07-09T18:27:23.593Z",
      "content": "<p>Nice! Very good job my friend, thanks for sharing!</p>",
      "rawMarkdown": "Nice! Very good job my friend, thanks for sharing!",
      "votes": 4
    },
    {
      "id": 2913074,
      "postDate": "2024-07-09T08:22:57.927Z",
      "content": "<p>Can we have the scripts to train the reward and policy model?</p>",
      "rawMarkdown": "Can we have the scripts to train the reward and policy model?"
    },
    {
      "id": 2919247,
      "postDate": "2024-07-12T18:53:19.480Z",
      "content": "<p>Nice! Very good job my friend, thanks for sharing!</p>\n<p>Also checkout my notebook!!</p>",
      "rawMarkdown": "Nice! Very good job my friend, thanks for sharing!\n\n\nAlso checkout my notebook!!",
      "votes": 1
    },
    {
      "id": 2913049,
      "postDate": "2024-07-09T07:44:12.993Z",
      "content": "<p>Training scripts for reward model and validation sets if can be made public. Also did you find local cv and leaderboard correlation in your testing.</p>",
      "rawMarkdown": "Training scripts for reward model and validation sets if can be made public. Also did you find local cv and leaderboard correlation in your testing.",
      "replies": [
        {
          "id": 2913586,
          "postDate": "2024-07-09T15:05:01.013Z",
          "content": "<p>Don't know the reason for downvote , it was stated in the competition that all details should be open sourced as to replicate the solution and which can help in research for next round of competition.</p>",
          "rawMarkdown": "Don't know the reason for downvote , it was stated in the competition that all details should be open sourced as to replicate the solution and which can help in research for next round of competition.",
          "votes": 1,
          "replies": [
            {
              "id": 2913628,
              "postDate": "2024-07-09T15:29:38.953Z",
              "content": "<p>Thank you for your interest in our work! It was not downvoted by me. You can see the codebase of fine-tuning from the link in the citation part.</p>",
              "rawMarkdown": "Thank you for your interest in our work! It was not downvoted by me. You can see the codebase of fine-tuning from the link in the citation part.",
              "votes": 2
            },
            {
              "id": 2913884,
              "postDate": "2024-07-09T17:00:47.013Z",
              "content": "<p>Thanks , also if the validation sets can be released.</p>",
              "rawMarkdown": "Thanks , also if the validation sets can be released."
            }
          ]
        }
      ]
    },
    {
      "id": 3107197,
      "postDate": "2025-01-26T06:03:04.797Z",
      "content": "<p>Nice sharing, follow you here from the bilibili webniar and it helpe me on the prize 2</p>",
      "rawMarkdown": "Nice sharing, follow you here from the bilibili webniar and it helpe me on the prize 2"
    },
    {
      "id": 3025009,
      "postDate": "2024-10-22T08:58:16.957Z",
      "content": "<p>Can I run the NoteBook using Kaggle GPU T4x2? I am facing out of memory error </p>",
      "rawMarkdown": "Can I run the NoteBook using Kaggle GPU T4x2? I am facing out of memory error "
    },
    {
      "id": 2937578,
      "postDate": "2024-07-27T08:10:32.587Z",
      "content": "<p>I want to ask why the labels during fine-tuning are the code of the solutions, rather than just the text of the solutions.</p>",
      "rawMarkdown": "I want to ask why the labels during fine-tuning are the code of the solutions, rather than just the text of the solutions."
    },
    {
      "id": 2913739,
      "postDate": "2024-07-09T16:08:14.727Z",
      "content": "<p>Please share the full working finetuning code for this competition, you had not yet share your Full finetuning code for both the policy and reward model .</p>",
      "rawMarkdown": "Please share the full working finetuning code for this competition, you had not yet share your Full finetuning code for both the policy and reward model .",
      "replies": [
        {
          "id": 2913790,
          "postDate": "2024-07-09T16:24:01.153Z",
          "content": "<p>Thanks for your interest. Please be patient, we are still working on cleaning the code, we will push the code to our github soon.</p>",
          "rawMarkdown": "Thanks for your interest. Please be patient, we are still working on cleaning the code, we will push the code to our github soon.",
          "votes": 6,
          "replies": [
            {
              "id": 2913910,
              "postDate": "2024-07-09T17:22:58.553Z",
              "content": "<p>Thanks, please also share: </p>\n<ol>\n<li>Your GPT4 prompt &amp; API code used to sample code solutions 2. Your methodology of filtering out wrongly generated solutions for your policy train set.</li>\n<li>The validation sets for both finetuning and local CV</li>\n<li>Type of GPU used for Finetuning and the environment details</li>\n<li>GPU hour or total training time required for final models.</li>\n</ol>",
              "rawMarkdown": "Thanks, please also share: \n1. Your GPT4 prompt & API code used to sample code solutions 2. Your methodology of filtering out wrongly generated solutions for your policy train set.\n3. The validation sets for both finetuning and local CV\n4. Type of GPU used for Finetuning and the environment details\n5. GPU hour or total training time required for final models.",
              "votes": 1
            }
          ]
        }
      ]
    },
    {
      "id": 2921556,
      "postDate": "2024-07-14T13:31:32.133Z",
      "rawMarkdown": "",
      "votes": 2,
      "isDeleted": true
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T06:54:52Z",
  "competition_id": 73231,
  "competition_slug": "ai-mathematical-olympiad-prize",
  "team_id": 11933308,
  "solution_url": "/competitions/ai-mathematical-olympiad-prize/writeups/cmu-math-2nd-place-solution-all-code-and-datasets-"
}