Team Ai
Apppublic

JimmyChin1998/Pytorch-Learning-File

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
DistilBERT_Experiment.ipynb1485 linesDownload Raw Back to root
1{2 "cells": [3  {4   "cell_type": "code",5   "execution_count": 1,6   "id": "b99032e0-8493-4322-b0d1-12a63b07c700",7   "metadata": {},8   "outputs": [9    {10     "name": "stdout",11     "output_type": "stream",12     "text": [13      "torch version: 2.5.1+cu118\n",14      "torchvision version: 0.20.1+cu118\n"15     ]16    }17   ],18   "source": [19    "# For this notebook to run with updated APIs, we need torch 1.12+ and torchvision 0.13+\n",20    "try:\n",21    "    import torch\n",22    "    import torchvision\n",23    "    print(f\"torch version: {torch.__version__}\")\n",24    "    print(f\"torchvision version: {torchvision.__version__}\")\n",25    "except:\n",26    "    print(f\"[INFO] torch/torchvision versions is not available\")\n",27    "\n",28    "# Continue with regular imports\n",29    "import matplotlib.pyplot as plt\n",30    "import torch\n",31    "import torchvision\n",32    "import os\n",33    "import pandas as pd\n",34    "\n",35    "from torch import nn\n",36    "from torchvision import transforms\n",37    "\n",38    "# Try to get torchinfo, install it if it doesn't work\n",39    "try:\n",40    "    from torchinfo import summary\n",41    "except:\n",42    "    print(\"[INFO] Couldn't find torchinfo... installing it.\")\n",43    "    !pip install -q torchinfo\n",44    "    from torchinfo import summary"45   ]46  },47  {48   "cell_type": "code",49   "execution_count": 59,50   "id": "8fedc3b3-acc4-4947-93bf-28289da0e047",51   "metadata": {},52   "outputs": [53    {54     "data": {55      "text/plain": [56       "'cuda'"57      ]58     },59     "execution_count": 59,60     "metadata": {},61     "output_type": "execute_result"62    }63   ],64   "source": [65    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",66    "device"67   ]68  },69  {70   "cell_type": "code",71   "execution_count": 2,72   "id": "e6b148a9-e056-4033-8298-c79ea02c41c0",73   "metadata": {},74   "outputs": [75    {76     "name": "stdout",77     "output_type": "stream",78     "text": [79      "4.47.1\n"80     ]81    }82   ],83   "source": [84    "import transformers\n",85    "print(transformers.__version__)  # 應該輸出 transformers 的版本號"86   ]87  },88  {89   "cell_type": "code",90   "execution_count": 12,91   "id": "5f27aa58-690b-4574-86a3-1a5514934450",92   "metadata": {},93   "outputs": [94    {95     "name": "stdout",96     "output_type": "stream",97     "text": [98      "Overwriting demos/DistilBERT_Experiment/model.py\n"99     ]100    }101   ],102   "source": [103    "%%writefile demos/DistilBERT_Experiment/model.py\n",104    "import torch\n",105    "from torch import nn\n",106    "import transformers\n",107    "from transformers import DistilBertForSequenceClassification, DistilBertTokenizer\n",108    "\n",109    "def create_distilbert_model(num_classes: int = 2, seed: int = 42):\n",110    "    \"\"\"\n",111    "    Creates a DistilBERT model for sentiment analysis with a customized classification head.\n",112    "\n",113    "    Args:\n",114    "        num_classes (int): Number of output classes.\n",115    "        seed (int): Random seed for reproducibility.\n",116    "\n",117    "    Returns:\n",118    "        model (torch.nn.Module): DistilBERT model with a custom classification head.\n",119    "        tokenizer (transformers.PreTrainedTokenizer): Tokenizer for text preprocessing.\n",120    "    \"\"\"\n",121    "    # Set random seed for reproducibility\n",122    "    torch.manual_seed(seed)\n",123    "\n",124    "    # Load pre-trained DistilBERT model\n",125    "    model = DistilBertForSequenceClassification.from_pretrained(\n",126    "        \"distilbert-base-uncased\",\n",127    "        num_labels=num_classes  # Output layer matches the number of classes\n",128    "    )\n",129    "\n",130    "    # Freeze base model parameters (optional)\n",131    "    for param in model.distilbert.parameters():\n",132    "        param.requires_grad = False\n",133    "\n",134    "    # Customize the classification head\n",135    "    model.classifier = nn.Sequential(\n",136    "        nn.Dropout(p=0.5),           # Add dropout to prevent overfitting\n",137    "        nn.Linear(768, 256),         # Add a hidden layer (768 -> 256)\n",138    "        nn.ReLU(),                   # Non-linear activation function\n",139    "        nn.Dropout(p=0.3),           # Add another dropout layer\n",140    "        nn.Linear(256, num_classes)  # Output layer (256 -> num_classes)\n",141    "    )\n",142    "\n",143    "    # model.classifier = nn.Sequential(\n",144    "    #     nn.Dropout(p=0.6),\n",145    "    #     nn.Linear(768, 256),\n",146    "    #     nn.ReLU(),\n",147    "    #     nn.Dropout(p=0.4),\n",148    "    #     nn.Linear(256, 2)\n",149    "    # )\n",150    "\n",151    "    # Load DistilBERT tokenizer\n",152    "    tokenizer = DistilBertTokenizer.from_pretrained(\"distilbert-base-uncased\")\n",153    "\n",154    "    return model, tokenizer\n",155    "\n",156    "def tokenize_texts_and_labels(tokenizer, texts, labels=None, max_length=128):\n",157    "    \"\"\"\n",158    "    將文本數據進行分詞,並處理標籤(如果提供)。\n",159    "    Args:\n",160    "        tokenizer: 分詞器,用於將文本轉換為模型輸入格式。\n",161    "        texts (list[str]): 文本數據列表。\n",162    "        labels (list[int], optional): 標籤列表,可選。\n",163    "        max_length (int): 最大文本長度。\n",164    "    Returns:\n",165    "        dict: 包含分詞結果的字典,包括 input_ids、attention_mask 和 labels(如果提供)。\n",166    "    \"\"\"\n",167    "    encodings = tokenizer(\n",168    "        list(texts),\n",169    "        padding=\"max_length\",\n",170    "        truncation=True,\n",171    "        max_length=max_length,\n",172    "        return_tensors=\"pt\"\n",173    "    )\n",174    "    if labels is not None:\n",175    "        encodings[\"labels\"] = torch.tensor(labels)  # 將標籤轉為 PyTorch 張量\n",176    "    return encodings"177   ]178  },179  {180   "cell_type": "code",181   "execution_count": 3,182   "id": "d984ebb6-b452-451b-9336-0239b99b60d6",183   "metadata": {},184   "outputs": [],185   "source": [186    "import sys\n",187    "import os\n",188    "\n",189    "# 新增 `demos/DistilBERT_Experiment/` 到 Python 的模組搜尋路徑\n",190    "sys.path.append(os.path.join(os.getcwd(), \"demos\", \"DistilBERT_Experiment\"))\n",191    "\n",192    "# 從 model 模組中匯入函數\n",193    "from model import create_distilbert_model"194   ]195  },196  {197   "cell_type": "code",198   "execution_count": 104,199   "id": "7f1ea2a0-c2bc-4184-b533-2304efc6eebf",200   "metadata": {},201   "outputs": [202    {203     "name": "stderr",204     "output_type": "stream",205     "text": [206      "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']\n",207      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"208     ]209    }210   ],211   "source": [212    "DistilBERT_Model, DistilBERT_Tokenizer = create_distilbert_model(num_classes=2, seed=42)"213   ]214  },215  {216   "cell_type": "code",217   "execution_count": 105,218   "id": "19404541-1d46-41e6-a28d-0763ba6d3731",219   "metadata": {},220   "outputs": [221    {222     "name": "stdout",223     "output_type": "stream",224     "text": [225      "DistilBertForSequenceClassification(\n",226      "  (distilbert): DistilBertModel(\n",227      "    (embeddings): Embeddings(\n",228      "      (word_embeddings): Embedding(30522, 768, padding_idx=0)\n",229      "      (position_embeddings): Embedding(512, 768)\n",230      "      (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",231      "      (dropout): Dropout(p=0.1, inplace=False)\n",232      "    )\n",233      "    (transformer): Transformer(\n",234      "      (layer): ModuleList(\n",235      "        (0-5): 6 x TransformerBlock(\n",236      "          (attention): DistilBertSdpaAttention(\n",237      "            (dropout): Dropout(p=0.1, inplace=False)\n",238      "            (q_lin): Linear(in_features=768, out_features=768, bias=True)\n",239      "            (k_lin): Linear(in_features=768, out_features=768, bias=True)\n",240      "            (v_lin): Linear(in_features=768, out_features=768, bias=True)\n",241      "            (out_lin): Linear(in_features=768, out_features=768, bias=True)\n",242      "          )\n",243      "          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",244      "          (ffn): FFN(\n",245      "            (dropout): Dropout(p=0.1, inplace=False)\n",246      "            (lin1): Linear(in_features=768, out_features=3072, bias=True)\n",247      "            (lin2): Linear(in_features=3072, out_features=768, bias=True)\n",248      "            (activation): GELUActivation()\n",249      "          )\n",250      "          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",251      "        )\n",252      "      )\n",253      "    )\n",254      "  )\n",255      "  (pre_classifier): Linear(in_features=768, out_features=768, bias=True)\n",256      "  (classifier): Sequential(\n",257      "    (0): Dropout(p=0.5, inplace=False)\n",258      "    (1): Linear(in_features=768, out_features=256, bias=True)\n",259      "    (2): ReLU()\n",260      "    (3): Dropout(p=0.3, inplace=False)\n",261      "    (4): Linear(in_features=256, out_features=2, bias=True)\n",262      "  )\n",263      "  (dropout): Dropout(p=0.2, inplace=False)\n",264      ")\n",265      "Total parameters: 67150850\n",266      "Trainable parameters: 787970\n"267     ]268    }269   ],270   "source": [271    "# 打印模型的結構\n",272    "print(DistilBERT_Model)\n",273    "\n",274    "# 計算參數總量和可訓練參數\n",275    "total_params = sum(p.numel() for p in DistilBERT_Model.parameters())\n",276    "trainable_params = sum(p.numel() for p in DistilBERT_Model.parameters() if p.requires_grad)\n",277    "\n",278    "print(f\"Total parameters: {total_params}\")\n",279    "print(f\"Trainable parameters: {trainable_params}\")"280   ]281  },282  {283   "cell_type": "code",284   "execution_count": 26,285   "id": "91f2bd69-9fb3-4756-a3e7-20d2fc6493bb",286   "metadata": {},287   "outputs": [288    {289     "name": "stdout",290     "output_type": "stream",291     "text": [292      "C:\\Users\\User\\Desktop\\Pytorch\\pytorchPractice\n"293     ]294    }295   ],296   "source": [297    "print(os.getcwd())  # 輸出當前工作目錄"298   ]299  },300  {301   "cell_type": "markdown",302   "id": "a4a600f6-c72a-444b-ad55-c1bc31884ee9",303   "metadata": {},304   "source": [305    "### 讀取 IMDb 數據集"306   ]307  },308  {309   "cell_type": "code",310   "execution_count": 27,311   "id": "a97c7663-58af-4cd8-b24f-d0b16415e04f",312   "metadata": {},313   "outputs": [314    {315     "name": "stdout",316     "output_type": "stream",317     "text": [318      "C:\\Users\\User\\Desktop\\Pytorch\\pytorchPractice\\data\\IMDb_Large_Movie_Review_Dataset\\aclImdb\n"319     ]320    }321   ],322   "source": [323    "IMDb_path = os.path.join(os.getcwd(), \"data\", \"IMDb_Large_Movie_Review_Dataset\", \"aclImdb\")\n",324    "print(IMDb_path)"325   ]326  },327  {328   "cell_type": "code",329   "execution_count": 38,330   "id": "27714990-ecdf-4dba-83ef-cdb4a7af08fb",331   "metadata": {},332   "outputs": [],333   "source": [334    "import os\n",335    "import pandas as pd\n",336    "\n",337    "def load_imdb_data(data_dir):\n",338    "    \"\"\"\n",339    "    加載 IMDb 數據集中的單一資料夾(train 或 test),並返回包含文本和標籤的 DataFrame。\n",340    "    Args:\n",341    "        data_dir (str): 資料夾的路徑(例如 'train' 或 'test' 資料夾)。\n",342    "    Returns:\n",343    "        pd.DataFrame: 包含 'text' 和 'label' 的 DataFrame。\n",344    "    \"\"\"\n",345    "    texts, labels = [], []\n",346    "    for sentiment in [\"pos\", \"neg\"]:  # 遍歷 'pos' 和 'neg' 資料夾\n",347    "        dir_path = os.path.join(data_dir, sentiment)\n",348    "        for file_name in os.listdir(dir_path):  # 遍歷該資料夾內的所有文件\n",349    "            with open(os.path.join(dir_path, file_name), \"r\", encoding=\"utf-8\") as f:\n",350    "                texts.append(f.read())  # 讀取文本內容\n",351    "            labels.append(1 if sentiment == \"pos\" else 0)  # 添加標籤\n",352    "    return pd.DataFrame({\"text\": texts, \"label\": labels})  # 返回 DataFrame"353   ]354  },355  {356   "cell_type": "code",357   "execution_count": 36,358   "id": "66df4473-98e7-44f2-a250-5dd5f144ecde",359   "metadata": {},360   "outputs": [],361   "source": [362    "# 加載 IMDb 數據集(不分train與Test)\n",363    "# 使用函式加載數據集\n",364    "# imdb_df = load_imdb_data(IMDb_path)\n",365    "\n",366    "# 查看數據\n",367    "# print(imdb_df.head())\n",368    "# print(f\"總共加載了 {len(imdb_df)} 條數據!\")"369   ]370  },371  {372   "cell_type": "code",373   "execution_count": 40,374   "id": "f60900fe-33a5-44e9-86b4-56e987148bbd",375   "metadata": {},376   "outputs": [377    {378     "name": "stdout",379     "output_type": "stream",380     "text": [381      "訓練集大小: 25000\n",382      "驗證集大小: 25000\n"383     ]384    }385   ],386   "source": [387    "# 加載 IMDb 並分開處理 train 和 test 數據\n",388    "# 加載 train 數據\n",389    "train_df = load_imdb_data(os.path.join(IMDb_path, \"train\"))\n",390    "\n",391    "# 加載 test 數據\n",392    "test_df = load_imdb_data(os.path.join(IMDb_path, \"test\"))\n",393    "\n",394    "print(f\"訓練集大小: {len(train_df)}\")\n",395    "print(f\"驗證集大小: {len(test_df)}\")"396   ]397  },398  {399   "cell_type": "code",400   "execution_count": 48,401   "id": "be51c4af-d267-46a1-b261-fdb713770424",402   "metadata": {},403   "outputs": [404    {405     "name": "stdout",406     "output_type": "stream",407     "text": [408      "每篇影評的平均字數為: 1325.07\n"409     ]410    }411   ],412   "source": [413    "# 計算每篇影評的字數\n",414    "train_text_lengths = train_df[\"text\"].apply(len)\n",415    "\n",416    "# 計算平均字數\n",417    "average_length = train_text_lengths.mean()\n",418    "\n",419    "# 輸出結果\n",420    "print(f\"每篇影評的平均字數為: {average_length:.2f}\")"421   ]422  },423  {424   "cell_type": "code",425   "execution_count": 49,426   "id": "7f64cbd5-9fe7-42f4-94c9-1f1c70092d37",427   "metadata": {},428   "outputs": [429    {430     "name": "stdout",431     "output_type": "stream",432     "text": [433      "50% 的影評長度在 174 單詞內\n",434      "75% 的影評長度在 284 單詞內\n",435      "90% 的影評長度在 458 單詞內\n",436      "95% 的影評長度在 598 單詞內\n",437      "99% 的影評長度在 913 單詞內\n"438     ]439    }440   ],441   "source": [442    "# 計算單詞數\n",443    "train_word_lengths = train_df[\"text\"].apply(lambda x: len(x.split()))\n",444    "\n",445    "# 查看不同分位數的文本長度\n",446    "for percentile in [50, 75, 90, 95, 99]:\n",447    "    length_at_percentile = train_word_lengths.quantile(percentile / 100)\n",448    "    print(f\"{percentile}% 的影評長度在 {length_at_percentile:.0f} 單詞內\")"449   ]450  },451  {452   "cell_type": "markdown",453   "id": "ef8eed79-48c5-43e5-abe3-30e4aaa22474",454   "metadata": {},455   "source": [456    "### 將讀取的 data 轉換成 model 的 input 格式"457   ]458  },459  {460   "cell_type": "code",461   "execution_count": 44,462   "id": "65a24cba-751f-43a8-9498-5c979831e5b8",463   "metadata": {},464   "outputs": [],465   "source": [466    "# tokenizer 的基本功能:\n",467    "# input_ids:文本的 token ID(數字表示)。\n",468    "# attention_mask:用於區分有效 token 和填充部分(padding)的掩碼。\n",469    "# 而 model 的 input 需要 labels"470   ]471  },472  {473   "cell_type": "code",474   "execution_count": 4,475   "id": "c11232ae-4134-440e-9ea0-795a5df965d5",476   "metadata": {},477   "outputs": [],478   "source": [479    "def tokenize_texts_and_labels(tokenizer, texts, labels=None, max_length=128):\n",480    "    \"\"\"\n",481    "    將文本數據進行分詞,並處理標籤(如果提供)。\n",482    "    Args:\n",483    "        tokenizer: 分詞器,用於將文本轉換為模型輸入格式。\n",484    "        texts (list[str]): 文本數據列表。\n",485    "        labels (list[int], optional): 標籤列表,可選。\n",486    "        max_length (int): 最大文本長度。\n",487    "    Returns:\n",488    "        dict: 包含分詞結果的字典,包括 input_ids、attention_mask 和 labels(如果提供)。\n",489    "    \"\"\"\n",490    "    encodings = tokenizer(\n",491    "        list(texts),\n",492    "        padding=\"max_length\",\n",493    "        truncation=True,\n",494    "        max_length=max_length,\n",495    "        return_tensors=\"pt\"\n",496    "    )\n",497    "    if labels is not None:\n",498    "        encodings[\"labels\"] = torch.tensor(labels)  # 將標籤轉為 PyTorch 張量\n",499    "    return encodings"500   ]501  },502  {503   "cell_type": "code",504   "execution_count": 99,505   "id": "2abd5227-cbfc-4f7a-b2e4-128fcfe25d8a",506   "metadata": {},507   "outputs": [],508   "source": [509    "# 處理訓練集\n",510    "train_encodings = tokenize_texts_and_labels(\n",511    "    DistilBERT_Tokenizer,\n",512    "    train_df[\"text\"],  # 傳入文本\n",513    "    labels = train_df[\"label\"],  # 傳入標籤\n",514    "    max_length=512\n",515    ")\n",516    "\n",517    "# 處理測試集\n",518    "test_encodings = tokenize_texts_and_labels(\n",519    "    DistilBERT_Tokenizer,\n",520    "    test_df[\"text\"],  # 傳入文本\n",521    "    labels = test_df[\"label\"],  # 傳入標籤\n",522    "    max_length=512\n",523    ")"524   ]525  },526  {527   "cell_type": "code",528   "execution_count": 85,529   "id": "b4f9fde0-5e15-4a3e-9c16-46b873df6d9b",530   "metadata": {},531   "outputs": [532    {533     "name": "stdout",534     "output_type": "stream",535     "text": [536      "<class 'transformers.tokenization_utils_base.BatchEncoding'>\n"537     ]538    }539   ],540   "source": [541    "print(type(train_encodings))"542   ]543  },544  {545   "cell_type": "code",546   "execution_count": 86,547   "id": "2ab86f7d-8bef-47b9-a444-bb6afc037313",548   "metadata": {},549   "outputs": [550    {551     "name": "stdout",552     "output_type": "stream",553     "text": [554      "Input IDs (前兩筆):\n",555      "tensor([[  101, 22953,  2213,  ...,     0,     0,     0],\n",556      "        [  101, 11573,  2791,  ...,     0,     0,     0]])\n",557      "\n",558      "Attention Mask (前兩筆):\n",559      "tensor([[1, 1, 1,  ..., 0, 0, 0],\n",560      "        [1, 1, 1,  ..., 0, 0, 0]])\n",561      "\n",562      "Labels (前兩筆):\n",563      "tensor([1, 1])\n"564     ]565    }566   ],567   "source": [568    "# 查看 input_ids 的前兩筆資料\n",569    "print(\"Input IDs (前兩筆):\")\n",570    "print(train_encodings[\"input_ids\"][:2])\n",571    "\n",572    "# 查看 attention_mask 的前兩筆資料\n",573    "print(\"\\nAttention Mask (前兩筆):\")\n",574    "print(train_encodings[\"attention_mask\"][:2])\n",575    "\n",576    "# 查看 labels 的前兩筆資料(如果有標籤)\n",577    "if \"labels\" in train_encodings:\n",578    "    print(\"\\nLabels (前兩筆):\")\n",579    "    print(train_encodings[\"labels\"][:2])"580   ]581  },582  {583   "cell_type": "markdown",584   "id": "51da01ee-64aa-4a0c-a077-ce9c65bca910",585   "metadata": {},586   "source": [587    "### 建立 Dataset 類\n",588    "### 創建 DataLoader"589   ]590  },591  {592   "cell_type": "code",593   "execution_count": 73,594   "id": "c74e991a-a393-4558-be2e-1d630b75a161",595   "metadata": {},596   "outputs": [],597   "source": [598    "from torch.utils.data import Dataset\n",599    "\n",600    "class IMDbDataset(Dataset):\n",601    "    def __init__(self, encodings):\n",602    "        \"\"\"\n",603    "        初始化 Dataset 類,將分詞後的數據封裝起來。\n",604    "        Args:\n",605    "            encodings (dict): 包含 input_ids、attention_mask 和(可選的)labels 的字典。\n",606    "        \"\"\"\n",607    "        self.encodings = encodings\n",608    "\n",609    "    def __len__(self):\n",610    "        \"\"\"\n",611    "        返回數據集的樣本數。\n",612    "        \"\"\"\n",613    "        return len(self.encodings[\"input_ids\"])\n",614    "\n",615    "    def __getitem__(self, idx):\n",616    "        \"\"\"\n",617    "        返回指定索引的數據(如 input_ids, attention_mask, labels)。\n",618    "        \"\"\"\n",619    "        item = {key: tensor[idx] for key, tensor in self.encodings.items()}\n",620    "        return item"621   ]622  },623  {624   "cell_type": "code",625   "execution_count": 100,626   "id": "2e41660d-2e2e-4bac-a853-84a831b13da1",627   "metadata": {},628   "outputs": [],629   "source": [630    "from torch.utils.data import DataLoader\n",631    "\n",632    "# 創建訓練集和測試集的 Dataset\n",633    "train_dataset = IMDbDataset(train_encodings)\n",634    "test_dataset = IMDbDataset(test_encodings)\n",635    "\n",636    "# 創建訓練集和測試集的 DataLoader\n",637    "train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\n",638    "test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)"639   ]640  },641  {642   "cell_type": "code",643   "execution_count": 101,644   "id": "cbde9720-0748-45aa-b1cf-115d26f84547",645   "metadata": {},646   "outputs": [647    {648     "name": "stdout",649     "output_type": "stream",650     "text": [651      "input_ids: torch.Size([16, 512])\n",652      "attention_mask: torch.Size([16, 512])\n",653      "labels: torch.Size([16])\n"654     ]655    }656   ],657   "source": [658    "# 檢查數據加載結果\n",659    "# 從訓練集 DataLoader 中取出一個批次\n",660    "batch = next(iter(train_loader))\n",661    "\n",662    "# 輸出批次的鍵和值形狀\n",663    "for key, value in batch.items():\n",664    "    print(f\"{key}: {value.shape}\")"665   ]666  },667  {668   "cell_type": "markdown",669   "id": "720b04e0-5faa-4258-b404-d9a7a2d055c8",670   "metadata": {},671   "source": [672    "### 創建 Training Process"673   ]674  },675  {676   "cell_type": "markdown",677   "id": "268be27d-f919-4a90-88bf-ddd65f3b611f",678   "metadata": {},679   "source": [680    "### DistilBERTForSequenceClassification 自帶 loss,無需單獨定義損失函數"681   ]682  },683  {684   "cell_type": "code",685   "execution_count": 91,686   "id": "f4830bad-a86e-4c5b-a1f9-ad6172147622",687   "metadata": {},688   "outputs": [],689   "source": [690    "import torch\n",691    "from tqdm.auto import tqdm\n",692    "from typing import Dict, List, Tuple\n",693    "\n",694    "def train_step(model: torch.nn.Module, \n",695    "               dataloader: torch.utils.data.DataLoader, \n",696    "               optimizer: torch.optim.Optimizer,\n",697    "               device: torch.device) -> Tuple[float, float]:\n",698    "    \"\"\"\n",699    "    Trains a DistilBERT model for a single epoch.\n",700    "    \"\"\"\n",701    "    # Set model to training mode\n",702    "    model.train()\n",703    "\n",704    "    # Initialize metrics\n",705    "    train_loss, train_acc = 0, 0\n",706    "\n",707    "    # Loop through DataLoader batches\n",708    "    for batch in dataloader:\n",709    "        # Move data to the target device\n",710    "        input_ids = batch[\"input_ids\"].to(device)\n",711    "        attention_mask = batch[\"attention_mask\"].to(device)\n",712    "        labels = batch[\"labels\"].to(device)\n",713    "\n",714    "        # Forward pass\n",715    "        outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",716    "        loss = outputs.loss  # Get the loss from model output\n",717    "        logits = outputs.logits  # Predicted logits\n",718    "\n",719    "        # Backward pass\n",720    "        optimizer.zero_grad()\n",721    "        loss.backward()\n",722    "        optimizer.step()\n",723    "\n",724    "        # Accumulate metrics\n",725    "        train_loss += loss.item()\n",726    "        preds = torch.argmax(logits, dim=1)\n",727    "        train_acc += (preds == labels).sum().item() / len(labels)\n",728    "\n",729    "    # Return average loss and accuracy\n",730    "    train_loss = train_loss / len(dataloader)\n",731    "    train_acc = train_acc / len(dataloader)\n",732    "    return train_loss, train_acc\n",733    "\n",734    "def test_step(model: torch.nn.Module, \n",735    "              dataloader: torch.utils.data.DataLoader, \n",736    "              device: torch.device) -> Tuple[float, float]:\n",737    "    \"\"\"\n",738    "    Evaluates a DistilBERT model for a single epoch.\n",739    "    \"\"\"\n",740    "    # Set model to evaluation mode\n",741    "    model.eval()\n",742    "\n",743    "    # Initialize metrics\n",744    "    test_loss, test_acc = 0, 0\n",745    "\n",746    "    # Disable gradient computation\n",747    "    with torch.no_grad():\n",748    "        for batch in dataloader:\n",749    "            # Move data to the target device\n",750    "            input_ids = batch[\"input_ids\"].to(device)\n",751    "            attention_mask = batch[\"attention_mask\"].to(device)\n",752    "            labels = batch[\"labels\"].to(device)\n",753    "\n",754    "            # Forward pass\n",755    "            outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",756    "            loss = outputs.loss  # Get the loss\n",757    "            logits = outputs.logits  # Predicted logits\n",758    "\n",759    "            # Accumulate metrics\n",760    "            test_loss += loss.item()\n",761    "            preds = torch.argmax(logits, dim=1)\n",762    "            test_acc += (preds == labels).sum().item() / len(labels)\n",763    "\n",764    "    # Return average loss and accuracy\n",765    "    test_loss = test_loss / len(dataloader)\n",766    "    test_acc = test_acc / len(dataloader)\n",767    "    return test_loss, test_acc\n",768    "\n",769    "# def train(model: torch.nn.Module, \n",770    "#           train_dataloader: torch.utils.data.DataLoader, \n",771    "#           test_dataloader: torch.utils.data.DataLoader, \n",772    "#           optimizer: torch.optim.Optimizer,\n",773    "#           epochs: int,\n",774    "#           device: torch.device) -> Dict[str, List]:\n",775    "#     \"\"\"\n",776    "#     Trains and evaluates a DistilBERT model for a specified number of epochs.\n",777    "#     \"\"\"\n",778    "#     # Create a dictionary to store results\n",779    "#     results = {\"train_loss\": [], \"train_acc\": [], \"test_loss\": [], \"test_acc\": []}\n",780    "\n",781    "#     # Loop through epochs\n",782    "#     for epoch in tqdm(range(epochs)):\n",783    "#         # Train the model\n",784    "#         train_loss, train_acc = train_step(model, train_dataloader, optimizer, device)\n",785    "\n",786    "#         # Test the model\n",787    "#         test_loss, test_acc = test_step(model, test_dataloader, device)\n",788    "\n",789    "#         # Print metrics for each epoch\n",790    "#         print(\n",791    "#             f\"Epoch {epoch+1}/{epochs}: \"\n",792    "#             f\"Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}, \"\n",793    "#             f\"Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.4f}\"\n",794    "#         )\n",795    "\n",796    "#         # Store metrics\n",797    "#         results[\"train_loss\"].append(train_loss)\n",798    "#         results[\"train_acc\"].append(train_acc)\n",799    "#         results[\"test_loss\"].append(test_loss)\n",800    "#         results[\"test_acc\"].append(test_acc)\n",801    "\n",802    "#     return results\n",803    "\n",804    "def train(model: torch.nn.Module, \n",805    "          train_dataloader: torch.utils.data.DataLoader, \n",806    "          test_dataloader: torch.utils.data.DataLoader, \n",807    "          optimizer: torch.optim.Optimizer,\n",808    "          epochs: int,\n",809    "          device: torch.device,\n",810    "          lr_scheduler=None) -> Dict[str, List]:\n",811    "    \"\"\"\n",812    "    Trains and evaluates a DistilBERT model for a specified number of epochs.\n",813    "    \"\"\"\n",814    "    # Create a dictionary to store results\n",815    "    results = {\"train_loss\": [], \"train_acc\": [], \"test_loss\": [], \"test_acc\": [], \"lr\": []}\n",816    "\n",817    "    # Loop through epochs\n",818    "    for epoch in tqdm(range(epochs)):\n",819    "        print(f\"Epoch {epoch+1}/{epochs}\")\n",820    "\n",821    "        # Train the model\n",822    "        train_loss, train_acc = train_step(model, train_dataloader, optimizer, device)\n",823    "\n",824    "        # Test the model\n",825    "        test_loss, test_acc = test_step(model, test_dataloader, device)\n",826    "\n",827    "        # Update learning rate if scheduler is provided\n",828    "        if lr_scheduler:\n",829    "            lr_scheduler.step()\n",830    "\n",831    "        # Get current learning rate\n",832    "        current_lr = optimizer.param_groups[0][\"lr\"]\n",833    "        results[\"lr\"].append(current_lr)\n",834    "\n",835    "        # Print metrics for each epoch\n",836    "        print(\n",837    "            f\"Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}, \"\n",838    "            f\"Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.4f}, \"\n",839    "            f\"Learning Rate: {current_lr:.6f}\"\n",840    "        )\n",841    "\n",842    "        # Store metrics\n",843    "        results[\"train_loss\"].append(train_loss)\n",844    "        results[\"train_acc\"].append(train_acc)\n",845    "        results[\"test_loss\"].append(test_loss)\n",846    "        results[\"test_acc\"].append(test_acc)\n",847    "\n",848    "    return results"849   ]850  },851  {852   "cell_type": "code",853   "execution_count": 92,854   "id": "1a307d22-594e-468f-ad79-f88a59fe50d7",855   "metadata": {856    "scrolled": true857   },858   "outputs": [859    {860     "name": "stdout",861     "output_type": "stream",862     "text": [863      "DistilBertForSequenceClassification(\n",864      "  (distilbert): DistilBertModel(\n",865      "    (embeddings): Embeddings(\n",866      "      (word_embeddings): Embedding(30522, 768, padding_idx=0)\n",867      "      (position_embeddings): Embedding(512, 768)\n",868      "      (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",869      "      (dropout): Dropout(p=0.1, inplace=False)\n",870      "    )\n",871      "    (transformer): Transformer(\n",872      "      (layer): ModuleList(\n",873      "        (0-5): 6 x TransformerBlock(\n",874      "          (attention): DistilBertSdpaAttention(\n",875      "            (dropout): Dropout(p=0.1, inplace=False)\n",876      "            (q_lin): Linear(in_features=768, out_features=768, bias=True)\n",877      "            (k_lin): Linear(in_features=768, out_features=768, bias=True)\n",878      "            (v_lin): Linear(in_features=768, out_features=768, bias=True)\n",879      "            (out_lin): Linear(in_features=768, out_features=768, bias=True)\n",880      "          )\n",881      "          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",882      "          (ffn): FFN(\n",883      "            (dropout): Dropout(p=0.1, inplace=False)\n",884      "            (lin1): Linear(in_features=768, out_features=3072, bias=True)\n",885      "            (lin2): Linear(in_features=3072, out_features=768, bias=True)\n",886      "            (activation): GELUActivation()\n",887      "          )\n",888      "          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",889      "        )\n",890      "      )\n",891      "    )\n",892      "  )\n",893      "  (pre_classifier): Linear(in_features=768, out_features=768, bias=True)\n",894      "  (classifier): Sequential(\n",895      "    (0): Dropout(p=0.5, inplace=False)\n",896      "    (1): Linear(in_features=768, out_features=256, bias=True)\n",897      "    (2): ReLU()\n",898      "    (3): Dropout(p=0.3, inplace=False)\n",899      "    (4): Linear(in_features=256, out_features=2, bias=True)\n",900      "  )\n",901      "  (dropout): Dropout(p=0.2, inplace=False)\n",902      ")\n"903     ]904    }905   ],906   "source": [907    "print(DistilBERT_Model)"908   ]909  },910  {911   "cell_type": "code",912   "execution_count": 107,913   "id": "16e022fc-d27f-42fa-977b-617eb033828b",914   "metadata": {},915   "outputs": [],916   "source": [917    "from torch.optim import AdamW\n",918    "\n",919    "# Move model to target device\n",920    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",921    "DistilBERT_Model.to(device)\n",922    "\n",923    "from torch.optim.lr_scheduler import StepLR\n",924    "# Define optimizer\n",925    "optimizer = AdamW(DistilBERT_Model.parameters(), lr=5e-5)\n",926    "lr_scheduler = StepLR(optimizer, step_size=2, gamma=0.9)"927   ]928  },929  {930   "cell_type": "code",931   "execution_count": 108,932   "id": "c5e5b1c4-687b-4479-b9df-aba275e4544a",933   "metadata": {},934   "outputs": [935    {936     "data": {937      "application/vnd.jupyter.widget-view+json": {938       "model_id": "82a9d8b32bb44845a07cc5605de7788a",939       "version_major": 2,940       "version_minor": 0941      },942      "text/plain": [943       "  0%|          | 0/10 [00:00<?, ?it/s]"944      ]945     },946     "metadata": {},947     "output_type": "display_data"948    },949    {950     "name": "stdout",951     "output_type": "stream",952     "text": [953      "Epoch 1/10\n",954      "Train Loss: 0.4809, Train Acc: 0.7704, Test Loss: 0.3495, Test Acc: 0.8475, Learning Rate: 0.000050\n",955      "Epoch 2/10\n",956      "Train Loss: 0.3730, Train Acc: 0.8358, Test Loss: 0.3320, Test Acc: 0.8576, Learning Rate: 0.000045\n",957      "Epoch 3/10\n",958      "Train Loss: 0.3576, Train Acc: 0.8444, Test Loss: 0.3346, Test Acc: 0.8571, Learning Rate: 0.000045\n",959      "Epoch 4/10\n",960      "Train Loss: 0.3528, Train Acc: 0.8460, Test Loss: 0.3207, Test Acc: 0.8629, Learning Rate: 0.000041\n",961      "Epoch 5/10\n",962      "Train Loss: 0.3464, Train Acc: 0.8510, Test Loss: 0.3175, Test Acc: 0.8666, Learning Rate: 0.000041\n",963      "Epoch 6/10\n",964      "Train Loss: 0.3455, Train Acc: 0.8504, Test Loss: 0.3151, Test Acc: 0.8662, Learning Rate: 0.000036\n",965      "Epoch 7/10\n",966      "Train Loss: 0.3395, Train Acc: 0.8530, Test Loss: 0.3127, Test Acc: 0.8682, Learning Rate: 0.000036\n",967      "Epoch 8/10\n",968      "Train Loss: 0.3395, Train Acc: 0.8542, Test Loss: 0.3127, Test Acc: 0.8665, Learning Rate: 0.000033\n",969      "Epoch 9/10\n",970      "Train Loss: 0.3361, Train Acc: 0.8542, Test Loss: 0.3118, Test Acc: 0.8672, Learning Rate: 0.000033\n",971      "Epoch 10/10\n",972      "Train Loss: 0.3369, Train Acc: 0.8545, Test Loss: 0.3191, Test Acc: 0.8619, Learning Rate: 0.000030\n"973     ]974    }975   ],976   "source": [977    "# 執行訓練\n",978    "results = train(\n",979    "    DistilBERT_Model,\n",980    "    train_loader,\n",981    "    test_loader,\n",982    "    optimizer,\n",983    "    epochs=10,\n",984    "    device=device,\n",985    "    lr_scheduler=lr_scheduler  # 如果不需要調度器,這裡可以設為 None\n",986    ")"987   ]988  },989  {990   "cell_type": "code",991   "execution_count": 110,992   "id": "339ba65c-afd9-418e-aebe-a5488a500065",993   "metadata": {},994   "outputs": [995    {996     "data": {997      "image/png": "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HD366KP184QAAADc2IIFC2QYhj766CM1a9bMdSvvxvn222/LbrcrIiJC+/fvP+W5qrOPj4+PJKmoqKjC9qoW/5ecH4ie6I8//tCvv/6qF154QX/729906aWX6sILL1RYWFiF/UJDQ2Wz2U5bkyTdeuutCgsL06uvvqoPP/xQqampuu+++057HAD3RIAGoNHz9/dX7969tWzZsgpTMh0Oh9599121atVKcXFxlY6LjIzUmDFjNHLkSO3YsaPKFudxcXF64okn1LVrV/3yyy9n9XkAAAC4O7vdrrffflvt2rXT999/X+n28MMPKyUlRV988YWGDBmi77//3rWURlWGDBmihIQEfffddyfdJyYmRpL022+/Vdj+2WefVbvu8lDN29u7wvbXX3+9wn1fX18NGDBAH3744UkDunI+Pj66++679fbbb2vmzJk677zz1K9fv2rXBMC90IUTQKPy3Xffac+ePZW2T58+XVdccYUuu+wyPfLII/Ly8tKcOXP0xx9/aMmSJa43Tb1799Y111yjbt26qVmzZtq2bZveeecd9enTR35+fvrtt990//336+abb1aHDh3k5eWl7777Tr/99psmTZpUz88WAADAvXzxxRc6ePCgnn/+eV166aWVHo+Pj9crr7yi+fPn65VXXtEXX3yhSy65RP/4xz/UtWtXHT16VF9++aUmTpyoTp06acKECVq6dKmuu+46TZo0Sb169VJBQYF++OEHXXPNNbrssssUFRWlQYMGafr06WrWrJmio6P17bffatmyZdWuu1OnTmrXrp0mTZokwzAUGhqq//73v1qxYkWlfcs7c/bu3VuTJk1S+/btlZaWps8++0yvv/66AgMDXfvee++9mjFjhjZt2qQ333yzVt9TAG7C3B4GAFA3yrtwnuyWlJRkrFq1yrj88ssNf39/w9fX17jooouM//73vxXOM2nSJKNnz55Gs2bNDG9vb6Nt27bGQw89ZGRkZBiGYRhpaWnGmDFjjE6dOhn+/v5GQECA0a1bN+Pf//63UVpaasZTBwAAcBvDhg0zvLy8TtmhcsSIEYaHh4eRmppq7Nu3z7jzzjuNqKgow9PT02jZsqVxyy23GGlpaa79jxw5Yjz44INGmzZtDE9PT6N58+bG1VdfbWzfvt21T0pKinHTTTcZoaGhRnBwsHHbbbcZGzdurLILp7+/f5V1bd261bjiiiuMwMBAo1mzZsbNN99sJCcnG5KMp59+utK+N998sxEWFmZ4eXkZbdq0McaMGWMUFhZWOu+ll15qhIaGGvn5+dX8LgJwRxbDMAzT0jsAAAAAABqp9PR0RUdH629/+5tmzJhhdjkAzgBTOAEAAAAAqEP79+/X7t279cILL8hqterBBx80uyQAZ4gmAgAAAAAA1KE333xTl156qf78808tXrxY55xzjtklAThDTOEEAAAAAAAAToERaAAAAAAAAMApEKABAAAAAAAAp0CABgAAAAAAAJxCk+rC6XA4dPDgQQUGBspisZhdDgAAaAAMw1BOTo5atmwpq5XPHt0V7/MAAEBN1eR9XpMK0A4ePKjWrVubXQYAAGiA9u3bp1atWpldBk6C93kAAKC2qvM+r0kFaIGBgZKc35igoCCTqwEAAA1Bdna2Wrdu7XofAffE+zwAAFBTNXmf16QCtPLh/EFBQbyxAgAANcK0QPfG+zwAAFBb1Xmfx0IeAAAAAAAAwCkQoAEAAAAAAACnQIAGAAAAAAAAnEKTWgMNAIC6ZhiGSktLZbfbzS4FtWSz2eTh4cEaZ02A3W5XSUmJ2WWgEeHfDwBoOgjQAACopeLiYqWkpCg/P9/sUnCG/Pz81KJFC3l5eZldCs6S3Nxc7d+/X4ZhmF0KGhn+/QCApoEADQCAWnA4HEpKSpLNZlPLli3l5eXFCIQGyDAMFRcX69ChQ0pKSlKHDh1ktbLCRWNjt9u1f/9++fn5KSIigtcq6gT/fgBA00KABgBALRQXF8vhcKh169by8/MzuxycAV9fX3l6emrv3r0qLi6Wj4+P2SWhjpWUlMgwDEVERMjX19fsctCI8O8HADQdfEQCAMAZYLRB48DPsWlg5BnOBv79AICmgX/tAQAAAAAAgFMgQAMAAAAAAABOgQANAADUWkxMjGbNmlUn51q5cqUsFouOHj1aJ+cDcExdvlYBAGiKaCIAAEATc+mll+q8886rk1+mf/75Z/n7+595UQAq4bUKAID7IEADAAAVGIYhu90uD4/Tv02IiIioh4oAVIXX6jHFxcXy8vIyuwwAQCPGFE4AAOqAYRjKLy415WYYRrXrHDNmjH744Qe99NJLslgsslgseuutt2SxWPTVV1+pZ8+e8vb21qpVq7Rr1y5dd911ioyMVEBAgC688EJ98803Fc534rQwi8WiN998U9dff738/PzUoUMHffbZZ7X+vn788cc699xz5e3trZiYGP3rX/+q8PicOXPUoUMH+fj4KDIyUjfddJPrsY8++khdu3aVr6+vwsLCNGjQIOXl5dW6FjQeDeH16s6vVbvdrrFjxyo2Nla+vr7q2LGjXnrppUr7LViwwPX6bdGihe6//37XY0ePHtXdd9+tyMhI+fj4KD4+Xv/73/8kSVOmTNF5551X4VyzZs1STExMhe/PsGHDNH36dLVs2VJxcXGSpHfffVc9e/ZUYGCgoqKidOuttyo9Pb3Cuf78809dffXVCgoKUmBgoPr3769du3bpxx9/lKenp1JTUyvs//DDD+uSSy6p1vcGANB4MQINAIA6UFBiV5envjLl2lunXSk/r+r9l/7SSy8pISFB8fHxmjZtmiTnL5OS9Pe//10vvvii2rZtq5CQEO3fv19XXXWVnn32Wfn4+Ojtt9/W0KFDtWPHDrVp0+ak15g6dapmzJihF154QbNnz9Zf//pX7d27V6GhoTV6Xps2bdItt9yiKVOmaPjw4Vq7dq3uvfdehYWFacyYMdq4caMeeOABvfPOO+rbt68OHz6sVatWSZJSUlI0cuRIzZgxQ9dff71ycnK0atWqGoWNaLwawuvVnV+rDodDrVq10gcffKDw8HCtXbtWd999t1q0aKFbbrlFkjR37lxNnDhR//znPzVkyBBlZWVpzZo1ruOHDBminJwcvfvuu2rXrp22bt0qm81Wre9huW+//VZBQUFasWKF67VdXFysZ555Rh07dlR6eroeeughjRkzRsuXL5ckHThwQJdccokuvfRSfffddwoKCtKaNWtUWlqqSy65RG3bttU777yjRx99VJJUWlqqd999V//85z9rVBsAoPEhQAMAoAkJDg6Wl5eX/Pz8FBUVJUnavn27JGnatGm64oorXPuGhYWpe/furvvPPvusPvnkE3322WcVRpKcaMyYMRo5cqQk6bnnntPs2bO1YcMG/eUvf6lRrTNnztTAgQP15JNPSpLi4uK0detWvfDCCxozZoySk5Pl7++va665RoGBgYqOjtb5558vyRmglZaW6oYbblB0dLQkqWvXrjW6PmAmd36tenp6aurUqa77sbGxWrt2rT744ANXgPbss8/q4Ycf1oMPPuja78ILL5QkffPNN9qwYYO2bdvmGjnWtm3b039TTuDv768333yzwtTNO++80/V127Zt9fLLL6tXr17Kzc1VQECAXn31VQUHB+v999+Xp6enJLlqkKSxY8dq4cKFrgDt888/V35+vut5AQCaLgI0AADqgK+nTVunXWnatetCz549K9zPy8vT1KlT9b///U8HDx5UaWmpCgoKlJycfMrzdOvWzfW1v7+/AgMDK02hqo5t27bpuuuuq7CtX79+mjVrlux2u6644gpFR0erbdu2+stf/qK//OUvrulo3bt318CBA9W1a1ddeeWVGjx4sG666SY1a9asxnWg8Wnor1d3eK2+9tprevPNN7V3714VFBSouLjYNe0yPT1dBw8e1MCBA6s8dsuWLWrVqlWF4Ko2unbtWmnds82bN2vKlCnasmWLDh8+LIfDIUlKTk5Wly5dtGXLFvXv398Vnp1ozJgxeuKJJ7Ru3TpddNFFWrBggW655RYaMAAACNAAAKgLFoul2tMo3dWJvyA++uij+uqrr/Tiiy+qffv28vX11U033aTi4uJTnufEX0wtFovrl9iaMAxDFoul0rZygYGB+uWXX7Ry5Up9/fXXeuqppzRlyhT9/PPPCgkJ0YoVK7R27Vp9/fXXmj17th5//HGtX79esbGxNa4FjUtDf72a/Vr94IMP9NBDD+lf//qX+vTpo8DAQL3wwgtav369JMnX1/eUx5/ucavVWmm6dUlJSaX9Tvw+5OXlafDgwRo8eLDeffddRUREKDk5WVdeeaXre3G6azdv3lxDhw7VwoUL1bZtWy1fvlwrV6485TEAgKaBJgIAADQxXl5estvtp91v1apVGjNmjK6//np17dpVUVFR2rNnz9kvsEyXLl20evXqCtvWrl2ruLg411pJHh4eGjRokGbMmKHffvtNe/bs0XfffSfJGQb069dPU6dO1ebNm+Xl5aVPPvmk3uoHzpS7vlZXrVqlvn376t5779X555+v9u3ba9euXa7HAwMDFRMTo2+//bbK47t166b9+/crISGhyscjIiKUmppaIUTbsmXLaevavn27MjIy9M9//lP9+/dXp06dKo2o69atm1atWlVlIFdu3Lhxev/99/X666+rXbt26tev32mvDQBo/AjQAABoYmJiYrR+/Xrt2bNHGRkZJx1x0r59ey1btkxbtmzRr7/+qltvvbVWI8lq6+GHH9a3336rZ555RgkJCXr77bf1yiuv6JFHHpEk/e9//9PLL7+sLVu2aO/evVq0aJEcDoc6duyo9evX67nnntPGjRuVnJysZcuW6dChQ+rcuXO91Q+cKXd9rbZv314bN27UV199pYSEBD355JP6+eefK+wzZcoU/etf/9LLL7+sxMRE/fLLL5o9e7YkacCAAbrkkkt04403asWKFUpKStIXX3yhL7/8UpJ06aWX6tChQ5oxY4Z27dqlV199VV988cVp62rTpo28vLw0e/Zs7d69W5999pmeeeaZCvvcf//9ys7O1ogRI7Rx40YlJibqnXfe0Y4dO1z7XHnllQoODtazzz6rO+6440y/XQCARoIArY58vGm//jLrR834crvZpQAAcEqPPPKIbDabunTp4priVJV///vfatasmfr27auhQ4fqyiuv1AUXXFBvdV5wwQX64IMP9P777ys+Pl5PPfWUpk2bpjFjxkiSQkJCtGzZMl1++eXq3LmzXnvtNS1ZskTnnnuugoKC9OOPP+qqq65SXFycnnjiCf3rX//SkCFD6q1+4Ey562t1/PjxuuGGGzR8+HD17t1bmZmZuvfeeyvsc/vtt2vWrFmaM2eOzj33XF1zzTVKTEx0Pf7xxx/rwgsv1MiRI9WlSxf9/e9/d42269y5s+bMmaNXX31V3bt314YNG1zB+alERETorbfe0ocffqguXbron//8p1588cUK+4SFhem7775Tbm6uBgwYoB49emjevHkVprNarVaNGTNGdrtdo0ePPpNvFdAwlRZJKb9Km9+VvnhMWni19NY10v8mSuvfkHavlLJTJDpbo4mxGE2on3t2draCg4OVlZWloKCgOj33kg3Jmrzsd10SF6FFd/aq03MDANxPYWGhkpKSFBsbKx8fH7PLwRk61c/zbL5/QN051c+J1ytq6q677lJaWpo+++yz0+7L3y80aAVHpNTfK94ObZccpac/1jtYioiTwjtKEWW38DgpJFqyMlYHDUNN3uc13NVT3UxcZIAkKSE1x+RKAAAAANRGVlaWfv75Zy1evFj/+c9/zC4HqDuGIR1NrhyWZZ2kW69PiBTVVYrqJkXFS7JIGTukQ2W3I0lSUZa0/2fn7XgevlJ4+7JgrdOxkC20reThVdXVgAaBAK2OdIgMlCSlZhcqq6BEwb5Vt8YGAKCpGj9+vN59990qH7vtttv02muv1XNFAKrSlF+r1113nTZs2KB7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4403Vthn/vz5at68ubZu3ar4+Hi99957OnTokH7++WdXUNi+/bH1t8aNG6fx48dr5syZ8vb21q+//qotW7Zo2bJlNa6vUTIMaf/PzjXN/vxUyj1u0IJfmNRlmDM0a9NHsrrf72QAaulkQdqeVVL0xc6pnU04SKtxgDZz5kyNHTtW48aNkyTNmjVLX331lebOnavp06ef9Lh77rlHt956q2w2W6WFS0/89Ov999+Xn59fpQDNw8OjRv/hFxUVqajoWEuU7Ozsah97JjpGBmpneq4S03J1acfm9XJNAIDJPP2cI0vMuvYZ2LRpk77//nsFBFRez2XXrl0aPHiwBg4cqK5du+rKK6/U4MGDddNNN6lZs2ZndN1y27ZtU58+fSqM+ujXr59yc3O1f/9+de/e/aTXDw0N1ZgxY3TllVfqiiuu0KBBg3TLLbeoRYsWdVIbGqkG+no147X60UcfadasWdq5c6croAsKCnI9vmXLFt11111VHrtlyxbZbDYNGDCg1teXpOjo6ArhmeR8vk8++aTWrVunjIwMORwOSVJycrJrtsv5559/0lF2w4YN0/33369PPvlEI0aM0IIFC3TZZZcpJibmjGpt0AxDStniXNPsz0+krH3HHvMJljoPda5rFnOJcx0wAI2XK0gr79r5trR3tfT2NU06SKvRGmjFxcXatGmTBg8eXGH74MGDtXbt2pMet3DhQu3atUtPP/10ta4zf/58jRgxQv7+FYe3JyYmqmXLloqNjdWIESO0e/fuU55n+vTpCg4Odt1at25dreufqfJGAjtoJAAATYfF4pyWZcbtDKfMOBwODR06VFu2bKlwS0xM1CWXXCKbzaYVK1boiy++UJcuXTR79mx17NhRSUlJdfKtMwyj0pSp8jWILBbLaa+/cOFC/fTTT+rbt6+WLl2quLg4rVu3rk5qQyPVQF+v9f1aXbdunUaMGKEhQ4bof//7nzZv3qzHH3+8wswRX9+Tz7Y41WOSZLVaK603duL6apIq/U4gSUOHDlVmZqbmzZun9evXa/369ZLkqu101/by8tKoUaO0cOFCFRcX67333tOdd955ymMarbSt0rfPSLMvkN64VFr7sjM88wqQug2XRi6VHtkpXfeq1O5ywjOgKQk+R7r6RemBLdKFdznXSCsP0hZeLSWtMrvCelWjAC0jI0N2u12RkZEVtp9qLbLE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ALQ3jPMAuDLWQAPgUTZs2HDK/V69ekmS+vTpo5SUFJWUlDgfX7t2raxWq8477zwFBQWpa9eu+uqrr86pho4dO2ratGl666239Mwzz2jhwoXn9HoAAABgnAfAXHSgAXAr5eXlysrKanDOy8vLuYDrBx98oCFDhmjkyJF6++23tXHjRr388suSpFtvvVWPPPKIpk6dqrlz5yo3N1f333+/pkyZoqioKEnS3LlzNX36dEVGRmrcuHEqKirS2rVrdf/9959RfX/84x+VnJysvn37qry8XJ9++ql69+7dgv8EAAAAPBPjPACujAANgFv5/PPPFRMT0+Bcz5499eOPP0oydk5677339Otf/1rR0dF6++231adPH0mSv7+/vvjiC/32t7/V+eefL39/f11//fX6+9//7nytqVOnqqysTE8//bR+97vfKSIiQjfccMMZ1+fj46PZs2dr37598vPz06hRo/Tee++1wCcHAADwbIzzALgyi8PhcJhdBAC0BIvFoo8//liTJk0yuxQAAAC0IMZ5AMzGGmgAAAAAAABAEwjQAAAAAAAAgCYwhRMAAAAAAABoAh1oAAAAAAAAQBMI0AAAAAAAAIAmEKABAAAAAAAATSBAAwAAAAAAAJpAgAYAAAAAAAA0gQANAAAAAAAAaAIBGgAAAAAAANAEAjQAAAAAAACgCf8fqaqlmRyQnfUAAAAASUVORK5CYII=",998      "text/plain": [999       "<Figure size 1500x700 with 2 Axes>"1000      ]1001     },1002     "metadata": {},1003     "output_type": "display_data"1004    }1005   ],1006   "source": [1007    "from helper_functions import plot_loss_curves\n",1008    "\n",1009    "# Check out the loss curves for FoodVision Big\n",1010    "plot_loss_curves(results)"1011   ]1012  },1013  {1014   "cell_type": "code",1015   "execution_count": 81,1016   "id": "bfdbbf8b-99a4-4408-a939-1f965e485554",1017   "metadata": {1018    "scrolled": true1019   },1020   "outputs": [1021    {1022     "data": {1023      "application/vnd.jupyter.widget-view+json": {1024       "model_id": "bb08d09334044e9097a9f1b2f5c69c4c",1025       "version_major": 2,1026       "version_minor": 01027      },1028      "text/plain": [1029       "  0%|          | 0/10 [00:00<?, ?it/s]"1030      ]1031     },1032     "metadata": {},1033     "output_type": "display_data"1034    },1035    {1036     "name": "stdout",1037     "output_type": "stream",1038     "text": [1039      "Epoch 1/10: Train Loss: 0.4794, Train Acc: 0.7721, Test Loss: 0.3494, Test Acc: 0.8460\n",1040      "Epoch 2/10: Train Loss: 0.3759, Train Acc: 0.8349, Test Loss: 0.3332, Test Acc: 0.8559\n",1041      "Epoch 3/10: Train Loss: 0.3585, Train Acc: 0.8441, Test Loss: 0.3362, Test Acc: 0.8518\n",1042      "Epoch 4/10: Train Loss: 0.3524, Train Acc: 0.8448, Test Loss: 0.3204, Test Acc: 0.8631\n",1043      "Epoch 5/10: Train Loss: 0.3477, Train Acc: 0.8471, Test Loss: 0.3172, Test Acc: 0.8646\n",1044      "Epoch 6/10: Train Loss: 0.3461, Train Acc: 0.8518, Test Loss: 0.3134, Test Acc: 0.8666\n",1045      "Epoch 7/10: Train Loss: 0.3436, Train Acc: 0.8511, Test Loss: 0.3116, Test Acc: 0.8665\n",1046      "Epoch 8/10: Train Loss: 0.3421, Train Acc: 0.8524, Test Loss: 0.3161, Test Acc: 0.8638\n",1047      "Epoch 9/10: Train Loss: 0.3404, Train Acc: 0.8516, Test Loss: 0.3093, Test Acc: 0.8686\n",1048      "Epoch 10/10: Train Loss: 0.3363, Train Acc: 0.8540, Test Loss: 0.3072, Test Acc: 0.8692\n"1049     ]1050    },1051    {1052     "data": {1053      "text/plain": [1054       "{'train_loss': [0.47936061399816626,\n",1055       "  0.37587976564849257,\n",1056       "  0.35846220623279945,\n",1057       "  0.3523591070823843,\n",1058       "  0.3476913379063152,\n",1059       "  0.34606650885449564,\n",1060       "  0.343617077671368,\n",1061       "  0.34210375884949434,\n",1062       "  0.34043249162777983,\n",1063       "  0.33634180508396677],\n",1064       " 'train_acc': [0.7720729366602687,\n",1065       "  0.8348928342930262,\n",1066       "  0.8441298784388995,\n",1067       "  0.8448096609085093,\n",1068       "  0.8471289187460013,\n",1069       "  0.8517674344209852,\n",1070       "  0.8511276391554703,\n",1071       "  0.8523672424824056,\n",1072       "  0.8516074856046065,\n",1073       "  0.8539667306461932],\n",1074       " 'test_loss': [0.3494455436815437,\n",1075       "  0.3331892572591226,\n",1076       "  0.33621524078193493,\n",1077       "  0.32035365790815135,\n",1078       "  0.3172186358586926,\n",1079       "  0.3134111074792723,\n",1080       "  0.31162461833414634,\n",1081       "  0.3160502322462655,\n",1082       "  0.30929588019831183,\n",1083       "  0.3072231247430037],\n",1084       " 'test_acc': [0.8460492642354447,\n",1085       "  0.8558861164427384,\n",1086       "  0.8518074216250799,\n",1087       "  0.8630838131797824,\n",1088       "  0.8646433141394754,\n",1089       "  0.8666026871401151,\n",1090       "  0.8664827255278311,\n",1091       "  0.8637635956493922,\n",1092       "  0.868562060140755,\n",1093       "  0.8691618682021753]}"1094      ]1095     },1096     "execution_count": 81,1097     "metadata": {},1098     "output_type": "execute_result"1099    }1100   ],1101   "source": [1102    "# train(DistilBERT_Model,\n",1103    "#       train_loader,\n",1104    "#       test_loader,\n",1105    "#       optimizer,\n",1106    "#       10,  # Number of epochs\n",1107    "#       device)  # Pass the device (e.g., torch.device(\"cuda\"))"1108   ]1109  },1110  {1111   "cell_type": "code",1112   "execution_count": 111,1113   "id": "b6f950c3-04c4-433a-a9dc-f453d4ab1170",1114   "metadata": {},1115   "outputs": [1116    {1117     "name": "stdout",1118     "output_type": "stream",1119     "text": [1120      "[INFO] Saving model to: models\\DistilBERT_Model_512_Ver2.pth\n"1121     ]1122    }1123   ],1124   "source": [1125    "from going_modular import utils\n",1126    "\n",1127    "# Create a model path\n",1128    "DistilBERT_Model_512_path_Ver2 = \"DistilBERT_Model_512_Ver2.pth\" \n",1129    "\n",1130    "# Save FoodVision Big model\n",1131    "utils.save_model(model=DistilBERT_Model,\n",1132    "                 target_dir=\"models\",\n",1133    "                 model_name=DistilBERT_Model_512_path_Ver2)"1134   ]1135  },1136  {1137   "cell_type": "code",1138   "execution_count": 113,1139   "id": "f7bd7fba-7d7d-4d49-aceb-53b3ecc95a9f",1140   "metadata": {},1141   "outputs": [1142    {1143     "name": "stdout",1144     "output_type": "stream",1145     "text": [1146      "Pretrained DistilBERT Model 512 model size: 256 MB\n"1147     ]1148    }1149   ],1150   "source": [1151    "from pathlib import Path\n",1152    "\n",1153    "DistilBERT_Model_512_path = \"DistilBERT_Model_512.pth\" \n",1154    "\n",1155    "# Get the model size in bytes then convert to megabytes\n",1156    "pretrained_DistilBERT_Model_512_model_size = Path(\"models\", DistilBERT_Model_512_path).stat().st_size // (1024*1024) # division converts bytes to megabytes (roughly) \n",1157    "print(f\"Pretrained DistilBERT Model 512 model size: {pretrained_DistilBERT_Model_512_model_size} MB\")"1158   ]1159  },1160  {1161   "cell_type": "markdown",1162   "id": "05cea55f-d4dc-4a55-8156-88e4a4f7bd5d",1163   "metadata": {},1164   "source": [1165    "# 測試"1166   ]1167  },1168  {1169   "cell_type": "code",1170   "execution_count": 5,1171   "id": "e30c78c4-fc8c-4957-911b-daf8ba66e8b7",1172   "metadata": {},1173   "outputs": [1174    {1175     "name": "stderr",1176     "output_type": "stream",1177     "text": [1178      "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']\n",1179      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"1180     ]1181    }1182   ],1183   "source": [1184    "DistilBERT_Model, DistilBERT_Tokenizer = create_distilbert_model(num_classes=2, seed=42)"1185   ]1186  },1187  {1188   "cell_type": "code",1189   "execution_count": 6,1190   "id": "6ba528fd-fe06-4b6f-a8f4-f966a2d941e2",1191   "metadata": {},1192   "outputs": [1193    {1194     "name": "stderr",1195     "output_type": "stream",1196     "text": [1197      "C:\\Users\\User\\AppData\\Local\\Temp\\ipykernel_15788\\2750169500.py:4: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",1198      "  torch.load(\n"1199     ]1200    },

Showing the first 1,200 of 1485 lines. Download the file for the rest.