{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-15T09:46:06.655536Z","iopub.execute_input":"2023-04-15T09:46:06.656114Z","iopub.status.idle":"2023-04-15T09:46:06.682061Z","shell.execute_reply.started":"2023-04-15T09:46:06.656069Z","shell.execute_reply":"2023-04-15T09:46:06.681152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # below is the code copied from the internet to clean the gpu cache\n# !pip install GPUtil\n# import torch\n# from GPUtil import showUtilization as gpu_usage\n# from numba import cuda\n\n# def free_gpu_cache():\n#     print(\"Initial GPU Usage\")\n#     gpu_usage()                             \n\n#     torch.cuda.empty_cache()\n\n#     cuda.select_device(0)\n#     cuda.close()\n#     cuda.select_device(0)\n\n#     print(\"GPU Usage after emptying the cache\")\n#     gpu_usage()\n\n# free_gpu_cache()","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:06.684315Z","iopub.execute_input":"2023-04-15T09:46:06.685079Z","iopub.status.idle":"2023-04-15T09:46:06.69004Z","shell.execute_reply.started":"2023-04-15T09:46:06.685041Z","shell.execute_reply":"2023-04-15T09:46:06.688964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport sys\nimport numpy as np\nimport pandas as pd\nimport codecs\nimport glob\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split\nfrom PIL import Image, ImageDraw\nimport cv2\nimport timm\nimport torch\nimport torchvision.models as models\nimport torchvision.transforms as transforms\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.autograd import Variable\nfrom torch.utils.data.dataset import Dataset","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:06.691684Z","iopub.execute_input":"2023-04-15T09:46:06.692188Z","iopub.status.idle":"2023-04-15T09:46:12.055033Z","shell.execute_reply.started":"2023-04-15T09:46:06.692151Z","shell.execute_reply":"2023-04-15T09:46:12.053738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#below are paramaters for data reading\nsampleNumber = 1000 # defining how many drawings to take from each class\nTEST_SPLIT_SIZE=0.05 # the train-test size\n#below are paramaters for image drawing\nBASE_SIZE = 299\nIMAGE_SIZE = 224 # the input size (both width and height) of the net\nMAX_STROKE_IDX = 10 # to encode the order of strokes with brightness, this is the max number of stroke that will affect the brightness\nBRIGHTNESS_CONSTANT = 13 # every new stroke's brightness will -13\nLINE_WIDTH = 6 # the line width of each stroke\nOFFSET = 22 # the offset when drawing strokes\nDROPOUT_RATE =  0.95 # the rate of dropping out points, if it is 0.95, means 5% of the points will be dropped out when drawing\n#below are parameters for training\nepochs = 25\nBATCH_SIZE = 125","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:12.058203Z","iopub.execute_input":"2023-04-15T09:46:12.058596Z","iopub.status.idle":"2023-04-15T09:46:12.065105Z","shell.execute_reply.started":"2023-04-15T09:46:12.058551Z","shell.execute_reply":"2023-04-15T09:46:12.063767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#below is the function used to sample the whole data, and convert them into small pkl\n# one is for train, another is for validate\ndef getSample(number, use_simplified = True):\n    if use_simplified:\n        all_csv_path = glob.glob('/kaggle/input/quickdraw-doodle-recognition/train_simplified/*.csv')\n    else:\n        all_csv_path = glob.glob('/kaggle/input/quickdraw-doodle-recognition/train_raw/*.csv')\n    all_df = []\n    #find every dataframe in the path and merge them\n    for path in all_csv_path:\n        temp_df = pd.read_csv(path, nrows=number, parse_dates=['timestamp'])\n        all_df.append(temp_df)\n    df = pd.concat(all_df, axis=0, ignore_index=True)  \n    #shuffle the result and encode the class label\n    df = df.reindex(np.random.permutation(df.index))\n    encoder = LabelEncoder().fit(df['word'])\n    df['word'] = encoder.transform(df['word'])\n    df_train, df_val = train_test_split(df, test_size=TEST_SPLIT_SIZE)\n    print('Train size:', len(df_train), 'Val size:', len(df_val))\n    print('Saving...')\n    df_train.to_pickle(os.path.join('/kaggle/working', 'train_' + str(number) + '.pkl'))\n    df_val.to_pickle(os.path.join('/kaggle/working', 'val_' + str(number) + '.pkl'))\n    print('Saving completed.')","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:12.06691Z","iopub.execute_input":"2023-04-15T09:46:12.067599Z","iopub.status.idle":"2023-04-15T09:46:12.078893Z","shell.execute_reply.started":"2023-04-15T09:46:12.067562Z","shell.execute_reply":"2023-04-15T09:46:12.077893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"getSample(sampleNumber, True)","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:12.080597Z","iopub.execute_input":"2023-04-15T09:46:12.081014Z","iopub.status.idle":"2023-04-15T09:46:20.286416Z","shell.execute_reply.started":"2023-04-15T09:46:12.080977Z","shell.execute_reply":"2023-04-15T09:46:20.285182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#efficientnet_b0 = 224\n#below is the code to conver the stroke into img matrix\n#here we encode the order of drawing into different colors\n#stroke consists of several lines, below is the function to draw a line\ndef draw_line_segment(image, start_point, end_point, color, width):\n        cv2.line(image, start_point, end_point, color, width)\n\n# below is the function to convert raw strokes into image\ndef draw_image(raw_strokes, size):\n    # create a basesize canvas first\n    canvas = np.zeros((BASE_SIZE, BASE_SIZE), np.uint8)\n    # get the strokes\n    strokes = eval(raw_strokes)\n    for stroke_idx, single_stroke in enumerate(strokes):   \n        #get all the Xs and Ys for all points of the stroke\n        x, y = single_stroke\n        #combine the x and ys to make a point list\n        points = list(zip(x, y))\n        for point_idx, (start, end) in enumerate(zip(points[:-1], points[1:])):\n            #randomly dropout points\n            if np.random.uniform() > DROPOUT_RATE:\n                continue\n            #adjust the brightness of current stroke\n            brightness = 255 - min(stroke_idx, MAX_STROKE_IDX) * BRIGHTNESS_CONSTANT\n            start_point = (start[0] + OFFSET, start[1] + OFFSET)\n            end_point = (end[0] + OFFSET, end[1] + OFFSET)\n            draw_line_segment(canvas, start_point, end_point, brightness, LINE_WIDTH)\n    if size != BASE_SIZE:\n        return cv2.resize(canvas, (size, size))\n    else:\n        return canvas\n\nclass ImageDataset(Dataset):\n    def __init__(self, drawings, labels, image_size, transform=None):\n        self.drawings = drawings\n        self.labels = labels\n        self.image_size = image_size\n        self.transform = transform\n    def __getitem__(self, idx):\n        single_channel_img = draw_image(self.drawings[idx], self.image_size)\n        three_channel_img = np.repeat(single_channel_img[..., np.newaxis], 3, axis=2)\n        img_as_pil = Image.fromarray(np.uint8(three_channel_img))\n        if self.transform:\n            img_transformed = self.transform(img_as_pil)\n        else:\n            img_transformed = img_as_pil\n            \n        label_tensor = torch.from_numpy(np.array([self.labels[idx]]))\n\n        return img_transformed, label_tensor\n\n    def __len__(self):\n        return len(self.drawings)","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.288449Z","iopub.execute_input":"2023-04-15T09:46:20.288881Z","iopub.status.idle":"2023-04-15T09:46:20.302284Z","shell.execute_reply.started":"2023-04-15T09:46:20.288826Z","shell.execute_reply":"2023-04-15T09:46:20.301213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = timm.create_model('efficientnet_b0', num_classes=340, in_chans = 3)","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.304069Z","iopub.execute_input":"2023-04-15T09:46:20.304586Z","iopub.status.idle":"2023-04-15T09:46:20.441521Z","shell.execute_reply.started":"2023-04-15T09:46:20.304549Z","shell.execute_reply":"2023-04-15T09:46:20.440467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_pickle('/kaggle/working/train_{num}.pkl'.format(num = sampleNumber))\ndf_val = pd.read_pickle('/kaggle/working/val_{num}.pkl'.format(num = sampleNumber))","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.443354Z","iopub.execute_input":"2023-04-15T09:46:20.443748Z","iopub.status.idle":"2023-04-15T09:46:20.618991Z","shell.execute_reply.started":"2023-04-15T09:46:20.443701Z","shell.execute_reply":"2023-04-15T09:46:20.617902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.623285Z","iopub.execute_input":"2023-04-15T09:46:20.623595Z","iopub.status.idle":"2023-04-15T09:46:20.642076Z","shell.execute_reply.started":"2023-04-15T09:46:20.623566Z","shell.execute_reply":"2023-04-15T09:46:20.640931Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"    train_loader = torch.utils.data.DataLoader(\n        ImageDataset(df_train['drawing'].values, df_train['word'].values, IMAGE_SIZE,\n                         transforms.Compose([\n                            transforms.RandomHorizontalFlip(),\n                            transforms.RandomVerticalFlip(),\n                            transforms.ToTensor(),\n                            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n            ])\n        ),\n        batch_size=BATCH_SIZE, shuffle=True, num_workers=2,\n    )\n\n    val_loader = torch.utils.data.DataLoader(\n        ImageDataset(df_val['drawing'].values, df_val['word'].values, IMAGE_SIZE,\n                         transforms.Compose([\n                            transforms.RandomHorizontalFlip(),\n                            transforms.RandomVerticalFlip(),\n                            transforms.ToTensor(),\n                            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n            ])\n        ),\n        batch_size=BATCH_SIZE, shuffle=False, num_workers=2,\n    )","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.643489Z","iopub.execute_input":"2023-04-15T09:46:20.645388Z","iopub.status.idle":"2023-04-15T09:46:20.6559Z","shell.execute_reply.started":"2023-04-15T09:46:20.645344Z","shell.execute_reply":"2023-04-15T09:46:20.654917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_loader)","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.657617Z","iopub.execute_input":"2023-04-15T09:46:20.658081Z","iopub.status.idle":"2023-04-15T09:46:20.667922Z","shell.execute_reply.started":"2023-04-15T09:46:20.658037Z","shell.execute_reply":"2023-04-15T09:46:20.666707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.to('cuda')\nloss_fn = nn.CrossEntropyLoss().to('cuda')\noptimizer = optim.Adam(model.parameters(), lr=0.01)\nscheduler = optim.lr_scheduler.StepLR(optimizer, step_size=len(train_loader)/10, gamma=0.95)","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:20.669442Z","iopub.execute_input":"2023-04-15T09:46:20.669729Z","iopub.status.idle":"2023-04-15T09:46:23.317436Z","shell.execute_reply.started":"2023-04-15T09:46:20.669697Z","shell.execute_reply":"2023-04-15T09:46:23.316369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def getAccuraryTop1_3(prediction, label):\n    with torch.no_grad():\n        batch_size = label.size(0)\n#         print(\"batch_size =\",batch_size)\n        _, pred = prediction.topk(3, 1, True, True)\n        pred = pred.t()\n        result_list = pred.eq(label.view(1, -1).expand_as(pred))\n        final_result = []\n        correct_top1 = result_list[:1].float().sum()\n        correct_top3 = result_list[:3].float().sum()\n        final_result.append(correct_top1.mul_(100.0 / batch_size))\n        final_result.append(correct_top3.mul_(100.0 / batch_size))\n        return final_result","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:23.318934Z","iopub.execute_input":"2023-04-15T09:46:23.319312Z","iopub.status.idle":"2023-04-15T09:46:23.327638Z","shell.execute_reply.started":"2023-04-15T09:46:23.319267Z","shell.execute_reply":"2023-04-15T09:46:23.326532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist_train_loss = []\nhist_train_acc1 = []\nhist_train_acc3 = []\n\nhist_test_loss = []\nhist_test_acc1 = []\nhist_test_acc3 = []","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:23.329312Z","iopub.execute_input":"2023-04-15T09:46:23.329938Z","iopub.status.idle":"2023-04-15T09:46:23.337807Z","shell.execute_reply.started":"2023-04-15T09:46:23.3299Z","shell.execute_reply":"2023-04-15T09:46:23.336892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for epoch in range(epochs):\n    train_losss, train_acc1s, train_acc3s = [], [], []\n    for i, data in enumerate(train_loader):\n        model = model.train()\n        \n        train_img, train_label = data\n        optimizer.zero_grad()\n        train_img = Variable(train_img).cuda()\n        train_label = Variable(train_label.view(-1)).cuda()\n            \n        output = model(train_img)\n        train_loss = loss_fn(output, train_label)\n        \n        train_loss.backward()\n        optimizer.step()\n        scheduler.step()\n        \n        train_losss.append(train_loss.item())\n        train_acc1, train_acc3 = getAccuraryTop1_3(output, train_label)\n        train_acc1s.append(train_acc1.data.item())\n        train_acc3s.append(train_acc3.item()) \n        if i%500 == 0:\n            print(i,'/',len(train_loader))   \n    val_losss, val_acc1s, val_acc3s = [], [], []\n    with torch.no_grad():\n        for data in val_loader:\n            val_images, val_labels = data\n            val_images = Variable(val_images).cuda()\n            val_labels = Variable(val_labels.view(-1)).cuda() \n                       \n            output = model(val_images)\n            val_loss = loss_fn(output, val_labels)\n            val_acc1, val_acc3 = getAccuraryTop1_3(output, val_labels) \n                \n            val_losss.append(val_loss.item())\n            val_acc1s.append(val_acc1.item())\n            val_acc3s.append(val_acc3.item())\n    \n    avg_train_loss = np.mean(train_losss, 0)\n    avg_train_acc1 = np.mean(train_acc1s, 0)\n    avg_train_acc3 = np.mean(train_acc3s, 0)\n    \n    avg_test_loss = np.mean(val_losss, 0)\n    avg_test_acc1 = np.mean(val_acc1s, 0)\n    avg_test_acc3 = np.mean(val_acc3s, 0)\n    \n    hist_train_loss.append(avg_train_loss)\n    hist_train_acc1.append(avg_train_acc1)\n    hist_train_acc3.append(avg_train_acc3)\n    \n    hist_test_loss.append(avg_test_loss)\n    hist_test_acc1.append(avg_test_acc1)\n    hist_test_acc3.append(avg_test_acc3)\n    \n    \n    logstr = 'epoch: {0:2s}\\t\\t{2:.4f}/{3:.4f}/{4:.4f}\\t\\t{5:.4f}/{6:.4f}/{7:.4f}'.format(\n        str(epoch), str(i),\n        avg_train_loss, avg_train_acc1, avg_train_acc3,\n        avg_test_loss, avg_test_acc1, avg_test_acc3,\n    )\n    print(logstr)\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2023-04-15T09:46:23.339532Z","iopub.execute_input":"2023-04-15T09:46:23.339949Z","iopub.status.idle":"2023-04-15T19:10:50.967303Z","shell.execute_reply.started":"2023-04-15T09:46:23.339913Z","shell.execute_reply":"2023-04-15T19:10:50.965933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n0\nplt.plot(range(1,epochs+1), hist_train_loss, \"-b\", label = \"Train Loss\")\nplt.plot(range(1,epochs+1), hist_test_loss, \"-r\", label = \"Test Loss\")\nplt.legend(loc=\"best\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.title(\"Training Profile EffientNet_b0\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-15T19:10:50.969481Z","iopub.execute_input":"2023-04-15T19:10:50.970174Z","iopub.status.idle":"2023-04-15T19:10:51.21504Z","shell.execute_reply.started":"2023-04-15T19:10:50.970129Z","shell.execute_reply":"2023-04-15T19:10:51.213887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(range(1,epochs+1), hist_train_acc3, \"-b\", label = \"Train Accuracy Top3\")\nplt.plot(range(1,epochs+1), hist_test_acc3, \"-r\", label = \"Test Accuracy Top3\")\nplt.legend(loc=\"best\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Training Profile EffientNet_b0\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-15T19:10:51.216658Z","iopub.execute_input":"2023-04-15T19:10:51.217057Z","iopub.status.idle":"2023-04-15T19:10:51.635783Z","shell.execute_reply.started":"2023-04-15T19:10:51.217018Z","shell.execute_reply":"2023-04-15T19:10:51.63481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(range(1,epochs+1), hist_train_acc1, \"-b\", label = \"Train Accuracy Top1\")\nplt.plot(range(1,epochs+1), hist_test_acc1, \"-r\", label = \"Test Accuracy Top1\")\nplt.legend(loc=\"best\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Training Profile EffientNet_b0\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-15T19:10:51.637119Z","iopub.execute_input":"2023-04-15T19:10:51.637732Z","iopub.status.idle":"2023-04-15T19:10:51.847756Z","shell.execute_reply.started":"2023-04-15T19:10:51.637691Z","shell.execute_reply":"2023-04-15T19:10:51.846775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}