1+ {
2+ "nbformat" : 4 ,
3+ "nbformat_minor" : 0 ,
4+ "metadata" : {
5+ "colab" : {
6+ "name" : " 08.Optimizing_AUROC_Loss_with_DenseNet121_on_Melanoma.ipynb" ,
7+ "provenance" : [],
8+ "collapsed_sections" : []
9+ },
10+ "kernelspec" : {
11+ "name" : " python3" ,
12+ "display_name" : " Python 3"
13+ },
14+ "language_info" : {
15+ "name" : " python"
16+ },
17+ "accelerator" : " GPU"
18+ },
19+ "cells" : [
20+ {
21+ "cell_type" : " markdown" ,
22+ "metadata" : {
23+ "id" : " ud6jh8GWr_qT"
24+ },
25+ "source" : [
26+ " * Author: Zhuoning Yuan\n " ,
27+ " * Project: https://github.com/Optimization-AI/LibAUC\n " ,
28+ " \n "
29+ ]
30+ },
31+ {
32+ "cell_type" : " markdown" ,
33+ "metadata" : {
34+ "id" : " dcqqRTWMsFKY"
35+ },
36+ "source" : [
37+ " # **Installing LibAUC**"
38+ ]
39+ },
40+ {
41+ "cell_type" : " code" ,
42+ "metadata" : {
43+ "id" : " Ter36EFG2k2g"
44+ },
45+ "source" : [
46+ " !pip install libauc"
47+ ],
48+ "execution_count" : null ,
49+ "outputs" : []
50+ },
51+ {
52+ "cell_type" : " markdown" ,
53+ "metadata" : {
54+ "id" : " rZL_V9NutBio"
55+ },
56+ "source" : [
57+ " # **Downloading Melanoma Dataset**\n " ,
58+ " \n " ,
59+ " * You can download dataset from here: https://www.kaggle.com/cdeotte/jpeg-melanoma-256x256. \n " ,
60+ " * In this tutorial, I am going to use JPEG Melanoma 256x256.\n " ,
61+ " \n "
62+ ]
63+ },
64+ {
65+ "cell_type" : " code" ,
66+ "metadata" : {
67+ "id" : " gXlAZOYRs_rf"
68+ },
69+ "source" : [
70+ " !cp /content/drive/MyDrive/LibAUC/melanoma_256x256.zip /content/\n " ,
71+ " !unzip melanoma_224x224.zip -d /content/melanoma/"
72+ ],
73+ "execution_count" : null ,
74+ "outputs" : []
75+ },
76+ {
77+ "cell_type" : " markdown" ,
78+ "metadata" : {
79+ "id" : " SWwE3v_R5Oku"
80+ },
81+ "source" : [
82+ " \n " ,
83+ " # **Importing LibAUC**"
84+ ]
85+ },
86+ {
87+ "cell_type" : " code" ,
88+ "metadata" : {
89+ "id" : " fDfVpPkp4o9O"
90+ },
91+ "source" : [
92+ " from libauc.losses import AUCMLoss\n " ,
93+ " from libauc.optimizers import PESG\n " ,
94+ " from libauc.models import DenseNet121, DenseNet169\n " ,
95+ " from libauc.datasets import Melanoma\n " ,
96+ " from libauc.utils import auroc\n " ,
97+ " \n " ,
98+ " import torch \n " ,
99+ " from PIL import Image\n " ,
100+ " import numpy as np\n " ,
101+ " import torchvision.transforms as transforms\n " ,
102+ " from torch.utils.data import Dataset"
103+ ],
104+ "execution_count" : 1 ,
105+ "outputs" : []
106+ },
107+ {
108+ "cell_type" : " markdown" ,
109+ "metadata" : {
110+ "id" : " l2swK5Mo7Kca"
111+ },
112+ "source" : [
113+ " # **Reproducibility**"
114+ ]
115+ },
116+ {
117+ "cell_type" : " code" ,
118+ "metadata" : {
119+ "id" : " OiiT5oEp7J3C"
120+ },
121+ "source" : [
122+ " def set_all_seeds(SEED):\n " ,
123+ " # REPRODUCIBILITY\n " ,
124+ " torch.manual_seed(SEED)\n " ,
125+ " np.random.seed(SEED)\n " ,
126+ " torch.backends.cudnn.deterministic = True\n " ,
127+ " torch.backends.cudnn.benchmark = False"
128+ ],
129+ "execution_count" : 2 ,
130+ "outputs" : []
131+ },
132+ {
133+ "cell_type" : " markdown" ,
134+ "metadata" : {
135+ "id" : " G-StcokOURv9"
136+ },
137+ "source" : [
138+ " # **Data Augmentation**"
139+ ]
140+ },
141+ {
142+ "cell_type" : " code" ,
143+ "metadata" : {
144+ "id" : " sQlAJDeoUTtR"
145+ },
146+ "source" : [
147+ " import albumentations as A\n " ,
148+ " from albumentations.pytorch.transforms import ToTensor\n " ,
149+ " \n " ,
150+ " def augmentations(image_size=256, is_test=True):\n " ,
151+ " # https://www.kaggle.com/vishnus/a-simple-pytorch-starter-code-single-fold-93\n " ,
152+ " imagenet_stats = {'mean':[0.485, 0.456, 0.406], 'std':[0.229, 0.224, 0.225]}\n " ,
153+ " train_tfms = A.Compose([\n " ,
154+ " A.Cutout(p=0.5),\n " ,
155+ " A.RandomRotate90(p=0.5),\n " ,
156+ " A.Flip(p=0.5),\n " ,
157+ " A.OneOf([\n " ,
158+ " A.RandomBrightnessContrast(brightness_limit=0.2,\n " ,
159+ " contrast_limit=0.2,\n " ,
160+ " ),\n " ,
161+ " A.HueSaturationValue(\n " ,
162+ " hue_shift_limit=20,\n " ,
163+ " sat_shift_limit=50,\n " ,
164+ " val_shift_limit=50)\n " ,
165+ " ], p=0.5),\n " ,
166+ " A.OneOf([\n " ,
167+ " A.IAAAdditiveGaussianNoise(),\n " ,
168+ " A.GaussNoise(),\n " ,
169+ " ], p=0.5),\n " ,
170+ " A.OneOf([\n " ,
171+ " A.MotionBlur(p=0.2),\n " ,
172+ " A.MedianBlur(blur_limit=3, p=0.1),\n " ,
173+ " A.Blur(blur_limit=3, p=0.1),\n " ,
174+ " ], p=0.5),\n " ,
175+ " A.ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.2, rotate_limit=45, p=0.5),\n " ,
176+ " A.OneOf([\n " ,
177+ " A.OpticalDistortion(p=0.3),\n " ,
178+ " A.GridDistortion(p=0.1),\n " ,
179+ " A.IAAPiecewiseAffine(p=0.3),\n " ,
180+ " ], p=0.5), \n " ,
181+ " ToTensor(normalize=imagenet_stats)\n " ,
182+ " ])\n " ,
183+ " \n " ,
184+ " test_tfms = A.Compose([ToTensor(normalize=imagenet_stats)])\n " ,
185+ " if is_test:\n " ,
186+ " return test_tfms\n " ,
187+ " else:\n " ,
188+ " return train_tfms"
189+ ],
190+ "execution_count" : 3 ,
191+ "outputs" : []
192+ },
193+ {
194+ "cell_type" : " markdown" ,
195+ "metadata" : {
196+ "id" : " fP4adNO97YBV"
197+ },
198+ "source" : [
199+ " # **Optimizing AUCM Loss**\n " ,
200+ " * Installation of `albumentations` is required!"
201+ ]
202+ },
203+ {
204+ "cell_type" : " code" ,
205+ "metadata" : {
206+ "colab" : {
207+ "base_uri" : " https://localhost:8080/" ,
208+ "height" : 519
209+ },
210+ "id" : " Xx7j0UYe6V0J" ,
211+ "outputId" : " 3bce73dc-ea0a-4639-b3ba-888b276a7d97"
212+ },
213+ "source" : [
214+ " # dataset\n " ,
215+ " trainSet = Melanoma(root='./melanoma/', is_test=False, test_size=0.2, transforms=augmentations)\n " ,
216+ " testSet = Melanoma(root='./melanoma/', is_test=True, test_size=0.2, transforms=augmentations)\n " ,
217+ " \n " ,
218+ " # paramaters\n " ,
219+ " SEED = 123\n " ,
220+ " BATCH_SIZE = 64\n " ,
221+ " lr = 0.1 \n " ,
222+ " gamma = 500\n " ,
223+ " imratio = trainSet.imratio\n " ,
224+ " weight_decay = 1e-5\n " ,
225+ " margin = 1.0\n " ,
226+ " \n " ,
227+ " # model\n " ,
228+ " set_all_seeds(SEED)\n " ,
229+ " model = DenseNet121(pretrained=True, last_activation=None, activations='relu', num_classes=1)\n " ,
230+ " model = model.cuda()\n " ,
231+ " \n " ,
232+ " trainloader = torch.utils.data.DataLoader(trainSet, batch_size=BATCH_SIZE, num_workers=2, shuffle=True)\n " ,
233+ " testloader = torch.utils.data.DataLoader(testSet, batch_size=BATCH_SIZE, num_workers=2, shuffle=False)\n " ,
234+ " \n " ,
235+ " # load your own pretrained model here\n " ,
236+ " # PATH = 'ce_pretrained_model.pth' \n " ,
237+ " # state_dict = torch.load(PATH)\n " ,
238+ " # state_dict.pop('classifier.weight', None)\n " ,
239+ " # state_dict.pop('classifier.bias', None) \n " ,
240+ " # model.load_state_dict(state_dict, strict=False)\n " ,
241+ " \n " ,
242+ " # define loss & optimizer\n " ,
243+ " Loss = AUCMLoss(imratio=imratio)\n " ,
244+ " optimizer = PESG(model, \n " ,
245+ " a=Loss.a, \n " ,
246+ " b=Loss.b, \n " ,
247+ " alpha=Loss.alpha, \n " ,
248+ " lr=lr, \n " ,
249+ " gamma=gamma, \n " ,
250+ " margin=margin, \n " ,
251+ " weight_decay=weight_decay)\n " ,
252+ " \n " ,
253+ " total_epochs = 16\n " ,
254+ " best_val_auc = 0\n " ,
255+ " for epoch in range(total_epochs):\n " ,
256+ " \n " ,
257+ " # reset stages \n " ,
258+ " if epoch== int(total_epochs*0.5) or epoch== int(total_epochs*0.75):\n " ,
259+ " optimizer.update_regularizer(decay_factor=10) \n " ,
260+ " \n " ,
261+ " # training \n " ,
262+ " for idx, data in enumerate(trainloader):\n " ,
263+ " train_data, train_labels = data\n " ,
264+ " train_data, train_labels = train_data.cuda(), train_labels.cuda()\n " ,
265+ " y_pred = model(train_data)\n " ,
266+ " y_pred = torch.sigmoid(y_pred)\n " ,
267+ " loss = Loss(y_pred, train_labels)\n " ,
268+ " optimizer.zero_grad()\n " ,
269+ " loss.backward()\n " ,
270+ " optimizer.step()\n " ,
271+ " \n " ,
272+ " # validation\n " ,
273+ " model.eval()\n " ,
274+ " with torch.no_grad(): \n " ,
275+ " test_pred = []\n " ,
276+ " test_true = [] \n " ,
277+ " for jdx, data in enumerate(testloader):\n " ,
278+ " test_data, test_label = data\n " ,
279+ " test_data = test_data.cuda()\n " ,
280+ " y_pred = model(test_data)\n " ,
281+ " y_pred = torch.sigmoid(y_pred)\n " ,
282+ " test_pred.append(y_pred.cpu().detach().numpy())\n " ,
283+ " test_true.append(test_label.numpy())\n " ,
284+ " \n " ,
285+ " test_true = np.concatenate(test_true)\n " ,
286+ " test_pred = np.concatenate(test_pred)\n " ,
287+ " val_auc = auroc(test_true, test_pred) \n " ,
288+ " model.train()\n " ,
289+ " \n " ,
290+ " if best_val_auc < val_auc:\n " ,
291+ " best_val_auc = val_auc\n " ,
292+ " \n " ,
293+ " print ('Epoch=%s, Loss=%.4f, Val_AUC=%.4f, lr=%.4f'%(epoch, loss, val_auc, optimizer.lr))\n " ,
294+ " \n " ,
295+ " print ('Best Val_AUC is %.4f'%best_val_auc)"
296+ ],
297+ "execution_count" : 7 ,
298+ "outputs" : [
299+ {
300+ "output_type" : " stream" ,
301+ "name" : " stdout" ,
302+ "text" : [
303+ " test set split is 0.2\n " ,
304+ " Found 26134 image in total, 464 postive images, 25670 negative images.\n " ,
305+ " test set split is 0.2\n " ,
306+ " Found 6558 image in total, 117 postive images, 6441 negative images.\n " ,
307+ " Epoch=0, Loss=0.0238, Val_AUC=0.8411, lr=0.1000\n " ,
308+ " Epoch=1, Loss=0.0245, Val_AUC=0.8697, lr=0.1000\n " ,
309+ " Epoch=2, Loss=0.0213, Val_AUC=0.8460, lr=0.1000\n " ,
310+ " Epoch=3, Loss=-0.0234, Val_AUC=0.8783, lr=0.1000\n "
311+ ]
312+ },
313+ ]
314+ }
315+ ]
316+ }
0 commit comments