{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nprint('1:  ',os.getcwd())  # 当前文件所在的路径\nprint('2:  ',os.listdir(os.getcwd()))  # 在/kaggle/working文件夹下有两个隐藏文件['.ipynb_checkpoints', '__notebook_source__.ipynb']\n# print('3:  ',os.listdir(\"../../\"))\nprint('4:  ',os.listdir(\"../\"))\nprint('5:  ',os.listdir(\"../input\"))   # input data\nprint('6:  ',os.listdir(\"../../kaggle\"))\nprint('7:  ',os.listdir(\"../../kaggle/working\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"package_paths = [\n    '../input/pytorch-image-models/pytorch-image-models-master',\n    '../input/image-fmix',\n    '../input/efficientnet-pytorch-07',  \n    '../input/cassava-utils',\n    '../input/cassava-utils'\n    \n]\n\nimport sys;\n\nfor pth in package_paths:\n    sys.path.append(pth)\n  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from cassavautils import seed_everything,get_img,rand_bbox, CassavaDataset,prepare_dataloader,train_one_epoch,valid_one_epoch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 导入依赖的库\n\nimport torch\nimport os\nimport time\nimport random\nimport pandas as pd\nimport numpy as np\nimport torch.nn.functional as F\n\nimport timm\nimport cv2\n\n\nfrom tqdm import tqdm\nfrom torch import nn\nfrom fmix import sample_mask, make_low_freq_image,binarise_mask\nfrom sklearn.model_selection import GroupKFold, StratifiedKFold\n\nfrom torch.utils.data import Dataset,DataLoader\nfrom torch.cuda.amp import GradScaler, autocast\nfrom torch.nn.modules.loss import _WeightedLoss\nfrom timm.models.layers import SelectAdaptivePool2d,Linear,create_conv2d,get_act_fn,hard_sigmoid\n\n\nfrom imp import reload\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import (\n    HorizontalFlip, VerticalFlip, IAAPerspective, ShiftScaleRotate, CLAHE, RandomRotate90,\n    Transpose, ShiftScaleRotate, Blur, OpticalDistortion, GridDistortion, HueSaturationValue,\n    IAAAdditiveGaussianNoise, GaussNoise, MotionBlur, MedianBlur, IAAPiecewiseAffine, RandomResizedCrop,\n    IAASharpen, IAAEmboss, RandomBrightnessContrast, Flip, OneOf, Compose, Normalize, Cutout, CoarseDropout,\n    ShiftScaleRotate, CenterCrop, Resize\n)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_img_path = '../input/cassava-leaf-disease-classification/train_images' #样本图片的路径\ntrain_csv_path = '../input/cassava-leaf-disease-classification/train.csv' #训练集合标记CSV","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 训练集数据增强\ndef get_train_transforms():\n    return Compose([\n        RandomResizedCrop(CFG['img_size'], CFG['img_size']),\n        Transpose(p=0.5),\n        HorizontalFlip(p=0.5),\n        VerticalFlip(p=0.5),\n        ShiftScaleRotate(p=0.5),\n        HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit=0.2, val_shift_limit=0.2, p=0.5),\n        RandomBrightnessContrast(brightness_limit=(-0.1, 0.1), contrast_limit=(-0.1, 0.1), p=0.5),\n        Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225], max_pixel_value=255.0, p=1.0),\n        CoarseDropout(p=0.5),\n        Cutout(p=0.5),\n        ToTensorV2(p=1.0),\n    ], p=1.)\n\n\n# 验证集的数据增强较少，是为了防止目标的特征损失\n# 验证集数据增强\ndef get_valid_transforms():\n    return Compose([\n        CenterCrop(CFG['img_size'], CFG['img_size'], p=1.),\n        Resize(CFG['img_size'], CFG['img_size']),\n        Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225], max_pixel_value=255.0, p=1.0),\n        ToTensorV2(p=1.0),\n    ], p=1.)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 引入RFB_module;\nclass BasicConv(nn.Module):\n    def __init__(self,\n                 in_planes,\n                 out_planes,\n                 kernel_size,\n                 stride=1,\n                 padding=0,\n                 dilation=1,\n                 groups=1,\n                 relu=True,\n                 bn=True,\n                 bias=False):\n        super(BasicConv, self).__init__()\n        self.out_channels = out_planes\n        self.conv = nn.Conv2d(in_planes,\n                              out_planes,\n                              kernel_size=kernel_size,\n                              stride=stride,\n                              padding=padding,\n                              dilation=dilation,\n                              groups=groups,\n                              bias=bias)\n        self.bn = nn.BatchNorm2d(\n            out_planes, eps=1e-5, momentum=0.01, affine=True) if bn else None\n        self.relu = nn.ReLU(inplace=True) if relu else None\n\n    def forward(self, x):\n        x = self.conv(x)\n        if self.bn is not None:\n            x = self.bn(x)\n        if self.relu is not None:\n            x = self.relu(x)\n        return x\n\n\nclass BasicRFB_small(nn.Module):\n    '''\n    [rfbs]\n    filters = 128\n    stride=1 or 2\n    scale = 1.0\n    '''\n    def __init__(self, in_planes, out_planes, stride=1, scale=0.1):\n        super(BasicRFB_small, self).__init__()\n        self.scale = scale\n        self.out_channels = out_planes\n        inter_planes = in_planes // 4\n\n        self.branch0 = nn.Sequential(\n            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=3,\n                      stride=1,\n                      padding=1,\n                      relu=False))\n        self.branch1 = nn.Sequential(\n            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=(3, 1),\n                      stride=1,\n                      padding=(1, 0)),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=3,\n                      stride=1,\n                      padding=3,\n                      dilation=3,\n                      relu=False))\n        self.branch2 = nn.Sequential(\n            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=(1, 3),\n                      stride=stride,\n                      padding=(0, 1)),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=3,\n                      stride=1,\n                      padding=3,\n                      dilation=3,\n                      relu=False))\n        self.branch3 = nn.Sequential(\n            BasicConv(in_planes, inter_planes // 2, kernel_size=1, stride=1),\n            BasicConv(inter_planes // 2, (inter_planes // 4) * 3,\n                      kernel_size=(1, 3),\n                      stride=1,\n                      padding=(0, 1)),\n            BasicConv((inter_planes // 4) * 3,\n                      inter_planes,\n                      kernel_size=(3, 1),\n                      stride=stride,\n                      padding=(1, 0)),\n            BasicConv(inter_planes,\n                      inter_planes,\n                      kernel_size=3,\n                      stride=1,\n                      padding=5,\n                      dilation=5,\n                      relu=False))\n\n        self.ConvLinear = BasicConv(4 * inter_planes,\n                                    out_planes,\n                                    kernel_size=1,\n                                    stride=1,\n                                    relu=False)\n        self.shortcut = BasicConv(in_planes,\n                                  out_planes,\n                                  kernel_size=1,\n                                  stride=stride,\n                                  relu=False)\n        self.relu = nn.ReLU(inplace=False)\n\n    def forward(self, x):\n        x0 = self.branch0(x)\n        x1 = self.branch1(x)\n        x2 = self.branch2(x)\n        x3 = self.branch3(x)\n\n        out = torch.cat((x0, x1, x2, x3), 1)\n        out = self.ConvLinear(out)\n        short = self.shortcut(x)\n        out = out * self.scale + short\n        out = self.relu(out)\n\n        return out\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 模型构建\nclass CassvaImgClassifier(nn.Module):\n    def __init__(self, model_arch, n_class, pretrained=False):\n        super().__init__()\n        self.model = timm.create_model(model_arch, pretrained=pretrained)\n        n_features = self.model.classifier.in_features\n\n\n        self.model.global_pool = nn.Sequential(\n            BasicFRB_small(in_planes=1792, out_planes=512,stride=1,scale=0.1),\n            SelectAdaptivePool2d(output_size=1, flatten=True)\n        )   # BasicRFB_small\n\n        self.model.classifier = nn.Linear(512, n_class)\n\n\n\n\n    def forward(self, x):\n        x = self.model(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 构建数据 配置参数\n# 使用5折训练数据，可控制当前训练第几折(0,1,2,3,4)\n# 每折训练效果不同，最终可将不同折结果融合，效果更佳；\nfold_num = 0\n\nCFG = {\n    'fold_num': 5,\n    'seed':666,\n    'model_arch': 'tf_efficientnet_b4_ns',\n    'img_size' : 512,\n    'epochs': 50,    \n    'train_bs' : 2,\n    'valid_bs' : 2,\n    'T_0': 10,\n    'lr': 1e-4,\n    'weight_decay': 1e-6,\n    'min_lr': 1e-6,\n    # support to do batch accumulation for backprop with effectively larger batch size;\n    'accum_iter':2,\n    'verbose_step':1,\n    'num_workers' : 4,\n    'device': 'cuda:0',\n}\n\n\n\ntrain = pd.read_csv(train_csv_path)\ntrain.head()\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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    torch.backends.cudnn.benchmark = True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fold_num = 0\nseed_everything(CFG['seed'])\n\nfolds = StratifiedKFold(n_splits=CFG['fold_num'],\n                        shuffle=True,\n                        random_state=CFG['seed']).split(\n                            np.arange(train.shape[0]), train.label.values)\n\ntrn_transform = get_train_transforms()\nval_transform = get_valid_transforms()\n\nfor fold, (trn_idx, val_idx) in enumerate(folds):\n    # if fold == fold_num:\n        print('Training with {} started'.format(fold))\n        print('Train : {}, Val : {}'.format(len(trn_idx), len(val_idx)))\n        train_loader, val_loader = prepare_dataloader(train,\n                                                          trn_idx,\n                                                          val_idx,\n                                                          data_root = train_img_path,\n                                                          trn_transform = trn_transform,\n                                                          val_transform = val_transform, \n                                                          bs = CFG['train_bs'], \n                                                          n_job = CFG['num_workers'])\n\n        device = torch.device(CFG['device'])\n\n        model = CassvaImgClassifier(CFG['model_arch'],\n                                    train.label.nunique(),\n                                    pretrained=False).to(device)\n        scaler = GradScaler()\n        optimizer = torch.optim.Adam(model.parameters(),\n                                     lr=CFG['lr'],\n                                     weight_decay=CFG['weight_decay'])\n\n        scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(\n            optimizer,\n            T_0=CFG['T_0'],\n            T_mult=1,\n            eta_min=CFG['min_lr'],\n            last_epoch=-1)\n\n        loss_tr = nn.CrossEntropyLoss().to(\n            device)\n        loss_fn = nn.CrossEntropyLoss().to(device)\n\n        for epoch in range(CFG['epochs']):\n            utils.train_one_epoch(epoch,\n                                model,\n                                loss_tr,\n                                optimizer,\n                                train_loader,\n                                device,\n                                scaler,\n                                scheduler=scheduler,\n                                schd_batch_update=False)\n\n            with torch.no_grad():\n                utils.valid_one_epoch(epoch,\n                                    model,\n                                    loss_fn,\n                                    val_loader,\n                                    device)\n\n            torch.save(\n                model.state_dict(),\n                '../model/{}_fold_{}_{}'.format(CFG['model_arch'], fold, epoch))\n\n        del model, optimizer, train_loader, val_loader, scaler, scheduler\n        torch.cuda.empty_cache()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}