{"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":"%matplotlib inline\n#這是juoyter notebook的magic word˙\n\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom IPython import display","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-07-06T03:51:55.382430Z","iopub.execute_input":"2021-07-06T03:51:55.382743Z","iopub.status.idle":"2021-07-06T03:51:55.402305Z","shell.execute_reply.started":"2021-07-06T03:51:55.382710Z","shell.execute_reply":"2021-07-06T03:51:55.400829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# iWildCam2020 revised1","metadata":{}},{"cell_type":"code","source":"import os\n#判斷是否在jupyter notebook上\ndef is_in_ipython():\n    \"Is the code running in the ipython environment (jupyter including)\"\n    program_name = os.path.basename(os.getenv('_', ''))\n\n    if ('jupyter-notebook' in program_name or # jupyter-notebook\n        'ipython'          in program_name or # ipython\n        'jupyter' in program_name or  # jupyter\n        'JPY_PARENT_PID'   in os.environ):    # ipython-notebook\n        return True\n    else:\n        return False\n\n\n#判斷是否在colab上\ndef is_in_colab():\n    if not is_in_ipython(): return False\n    try:\n        from google import colab\n        return True\n    except: return False\n\n#判斷是否在kaggke_kernal上\ndef is_in_kaggle_kernal():\n    if 'kaggle' in os.environ['PYTHONPATH']:\n        return True\n    else:\n        return False\n\nif is_in_colab():\n    from google.colab import drive\n    drive.mount('/content/gdrive')","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:51:58.205850Z","iopub.execute_input":"2021-07-06T03:51:58.206208Z","iopub.status.idle":"2021-07-06T03:51:58.213767Z","shell.execute_reply.started":"2021-07-06T03:51:58.206177Z","shell.execute_reply":"2021-07-06T03:51:58.212833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ['TRIDENT_BACKEND'] = 'pytorch'\n\nif is_in_kaggle_kernal():\n    os.environ['TRIDENT_HOME'] = './trident'\n    \nelif is_in_colab():\n    os.environ['TRIDENT_HOME'] = '/content/gdrive/My Drive/trident'\n\n#為確保安裝最新版 \n!pip uninstall tridentx -y\n!pip install tridentx --upgrade\nimport json\nimport copy\nimport numpy as np\n#調用trident api\nimport trident as T\nfrom trident import *\nfrom trident.models import resnet,efficientnet","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:51:58.533090Z","iopub.execute_input":"2021-07-06T03:51:58.533374Z","iopub.status.idle":"2021-07-06T03:52:12.534075Z","shell.execute_reply.started":"2021-07-06T03:51:58.533347Z","shell.execute_reply":"2021-07-06T03:52:12.533022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"由於這個競賽原始數據非常巨大，也因此我們無法直接載入，我已經將所需要的部分檔案上傳到我的google drive並開放權限。然後您只需要利用trident api中的download_file_from_google_drive函數即可方便的下載，預設下載目錄會是trident api的主資料夾下方的downloads資料夾。下載後，我們可以透過讀讀取標註json檔來解讀標註內容。","metadata":{}},{"cell_type":"markdown","source":"了解你的數據是在做數據分析前非常重要的階段，我們也稱這個階段為DAE (Data Exploration Analysis)，如果是處理表格型態的內容，最方便的莫過於pandas。身為數據科學家，千萬不要講到熊貓直覺反應是要點外賣。pandas最大的好處在於它整合了多種數據來源的讀取與寫入，即使是像這次屬於非結構數據的json檔，它也能轉換成表格型態數據(DataFrame)","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\nwith open('../input/iwildcam-2020-fgvc7/iwildcam2020_train_annotations.json') as json_file:\n    train_data = json.load(json_file)\n\n\nwith open('../input/iwildcam-2020-fgvc7/iwildcam2020_test_information.json') as test_json_file:\n    test_data = json.load(test_json_file)\n\n    \ndf_train = pd.DataFrame({'id': [item['id'] for item in train_data['annotations']],\n                         'category_id': [item['category_id'] for item in train_data['annotations']],\n                         'image_id': [item['image_id'] for item in train_data['annotations']],\n                         'location': [item['location'] for item in train_data['images']],\n                         'file_name': [item['file_name'] for item in train_data['images']]})\ndf_test = pd.DataFrame({'image_id': [item['id'] for item in train_data['images']],\n                         'location': [item['location'] for item in train_data['images']],\n                         'file_name': [item['file_name'] for item in train_data['images']]})\n\n\n\ndf_train","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:12.535886Z","iopub.execute_input":"2021-07-06T03:52:12.536424Z","iopub.status.idle":"2021-07-06T03:52:15.401653Z","shell.execute_reply.started":"2021-07-06T03:52:12.536378Z","shell.execute_reply":"2021-07-06T03:52:15.400848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"接下來可以透過類似的方式將train_data['categories']取出建構成新的dtaframe，並列印一下，這才知道，原來出現最多次的是「人類」這種動物。而除了人類這種動物之外，是一種叫做「眼斑吐綬雞(meleagris ocellata)」的動物。而更變態的是，標註中的類別還出現了0次的動物，而且數量還不少。所以我們這時可以做個過濾，排除掉不存在於圖片標註中的類別","metadata":{}},{"cell_type":"markdown","source":"我們可以利用is_in這個函數來進行欄位的篩選，這才知道像是舊世界綠猴(chlorocebus pygerythrus)等動物其實只出現過一次，而原本類別檔中出現最多次的人類竟然不見了，可見category中的數量是完全不可信的，只能參考它的category_id以及名稱之間的對應。更糟的是，雖然訓練及與測試集的類別表看起來是一致的，但是由於它不可能給測試集的標註，我們只能根據category中數量大於零來作為判斷，然後一去重複比對之下，竟然出現測試集出現了意料之外的動物的這種劇情。我檢查半天我沒寫錯，查了一下討論區，看到了以下留言：\n\nhttps://www.kaggle.com/c/iwildcam-2020-fgvc7/discussion/143071\n\n好吧，只能暫時相信出題方了。而也因此我開始擔心圖片annotations中的註記是否跟圖片一致....","metadata":{}},{"cell_type":"code","source":"df_category_train=pd.DataFrame({'id': [item['id'] for item in train_data['categories']],\n                         'name': [item['name'] for item in train_data['categories']],\n                         'count': [item['count'] for item in train_data['categories']]})\n\ndf_category_test=pd.DataFrame({'id': [item['id'] for item in test_data['categories']],\n                         'name': [item['name'] for item in test_data['categories']],\n                         'count': [item['count'] for item in test_data['categories']]})\n\ndf_category_train=df_category_train.sort_values(['count'],ascending=False) \nprint(df_category_train)\ndf_category_test=df_category_test.sort_values(['count'],ascending=False) \nprint(df_category_test)\n\n#基於標註檔，產生有在標註檔內的所有圖片的清單，進行去重複(set)、排序(sorted)以及轉換成清單(list)\nanimal_category_lists=list(sorted(set([item['category_id'] for item in train_data['annotations']])))\n\n\n#進行篩選\ndf_category_train=df_category_train[df_category_train['id'].isin(animal_category_lists)]\nprint(df_category_train)\n\ndf_category_test=df_category_test[df_category_test['count']>0]\nprint(df_category_test)\n\nanimal_category_lists_train=[category_id.item() for category_id in df_category_train[['id']].to_numpy().astype(np.int64)]\nprint(animal_category_lists_train[:5])\n\nanimal_category_lists_test=[category_id.item() for category_id in df_category_test[['id']].to_numpy().astype(np.int64)]\nprint(animal_category_lists_test[:5])\n\n#檢查是不是所有df_category_test數量不為零的動物都有出現在df_category_train的類別代號中\ncategory_missing_list=[category_id for category_id in animal_category_lists_test if category_id not in animal_category_lists_train]\nprint(category_missing_list)\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:15.403610Z","iopub.execute_input":"2021-07-06T03:52:15.403973Z","iopub.status.idle":"2021-07-06T03:52:15.465451Z","shell.execute_reply.started":"2021-07-06T03:52:15.403934Z","shell.execute_reply":"2021-07-06T03:52:15.464311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"除了數量外，我們也要注意到，出現最多的動物以及出現最少的動物，其圖片數量相差了1.6萬倍，我們可以透過value_counts()來計算次數分配表，然後透過pandas中的plot自動畫圖。","metadata":{}},{"cell_type":"code","source":"#with open('../input/iwildcam-2020-fgvc7/iwildcam2020_megadetector_results.json') as json_file:\n#    detector_data = json.load(json_file)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:15.467030Z","iopub.execute_input":"2021-07-06T03:52:15.467376Z","iopub.status.idle":"2021-07-06T03:52:15.471616Z","shell.execute_reply.started":"2021-07-06T03:52:15.467340Z","shell.execute_reply":"2021-07-06T03:52:15.470561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#print(detector_data)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:15.473295Z","iopub.execute_input":"2021-07-06T03:52:15.473703Z","iopub.status.idle":"2021-07-06T03:52:15.480633Z","shell.execute_reply.started":"2021-07-06T03:52:15.473636Z","shell.execute_reply":"2021-07-06T03:52:15.479880Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"由於有許多動物只出現一次，為了避免包含只有出現過一次的動物的圖片因為數據增強或是其他因素意外的沒有呈現出該動物特徵而讓整個動物類別都無法識別，因此，我打算先把所有出現頻率超低的動物先列出來，然後將包含這些動物的圖片多複製幾分與原圖片集融合，這樣就比較不會有前述的問題。","metadata":{}},{"cell_type":"code","source":"rare_animals=OrderedDict()\ndf_animal_frequency=df_train['category_id'].value_counts()\ndf_animal_frequency=df_animal_frequency[df_animal_frequency<=10]\nfor item in  df_animal_frequency.iteritems() :\n    print(item)\n    rare_animals[item[0]]=item[1]","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:15.481801Z","iopub.execute_input":"2021-07-06T03:52:15.482342Z","iopub.status.idle":"2021-07-06T03:52:15.504359Z","shell.execute_reply.started":"2021-07-06T03:52:15.482303Z","shell.execute_reply":"2021-07-06T03:52:15.503599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"我們可以透過以下語法抓出所有圖片，以及統計一下數量。經過去重複，還好去重前後數量都是217959，這個數字是合的。沒有出現我覺得最討人厭的一張照片出現兩種動物，也因此，這個題目是可以符合圖像識別的要求(但這只是最低要求，我只是要用它做個baseline以及展示一下多類別不均衡如何解)，那我們就開始來做出baseline吧。","metadata":{}},{"cell_type":"code","source":"import glob\n#透過glob所全部train資料夾中所有可用圖片\nimgs=glob.glob('../input/iwildcam-2020-fgvc7/train/*.jpg')\nprint(len(imgs))\nprint(imgs[:5])\n\n#將圖檔路徑去除資料夾部分後進行去重複\nimg_pathes=[img.split('/')[-1] for img in imgs]\nimg_pathes=list(sorted(set(img_pathes)))\nprint(len(img_pathes))\nprint(img_pathes[:5])\n\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:15.505491Z","iopub.execute_input":"2021-07-06T03:52:15.505810Z","iopub.status.idle":"2021-07-06T03:52:16.572793Z","shell.execute_reply.started":"2021-07-06T03:52:15.505777Z","shell.execute_reply":"2021-07-06T03:52:16.571833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"但是仔細看可以發現，我們的動物類別id並不是連續數字，中間是有跳過的，而且既然出題方都說了測試集不會出現意料之外的動物，那麼我們就按照訓練集出來的類別清單(animal_category_lists_train)來建構標籤囉。","metadata":{}},{"cell_type":"code","source":"label2category=OrderedDict()\ncategory2label=OrderedDict()\n#產生能將category_id轉label的字典\nfor i in range(len(animal_category_lists_train)):\n    category2label[animal_category_lists_train[i]]=i\n    label2category[i]=animal_category_lists_train[i]\n\n#建構出轉成標籤id\nlabel_idxes=[category2label[item['category_id']] for item in train_data['annotations']]\nimage_pathes=['../input/iwildcam-2020-fgvc7/train/'+item['file_name'] for item in train_data['images']]\n\nprint('label_idxes',label_idxes[:5])\nprint('image_pathes',image_pathes[:5])\nprint('label2category',list(label2category.items())[:5])\nprint('category2label',list(category2label.items())[:5])","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:19.830159Z","iopub.execute_input":"2021-07-06T03:52:19.830494Z","iopub.status.idle":"2021-07-06T03:52:19.935929Z","shell.execute_reply.started":"2021-07-06T03:52:19.830464Z","shell.execute_reply":"2021-07-06T03:52:19.934919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nrare_images=[]\nrare_labels=[]\nfor i in range(len(image_pathes)):\n    img=image_pathes[i]\n    label=label_idxes[i]\n    if label2category[label] in rare_animals:\n        cnt=rare_animals[label2category[label]]\n        for n in range(int(20.0/cnt)):\n             rare_images.append(img) \n             rare_labels.append(label) \n        \nprint(len(rare_images))\nprint(len(rare_labels))\nprint(rare_images[:5])\nprint(rare_labels[:5])","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:23.263599Z","iopub.execute_input":"2021-07-06T03:52:23.264023Z","iopub.status.idle":"2021-07-06T03:52:23.435881Z","shell.execute_reply.started":"2021-07-06T03:52:23.263983Z","shell.execute_reply":"2021-07-06T03:52:23.434964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_size = (300,300)\n\nimg_ds=ImageDataset(image_pathes+rare_images,symbol='image')\nlabel_ds=LabelDataset(label_idxes+rare_labels,symbol='label')\n\n#與Iterator構成data provider\ndata_provider=DataProvider(traindata=Iterator(data=img_ds,label=label_ds))\n\ndata_provider.image_transform_funcs=[\n    Resize(train_size),\n    CLAHE(),\n    RandomAdjustGamma(scale=(0.8,1.2)),#調整明暗\n    RandomAdjustHue(scale=(-0.2,0.2)),#調整色相\n    RandomAdjustSaturation(scale=(0.8,1.2)),#調整飽和度\n    SaltPepperNoise(0.005, keep_prob=0.5),#加入胡椒鹽噪音\n    RandomErasing(size_range=(0.05, 0.2), transparency_range=(0.4, 0.8), transparancy_ratio=1.0, keep_prob=0.5), #加入隨機擦去\n    RandomTransformAffine(rotation_range=45, zoom_range=0.00, shift_range=0.00, shear_range=0.2, random_flip=0.15),#隨機仿射變換\n    Normalize(127.5,127.5)] #標準化\n\n\ndata,labels=data_provider.next()\nprint(data.shape)\nprint(labels)\n\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:27.822480Z","iopub.execute_input":"2021-07-06T03:52:27.822826Z","iopub.status.idle":"2021-07-06T03:52:33.133807Z","shell.execute_reply.started":"2021-07-06T03:52:27.822793Z","shell.execute_reply":"2021-07-06T03:52:33.132992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"用preview_images預覽一下圖片，一看嚇到，是我運氣不好嗎?一預覽就看到一堆純黑的圖。","metadata":{}},{"cell_type":"code","source":"%%time\ndata_provider.preview_images()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:33.141727Z","iopub.execute_input":"2021-07-06T03:52:33.143879Z","iopub.status.idle":"2021-07-06T03:52:34.230658Z","shell.execute_reply.started":"2021-07-06T03:52:33.143836Z","shell.execute_reply":"2021-07-06T03:52:34.229625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom trident.models import efficientnet\n\nnet1=efficientnet.EfficientNetB0(pretrained=True,include_top=False,classes=len(animal_category_lists_train),input_shape=(3,train_size[1],train_size[0]),freeze_features=True)\nnet1.model.add_module('last_conv',Conv2d_Block((3,3),num_filters=len(animal_category_lists_train),use_bias=False,activation=None, normalization='l2'))\ncam=ShortCut(\n    Identity(),\n    Sequential(\n    GlobalAvgPool2d(),\n    Reshape((len(animal_category_lists_train),1,1)),\n    Conv2d((1,1),num_filters=len(animal_category_lists_train),use_bias=False,activation=None)\n    )\n,mode='dot'\n)\n\nnet1.model.add_module('cam',cam)\nnet1.model.add_module('aggregate1',Aggregation('sum',axis=2))\nnet1.model.add_module('aggregate2',Aggregation('sum',axis=3))\nnet1.model.add_module('reshape',Reshape((len(animal_category_lists_train))))\nnet1.model.add_module('sigmoid',Sigmoid())\nnet1.model.add_module('fc',Dense((len(animal_category_lists_train))))\nnet1.model.add_module('softmax',SoftMax(axis=-1,add_noise=True,noise_intensity=0.12))\nnet1.summary()\n\nnet1.model.block7a.trainable=True","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:42.373930Z","iopub.execute_input":"2021-07-06T03:52:42.374293Z","iopub.status.idle":"2021-07-06T03:52:47.459678Z","shell.execute_reply.started":"2021-07-06T03:52:42.374257Z","shell.execute_reply":"2021-07-06T03:52:47.458870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from trident.models import visual_transformer\nvit=visual_transformer.VisionTransformer_small(input_shape=(3,train_size[1],train_size[0]),patch_size=16,num_classes=len(animal_category_lists_train))\nvit.model.trainable=True\nvit.summary()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:52:58.391430Z","iopub.execute_input":"2021-07-06T03:52:58.391760Z","iopub.status.idle":"2021-07-06T03:52:59.020336Z","shell.execute_reply.started":"2021-07-06T03:52:58.391724Z","shell.execute_reply":"2021-07-06T03:52:59.019421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"is_resume=False  #是否接續訓練\n\n#如果是接續訓練且存在歷史存檔，則載入之\nif is_resume:\n    if os.path.exists('./Models/revised2_net1.pth'):\n        net1.load_model('./Models/revised2_net1.pth')\n        net1.model.block7a.trainable=True\n        print('net1 loaded!!')\n\n    if os.path.exists('./Models/revised2_vit.pth'):\n        vit.load_model('./Models/revised2_vit.pth')\n        print('vit loaded!!')","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:53:00.228859Z","iopub.execute_input":"2021-07-06T03:53:00.229211Z","iopub.status.idle":"2021-07-06T03:53:00.234589Z","shell.execute_reply.started":"2021-07-06T03:53:00.229180Z","shell.execute_reply":"2021-07-06T03:53:00.233504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"這兩個baseline主要是用來確認，哪一個類別不平衡的校正策略比較好。請注意，由於建模圖片數量又多，圖檔尺寸又超大，即使只跑一個epoch都要很久，為了不浪費gpu時數資源，請注意，建議要把Resize類的轉換放在第一個，時間會差非常非常多...還有不要用原來的start_now()，改用only_steps(num_steps=步數)只需要指定步數即可。","metadata":{}},{"cell_type":"code","source":"net1.with_optimizer(optimizer=AdaBelief,lr=1e-3,betas=(0.9, 0.999),gradient_centralization='all')\\\n.with_loss(CrossEntropyLoss(auto_balance=True))\\\n.with_loss(FocalLoss,loss_weight=0.5)\\\n.with_metric(accuracy,name='accuracy')\\\n.with_metric(accuracy,topk=5,name='top5_accuracy',print_only=True)\\\n.with_regularizer('l2',reg_weight=5e-5)\\\n.adjust_learning_rate_scheduling(200,unit='batch',new_value=5e-4)\\\n.with_accumulate_grads(4)\\\n.with_callbacks(MixupCallback(alpha= 1,loss_criterion=CrossEntropyLoss,loss_weight=0.5))\\\n.with_learning_rate_scheduler(StepLR(frequency=1000,unit='batch',gamma=0.5))\\\n.with_model_save_path('./Models/revised2_net1.pth')\\\n.with_automatic_mixed_precision_training()\n\n\n#transformer一樣也是可以使用mixup的\nvit.with_optimizer(optimizer=Lamb,lr=1e-3,betas=(0.9, 0.999),gradient_centralization='all')\\\n.with_loss(CrossEntropyLoss(auto_balance=True))\\\n.with_loss(FocalLoss,loss_weight=0.5)\\\n.with_metric(accuracy,name='accuracy')\\\n.with_metric(accuracy,topk=5,name='top5_accuracy',print_only=True)\\\n.with_regularizer('l2',reg_weight=5e-5)\\\n.with_accumulate_grads(4)\\\n.with_grad_clipping(3)\\\n.with_callbacks(MixupCallback(alpha= 1,loss_criterion=CrossEntropyLoss,loss_weight=0.5))\\\n.with_learning_rate_scheduler(StepLR(frequency=1000,unit='batch',gamma=0.5))\\\n.with_model_save_path('./Models/revised2_vit.pth')\\\n.with_automatic_mixed_precision_training()\n\n\n#如果兩個模型都做mixup，批次設定到64，gpu會爆掉\nplan=TrainingPlan()\\\n    .add_training_item(net1,name='net1')\\\n    .add_training_item(vit,name='vit')\\\n    .with_data_loader(data_provider)\\\n    .with_batch_size(16)\\\n    .repeat_epochs(1)\\\n    .print_gradients_scheduling(20,unit='batch') \\\n    .print_progress_scheduling(5,unit='batch') \\\n    .display_loss_metric_curve_scheduling(100)\\\n    .save_model_scheduling(10,unit='batch')\n\n\nplan.only_steps(num_steps=4000, collect_data_inteval=5)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:53:24.337017Z","iopub.execute_input":"2021-07-06T03:53:24.337347Z","iopub.status.idle":"2021-07-06T06:59:06.491665Z","shell.execute_reply.started":"2021-07-06T03:53:24.337316Z","shell.execute_reply":"2021-07-06T06:59:06.490124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"之前的提交範例是一筆一筆的推論，結合infer_single_image，所有有人問到，難道不可以一整個批次推論嗎?能否將數據包裝成data provider來進行批次推論呢？可以的，請參考以下範例。","metadata":{}},{"cell_type":"code","source":"bad_images=['86994b3e-21bc-11ea-a13a-137349068a90.jpg',\n'882a533a-21bc-11ea-a13a-137349068a90.jpg',\n'88a28616-21bc-11ea-a13a-137349068a90.jpg',\n'88b99aae-21bc-11ea-a13a-137349068a90.jpg',\n'89362ed4-21bc-11ea-a13a-137349068a90.jpg',\n'8985bb98-21bc-11ea-a13a-137349068a90.jpg',\n'89e09b26-21bc-11ea-a13a-137349068a90.jpg',\n'8a804608-21bc-11ea-a13a-137349068a90.jpg',\n'8b8e02a6-21bc-11ea-a13a-137349068a90.jpg',\n'8b91394e-21bc-11ea-a13a-137349068a90.jpg',\n'8cc46b6a-21bc-11ea-a13a-137349068a90.jpg',\n'8d705d8a-21bc-11ea-a13a-137349068a90.jpg',\n'8e930668-21bc-11ea-a13a-137349068a90.jpg',\n'8e940310-21bc-11ea-a13a-137349068a90.jpg',\n'8ea6a768-21bc-11ea-a13a-137349068a90.jpg',\n'8fff9dc2-21bc-11ea-a13a-137349068a90.jpg',\n'9044a3b8-21bc-11ea-a13a-137349068a90.jpg',\n'920ee4c4-21bc-11ea-a13a-137349068a90.jpg',\n'950ed288-21bc-11ea-a13a-137349068a90.jpg',\n'9522d4fe-21bc-11ea-a13a-137349068a90.jpg',\n'96bacf06-21bc-11ea-a13a-137349068a90.jpg',\n'98552f5a-21bc-11ea-a13a-137349068a90.jpg',\n'98da656c-21bc-11ea-a13a-137349068a90.jpg',\n'9955d012-21bc-11ea-a13a-137349068a90.jpg']\n\n\n\ntest_imgs=glob.glob('../input/iwildcam-2020-fgvc7/test/*.jpg')\nprint(len(test_imgs))\ntest_imgs=[img_path for img_path in test_imgs if img_path.split('/')[-1] not in bad_images]\nprint(len(test_imgs))\n\n\nimg_ds=ImageDataset(test_imgs,symbol='image')\n#請注意，要設定object_type=ObjectType.image_path，這樣就可以確保輸出為stype=np.string_的numpy array\nimgpath_ds=ImageDataset(test_imgs,object_type=ObjectType.image_path,symbol='img_path')\n\n#與Iterator構成data provider\n#設定is_shuffle=False表示不隨機打亂\ntest_data_provider=DataProvider(traindata=Iterator(data=img_ds,label=imgpath_ds,is_shuffle=False))\n\n#保留有意義的數據清洗\ntest_data_provider.image_transform_funcs=[\n    Resize((224,224)),\n    CLAHE(),\n    Normalize(127.5,127.5)] #標準化\n\n\ndata,labels=test_data_provider.next()\nprint(data.shape)\nprint(labels)\nprint(labels[0].decode())\ntest_data_provider.preview_images()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T06:59:06.495747Z","iopub.execute_input":"2021-07-06T06:59:06.496028Z","iopub.status.idle":"2021-07-06T06:59:09.055462Z","shell.execute_reply.started":"2021-07-06T06:59:06.496002Z","shell.execute_reply":"2021-07-06T06:59:09.049450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subms = []\nwith open('../input/iwildcam-2020-fgvc7/sample_submission.csv') as file:\n    lines = file.readlines()\n\nfor id, line in enumerate(lines):\n    line = line.replace('\\n','').split(',')\n    if id>0:\n        subms.append(line[0])\n    \nprint(len(subms))\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T07:18:31.340912Z","iopub.execute_input":"2021-07-06T07:18:31.341237Z","iopub.status.idle":"2021-07-06T07:18:31.410317Z","shell.execute_reply.started":"2021-07-06T07:18:31.341207Z","shell.execute_reply":"2021-07-06T07:18:31.409269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"這段語法可以用來清除gpu快取，可以釋放出更多的GPU","metadata":{}},{"cell_type":"code","source":"import torch\ntorch.cuda.synchronize()\ntorch.cuda.empty_cache()\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T06:59:14.653051Z","iopub.execute_input":"2021-07-06T06:59:14.653816Z","iopub.status.idle":"2021-07-06T06:59:15.339072Z","shell.execute_reply.started":"2021-07-06T06:59:14.653764Z","shell.execute_reply":"2021-07-06T06:59:15.337833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_model = net1\n\nwith open('my_submission.csv','w',encoding='utf-8-sig') as subfile:\n    subfile.write('Id,Category\\n')\n    for file in tqdm(subms):\n        fname = '../input/iwildcam-2020-fgvc7/test/{}.jpg'.format(file)\n        if os.path.exists(fname):\n            timg = cv2.imread(fname)\n        try:\n            timg = cv2.resize(timg, train_size)\n            timg = (timg-127.5)/127.5\n            infer_results=best_model.infer_single_image(timg)\n            infre = label2category[np.argmax(infer_results, axis=0)]\n        except:\n            print('cannot infre', fname)\n            infre = 0\n            pass\n        \n        subfile.writelines('{},{}\\n'.format(subms,infre))","metadata":{"execution":{"iopub.status.busy":"2021-07-06T08:04:03.742174Z","iopub.execute_input":"2021-07-06T08:04:03.742504Z","iopub.status.idle":"2021-07-06T08:23:37.849493Z","shell.execute_reply.started":"2021-07-06T08:04:03.742472Z","shell.execute_reply":"2021-07-06T08:23:37.847887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'Models/revised2_net1.pth')","metadata":{"execution":{"iopub.status.busy":"2021-07-06T08:25:27.173026Z","iopub.execute_input":"2021-07-06T08:25:27.173344Z","iopub.status.idle":"2021-07-06T08:25:27.178339Z","shell.execute_reply.started":"2021-07-06T08:25:27.173315Z","shell.execute_reply":"2021-07-06T08:25:27.177405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"net1.eval()\nvit.eval()\n\ntest_data_provider.batch_size=64\ntest_data_provider.traindata.batch_sampler.reset()\n\nsubmission_rows=['Id,Category\\n']\nfor i,(img,img_path) in tqdm(enumerate(test_data_provider)):\n    out1=net1(img)\n\n    out2=vit(img)\n    #基於輸出平均值\n    out3=np.argmax((out1+out2)/2,axis=1)\n    #基於兩個模型評估的最大機率\n    #out3=np.argmax(np.where(out1>out2,out1,out2),axis=1)\n    for k in range(len(out3)):\n        _,image_id,_=split_path(img_path[k].decode())\n        if i==0 and k==0:\n            print(image_id)\n        category_id=label2category[out3[k]]\n        if image_id in submission_dict and image_id+'.jpg' not in bad_images:\n            submission_dict[image_id]=category_id\n        #submission_rows.append('{0},{1}\\n'.format(image_id,category_id))\n        #if  (len(submission_rows)-1)%1000==0:\n        #    print('{0}'.format(len(submission_rows)-1))\n        if None not in submission_dict.value_list:\n            break\n  \n \n\n        \n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T06:59:15.340944Z","iopub.execute_input":"2021-07-06T06:59:15.341405Z","iopub.status.idle":"2021-07-06T06:59:20.454639Z","shell.execute_reply.started":"2021-07-06T06:59:15.341333Z","shell.execute_reply":"2021-07-06T06:59:20.452525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for k,v in submission_dict.items():\n    submission_rows.append('{0},{1}\\n'.format(k,v))\nprint(len(submission_rows))\nwith open('results/submission.csv','w',encoding='utf-8-sig') as f:\n    f.writelines(submission_rows)\n\nfr=open('results/submission.csv','r',encoding='utf-8-sig')\nrows=fr.readlines()\nprint(rows[:3])\n        ","metadata":{"execution":{"iopub.status.busy":"2021-07-06T06:59:20.455856Z","iopub.status.idle":"2021-07-06T06:59:20.456577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"api_token= {\"username\":\"chenghsuntseng\",\"key\":\"44cfe92076e822340cdabfa0083ae642\"} #請換成你自己的kaggle認證#請換成你自己的kaggle認證\nimport json\nimport zipfile\nimport os\n\n\nif not os.path.exists(\"/root/.kaggle\"):\n    os.makedirs(\"/root/.kaggle\")\n \nwith open('/root/.kaggle/kaggle.json', 'w') as file:\n    json.dump(api_token, file)\n!chmod 600 /root/.kaggle/kaggle.json\n\n\nif not os.path.exists(\"/kaggle\"):\n    os.makedirs(\"/kaggle\")\n\n\n!kaggle competitions submit -c iwildcam-2020-fgvc7 -f 'results/submission.csv' -m 'my test-5 wild_cam race.'","metadata":{"execution":{"iopub.status.busy":"2021-07-06T06:59:20.457805Z","iopub.status.idle":"2021-07-06T06:59:20.458419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}