{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1. Define Some Libraries","metadata":{}},{"cell_type":"code","source":"import torch\nimport torchvision\nimport torch.utils.data\nfrom torchvision import transforms\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\n\n","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:35.243427Z","iopub.execute_input":"2023-03-22T03:14:35.244311Z","iopub.status.idle":"2023-03-22T03:14:38.252635Z","shell.execute_reply.started":"2023-03-22T03:14:35.244273Z","shell.execute_reply":"2023-03-22T03:14:38.251291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder, LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score\nimport numpy as np\nimport math, random\nimport pandas as pd\nimport pathlib\nimport glob\nimport cv2 as cv\nimport numpy as np\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport random\nfrom sklearn.model_selection import train_test_split\nimport copy\nimport time \nfrom collections import defaultdict\nfrom tqdm import tqdm\nimport os\nimport json\n","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:38.258775Z","iopub.execute_input":"2023-03-22T03:14:38.259416Z","iopub.status.idle":"2023-03-22T03:14:39.191987Z","shell.execute_reply.started":"2023-03-22T03:14:38.259382Z","shell.execute_reply":"2023-03-22T03:14:39.190332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\nseed = 1999\nseed_everything(seed)","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.195107Z","iopub.execute_input":"2023-03-22T03:14:39.196834Z","iopub.status.idle":"2023-03-22T03:14:39.208138Z","shell.execute_reply.started":"2023-03-22T03:14:39.196793Z","shell.execute_reply":"2023-03-22T03:14:39.207051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    isOneHot = False\n    label_map = {'dot': 0, 'horizontal_bar' : 1, 'vertical_bar': 2, 'line': 3, 'scatter': 4}\n    num_classes = 5\n    batchSize = 32\n    fold_train = 0","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.213927Z","iopub.execute_input":"2023-03-22T03:14:39.214852Z","iopub.status.idle":"2023-03-22T03:14:39.223598Z","shell.execute_reply.started":"2023-03-22T03:14:39.214811Z","shell.execute_reply":"2023-03-22T03:14:39.222387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Meta Data","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/benetech-metadata/df_train.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.226334Z","iopub.execute_input":"2023-03-22T03:14:39.230438Z","iopub.status.idle":"2023-03-22T03:14:39.411995Z","shell.execute_reply.started":"2023-03-22T03:14:39.230394Z","shell.execute_reply":"2023-03-22T03:14:39.411061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.chart_type.value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.416032Z","iopub.execute_input":"2023-03-22T03:14:39.418232Z","iopub.status.idle":"2023-03-22T03:14:39.437659Z","shell.execute_reply.started":"2023-03-22T03:14:39.418191Z","shell.execute_reply":"2023-03-22T03:14:39.436768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"files_and_labels = {}\nfor dirname, _, filenames in os.walk('/kaggle/input/benetech-making-graphs-accessible/test/images'):\n    for filename in filenames:\n        files_and_labels[os.path.join(dirname, filename)] = 'line'\ndf_test = pd.DataFrame(files_and_labels, index = [0]).T.reset_index().rename(columns = {'index':'filename', 0 :'chart_type'})\ndf_test","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.441568Z","iopub.execute_input":"2023-03-22T03:14:39.443749Z","iopub.status.idle":"2023-03-22T03:14:39.477418Z","shell.execute_reply.started":"2023-03-22T03:14:39.443713Z","shell.execute_reply":"2023-03-22T03:14:39.476638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Define Dataset ","metadata":{}},{"cell_type":"code","source":"transforms_train = transforms.Compose(\n    [transforms.ToTensor(),\n     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\ntransforms_test = transforms.Compose(\n    [transforms.ToTensor(),\n     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.481062Z","iopub.execute_input":"2023-03-22T03:14:39.481376Z","iopub.status.idle":"2023-03-22T03:14:39.489001Z","shell.execute_reply.started":"2023-03-22T03:14:39.481333Z","shell.execute_reply":"2023-03-22T03:14:39.487293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageCharts(torch.utils.data.Dataset):\n    def __init__(self, df, transforms  = None): ### phase = train/test\n        self.df = df\n        self.transforms = transforms\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self,idx):\n        name_img = self.df.iloc[idx]['filename']\n        img = cv.imread(name_img)\n        img = cv.cvtColor(img,cv.COLOR_BGR2RGB)\n        img = cv.resize(img,(500,300))\n        img = img.astype(np.float32)/255.0\n\n        label = np.array(self.df.iloc[idx]['label'])\n\n        if(self.transforms is not None):\n            img = self.transforms(img)\n        return img, label","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.490790Z","iopub.execute_input":"2023-03-22T03:14:39.491730Z","iopub.status.idle":"2023-03-22T03:14:39.504296Z","shell.execute_reply.started":"2023-03-22T03:14:39.491692Z","shell.execute_reply":"2023-03-22T03:14:39.502961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def cv_split(Xtrain, ytrain, n_folds, seed):\n    kfold = StratifiedKFold(n_splits = n_folds, shuffle = True, random_state = seed)\n    for num, (train_index, val_index) in enumerate(kfold.split(Xtrain, ytrain)):\n        Xtrain.loc[val_index, 'fold'] = int(num)\n    Xtrain['fold'] = Xtrain['fold'].astype(int)\n    return Xtrain\n\nmeta_df = cv_split(df,df['chart_type'], 5, 42)\nmeta_df['label'] = meta_df['chart_type'].apply(lambda x: CFG.label_map[x])\nmeta_df.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.508183Z","iopub.execute_input":"2023-03-22T03:14:39.508699Z","iopub.status.idle":"2023-03-22T03:14:39.642916Z","shell.execute_reply.started":"2023-03-22T03:14:39.508651Z","shell.execute_reply":"2023-03-22T03:14:39.641900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = ImageCharts(meta_df[meta_df.fold != CFG.fold_train].reset_index(), transforms=transforms_train)\nval_ds = ImageCharts(meta_df[meta_df.fold == CFG.fold_train].reset_index(), transforms=transforms_train)\ntrain_dl = torch.utils.data.DataLoader(train_ds, batch_size= CFG.batchSize, shuffle=True)\nval_dl = torch.utils.data.DataLoader(val_ds, batch_size= CFG.batchSize, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.647197Z","iopub.execute_input":"2023-03-22T03:14:39.649481Z","iopub.status.idle":"2023-03-22T03:14:39.671022Z","shell.execute_reply.started":"2023-03-22T03:14:39.649441Z","shell.execute_reply":"2023-03-22T03:14:39.669920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a,b = next(iter(train_dl))\nprint(a.shape)\nprint(b.shape)\nprint('chart_type:',list(CFG.label_map)[b[0].detach().numpy()])\nplt.imshow(a[0].permute(1,2,0))","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:39.672423Z","iopub.execute_input":"2023-03-22T03:14:39.672769Z","iopub.status.idle":"2023-03-22T03:14:40.608010Z","shell.execute_reply.started":"2023-03-22T03:14:39.672734Z","shell.execute_reply":"2023-03-22T03:14:40.607016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Define Model - ResNet50","metadata":{}},{"cell_type":"code","source":"model = torchvision.models.resnet50(pretrained=False)\n\n\nnum_features = model.fc.in_features\nmodel.fc = nn.Linear(num_features, CFG.num_classes)\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmyModel = model.to(device)\nnext(myModel.parameters()).device","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:40.609079Z","iopub.execute_input":"2023-03-22T03:14:40.609467Z","iopub.status.idle":"2023-03-22T03:14:43.712349Z","shell.execute_reply.started":"2023-03-22T03:14:40.609420Z","shell.execute_reply":"2023-03-22T03:14:43.711294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Training","metadata":{}},{"cell_type":"code","source":"def training(model, train_dl, val_dl, num_epochs):\n  # Loss Function, Optimizer and Scheduler\n  criterion = nn.CrossEntropyLoss()\n  optimizer = torch.optim.Adam(model.parameters(),lr=0.0001)\n  scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.001,\n                                                steps_per_epoch=int(len(train_dl)),\n                                                epochs=num_epochs,\n                                                anneal_strategy='linear')\n\n  # Repeat for each epoch\n  best_acc = -1\n  for epoch in range(num_epochs):\n    running_loss = 0.0\n    correct_prediction = 0\n    total_prediction = 0\n\n    # Repeat for each batch in the training set\n    for i, data in enumerate(train_dl):\n        # Get the input features and target labels, and put them on the GPU\n        inputs, labels = data[0].to(device), data[1].to(device)\n\n        # Normalize the inputs\n        inputs_m, inputs_s = inputs.mean(), inputs.std()\n        inputs = (inputs - inputs_m) / inputs_s\n\n        # Zero the parameter gradients\n        optimizer.zero_grad()\n\n        # forward + backward + optimize\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        scheduler.step()\n\n        # Keep stats for Loss and Accuracy\n        running_loss += loss.item()\n\n        # Get the predicted class with the highest score\n        _, prediction = torch.max(outputs,1)\n        # Count of predictions that matched the target label\n        correct_prediction += (prediction == labels).sum().item()\n        total_prediction += prediction.shape[0]\n\n        if (i + 1) % 50 == 0:    # print every 10 mini-batches\n           print('Epoch [{}/{}], Step [{}/{}], Loss : {:.4f}'\n            .format(epoch + 1, num_epochs, i + 1, len(train_dl), running_loss/(i + 1)))\n    \n    # Print stats at the end of the epoch\n    num_batches = len(train_dl)\n    avg_loss = running_loss / num_batches\n    acc = correct_prediction/total_prediction\n    print(f'Epoch: {epoch + 1}, Loss: {avg_loss:.4f}, Accuracy: {acc:.4f}')\n\n    gt = []\n    pred = []\n\n    with torch.no_grad():\n        correct = 0\n        total = 0\n        val_loss = 0 \n        for idx, data_ in enumerate(val_dl):\n            inputs, labels = data_[0].to(device), data_[1].to(device)\n\n            # Normalize the inputs\n            inputs_m, inputs_s = inputs.mean(), inputs.std()\n            inputs = (inputs - inputs_m) / inputs_s\n\n            # forward + backward + optimize\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n\n            # Keep stats for Loss and Accuracy\n            val_loss += loss.item()\n\n            # Get the predicted class with the highest score\n            _, prediction = torch.max(outputs,1)\n            predi = torch.softmax(outputs, dim = -1)\n            gt.append(labels)\n            pred.append(predi[:,1])\n            # Count of predictions that matched the target label\n            correct += (prediction == labels).sum().item()\n            total += prediction.shape[0]\n        print('Accuracy of the network val: {:.4f} %'.format(100 * correct / total))\n\n        final_score = 100 * correct / total\n\n\n        if (best_acc < final_score):\n            best_acc = final_score\n            print(\"Saving best model!\")\n            torch.save(model.state_dict(), f'Benetech _ResNet50_fold0.pth')\n\n  print('Finished Training')\n  \nnum_epochs = 1   # Just for demo, adjust this higher.\ntraining(myModel, train_dl, val_dl, num_epochs)","metadata":{"execution":{"iopub.status.busy":"2023-03-22T03:14:43.714089Z","iopub.execute_input":"2023-03-22T03:14:43.714476Z","iopub.status.idle":"2023-03-22T03:45:45.304961Z","shell.execute_reply.started":"2023-03-22T03:14:43.714436Z","shell.execute_reply":"2023-03-22T03:45:45.303264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}