{"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#這是jupyter 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":"2022-06-06T08:28:26.066955Z","iopub.execute_input":"2022-06-06T08:28:26.067392Z","iopub.status.idle":"2022-06-06T08:28:26.079920Z","shell.execute_reply.started":"2022-06-06T08:28:26.067305Z","shell.execute_reply":"2022-06-06T08:28:26.078552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# iWildCam2020 資料預處理","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":"2022-06-06T08:28:26.086967Z","iopub.execute_input":"2022-06-06T08:28:26.087382Z","iopub.status.idle":"2022-06-06T08:28:26.099796Z","shell.execute_reply.started":"2022-06-06T08:28:26.087338Z","shell.execute_reply":"2022-06-06T08:28:26.098583Z"},"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 ../input/trident/tridentx-0.7.5-py3-none-any.whl --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\nimport cv2\nimport glob\nimport json","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:28:26.108413Z","iopub.execute_input":"2022-06-06T08:28:26.108720Z","iopub.status.idle":"2022-06-06T08:28:44.422665Z","shell.execute_reply.started":"2022-06-06T08:28:26.108692Z","shell.execute_reply":"2022-06-06T08:28:44.421396Z"},"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":"Python是一種動態型別的語言，他不像C#這類語言需要事先宣告型別，很方便但是也很惱人，因為它不是真的沒有型別，所以你如果做的操作與型別不符仍會報錯，所以介紹一下我個人在分析時確認型別的訣竅，我會先列印出該物件的\\_\\_class\\_\\_\\.\\_\\_mro\\_\\_，也就是型別繼承的順序，例如還原過後的標註檔，它的mro顯示它是繼承dict，所以我們就可以進一步檢視它的keys()，若它是個清單，我們則可以列印出它的前5筆內容，這是我個人在處以未知型別時常用的手法。雖然\\_\\_class\\_\\_\\.\\_\\_name\\_\\_就能檢視型別名稱，但是萬一這個型別我們不認識，或者是它是繼承多種型別，那就還是無法處理，所以我乾脆使用mro，可以顯示整個物件繼承順序，這樣在實務上會比較方便判讀。","metadata":{}},{"cell_type":"code","source":"\nwith open('../input/iwildcam-2020-fgvc7/iwildcam2020_train_annotations.json') as json_file:\n    train_data = json.load(json_file)\n    #先查看文件還原後的型別\n    print(train_data.__class__.__mro__)\n    print(train_data.__class__.__name__)\n    #確認是dict，就先檢查keys\n    print(train_data.keys())\n    #查看各個keys型別\n    print(train_data['annotations'].__class__.__mro__)\n    print(train_data['images'].__class__.__mro__)\n    print(train_data['categories'].__class__.__mro__)\n    print(train_data['info'].__class__.__mro__)\n    #查看各個keys內容\n    print('annotations內容')\n    print(train_data['annotations'][:5])\n    print('images內容')\n    print(train_data['images'][:5])\n    print('categories內容')\n    print(train_data['categories'][:5])\n    print('info內容')\n    print(train_data['info'].keys())\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    print('以下為測試集數據')\n    print(test_data.__class__.__mro__)\n    print(test_data.keys())\n    print('images內容')\n    print(train_data['images'][:5])\n    print('categories內容')\n    print(train_data['categories'][:5])\n   ","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:28:44.424918Z","iopub.execute_input":"2022-06-06T08:28:44.425702Z","iopub.status.idle":"2022-06-06T08:28:46.486655Z","shell.execute_reply.started":"2022-06-06T08:28:44.425599Z","shell.execute_reply":"2022-06-06T08:28:46.485397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"了解你的數據是在做數據分析前非常重要的階段，我們也稱這個階段為DAE (Data Exploration Analysis)，如果是處理表格型態的內容，最方便的莫過於pandas。身為數據科學家，千萬不要講到熊貓直覺反應是要點外賣。pandas最大的好處在於它整合了多種數據來源的讀取與寫入，即使是像這次屬於非結構數據的json檔，它也能轉換成表格型態數據(DataFrame)","metadata":{}},{"cell_type":"code","source":"import pandas as pd\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":"2022-06-06T08:29:08.094262Z","iopub.execute_input":"2022-06-06T08:29:08.094717Z","iopub.status.idle":"2022-06-06T08:29:08.974208Z","shell.execute_reply.started":"2022-06-06T08:29:08.094683Z","shell.execute_reply":"2022-06-06T08:29:08.973086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"接下來可以透過類似的方式將train_data['categories']取出建構成新的dtaframe，並列印一下，這才知道，原來出現最多次的是「人類」這種動物。而除了人類這種動物之外，是一種叫做「眼斑吐綬雞(meleagris ocellata)」的動物。而更變態的是，標註中的類別還出現了0次的動物，而且數量還不少。所以我們這時可以做個過濾，排除掉不存在於圖片標註中的類別","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)","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:29:41.321923Z","iopub.execute_input":"2022-06-06T08:29:41.322439Z","iopub.status.idle":"2022-06-06T08:29:41.374625Z","shell.execute_reply.started":"2022-06-06T08:29:41.322390Z","shell.execute_reply":"2022-06-06T08:29:41.373184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"#基於標註檔，產生有在標註檔內的所有圖片的清單，進行去重複(set)、排序(sorted)以及轉換成清單(list)\nanimal_category_lists=list(sorted(set([item['category_id'] for item in train_data['annotations']])))\nprint(len(animal_category_lists))\n\n#進行篩選\ndf_category_train=df_category_train[df_category_train['id'].isin(animal_category_lists)]\nprint(len(df_category_train))\n\ndf_category_test=df_category_test[df_category_test['count']>0]\nprint(len(df_category_test))\n\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\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:32:16.110292Z","iopub.execute_input":"2022-06-06T08:32:16.110849Z","iopub.status.idle":"2022-06-06T08:32:16.169614Z","shell.execute_reply.started":"2022-06-06T08:32:16.110795Z","shell.execute_reply":"2022-06-06T08:32:16.168521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"除了數量外，我們也要注意到，出現最多的動物以及出現最少的動物，其圖片數量相差了1.6萬倍，我們可以透過value_counts()來計算次數分配表，然後透過pandas中的plot自動畫圖。","metadata":{}},{"cell_type":"code","source":"#設定輸出圖的尺寸與dpi\nfig=plt.figure(figsize=(12, 6), dpi=96)\n#列印出每種動物的照片數頻率分布(一張照片只計算為1，不管裡面出現多少隻)\ndf_animal_frequency=df_train['category_id'].value_counts()\n#列印df_animal_frequency直接會自動展示頭尾5筆以及欄位定義與型別\nprint(df_animal_frequency)\n#而且還可以自動畫圖\ndf_animal_frequency.plot(kind='bar')","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:33:11.922537Z","iopub.execute_input":"2022-06-06T08:33:11.922913Z","iopub.status.idle":"2022-06-06T08:33:14.718796Z","shell.execute_reply.started":"2022-06-06T08:33:11.922883Z","shell.execute_reply":"2022-06-06T08:33:14.717698Z"},"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))\n\nprint(img_pathes[:5])","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:35:12.750733Z","iopub.execute_input":"2022-06-06T08:35:12.751194Z","iopub.status.idle":"2022-06-06T08:35:17.410753Z","shell.execute_reply.started":"2022-06-06T08:35:12.751162Z","shell.execute_reply":"2022-06-06T08:35:17.409512Z"},"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[:5])\nprint(image_pathes[:5])","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:36:29.878954Z","iopub.execute_input":"2022-06-06T08:36:29.879459Z","iopub.status.idle":"2022-06-06T08:36:29.993624Z","shell.execute_reply.started":"2022-06-06T08:36:29.879396Z","shell.execute_reply":"2022-06-06T08:36:29.992114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nimg_ds=ImageDataset(image_pathes,symbol='image')\nlabel_ds=LabelDataset(label_idxes,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    RandomAdjustGamma(scale=(0.6,1.4)),#調整明暗\n    RandomAdjustHue(scale=(-0.5,0.5)),#調整色相\n    RandomAdjustSaturation(scale=(0.6,1.4)),#調整飽和度\n    SaltPepperNoise(0.01),#加入胡椒鹽噪音\n    RandomErasing(), #加入隨機擦去\n    RandomRescaleCrop((224,224),scale=(0.5,2)),#縮放裁切至(224,224)\n    Normalize(127.5,127.5)] #標準化\n\ndata,labels=data_provider.next()\nprint(data.shape)\nprint(labels)\n\n","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:38:39.166890Z","iopub.execute_input":"2022-06-06T08:38:39.167337Z","iopub.status.idle":"2022-06-06T08:38:47.901447Z","shell.execute_reply.started":"2022-06-06T08:38:39.167296Z","shell.execute_reply":"2022-06-06T08:38:47.900350Z"},"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":"2022-06-06T08:38:56.087856Z","iopub.execute_input":"2022-06-06T08:38:56.088286Z","iopub.status.idle":"2022-06-06T08:38:58.588788Z","shell.execute_reply.started":"2022-06-06T08:38:56.088233Z","shell.execute_reply":"2022-06-06T08:38:58.587858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"我決定先取200筆圖片(不使用data_provider，畢竟上面加入了數據增強，所以其輸出圖片不等於真實圖片)檢查到底那些圖是真的全黑還是接近黑而已，以及它們對應的標籤是不是0(無動物)","metadata":{}},{"cell_type":"code","source":"image_samples=image_pathes[:200]\nlabel_samples=label_idxes[:200]\nimage_avg_pixel=[]\nfor i in range(200):\n    arr=image2array(image_samples[i])\n    avg_pixel=arr.mean()\n    image_avg_pixel.append(avg_pixel)\n    if avg_pixel<30:\n        print('label:{0} image_path:{1} avg_pixel:{2}  shape:{3}'.format(label_samples[i],image_samples[i],avg_pixel,arr.shape),flush=True)\n        display.display(array2image(image2array(image_samples[i])))","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:39:47.953383Z","iopub.execute_input":"2022-06-06T08:39:47.953799Z","iopub.status.idle":"2022-06-06T08:40:17.175198Z","shell.execute_reply.started":"2022-06-06T08:39:47.953766Z","shell.execute_reply":"2022-06-06T08:40:17.173994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"還好只是自己嚇自己，原來是用錯了縮放方法，RandomRescaleCrop((224,224),scale=(0.9,1.1))是指從圖片中隨機切取出(224,224)的0.9\\~1.1倍大的區域，縮放至(224,224)，因為它們的圖片超大也因此切到局部。  \n\n另外，明暗調整前應該要加個AutoLevel，讓太暗的圖片可以變得比較清晰，也不至於暗的圖恰好遇到Gamma較大(變暗)的情形而變得更暗。此外，由於很多動物很小，所以在使用隨機擦除時，我將透明比例設為1，也就是不會有擦除部分不透明的情況(透明度介於0.4\\~0.8之間)，胡椒鹽噪音用得更收斂些，只敢用到0.005。由於縮放是將整圖縮放至(224,224)，而且這個案例不會有不適用框間不變性的問題，因此我們額外再加入RandomTransformAffine。  \n\n故意示範這個場景是要讓各位了解，不要把數據增強當作標準配方照抄，要按照目前數據情況做調整。\n","metadata":{}},{"cell_type":"code","source":"data_provider.image_transform_funcs=[\n    Resize((224,224)),\n    AutoLevel(),\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","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:43:04.546177Z","iopub.execute_input":"2022-06-06T08:43:04.546665Z","iopub.status.idle":"2022-06-06T08:43:04.555367Z","shell.execute_reply.started":"2022-06-06T08:43:04.546635Z","shell.execute_reply":"2022-06-06T08:43:04.554136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ndata_provider.preview_images()","metadata":{"execution":{"iopub.status.busy":"2022-06-06T08:43:08.343050Z","iopub.execute_input":"2022-06-06T08:43:08.343867Z","iopub.status.idle":"2022-06-06T08:43:09.434593Z","shell.execute_reply.started":"2022-06-06T08:43:08.343820Z","shell.execute_reply":"2022-06-06T08:43:09.433448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from trident.models import efficientnet\n\nnet1=efficientnet.EfficientNetB0(pretrained=True,include_top=True,classes=len(animal_category_lists_train),input_shape=(3,224,224),freeze_features=True)\n\nnet2=efficientnet.EfficientNetB0(pretrained=True,include_top=True,classes=len(animal_category_lists_train),input_shape=(3,224,224),freeze_features=True)\n\nnet1.summary()","metadata":{"execution":{"iopub.status.busy":"2022-06-06T09:08:54.003465Z","iopub.execute_input":"2022-06-06T09:08:54.003868Z","iopub.status.idle":"2022-06-06T09:08:55.625916Z","shell.execute_reply.started":"2022-06-06T09:08:54.003836Z","shell.execute_reply":"2022-06-06T09:08:55.624796Z"},"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_metric(accuracy,name='accuracy')\\\n.with_metric(accuracy,topk=5,name='top5_accuracy')\\\n.with_regularizer('l2')\\\n.with_learning_rate_scheduler(reduce_lr_on_plateau,monitor='accuracy',mode='max',factor=0.5,patience=1,cooldown=0,threshold=5e-5,warmup=0)\\\n.with_model_save_path('Models/baseline_net1.pth')\\\n.with_automatic_mixed_precision_training()\n\nnet2.with_optimizer(optimizer=AdaBelief,lr=1e-3,betas=(0.9, 0.999),gradient_centralization='all')\\\n.with_loss(CrossEntropyLoss)\\\n.with_loss(FocalLoss,loss_weight=0.5)\\\n.with_metric(accuracy,name='accuracy')\\\n.with_metric(accuracy,topk=5,name='top5_accuracy')\\\n.with_regularizer('l2')\\\n.with_learning_rate_scheduler(reduce_lr_on_plateau,monitor='accuracy',mode='max',factor=0.5,patience=1,cooldown=0,threshold=5e-5,warmup=0)\\\n.with_model_save_path('Models/baseline_net2.pth')\\\n.with_automatic_mixed_precision_training()\n\n\n\nplan=TrainingPlan()\\\n    .add_training_item(net1)\\\n    .add_training_item(net2)\\\n    .with_data_loader(data_provider)\\\n    .repeat_epochs(80)\\\n    .with_batch_size(256)\\\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#因為圖片數量實在太大，所以改用only_steps\n#而且圖片尺寸也很大，變成載入快取也要很久，建議把print_progress_scheduling設小一點\n#第一次列印進度會較久(須完全載入快取)\nplan.start_now()\n","metadata":{"execution":{"iopub.status.busy":"2022-06-06T09:08:55.627849Z","iopub.execute_input":"2022-06-06T09:08:55.628355Z"},"trusted":true},"execution_count":null,"outputs":[]}]}