{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile stage1.py\n", "import os\n", "# 安装包的路径,要修改为自己的上传路径\n", "os.system(\"pip install polars==1.12.0 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install transformers==4.42.4 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install datasets==3.1.0 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install sentence_transformers==3.2.1 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install peft==0.11.1 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install trl==0.8.6 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install accelerate==1.1.1 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "os.system(\"pip install einops==0.8.0 --no-index --find-links=/kaggle/input/eedi-llmemb-lib\")\n", "\n", "os.system(\"pip install /kaggle/input/flash-attn-lib/flash_attn-2.5.8cu122torch2.3cxx11abiTRUE-cp310-cp310-linux_x86_64.whl\")\n", "\n", "import sys\n", "sys.path.append(\"/kaggle/input/utilsfile/\")\n", "\n", "\n", "import os\n", "import copy\n", "from dataclasses import dataclass\n", "import argparse\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import time\n", "import gc\n", "import ast\n", "from tqdm import tqdm\n", "import json\n", "import shutil\n", "import sys\n", "from glob import glob\n", "\n", "import polars as pl\n", "import polars\n", "from sklearn.model_selection import KFold\n", "from sklearn.metrics import log_loss, accuracy_score\n", "from sklearn.metrics.pairwise import cosine_similarity\n", "from scipy.special import softmax\n", "\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "from torch.utils.data import Dataset, DataLoader\n", "from torch import Tensor\n", "\n", "# from datasets import Dataset, DatasetDict, load_dataset\n", "import transformers\n", "import datasets\n", "import sentence_transformers\n", "from transformers import (\n", " BitsAndBytesConfig,\n", " AutoModelForCausalLM,\n", " AutoModel,\n", " AutoTokenizer,\n", "\n", " PreTrainedTokenizerFast,\n", " PreTrainedTokenizerBase, \n", " Trainer,\n", " TrainingArguments,\n", " DataCollatorWithPadding,\n", " DataCollatorForSeq2Seq,\n", ")\n", "from transformers.modeling_outputs import CausalLMOutputWithPast\n", "from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType, PeftModel\n", "from trl import SFTTrainer, DataCollatorForCompletionOnlyLM\n", "from accelerate import Accelerator\n", "\n", "from utils import seed_torch, current_date_time, get_timediff\n", "from utils import load_yaml, simple_namespace, compare_yaml, format_diffs, write_to_summary_log, init_logger\n", "from utils import zip_files_in_directory, upload_to_kaggle\n", "from utils import mapk\n", "\n", "os.environ['TOKENIZERS_PARALLELISM'] = 'true' # 或 'true' 以启用\n", "\n", "base_dir = \"..\"\n", "input_dir = f\"{base_dir}/input\"\n", "comp_dir = f\"{input_dir}/eedi-mining-misconceptions-in-mathematics\"\n", "output_dir = f\"/kaggle/working/\"\n", "\n", "last_stage_dir = f\"/kaggle/input/12231510-retriever/12231510_retriever\" # 需要修改自己的模型路径\n", "adapter_model_path = f\"{last_stage_dir}/12231510adapetermodel\" # 需要修改自己的模型路径\n", "\n", "yaml_path = glob(f\"{last_stage_dir}/*.yaml\")[0]\n", "cfg = load_yaml(yaml_path)\n", "cfg = simple_namespace(cfg)\n", "\n", "seed_torch(cfg.general.seed)\n", "cur_time = current_date_time()\n", "cur_time_abbr = cur_time.replace(\"-\", \"\").replace(\":\", \"\").replace(\" \", \"\")[4:12]\n", "output_dir = f\"{output_dir}/{cur_time_abbr}_infer\"\n", "os.makedirs(output_dir, exist_ok=True)\n", "LOGGER = init_logger(f'{output_dir}/train.log')\n", "# shutil.copy(yaml_path, yaml_path.replace(last_stage_dir, output_dir))\n", "\n", "num_gpus = torch.cuda.device_count()\n", "LOGGER.info(f\"可用的 GPU 数量: {num_gpus}\")\n", "\n", "\n", "LOGGER.info(f\"polars=={polars.__version__}\")\n", "LOGGER.info(f\"torch=={torch.__version__}\")\n", "LOGGER.info(f\"transformers=={transformers.__version__}\")\n", "LOGGER.info(f\"datasets=={datasets.__version__}\")\n", "LOGGER.info(f\"sentence_transformers=={sentence_transformers.__version__}\")\n", "LOGGER.info(f\"\")\n", "\n", "# %% ================== Read data =======================\n", "train_df = pl.read_csv(f\"{comp_dir}/test.csv\")\n", "LOGGER.info(f\"len(train_df): {len(train_df)}\")\n", "\n", "misconception_mapping_df = pl.read_csv(f\"{comp_dir}/misconception_mapping.csv\")\n", "LOGGER.info(f\"len(misconception_mapping_df): {len(misconception_mapping_df)}\")\n", "LOGGER.info(f\"\")\n", "\n", "# 定义常用的列名列表\n", "common_col = [\n", " \"QuestionId\",\n", " \"ConstructName\",\n", " \"SubjectName\",\n", " \"QuestionText\",\n", " \"CorrectAnswer\",\n", "]\n", "\n", "# 对训练集数据进行处理,转换为长表格式,并添加需要的列\n", "long_df = (\n", " train_df\n", " # 选择需要的列,包括common_col和所有的Answer[A-D]Text列\n", " .select(\n", " pl.col(common_col + [f\"Answer{alpha}Text\" for alpha in [\"A\", \"B\", \"C\", \"D\"]])\n", " )\n", " # 获取 CorrectAnswer 的 Text,创建新列 CorrectAnswerText\n", " .with_columns(\n", " pl.when(pl.col(\"CorrectAnswer\") == \"A\").then(pl.col(\"AnswerAText\"))\n", " .when(pl.col(\"CorrectAnswer\") == \"B\").then(pl.col(\"AnswerBText\"))\n", " .when(pl.col(\"CorrectAnswer\") == \"C\").then(pl.col(\"AnswerCText\"))\n", " .when(pl.col(\"CorrectAnswer\") == \"D\").then(pl.col(\"AnswerDText\"))\n", " .otherwise(None)\n", " .alias(\"CorrectAnswerText\")\n", " )\n", " # 使用unpivot函数将宽表转换为长表,将Answer[A-D]Text列展开\n", " .unpivot(\n", " index=common_col+[\"CorrectAnswerText\"], # 保持这些列不变\n", " variable_name=\"AnswerType\", # 展开列的名称存储在新列AnswerType中\n", " value_name=\"AnswerText\", # 展开列的值存储在新列AnswerText中\n", " )\n", " # 添加新列\n", " .with_columns(\n", " # 将ConstructName、SubjectName、QuestionText和AnswerText列拼接成一个字符串,存储在AllText列中\n", " pl.concat_str(\n", " [\n", " '### Construct\\n' + pl.col(\"ConstructName\"),\n", " '\\n### Subject\\n' + pl.col(\"SubjectName\"),\n", " '\\n### Question\\n'+ pl.col(\"QuestionText\"),\n", " '\\n### Correct Answer\\n' + pl.col(\"CorrectAnswerText\"),\n", " '\\n### Wrong Answer\\n' + pl.col(\"AnswerText\"),\n", " ],\n", " separator=\"\", ####\n", " ).alias(\"AllText\"),\n", " # 从AnswerType列中提取选项字母(A-D),存储在AnswerAlphabet列中\n", " pl.col(\"AnswerType\").str.extract(r\"Answer([A-D])Text$\").alias(\"AnswerAlphabet\"),\n", " )\n", " # 创建QuestionId_Answer列,将QuestionId和AnswerAlphabet拼接,形成唯一标识\n", " .with_columns(\n", " pl.concat_str(\n", " [pl.col(\"QuestionId\"), pl.col(\"AnswerAlphabet\")], separator=\"_\"\n", " ).alias(\"QuestionId_Answer\"),\n", " )\n", " # 按照QuestionId_Answer进行排序\n", " .sort(\"QuestionId_Answer\")\n", ")\n", "\n", "LOGGER.info(f\"long_df len has nan: {len(long_df)}\")\n", "\n", "\n", "long_df = long_df.to_pandas()\n", "long_df = long_df[long_df[\"CorrectAnswer\"] != long_df[\"AnswerAlphabet\"]].reset_index(drop=True)\n", "long_df\n", "\n", "def add_suffix(text, suffix_text, is_query):\n", " text = f\"{suffix_text}{text}\"\n", " text = text.strip()\n", " if is_query:\n", " text = f\"{text}\\n\"\n", " return text\n", "\n", "def last_token_pool(last_hidden_states: Tensor,\n", " attention_mask: Tensor) -> Tensor:\n", " left_padding = (attention_mask[:, -1].sum() == attention_mask.shape[0])\n", " if left_padding:\n", " return last_hidden_states[:, -1]\n", " else:\n", " sequence_lengths = attention_mask.sum(dim=1) - 1\n", " batch_size = last_hidden_states.shape[0]\n", " return last_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]\n", "\n", "\n", "\n", "base_model = AutoModel.from_pretrained(\n", " \"/kaggle/input/qwen2.5/transformers/3b-instruct/1\",\n", " torch_dtype=torch.bfloat16 if cfg.training.amp==\"bf16\" else torch.float16,\n", " device_map=\"auto\",\n", " trust_remote_code=True,\n", " # quantization_config=bnb_config, \n", " local_files_only=True,\n", ")\n", "\n", "# 加载 finetune 后的 adapter 模型\n", "model = PeftModel.from_pretrained(base_model, adapter_model_path)\n", "\n", "# model.eval()\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\n", " adapter_model_path, \n", " trust_remote_code=True\n", ")\n", "\n", "start_time = time.time()\n", "\n", "model.eval()\n", "batch_size = 4\n", "\n", "print(long_df[\"AllText\"].to_list()[0])\n", "\n", "query_list = long_df[\"AllText\"].to_list()\n", "query_result = []\n", "for i in tqdm(range(0, len(query_list), batch_size)):\n", " batch_query_list = query_list[i:i+batch_size]\n", " batch_query_list = [add_suffix(x, cfg.data.query_prefix, is_query=True) for x in batch_query_list]\n", " query_encodings = tokenizer(\n", " batch_query_list,\n", " padding=True,\n", " truncation=True,\n", " return_tensors='pt',\n", " max_length=cfg.model.query_max_length,\n", " )\n", " input_ids = query_encodings['input_ids'].to(model.device)\n", " attention_mask = query_encodings['attention_mask'].to(model.device)\n", " with torch.no_grad():\n", " outputs = model(input_ids=input_ids, attention_mask=attention_mask) \n", " embeddings = last_token_pool(outputs.last_hidden_state, attention_mask)\n", " embeddings = F.normalize(embeddings, p=2, dim=1) # shape: (4370, 4096)\n", " query_result.append(embeddings)\n", " torch.cuda.empty_cache()\n", "query_embeddings = torch.cat(query_result, dim=0)\n", "\n", "print(batch_query_list[0])\n", "\n", "\n", "misconception_name = misconception_mapping_df[\"MisconceptionName\"].to_list()\n", "misconception_result = []\n", "for i in tqdm(range(0, len(misconception_name), batch_size)):\n", " batch_misconception_name = misconception_name[i:i+batch_size]\n", " batch_misconception_name = [add_suffix(x, cfg.data.mis_prefix, is_query=False) for x in batch_misconception_name]\n", " misconception_encodings = tokenizer(\n", " batch_misconception_name,\n", " padding=True,\n", " truncation=True,\n", " return_tensors='pt',\n", " max_length=cfg.model.mis_max_length,\n", " )\n", " input_ids = misconception_encodings['input_ids'].to(model.device)\n", " attention_mask = misconception_encodings['attention_mask'].to(model.device)\n", " with torch.no_grad():\n", " outputs = model(input_ids=input_ids, attention_mask=attention_mask) \n", " embeddings = last_token_pool(outputs.last_hidden_state, attention_mask)\n", " embeddings = F.normalize(embeddings, p=2, dim=1) # shape: (2587, 4096)\n", " misconception_result.append(embeddings)\n", " torch.cuda.empty_cache()\n", "misconception_embeddings = torch.cat(misconception_result, dim=0)\n", "\n", "\n", "print(batch_misconception_name[0])\n", "\n", "scores = (query_embeddings @ misconception_embeddings.T) * 100 # shape: (4370, 2587)\n", "scores = scores.float()\n", "scores = scores.cpu().numpy()\n", "LOGGER.info(f\"{scores.shape = }\")\n", "\n", "# 获取误解id的index,按照score排序\n", "preds_all_mm_ids = np.argsort(-scores, axis=1)\n", "preds_top25_mm_ids = preds_all_mm_ids[:, :25]\n", "long_df[\"MisconceptionId\"] = preds_top25_mm_ids.tolist()\n", "long_df[\"MisconceptionId\"] = long_df[\"MisconceptionId\"].apply(lambda x: \" \".join(map(str, x)))\n", "\n", "long_df.to_parquet(\"test.pq\")\n", "long_df[[\"QuestionId_Answer\", \"MisconceptionId\"]].to_csv(\"submission2.csv\", index=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!python stage1.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "import sys\n", "sys.path.append(\"/kaggle/input/utilsfile/\")\n", "\n", "\n", "import os\n", "import copy\n", "from dataclasses import dataclass\n", "import argparse\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import time\n", "import gc\n", "import ast\n", "from tqdm import tqdm\n", "import json\n", "import shutil\n", "import sys\n", "from glob import glob\n", "\n", "import polars as pl\n", "import polars\n", "from sklearn.model_selection import KFold\n", "from sklearn.metrics import log_loss, accuracy_score\n", "from sklearn.metrics.pairwise import cosine_similarity\n", "from scipy.special import softmax\n", "\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "from torch.utils.data import Dataset, DataLoader\n", "from torch import Tensor\n", "\n", "# from datasets import Dataset, DatasetDict, load_dataset\n", "import transformers\n", "import datasets\n", "import sentence_transformers\n", "from transformers import (\n", " BitsAndBytesConfig,\n", " AutoModelForCausalLM,\n", " AutoModel,\n", " AutoTokenizer,\n", "\n", " PreTrainedTokenizerFast,\n", " PreTrainedTokenizerBase, \n", " Trainer,\n", " TrainingArguments,\n", " DataCollatorWithPadding,\n", " DataCollatorForSeq2Seq,\n", ")\n", "from transformers.modeling_outputs import CausalLMOutputWithPast\n", "from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType, PeftModel\n", "from trl import SFTTrainer, DataCollatorForCompletionOnlyLM\n", "from accelerate import Accelerator\n", "\n", "\n", "from utils import seed_torch, current_date_time, get_timediff\n", "from utils import load_yaml, simple_namespace, compare_yaml, format_diffs, write_to_summary_log, init_logger\n", "from utils import zip_files_in_directory, upload_to_kaggle\n", "from utils import mapk\n", "\n", "os.environ['TOKENIZERS_PARALLELISM'] = 'true' \n", "\n", "base_dir = \"..\"\n", "input_dir = f\"{base_dir}/input\"\n", "comp_dir = f\"{input_dir}/eedi-mining-misconceptions-in-mathematics\"\n", "output_dir = f\"/kaggle/working/\"\n", "\n", "last_stage_dir = f\"/kaggle/input/000000-reranker/000000_reranker\" # 需要修改自己的模型路径\n", "adapter_model_path = f\"{last_stage_dir}/checkpoint-874\" # 需要修改自己的模型路径\n", "\n", "yaml_path = glob(f\"{last_stage_dir}/*.yaml\")[0]\n", "cfg = load_yaml(yaml_path)\n", "cfg = simple_namespace(cfg)\n", "\n", "seed_torch(cfg.general.seed)\n", "cur_time = current_date_time()\n", "cur_time_abbr = cur_time.replace(\"-\", \"\").replace(\":\", \"\").replace(\" \", \"\")[4:12]\n", "output_dir = f\"{output_dir}/{cur_time_abbr}_infer_stage2\"\n", "os.makedirs(output_dir, exist_ok=True)\n", "LOGGER = init_logger(f'{output_dir}/infer_stage2.log')\n", "# shutil.copy(yaml_path, yaml_path.replace(last_stage_dir, output_dir))\n", "\n", "num_gpus = torch.cuda.device_count()\n", "LOGGER.info(f\"可用的 GPU 数量: {num_gpus}\")\n", "\n", "\n", "LOGGER.info(f\"polars=={polars.__version__}\")\n", "LOGGER.info(f\"torch=={torch.__version__}\")\n", "LOGGER.info(f\"transformers=={transformers.__version__}\")\n", "LOGGER.info(f\"datasets=={datasets.__version__}\")\n", "LOGGER.info(f\"sentence_transformers=={sentence_transformers.__version__}\")\n", "LOGGER.info(f\"\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "misconception_mapping_df = pl.read_csv(f\"{comp_dir}/misconception_mapping.csv\")\n", "misconception_name = misconception_mapping_df[\"MisconceptionName\"].to_list()\n", "misconception_dict = misconception_mapping_df.to_pandas().set_index('MisconceptionId')['MisconceptionName'].to_dict()\n", "LOGGER.info(f\"len(misconception_mapping_df): {len(misconception_mapping_df)}\")\n", "LOGGER.info(f\"\")\n", "\n", "test_df = pd.read_parquet(\"test.pq\")[[\"QuestionId_Answer\", \"AllText\", \"MisconceptionId\"]]\n", "test_df[\"preds_all_mm_ids\"] = test_df[\"MisconceptionId\"].apply(lambda x: x.split(\" \"))\n", "test_df[\"preds_all_mm_ids\"] = test_df[\"preds_all_mm_ids\"].apply(lambda x_list: [int(x) for x in x_list])\n", "def data_preprocess(df, is_train):\n", " df[\"top_mm_ids\"] = df[\"preds_all_mm_ids\"].apply(lambda x: x[:5])\n", "\n", " # 对 top_mm_ids 的顺序洗牌\n", " df[\"top_mm_ids\"] = df[\"top_mm_ids\"].apply(lambda x: np.random.permutation(x).tolist())\n", "\n", " # 新建一列 top_mm_texts, 也是一个列表, 其中的值是top_mm_ids对应于misconception_dict中的value\n", " df[\"top_mm_texts\"] = df[\"top_mm_ids\"].apply(lambda ids: [misconception_dict[id] for id in ids])\n", "\n", " # 在 AllText 后面加上新\"\\n\\nHere are 5 possible candidates for misconception:\\n\"\n", " df[\"AllText\"] = df[\"AllText\"] + \"\\n\\nHere are 5 possible candidates for misconception:\\n\"\n", "\n", " # 在 AllText 后面加上5个候选项,候选项来自top_mm_texts, 然后要这样的格式 \"A. candidate0\\nB. candidate1\\nC. candidate2\\nD. candidate3\\nE. candidate4\"\n", " df[\"AllText\"] = df.apply(\n", " lambda row: row[\"AllText\"] + \"\\n\".join([f\"{chr(65+i)}. {candidate}\" for i, candidate in enumerate(row[\"top_mm_texts\"])]),\n", " axis=1\n", " )\n", "\n", " # 在 AllText 后面加上新\"\\nWhich misconception candidate best explains what led to the wrong answer? (Please directly answer A, B, C, D or E)\"\n", " df[\"AllText\"] = df[\"AllText\"] + \"\\nWhich misconception candidate best explains what led to the wrong answer? (Please directly answer A, B, C, D or E)\\nAnswer:\"\n", "\n", " return df\n", "\n", "test_df = data_preprocess(test_df, is_train=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f\"adapter_model_path: {adapter_model_path}\")\n", "\n", "base_model = AutoModelForCausalLM.from_pretrained(\n", " \"/kaggle/input/qwen2.5/transformers/3b-instruct/1\",\n", " torch_dtype=torch.bfloat16 if cfg.training.amp==\"bf16\" else torch.float16,\n", " device_map=\"auto\",\n", " trust_remote_code=True,\n", " # quantization_config=bnb_config, \n", " local_files_only=True,\n", ")\n", "\n", "# 加载 finetune 后的 adapter 模型\n", "model = PeftModel.from_pretrained(base_model, adapter_model_path)\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\n", " adapter_model_path, \n", " trust_remote_code=True\n", ")\n", "\n", "model.eval()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "PROMPT = \"\"\"<|im_start|>system\n", "Given a math question and its incorrect answer, identify the underlying misconception that led to the mistake.<|im_end|>\n", "<|im_start|>user\n", "{AllText}<|im_end|>\n", "<|im_start|>assistant\n", "\"\"\"\n", "\n", "def apply_template(row):\n", " instruction_text = PROMPT.format(\n", " AllText=row[\"AllText\"],\n", " )\n", " return instruction_text\n", "\n", "test_df[[\"instruction\"]] = test_df.apply(lambda row: pd.Series(apply_template(row)), axis=1)\n", "test_df[\"instruction_token_len\"] = test_df[\"instruction\"].apply(lambda x: len(tokenizer(x)[\"input_ids\"]))\n", "LOGGER.info(f\"test instruction_token_len range: {test_df['instruction_token_len'].min()} ~ {test_df['instruction_token_len'].max()}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(test_df[\"instruction\"][0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "l2i_dict = {\"A\":0, \"B\":1, \"C\":2, \"D\":3, \"E\":4}\n", "\n", "for _, row in tqdm(test_df.iterrows(), total=len(test_df)):\n", " top_mm_ids = row['top_mm_ids']\n", " \n", " inputs = tokenizer(\n", " row['instruction'], \n", " # padding=True,\n", " truncation=True, \n", " return_tensors=\"pt\",\n", " max_length=768, \n", " )\n", "\n", " input_ids = inputs['input_ids'].to(model.device)\n", " attention_mask = inputs['attention_mask'].to(model.device)\n", "\n", " with torch.no_grad():\n", " output = model(input_ids=input_ids, attention_mask=attention_mask)\n", " \n", " output = output.logits\n", " # 找出 attention_mask 中非零元素的索引,因为 attention_mask 中的非零元素对应的是输入的有效 token\n", " non_zero_indices = torch.nonzero(inputs['attention_mask'])\n", " # 获取最后一个有效 token 的索引\n", " last_one_index = non_zero_indices[-1][1].item()\n", " # 获取最后一个有效 token 对应的 logits\n", " first_token_probs = output[0][last_one_index]\n", "\n", " # 对每一个选项(' A',' B',' C',' D',' E')进行处理\n", " # tokenizer(option).input_ids[-1] 是获取选项对应的 id\n", " # first_token_probs[id] 是获取该 id 对应的 logits\n", " # 然后将 logits 和选项一起作为一个元组存储在 options_list 中\n", " options_list = [\n", " (first_token_probs[tokenizer('A').input_ids[-1]], 'A'),\n", " (first_token_probs[tokenizer('B').input_ids[-1]], 'B'),\n", " (first_token_probs[tokenizer('C').input_ids[-1]], 'C'),\n", " (first_token_probs[tokenizer('D').input_ids[-1]], 'D'),\n", " (first_token_probs[tokenizer('E').input_ids[-1]], 'E'),\n", " ]\n", " # 对 options_list 进行排序,排序的依据是 logits,也就是每个选项的概率\n", " options_list = sorted(options_list, reverse=True)\n", " \n", " top5_index = [l2i_dict[x[1]] for x in options_list]\n", " sorted_ids = [top_mm_ids[idx] for idx in top5_index]\n", " \n", " row['preds_all_mm_ids'][:5] = sorted_ids" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 保存 submission.csv\n", "test_df[\"MisconceptionId\"] = test_df[\"preds_all_mm_ids\"].apply(lambda x: \" \".join(map(str, x))) # 列表转字符串\n", "test_df[[\"QuestionId_Answer\", \"MisconceptionId\"]].to_csv(\"submission.csv\", index=False)\n", "test_df" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 }