|
a |
|
b/fine-tune.ipynb |
|
|
1 |
{ |
|
|
2 |
"cells": [ |
|
|
3 |
{ |
|
|
4 |
"cell_type": "markdown", |
|
|
5 |
"id": "6614ed41-7f65-4495-aa3d-8fba22013597", |
|
|
6 |
"metadata": {}, |
|
|
7 |
"source": [ |
|
|
8 |
"Different learning rates, number of epochs, and batch sizes were explored, but the results did not change much." |
|
|
9 |
] |
|
|
10 |
}, |
|
|
11 |
{ |
|
|
12 |
"cell_type": "code", |
|
|
13 |
"execution_count": 1, |
|
|
14 |
"id": "9bff167f-c177-4f9f-9408-bd499f2d63e8", |
|
|
15 |
"metadata": {}, |
|
|
16 |
"outputs": [], |
|
|
17 |
"source": [ |
|
|
18 |
"import pandas as pd\n", |
|
|
19 |
"import numpy as np\n", |
|
|
20 |
"import torch\n", |
|
|
21 |
"from sklearn.model_selection import train_test_split\n", |
|
|
22 |
"from torch.utils.data import TensorDataset, DataLoader\n", |
|
|
23 |
"from transformers import AutoTokenizer, AutoModelForSequenceClassification\n", |
|
|
24 |
"from tqdm import tqdm\n", |
|
|
25 |
"import torch.nn as nn" |
|
|
26 |
] |
|
|
27 |
}, |
|
|
28 |
{ |
|
|
29 |
"cell_type": "code", |
|
|
30 |
"execution_count": 2, |
|
|
31 |
"id": "c1d30e92-0aea-498c-8d3f-d8b24cf4aeeb", |
|
|
32 |
"metadata": {}, |
|
|
33 |
"outputs": [ |
|
|
34 |
{ |
|
|
35 |
"name": "stdout", |
|
|
36 |
"output_type": "stream", |
|
|
37 |
"text": [ |
|
|
38 |
"Number of examples is: 560\n" |
|
|
39 |
] |
|
|
40 |
}, |
|
|
41 |
{ |
|
|
42 |
"data": { |
|
|
43 |
"text/html": [ |
|
|
44 |
"<div>\n", |
|
|
45 |
"<style scoped>\n", |
|
|
46 |
" .dataframe tbody tr th:only-of-type {\n", |
|
|
47 |
" vertical-align: middle;\n", |
|
|
48 |
" }\n", |
|
|
49 |
"\n", |
|
|
50 |
" .dataframe tbody tr th {\n", |
|
|
51 |
" vertical-align: top;\n", |
|
|
52 |
" }\n", |
|
|
53 |
"\n", |
|
|
54 |
" .dataframe thead th {\n", |
|
|
55 |
" text-align: right;\n", |
|
|
56 |
" }\n", |
|
|
57 |
"</style>\n", |
|
|
58 |
"<table border=\"1\" class=\"dataframe\">\n", |
|
|
59 |
" <thead>\n", |
|
|
60 |
" <tr style=\"text-align: right;\">\n", |
|
|
61 |
" <th></th>\n", |
|
|
62 |
" <th>CANONICAL_SMILES</th>\n", |
|
|
63 |
" <th>pIC50</th>\n", |
|
|
64 |
" </tr>\n", |
|
|
65 |
" </thead>\n", |
|
|
66 |
" <tbody>\n", |
|
|
67 |
" <tr>\n", |
|
|
68 |
" <th>0</th>\n", |
|
|
69 |
" <td>Nc1nc(N)c2c(Sc3ccccc3)cccc2n1</td>\n", |
|
|
70 |
" <td>6.21</td>\n", |
|
|
71 |
" </tr>\n", |
|
|
72 |
" <tr>\n", |
|
|
73 |
" <th>1</th>\n", |
|
|
74 |
" <td>COc1ccc(OC)c(Cc2sc3nc(N)nc(N)c3c2C)c1</td>\n", |
|
|
75 |
" <td>6.14</td>\n", |
|
|
76 |
" </tr>\n", |
|
|
77 |
" <tr>\n", |
|
|
78 |
" <th>2</th>\n", |
|
|
79 |
" <td>CN(Cc1coc2nc(N)nc(N)c12)c3ccc(cc3)C(=O)N[C@@H]...</td>\n", |
|
|
80 |
" <td>6.66</td>\n", |
|
|
81 |
" </tr>\n", |
|
|
82 |
" <tr>\n", |
|
|
83 |
" <th>3</th>\n", |
|
|
84 |
" <td>Nc1nc(N)c2nc(CSc3ccc(cc3)C(=O)NC(CCC(=O)O)C(=O...</td>\n", |
|
|
85 |
" <td>5.57</td>\n", |
|
|
86 |
" </tr>\n", |
|
|
87 |
" <tr>\n", |
|
|
88 |
" <th>4</th>\n", |
|
|
89 |
" <td>Nc1nc(N)c2nc(CCSc3ccc(cc3)C(=O)NC(CCC(=O)O)C(=...</td>\n", |
|
|
90 |
" <td>4.60</td>\n", |
|
|
91 |
" </tr>\n", |
|
|
92 |
" </tbody>\n", |
|
|
93 |
"</table>\n", |
|
|
94 |
"</div>" |
|
|
95 |
], |
|
|
96 |
"text/plain": [ |
|
|
97 |
" CANONICAL_SMILES pIC50\n", |
|
|
98 |
"0 Nc1nc(N)c2c(Sc3ccccc3)cccc2n1 6.21\n", |
|
|
99 |
"1 COc1ccc(OC)c(Cc2sc3nc(N)nc(N)c3c2C)c1 6.14\n", |
|
|
100 |
"2 CN(Cc1coc2nc(N)nc(N)c12)c3ccc(cc3)C(=O)N[C@@H]... 6.66\n", |
|
|
101 |
"3 Nc1nc(N)c2nc(CSc3ccc(cc3)C(=O)NC(CCC(=O)O)C(=O... 5.57\n", |
|
|
102 |
"4 Nc1nc(N)c2nc(CCSc3ccc(cc3)C(=O)NC(CCC(=O)O)C(=... 4.60" |
|
|
103 |
] |
|
|
104 |
}, |
|
|
105 |
"execution_count": 2, |
|
|
106 |
"metadata": {}, |
|
|
107 |
"output_type": "execute_result" |
|
|
108 |
} |
|
|
109 |
], |
|
|
110 |
"source": [ |
|
|
111 |
"# Load the dataset\n", |
|
|
112 |
"df = pd.read_csv(\"data/hDHFR_pIC50_data.csv\")[[\"CANONICAL_SMILES\", \"pIC50\"]]\n", |
|
|
113 |
"print(f'Number of examples is: {len(df)}')\n", |
|
|
114 |
"df.head()" |
|
|
115 |
] |
|
|
116 |
}, |
|
|
117 |
{ |
|
|
118 |
"cell_type": "code", |
|
|
119 |
"execution_count": 3, |
|
|
120 |
"id": "04851bc1-5707-4bd5-b39d-0d5d618dd116", |
|
|
121 |
"metadata": {}, |
|
|
122 |
"outputs": [ |
|
|
123 |
{ |
|
|
124 |
"name": "stderr", |
|
|
125 |
"output_type": "stream", |
|
|
126 |
"text": [ |
|
|
127 |
"Some weights of RobertaForSequenceClassification were not initialized from the model checkpoint at DeepChem/ChemBERTa-77M-MLM and are newly initialized: ['classifier.dense.weight', 'classifier.out_proj.bias', 'classifier.out_proj.weight', 'classifier.dense.bias']\n", |
|
|
128 |
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" |
|
|
129 |
] |
|
|
130 |
}, |
|
|
131 |
{ |
|
|
132 |
"name": "stdout", |
|
|
133 |
"output_type": "stream", |
|
|
134 |
"text": [ |
|
|
135 |
"512\n" |
|
|
136 |
] |
|
|
137 |
} |
|
|
138 |
], |
|
|
139 |
"source": [ |
|
|
140 |
"# Load the pre-trained model and tokenizer\n", |
|
|
141 |
"model_name = \"DeepChem/ChemBERTa-77M-MLM\"\n", |
|
|
142 |
"model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=1)\n", |
|
|
143 |
"tokenizer = AutoTokenizer.from_pretrained(model_name)\n", |
|
|
144 |
"\n", |
|
|
145 |
"# Determine the maximum sequence length\n", |
|
|
146 |
"max_length = tokenizer.model_max_length\n", |
|
|
147 |
"print(max_length)" |
|
|
148 |
] |
|
|
149 |
}, |
|
|
150 |
{ |
|
|
151 |
"cell_type": "code", |
|
|
152 |
"execution_count": 4, |
|
|
153 |
"id": "755634da-6e15-46c3-a9d2-fdc7bd2aa75e", |
|
|
154 |
"metadata": {}, |
|
|
155 |
"outputs": [ |
|
|
156 |
{ |
|
|
157 |
"name": "stderr", |
|
|
158 |
"output_type": "stream", |
|
|
159 |
"text": [ |
|
|
160 |
"100%|██████████████████████████████████████| 560/560 [00:00<00:00, 15447.41it/s]\n" |
|
|
161 |
] |
|
|
162 |
} |
|
|
163 |
], |
|
|
164 |
"source": [ |
|
|
165 |
"# Tokenization function\n", |
|
|
166 |
"def tokenize(string):\n", |
|
|
167 |
" \"\"\"\n", |
|
|
168 |
" Tokenize and encode a string using the provided tokenizer.\n", |
|
|
169 |
" \n", |
|
|
170 |
" Parameters:\n", |
|
|
171 |
" string (str): Input string to be tokenized.\n", |
|
|
172 |
" \n", |
|
|
173 |
" Returns:\n", |
|
|
174 |
" Tuple of input_ids and attention_mask.\n", |
|
|
175 |
" \"\"\"\n", |
|
|
176 |
" encodings = tokenizer.encode_plus(\n", |
|
|
177 |
" string,\n", |
|
|
178 |
" add_special_tokens=True,\n", |
|
|
179 |
" truncation=True,\n", |
|
|
180 |
" padding=\"max_length\",\n", |
|
|
181 |
" max_length=max_length,\n", |
|
|
182 |
" return_attention_mask=True\n", |
|
|
183 |
" )\n", |
|
|
184 |
" input_ids = encodings[\"input_ids\"]\n", |
|
|
185 |
" attention_mask = encodings[\"attention_mask\"]\n", |
|
|
186 |
" return input_ids, attention_mask\n", |
|
|
187 |
"\n", |
|
|
188 |
"# Tokenize the 'CANONICAL_SMILES' column and create new columns 'input_ids' and 'attention_mask'\n", |
|
|
189 |
"tqdm.pandas()\n", |
|
|
190 |
"df[[\"input_ids\", \"attention_mask\"]] = df[\"CANONICAL_SMILES\"].progress_apply(lambda x: tokenize(x)).apply(pd.Series)" |
|
|
191 |
] |
|
|
192 |
}, |
|
|
193 |
{ |
|
|
194 |
"cell_type": "code", |
|
|
195 |
"execution_count": 5, |
|
|
196 |
"id": "63fade54-27fa-4ff1-af69-ea8d96c4ec1d", |
|
|
197 |
"metadata": {}, |
|
|
198 |
"outputs": [ |
|
|
199 |
{ |
|
|
200 |
"name": "stdout", |
|
|
201 |
"output_type": "stream", |
|
|
202 |
"text": [ |
|
|
203 |
"There are 448 molecules in Train df.\n", |
|
|
204 |
"There are 56 molecules in Val df.\n", |
|
|
205 |
"There are 56 molecules in Test df.\n" |
|
|
206 |
] |
|
|
207 |
} |
|
|
208 |
], |
|
|
209 |
"source": [ |
|
|
210 |
"# Split the dataset into train, validation, and test sets\n", |
|
|
211 |
"train_df, temp_df = train_test_split(df, test_size=0.2, random_state=21)\n", |
|
|
212 |
"val_df, test_df = train_test_split(temp_df, test_size=0.5, random_state=21)\n", |
|
|
213 |
"print(f\"There are {len(train_df)} molecules in Train df.\")\n", |
|
|
214 |
"print(f\"There are {len(val_df)} molecules in Val df.\")\n", |
|
|
215 |
"print(f\"There are {len(test_df)} molecules in Test df.\")" |
|
|
216 |
] |
|
|
217 |
}, |
|
|
218 |
{ |
|
|
219 |
"cell_type": "code", |
|
|
220 |
"execution_count": 6, |
|
|
221 |
"id": "a7d9638c-b3fc-4063-8ea8-a1303178466f", |
|
|
222 |
"metadata": {}, |
|
|
223 |
"outputs": [], |
|
|
224 |
"source": [ |
|
|
225 |
"# Function to convert data to PyTorch tensors\n", |
|
|
226 |
"def get_tensor_data(data):\n", |
|
|
227 |
" \"\"\"\n", |
|
|
228 |
" Convert data to PyTorch tensors.\n", |
|
|
229 |
" \n", |
|
|
230 |
" Parameters:\n", |
|
|
231 |
" data (DataFrame): Input data containing 'input_ids', 'attention_mask', and 'pIC50' columns.\n", |
|
|
232 |
" \n", |
|
|
233 |
" Returns:\n", |
|
|
234 |
" TensorDataset containing input_ids, attention_mask, and labels tensors.\n", |
|
|
235 |
" \"\"\"\n", |
|
|
236 |
" input_ids_tensor = torch.tensor(data[\"input_ids\"].tolist(), dtype=torch.int32)\n", |
|
|
237 |
" attention_mask_tensor = torch.tensor(data[\"attention_mask\"].tolist(), dtype=torch.int32)\n", |
|
|
238 |
" labels_tensor = torch.tensor(data[\"pIC50\"].tolist(), dtype=torch.float32)\n", |
|
|
239 |
" return TensorDataset(input_ids_tensor, attention_mask_tensor, labels_tensor)\n", |
|
|
240 |
"\n", |
|
|
241 |
"# Create datasets and data loaders\n", |
|
|
242 |
"train_dataset = get_tensor_data(train_df)\n", |
|
|
243 |
"val_dataset = get_tensor_data(val_df)\n", |
|
|
244 |
"test_dataset = get_tensor_data(test_df)\n", |
|
|
245 |
"\n", |
|
|
246 |
"batch_size = 32\n", |
|
|
247 |
"train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n", |
|
|
248 |
"val_loader = DataLoader(val_dataset, batch_size=batch_size)\n", |
|
|
249 |
"test_loader = DataLoader(test_dataset, batch_size=batch_size)" |
|
|
250 |
] |
|
|
251 |
}, |
|
|
252 |
{ |
|
|
253 |
"cell_type": "code", |
|
|
254 |
"execution_count": 7, |
|
|
255 |
"id": "6ebfebf6-b6db-4082-ab9a-70b79884014f", |
|
|
256 |
"metadata": {}, |
|
|
257 |
"outputs": [ |
|
|
258 |
{ |
|
|
259 |
"name": "stderr", |
|
|
260 |
"output_type": "stream", |
|
|
261 |
"text": [ |
|
|
262 |
" 10%|████▍ | 1/10 [00:04<00:37, 4.12s/it]" |
|
|
263 |
] |
|
|
264 |
}, |
|
|
265 |
{ |
|
|
266 |
"name": "stdout", |
|
|
267 |
"output_type": "stream", |
|
|
268 |
"text": [ |
|
|
269 |
"epoch 1: Train Loss 13.7115, Val Loss 3.4070\n" |
|
|
270 |
] |
|
|
271 |
}, |
|
|
272 |
{ |
|
|
273 |
"name": "stderr", |
|
|
274 |
"output_type": "stream", |
|
|
275 |
"text": [ |
|
|
276 |
" 20%|████████▊ | 2/10 [00:07<00:29, 3.68s/it]" |
|
|
277 |
] |
|
|
278 |
}, |
|
|
279 |
{ |
|
|
280 |
"name": "stdout", |
|
|
281 |
"output_type": "stream", |
|
|
282 |
"text": [ |
|
|
283 |
"epoch 2: Train Loss 1.8040, Val Loss 1.3049\n" |
|
|
284 |
] |
|
|
285 |
}, |
|
|
286 |
{ |
|
|
287 |
"name": "stderr", |
|
|
288 |
"output_type": "stream", |
|
|
289 |
"text": [ |
|
|
290 |
" 30%|█████████████▏ | 3/10 [00:10<00:24, 3.54s/it]" |
|
|
291 |
] |
|
|
292 |
}, |
|
|
293 |
{ |
|
|
294 |
"name": "stdout", |
|
|
295 |
"output_type": "stream", |
|
|
296 |
"text": [ |
|
|
297 |
"epoch 3: Train Loss 1.4318, Val Loss 1.2696\n" |
|
|
298 |
] |
|
|
299 |
}, |
|
|
300 |
{ |
|
|
301 |
"name": "stderr", |
|
|
302 |
"output_type": "stream", |
|
|
303 |
"text": [ |
|
|
304 |
" 40%|█████████████████▌ | 4/10 [00:14<00:20, 3.48s/it]" |
|
|
305 |
] |
|
|
306 |
}, |
|
|
307 |
{ |
|
|
308 |
"name": "stdout", |
|
|
309 |
"output_type": "stream", |
|
|
310 |
"text": [ |
|
|
311 |
"epoch 4: Train Loss 1.4239, Val Loss 1.2848\n" |
|
|
312 |
] |
|
|
313 |
}, |
|
|
314 |
{ |
|
|
315 |
"name": "stderr", |
|
|
316 |
"output_type": "stream", |
|
|
317 |
"text": [ |
|
|
318 |
" 50%|██████████████████████ | 5/10 [00:17<00:17, 3.44s/it]" |
|
|
319 |
] |
|
|
320 |
}, |
|
|
321 |
{ |
|
|
322 |
"name": "stdout", |
|
|
323 |
"output_type": "stream", |
|
|
324 |
"text": [ |
|
|
325 |
"epoch 5: Train Loss 1.4157, Val Loss 1.3262\n" |
|
|
326 |
] |
|
|
327 |
}, |
|
|
328 |
{ |
|
|
329 |
"name": "stderr", |
|
|
330 |
"output_type": "stream", |
|
|
331 |
"text": [ |
|
|
332 |
" 60%|██████████████████████████▍ | 6/10 [00:21<00:13, 3.42s/it]" |
|
|
333 |
] |
|
|
334 |
}, |
|
|
335 |
{ |
|
|
336 |
"name": "stdout", |
|
|
337 |
"output_type": "stream", |
|
|
338 |
"text": [ |
|
|
339 |
"epoch 6: Train Loss 1.3806, Val Loss 1.2986\n" |
|
|
340 |
] |
|
|
341 |
}, |
|
|
342 |
{ |
|
|
343 |
"name": "stderr", |
|
|
344 |
"output_type": "stream", |
|
|
345 |
"text": [ |
|
|
346 |
" 70%|██████████████████████████████▊ | 7/10 [00:24<00:10, 3.44s/it]" |
|
|
347 |
] |
|
|
348 |
}, |
|
|
349 |
{ |
|
|
350 |
"name": "stdout", |
|
|
351 |
"output_type": "stream", |
|
|
352 |
"text": [ |
|
|
353 |
"epoch 7: Train Loss 1.3577, Val Loss 1.2738\n" |
|
|
354 |
] |
|
|
355 |
}, |
|
|
356 |
{ |
|
|
357 |
"name": "stderr", |
|
|
358 |
"output_type": "stream", |
|
|
359 |
"text": [ |
|
|
360 |
" 80%|███████████████████████████████████▏ | 8/10 [00:27<00:06, 3.46s/it]" |
|
|
361 |
] |
|
|
362 |
}, |
|
|
363 |
{ |
|
|
364 |
"name": "stdout", |
|
|
365 |
"output_type": "stream", |
|
|
366 |
"text": [ |
|
|
367 |
"epoch 8: Train Loss 1.3578, Val Loss 1.2921\n" |
|
|
368 |
] |
|
|
369 |
}, |
|
|
370 |
{ |
|
|
371 |
"name": "stderr", |
|
|
372 |
"output_type": "stream", |
|
|
373 |
"text": [ |
|
|
374 |
" 90%|███████████████████████████████████████▌ | 9/10 [00:31<00:03, 3.47s/it]" |
|
|
375 |
] |
|
|
376 |
}, |
|
|
377 |
{ |
|
|
378 |
"name": "stdout", |
|
|
379 |
"output_type": "stream", |
|
|
380 |
"text": [ |
|
|
381 |
"epoch 9: Train Loss 1.3547, Val Loss 1.3023\n" |
|
|
382 |
] |
|
|
383 |
}, |
|
|
384 |
{ |
|
|
385 |
"name": "stderr", |
|
|
386 |
"output_type": "stream", |
|
|
387 |
"text": [ |
|
|
388 |
"100%|███████████████████████████████████████████| 10/10 [00:34<00:00, 3.49s/it]" |
|
|
389 |
] |
|
|
390 |
}, |
|
|
391 |
{ |
|
|
392 |
"name": "stdout", |
|
|
393 |
"output_type": "stream", |
|
|
394 |
"text": [ |
|
|
395 |
"epoch 10: Train Loss 1.3551, Val Loss 1.3414\n" |
|
|
396 |
] |
|
|
397 |
}, |
|
|
398 |
{ |
|
|
399 |
"name": "stderr", |
|
|
400 |
"output_type": "stream", |
|
|
401 |
"text": [ |
|
|
402 |
"\n" |
|
|
403 |
] |
|
|
404 |
} |
|
|
405 |
], |
|
|
406 |
"source": [ |
|
|
407 |
"# Loss criterion and optimizer\n", |
|
|
408 |
"criterion = nn.MSELoss()\n", |
|
|
409 |
"optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3)\n", |
|
|
410 |
"device = torch.device(\"mps\")\n", |
|
|
411 |
"model.to(device)\n", |
|
|
412 |
"\n", |
|
|
413 |
"epochs = 10\n", |
|
|
414 |
"torch.manual_seed(12345)\n", |
|
|
415 |
"for epoch in tqdm(range(epochs)):\n", |
|
|
416 |
" # Training loop\n", |
|
|
417 |
" model.train()\n", |
|
|
418 |
" total_train_loss = 0\n", |
|
|
419 |
" for batch in train_loader:\n", |
|
|
420 |
" optimizer.zero_grad(set_to_none=True)\n", |
|
|
421 |
" input_ids, attention_mask, labels = batch\n", |
|
|
422 |
" input_ids, attention_mask, labels = input_ids.to(device), attention_mask.to(device), labels.to(device)\n", |
|
|
423 |
" output_dict = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n", |
|
|
424 |
" predictions = output_dict.logits.squeeze(dim=1)\n", |
|
|
425 |
" loss = criterion(predictions, labels)\n", |
|
|
426 |
" loss.backward()\n", |
|
|
427 |
" optimizer.step()\n", |
|
|
428 |
" total_train_loss += loss.item()\n", |
|
|
429 |
" avg_train_loss = total_train_loss / len(train_loader)\n", |
|
|
430 |
"\n", |
|
|
431 |
" # Validation loop\n", |
|
|
432 |
" model.eval()\n", |
|
|
433 |
" total_val_loss = 0\n", |
|
|
434 |
" with torch.no_grad():\n", |
|
|
435 |
" for batch in val_loader:\n", |
|
|
436 |
" input_ids, attention_mask, labels = batch\n", |
|
|
437 |
" input_ids, attention_mask, labels = input_ids.to(device), attention_mask.to(device), labels.to(device)\n", |
|
|
438 |
" output_dict = model(input_ids, attention_mask=attention_mask, labels=labels)\n", |
|
|
439 |
" predictions = output_dict.logits.squeeze(dim=1)\n", |
|
|
440 |
" loss = criterion(predictions, labels)\n", |
|
|
441 |
" total_val_loss += loss.item()\n", |
|
|
442 |
" avg_val_loss = total_val_loss / len(val_loader)\n", |
|
|
443 |
" print(f\"epoch {epoch + 1}: Train Loss {avg_train_loss:.4f}, Val Loss {avg_val_loss:.4f}\")\n" |
|
|
444 |
] |
|
|
445 |
}, |
|
|
446 |
{ |
|
|
447 |
"cell_type": "code", |
|
|
448 |
"execution_count": 8, |
|
|
449 |
"id": "e15f9a1f-80de-4e97-bb52-03ce819f9ca4", |
|
|
450 |
"metadata": {}, |
|
|
451 |
"outputs": [ |
|
|
452 |
{ |
|
|
453 |
"name": "stdout", |
|
|
454 |
"output_type": "stream", |
|
|
455 |
"text": [ |
|
|
456 |
"Test Loss 1.4417\n" |
|
|
457 |
] |
|
|
458 |
} |
|
|
459 |
], |
|
|
460 |
"source": [ |
|
|
461 |
"# Testing loop\n", |
|
|
462 |
"total_test_loss = 0\n", |
|
|
463 |
"test_labels = []\n", |
|
|
464 |
"test_predictions = []\n", |
|
|
465 |
"with torch.no_grad():\n", |
|
|
466 |
" for batch in test_loader:\n", |
|
|
467 |
" input_ids, attention_mask, labels = batch\n", |
|
|
468 |
" input_ids, attention_mask, labels = input_ids.to(device), attention_mask.to(device), labels.to(device)\n", |
|
|
469 |
" output_dict = model(input_ids, attention_mask=attention_mask, labels=labels)\n", |
|
|
470 |
" predictions = output_dict.logits.squeeze(dim=1)\n", |
|
|
471 |
" loss = criterion(predictions, labels)\n", |
|
|
472 |
" total_test_loss += loss.item()\n", |
|
|
473 |
" test_labels.extend(labels.tolist())\n", |
|
|
474 |
" test_predictions.extend(predictions.tolist())\n", |
|
|
475 |
"avg_test_loss = total_test_loss / len(test_loader)\n", |
|
|
476 |
"print(f\"Test Loss {avg_test_loss:.4f}\")" |
|
|
477 |
] |
|
|
478 |
}, |
|
|
479 |
{ |
|
|
480 |
"cell_type": "code", |
|
|
481 |
"execution_count": 9, |
|
|
482 |
"id": "a5325e19-2edd-4732-8732-e6b679fe7561", |
|
|
483 |
"metadata": {}, |
|
|
484 |
"outputs": [ |
|
|
485 |
{ |
|
|
486 |
"data": { |
|
|
487 |
"image/png": "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", |
|
|
488 |
"text/plain": [ |
|
|
489 |
"<Figure size 640x480 with 1 Axes>" |
|
|
490 |
] |
|
|
491 |
}, |
|
|
492 |
"metadata": {}, |
|
|
493 |
"output_type": "display_data" |
|
|
494 |
} |
|
|
495 |
], |
|
|
496 |
"source": [ |
|
|
497 |
"import matplotlib.pyplot as plt\n", |
|
|
498 |
"plt.scatter(test_predictions, test_labels)\n", |
|
|
499 |
"plt.plot([4, 8], [4, 8], 'k--')\n", |
|
|
500 |
"plt.xlabel('Predicted')\n", |
|
|
501 |
"plt.ylabel('Actual');" |
|
|
502 |
] |
|
|
503 |
} |
|
|
504 |
], |
|
|
505 |
"metadata": { |
|
|
506 |
"kernelspec": { |
|
|
507 |
"display_name": "Python 3 (ipykernel)", |
|
|
508 |
"language": "python", |
|
|
509 |
"name": "python3" |
|
|
510 |
}, |
|
|
511 |
"language_info": { |
|
|
512 |
"codemirror_mode": { |
|
|
513 |
"name": "ipython", |
|
|
514 |
"version": 3 |
|
|
515 |
}, |
|
|
516 |
"file_extension": ".py", |
|
|
517 |
"mimetype": "text/x-python", |
|
|
518 |
"name": "python", |
|
|
519 |
"nbconvert_exporter": "python", |
|
|
520 |
"pygments_lexer": "ipython3", |
|
|
521 |
"version": "3.9.18" |
|
|
522 |
} |
|
|
523 |
}, |
|
|
524 |
"nbformat": 4, |
|
|
525 |
"nbformat_minor": 5 |
|
|
526 |
} |