{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:38.796154Z","iopub.execute_input":"2026-02-04T05:36:38.796443Z","iopub.status.idle":"2026-02-04T05:36:39.074046Z","shell.execute_reply.started":"2026-02-04T05:36:38.796415Z","shell.execute_reply":"2026-02-04T05:36:39.073272Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Import basic libraries\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport re\nfrom collections import Counter\nfrom pathlib import Path\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set plotting style\nsns.set_style('whitegrid')\nplt.rcParams['figure.figsize'] = (12, 6)\n\nprint(\"[OK] Libraries imported successfully!\")\nprint(f\"Pandas version: {pd.__version__}\")\nprint(f\"NumPy version: {np.__version__}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:39.075569Z","iopub.execute_input":"2026-02-04T05:36:39.07593Z","iopub.status.idle":"2026-02-04T05:36:39.949234Z","shell.execute_reply.started":"2026-02-04T05:36:39.075907Z","shell.execute_reply":"2026-02-04T05:36:39.94826Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Data paths (Kaggle environment)\nINPUT_PATH = Path('/kaggle/input/deep-past-initiative-machine-translation')\nOUTPUT_PATH = Path('/kaggle/working')\n\n# List all available files\nprint(\"[INFO] Available data files:\")\nfor file in sorted(INPUT_PATH.glob('*')):\n    size_mb = file.stat().st_size / (1024 * 1024)\n    print(f\"  - {file.name:30s} ({size_mb:>8.2f} MB)\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:39.950196Z","iopub.execute_input":"2026-02-04T05:36:39.950726Z","iopub.status.idle":"2026-02-04T05:36:39.962433Z","shell.execute_reply.started":"2026-02-04T05:36:39.950672Z","shell.execute_reply":"2026-02-04T05:36:39.961737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load main datasets\nprint(\"\\n[INFO] Loading datasets...\")\ntrain = pd.read_csv(INPUT_PATH / 'train.csv')\ntest = pd.read_csv(INPUT_PATH / 'test.csv')\nsample_submission = pd.read_csv(INPUT_PATH / 'sample_submission.csv')\n\nprint(f\"\\n[OK] Data loaded successfully!\")\nprint(f\"Training set: {len(train):,} samples\")\nprint(f\"Test set: {len(test):,} samples\")\nprint(f\"\\nTraining columns: {train.columns.tolist()}\")\nprint(f\"Test columns: {test.columns.tolist()}\")\n\n# Rename columns to standard names for easier processing\nprint(\"\\n[INFO] Standardizing column names...\")\ntrain = train.rename(columns={'transliteration': 'source', 'translation': 'target'})\ntest = test.rename(columns={'transliteration': 'source'})\n\nprint(f\"[OK] Standardized columns - Train: {train.columns.tolist()}\")\nprint(f\"[OK] Standardized columns - Test: {test.columns.tolist()}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:39.964193Z","iopub.execute_input":"2026-02-04T05:36:39.9648Z","iopub.status.idle":"2026-02-04T05:36:40.047135Z","shell.execute_reply.started":"2026-02-04T05:36:39.964771Z","shell.execute_reply":"2026-02-04T05:36:40.046337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Preview training data\nprint(\"\\n[INFO] Training data sample:\")\ndisplay(train.head(5))\n\nprint(\"\\n[INFO] Test data sample:\")\ndisplay(test.head(3))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:40.04815Z","iopub.execute_input":"2026-02-04T05:36:40.048445Z","iopub.status.idle":"2026-02-04T05:36:40.073704Z","shell.execute_reply.started":"2026-02-04T05:36:40.048418Z","shell.execute_reply":"2026-02-04T05:36:40.073066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check for missing values\nprint(\"[INFO] Missing values check:\")\nprint(\"\\nTraining set:\")\nprint(train.isnull().sum())\n\nprint(\"\\nTest set:\")\nprint(test.isnull().sum())\n\n# Basic statistics\nprint(\"\\n[INFO] Basic statistics:\")\ntrain['source_len'] = train['source'].str.len()\ntrain['target_len'] = train['target'].str.len()\n\nprint(f\"\\nSource text length: {train['source_len'].mean():.1f} +/- {train['source_len'].std():.1f}\")\nprint(f\"Target text length: {train['target_len'].mean():.1f} +/- {train['target_len'].std():.1f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:40.074579Z","iopub.execute_input":"2026-02-04T05:36:40.074796Z","iopub.status.idle":"2026-02-04T05:36:40.08579Z","shell.execute_reply.started":"2026-02-04T05:36:40.074777Z","shell.execute_reply":"2026-02-04T05:36:40.084996Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Text cleaning function\ndef clean_text(text):\n    \"\"\"Clean and normalize text\"\"\"\n    if pd.isna(text):\n        return ''\n    \n    # Convert to string and strip\n    text = str(text).strip()\n    \n    # Remove extra whitespace\n    text = re.sub(r'\\s+', ' ', text)\n    \n    # Remove special control characters\n    text = re.sub(r'[\\x00-\\x1f\\x7f-\\x9f]', '', text)\n    \n    return text\n\n# Apply cleaning\nprint(\"[INFO] Cleaning text...\")\ntrain['source_clean'] = train['source'].apply(clean_text)\ntrain['target_clean'] = train['target'].apply(clean_text)\ntest['source_clean'] = test['source'].apply(clean_text)\n\n# Remove empty rows\nbefore = len(train)\ntrain = train[(train['source_clean'] != '') & (train['target_clean'] != '')].reset_index(drop=True)\nafter = len(train)\n\nprint(f\"[OK] Removed {before - after} empty rows\")\nprint(f\"[OK] Final training set: {after:,} samples\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:40.086656Z","iopub.execute_input":"2026-02-04T05:36:40.086932Z","iopub.status.idle":"2026-02-04T05:36:40.22588Z","shell.execute_reply.started":"2026-02-04T05:36:40.086913Z","shell.execute_reply":"2026-02-04T05:36:40.225087Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Text length distribution\nfig, axes = plt.subplots(1, 2, figsize=(15, 5))\n\n# Source length\naxes[0].hist(train['source_len'], bins=50, edgecolor='black', alpha=0.7)\naxes[0].set_xlabel('Character Count')\naxes[0].set_ylabel('Frequency')\naxes[0].set_title('Source Text Length Distribution (Akkadian)')\naxes[0].axvline(train['source_len'].median(), color='r', linestyle='--', label=f'Median: {train[\"source_len\"].median():.0f}')\naxes[0].legend()\n\n# Target length\naxes[1].hist(train['target_len'], bins=50, edgecolor='black', alpha=0.7, color='orange')\naxes[1].set_xlabel('Character Count')\naxes[1].set_ylabel('Frequency')\naxes[1].set_title('Target Text Length Distribution (English)')\naxes[1].axvline(train['target_len'].median(), color='r', linestyle='--', label=f'Median: {train[\"target_len\"].median():.0f}')\naxes[1].legend()\n\nplt.tight_layout()\nplt.savefig(OUTPUT_PATH / 'text_length_distribution.png', dpi=150, bbox_inches='tight')\nplt.show()\n\nprint(\"[OK] Length distribution plotted\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:40.226863Z","iopub.execute_input":"2026-02-04T05:36:40.227182Z","iopub.status.idle":"2026-02-04T05:36:41.142621Z","shell.execute_reply.started":"2026-02-04T05:36:40.227152Z","shell.execute_reply":"2026-02-04T05:36:41.141895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Vocabulary analysis\ndef build_vocabulary(texts, top_n=20):\n    \"\"\"Build vocabulary from texts\"\"\"\n    all_words = []\n    for text in texts:\n        words = text.lower().split()\n        all_words.extend(words)\n    return Counter(all_words).most_common(top_n)\n\nprint(\"[INFO] Building vocabularies...\")\nsource_vocab = build_vocabulary(train['source_clean'], top_n=30)\ntarget_vocab = build_vocabulary(train['target_clean'], top_n=30)\n\nprint(\"\\n[INFO] Top 20 Akkadian words:\")\nfor word, count in source_vocab[:20]:\n    print(f\"  {word:15s} : {count:5d}\")\n\nprint(\"\\n[INFO] Top 20 English words:\")\nfor word, count in target_vocab[:20]:\n    print(f\"  {word:15s} : {count:5d}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:41.143716Z","iopub.execute_input":"2026-02-04T05:36:41.143963Z","iopub.status.idle":"2026-02-04T05:36:41.220405Z","shell.execute_reply.started":"2026-02-04T05:36:41.143943Z","shell.execute_reply":"2026-02-04T05:36:41.219607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize top words\nfig, axes = plt.subplots(1, 2, figsize=(16, 6))\n\n# Akkadian\nwords, counts = zip(*source_vocab[:15])\naxes[0].barh(range(len(words)), counts, color='steelblue')\naxes[0].set_yticks(range(len(words)))\naxes[0].set_yticklabels(words)\naxes[0].set_xlabel('Frequency')\naxes[0].set_title('Top 15 Akkadian Words')\naxes[0].invert_yaxis()\n\n# English\nwords, counts = zip(*target_vocab[:15])\naxes[1].barh(range(len(words)), counts, color='coral')\naxes[1].set_yticks(range(len(words)))\naxes[1].set_yticklabels(words)\naxes[1].set_xlabel('Frequency')\naxes[1].set_title('Top 15 English Words')\naxes[1].invert_yaxis()\n\nplt.tight_layout()\nplt.savefig(OUTPUT_PATH / 'top_words.png', dpi=150, bbox_inches='tight')\nplt.show()\n\nprint(\"[OK] Word frequency visualization completed\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:41.222334Z","iopub.execute_input":"2026-02-04T05:36:41.222555Z","iopub.status.idle":"2026-02-04T05:36:42.00592Z","shell.execute_reply.started":"2026-02-04T05:36:41.222535Z","shell.execute_reply":"2026-02-04T05:36:42.005049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Install required packages\nprint(\"[INFO] Installing required packages...\")\n\n# Suppress warnings\nimport os\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'\n\n!pip install -q transformers sacrebleu tokenizers scikit-learn\n\nprint(\"[OK] Packages installed\")\n\n# Import deep learning libraries\nimport torch\nfrom transformers import (\n    MarianMTModel, \n    MarianTokenizer,\n    Seq2SeqTrainingArguments,\n    Seq2SeqTrainer,\n    DataCollatorForSeq2Seq\n)\nfrom torch.utils.data import Dataset\nimport sacrebleu\nfrom sklearn.model_selection import train_test_split\n\nprint(\"[OK] Deep learning libraries imported\")\nprint(f\"PyTorch version: {torch.__version__}\")\nprint(f\"CUDA available: {torch.cuda.is_available()}\")\nif torch.cuda.is_available():\n    print(f\"GPU: {torch.cuda.get_device_name(0)}\")\n    print(f\"GPU Memory: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.2f} GB\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:36:42.007354Z","iopub.execute_input":"2026-02-04T05:36:42.007711Z","iopub.status.idle":"2026-02-04T05:37:15.830577Z","shell.execute_reply.started":"2026-02-04T05:36:42.007659Z","shell.execute_reply":"2026-02-04T05:37:15.82974Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create dataset class\nclass TranslationDataset(Dataset):\n    def __init__(self, source_texts, target_texts, tokenizer, max_length=128):\n        self.source_texts = source_texts\n        self.target_texts = target_texts\n        self.tokenizer = tokenizer\n        self.max_length = max_length\n    \n    def __len__(self):\n        return len(self.source_texts)\n    \n    def __getitem__(self, idx):\n        source = str(self.source_texts[idx])\n        target = str(self.target_texts[idx])\n        \n        # Tokenize\n        model_inputs = self.tokenizer(\n            source, \n            max_length=self.max_length, \n            truncation=True,\n            padding='max_length'\n        )\n        \n        # Tokenize targets\n        with self.tokenizer.as_target_tokenizer():\n            labels = self.tokenizer(\n                target, \n                max_length=self.max_length, \n                truncation=True,\n                padding='max_length'\n            )\n        \n        model_inputs['labels'] = labels['input_ids']\n        \n        return {k: torch.tensor(v) for k, v in model_inputs.items()}\n\nprint(\"[OK] Dataset class defined\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:37:15.831732Z","iopub.execute_input":"2026-02-04T05:37:15.832393Z","iopub.status.idle":"2026-02-04T05:37:15.84033Z","shell.execute_reply.started":"2026-02-04T05:37:15.832365Z","shell.execute_reply":"2026-02-04T05:37:15.839346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load pre-trained model\nprint(\"[INFO] Loading pre-trained model...\")\nmodel_name = 'Helsinki-NLP/opus-mt-mul-en'\n\ntokenizer = MarianTokenizer.from_pretrained(model_name)\nmodel = MarianMTModel.from_pretrained(model_name)\n\n# Move model to GPU if available\nif torch.cuda.is_available():\n    model = model.cuda()\n\nprint(f\"[OK] Model loaded: {model_name}\")\nprint(f\"Model parameters: {sum(p.numel() for p in model.parameters()):,}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:37:15.841445Z","iopub.execute_input":"2026-02-04T05:37:15.84174Z","iopub.status.idle":"2026-02-04T05:37:21.169706Z","shell.execute_reply.started":"2026-02-04T05:37:15.84171Z","shell.execute_reply":"2026-02-04T05:37:21.168918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prepare datasets\nprint(\"[INFO] Preparing datasets...\")\n\n# Split train into train/val\ntrain_texts, val_texts, train_labels, val_labels = train_test_split(\n    train['source_clean'].tolist(),\n    train['target_clean'].tolist(),\n    test_size=0.1,\n    random_state=42\n)\n\ntrain_dataset = TranslationDataset(train_texts, train_labels, tokenizer)\nval_dataset = TranslationDataset(val_texts, val_labels, tokenizer)\n\nprint(f\"[OK] Training samples: {len(train_dataset):,}\")\nprint(f\"[OK] Validation samples: {len(val_dataset):,}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:37:21.17075Z","iopub.execute_input":"2026-02-04T05:37:21.171076Z","iopub.status.idle":"2026-02-04T05:37:21.181878Z","shell.execute_reply.started":"2026-02-04T05:37:21.171043Z","shell.execute_reply":"2026-02-04T05:37:21.181159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define training arguments\ntraining_args = Seq2SeqTrainingArguments(\n    output_dir=str(OUTPUT_PATH / 'model_output'),\n    eval_strategy='epoch',  # 改这里：evaluation_strategy -> eval_strategy\n    learning_rate=5e-5,\n    per_device_train_batch_size=16,\n    per_device_eval_batch_size=16,\n    num_train_epochs=3,\n    weight_decay=0.01,\n    save_total_limit=2,\n    predict_with_generate=True,\n    fp16=torch.cuda.is_available(),\n    logging_steps=100,\n    save_strategy='epoch',\n    load_best_model_at_end=True,\n    metric_for_best_model='loss',\n    greater_is_better=False,\n)\n\n# Data collator\ndata_collator = DataCollatorForSeq2Seq(tokenizer, model=model)\n\n# Create trainer\ntrainer = Seq2SeqTrainer(\n    model=model,\n    args=training_args,\n    train_dataset=train_dataset,\n    eval_dataset=val_dataset,\n    data_collator=data_collator,\n    tokenizer=tokenizer,\n)\n\nprint(\"[OK] Trainer initialized\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:37:21.182743Z","iopub.execute_input":"2026-02-04T05:37:21.182971Z","iopub.status.idle":"2026-02-04T05:37:24.433469Z","shell.execute_reply.started":"2026-02-04T05:37:21.18295Z","shell.execute_reply":"2026-02-04T05:37:24.432585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train the model\nprint(\"[START] Training model...\")\nprint(\"This may take 1-2 hours depending on GPU...\\n\")\n\ntrainer.train()\n\nprint(\"\\n[OK] Training completed!\")\n\n# Save the model\nmodel.save_pretrained(OUTPUT_PATH / 'final_model')\ntokenizer.save_pretrained(OUTPUT_PATH / 'final_model')\n\nprint(\"[OK] Model saved to /kaggle/working/final_model\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T05:37:24.434559Z","iopub.execute_input":"2026-02-04T05:37:24.43505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluation on validation set\nprint(\"[INFO] Evaluating on validation set...\")\n\ndef translate_batch(texts, model, tokenizer, batch_size=32):\n    \"\"\"Translate a batch of texts\"\"\"\n    translations = []\n    \n    for i in range(0, len(texts), batch_size):\n        batch = texts[i:i+batch_size]\n        inputs = tokenizer(batch, return_tensors='pt', padding=True, truncation=True, max_length=128)\n        \n        if torch.cuda.is_available():\n            inputs = {k: v.cuda() for k, v in inputs.items()}\n        \n        with torch.no_grad():\n            outputs = model.generate(**inputs, max_length=128, num_beams=4)\n        \n        batch_translations = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n        translations.extend(batch_translations)\n        \n        # Progress\n        if (i // batch_size) % 10 == 0:\n            print(f\"  Processed {i + len(batch)}/{len(texts)} samples...\")\n    \n    return translations\n\n# Translate validation set (first 100 samples)\nval_predictions = translate_batch(val_texts[:100], model, tokenizer)\n\n# Calculate BLEU score\nbleu = sacrebleu.corpus_bleu(val_predictions, [val_labels[:100]])\nprint(f\"\\n[OK] Validation BLEU: {bleu.score:.2f}\")\n\n# Show some examples\nprint(\"\\n[INFO] Sample translations:\")\nfor i in range(min(3, len(val_predictions))):\n    print(f\"\\nExample {i+1}:\")\n    print(f\"Source:     {val_texts[i][:100]}...\")\n    print(f\"Reference:  {val_labels[i][:100]}...\")\n    print(f\"Predicted:  {val_predictions[i][:100]}...\")\n","metadata":{"trusted":true,"execution":{"execution_failed":"2026-02-04T07:55:31.396Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Generate predictions for test set\nprint(\"[INFO] Generating predictions for test set...\")\nprint(f\"Total test samples: {len(test):,}\")\n\ntest_sources = test['source_clean'].tolist()\ntest_predictions = translate_batch(test_sources, model, tokenizer)\n\nprint(f\"\\n[OK] Generated {len(test_predictions):,} predictions\")\n\n# Preview\nprint(\"\\n[INFO] Test predictions preview:\")\nfor i in range(3):\n    print(f\"\\nTest {i+1}:\")\n    print(f\"Source:    {test_sources[i][:100]}...\")\n    print(f\"Predicted: {test_predictions[i][:100]}...\")\n","metadata":{"trusted":true,"execution":{"execution_failed":"2026-02-04T07:55:31.398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create submission file\nsubmission = pd.DataFrame({\n    'id': test['id'],\n    'target': test_predictions\n})\n\n# Save submission\nsubmission_path = OUTPUT_PATH / 'submission.csv'\nsubmission.to_csv(submission_path, index=False)\n\nprint(f\"[OK] Submission file created: {submission_path}\")\nprint(f\"[OK] Total predictions: {len(submission):,}\")\n\n# Preview submission\nprint(\"\\n[INFO] Submission preview:\")\ndisplay(submission.head(10))\n\n# Verify format\nprint(\"\\n[INFO] Submission format verification:\")\nprint(f\"Columns: {submission.columns.tolist()}\")\nprint(f\"Shape: {submission.shape}\")\nprint(f\"Missing values: {submission.isnull().sum().sum()}\")\nprint(f\"Sample submission shape: {sample_submission.shape}\")\n\n# Check if shapes match\nif submission.shape == sample_submission.shape:\n    print(\"\\n[OK] Submission format is CORRECT!\")\nelse:\n    print(\"\\n[WARNING] Submission shape does not match sample submission!\")\n\nprint(\"\\n\" + \"=\"*60)\nprint(\"[SUCCESS] All steps completed!\")\nprint(\"=\"*60)\nprint(\"\\nNext steps:\")\nprint(\"1. Click 'Save Version' in the top right\")\nprint(\"2. Wait for the notebook to finish running\")\nprint(\"3. Go to 'Output' tab and click 'Submit to Competition'\")\nprint(\"4. Check your score on the leaderboard!\")\nprint(\"\\nGood luck!\")\n","metadata":{"trusted":true,"execution":{"execution_failed":"2026-02-04T07:55:31.398Z"}},"outputs":[],"execution_count":null}]}