{"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":"import pandas as pd\nimport numpy as np\nimport os\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nimport matplotlib.pyplot as plt\nfrom PIL import Image # pil及cv库，用于图片的打开修改等工作\nimport torchvision\nimport cv2\nprint(torch.__version__)  # 检查pytorch的版本\nprint(torch.cuda.is_available())  # 确定你的电脑的cuda版本，需要与你安装的pytorch的cuda版本匹配\nprint(torch.version.cuda)  # 确定你的电脑的cuda版本，需要与安装的pytorchd版本匹配\nPATH = \"../input/sorghum-id-fgvc-9/\"\nTRAIN_IMG = PATH + \"train_images/\"\nTEST_IMG = PATH+\"test/\"\nIMG_WIDE = 224\nIMG_HEIGHT =224\nNUM_CLASS = 100\n\nclass opts:\n    batch_size = 16\n    lr = 0.0005\n    weight_delay = 1e-4\n    epoch = 30\n    use_gpu = True;\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(opts.device)","metadata":{"execution":{"iopub.status.busy":"2022-04-26T12:20:52.344283Z","iopub.execute_input":"2022-04-26T12:20:52.344633Z","iopub.status.idle":"2022-04-26T12:20:54.292251Z","shell.execute_reply.started":"2022-04-26T12:20:52.344556Z","shell.execute_reply":"2022-04-26T12:20:54.291483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install efficientnet_pytorch\n\nfrom efficientnet_pytorch import EfficientNet\nmodel = EfficientNet.from_name('efficientnet-b2')\n\nfrom efficientnet_pytorch import EfficientNet\nmodel = EfficientNet.from_pretrained('efficientnet-b2')\n#for k,v in model.named_parameters():\n #   print('{}: {}'.format(k, v.requires_grad))\n#for k,v in model.named_parameters():\n #   if 'bn' in k:\n  #      v.requires_grad = False\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2022-04-26T12:21:25.591255Z","iopub.execute_input":"2022-04-26T12:21:25.591518Z","iopub.status.idle":"2022-04-26T12:21:37.010451Z","shell.execute_reply.started":"2022-04-26T12:21:25.591486Z","shell.execute_reply":"2022-04-26T12:21:37.009689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_msg = pd.read_csv(PATH + \"train_cultivar_mapping.csv\")\ntrain_msg.dropna(inplace=True)  #这行可以去掉标题和存在数据缺失的项\nprint (f\"number of train data = {len(train_msg)}\")\ntrain_msg.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-26T11:45:47.987871Z","iopub.execute_input":"2022-04-26T11:45:47.988132Z","iopub.status.idle":"2022-04-26T11:45:48.025317Z","shell.execute_reply.started":"2022-04-26T11:45:47.988102Z","shell.execute_reply":"2022-04-26T11:45:48.024606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#这一部分主要是pandas的应用，注意以下这些函数：apply，map，unique，index函数以及python的lambda功能\nsorghum_type = list(train_msg[\"cultivar\"].unique())\nprint(len(sorghum_type))\ntrain_msg[\"dir\"] = train_msg[\"image\"].apply( lambda image:TRAIN_IMG+image )\ntrain_msg[\"dir_is_true\"] = train_msg[\"dir\"].apply(lambda dir: os.path.exists(dir))\ntrain_msg[\"sorghum_type\"] = train_msg[\"cultivar\"].map(lambda type:sorghum_type.index(type))\ntrain_msg.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-26T11:45:50.131181Z","iopub.execute_input":"2022-04-26T11:45:50.131949Z","iopub.status.idle":"2022-04-26T11:45:59.702782Z","shell.execute_reply.started":"2022-04-26T11:45:50.131912Z","shell.execute_reply":"2022-04-26T11:45:59.702116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"RATIO = 0.9\ntfms = transforms.Compose([transforms.RandomResizedCrop(448), \n    transforms.RandomAdjustSharpness(2.),\n    transforms.RandomRotation(90),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),])\ntsfm = transforms.Compose([transforms.RandomResizedCrop(448), \n    transforms.RandomAdjustSharpness(2.),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),])\nclass MyDataset(Dataset):\n    def __init__(self,train_msg,mode = \"train\",trans = tfms):\n        \"\"\"\n        :param train_msg: 整理后的地址和品种信息\n        :param mode: 训练集/验证集\n        :param trans: 数据预处理函数\n        \"\"\"\n        self.trans = trans\n        self.mode = mode\n        num_all = int(len(train_msg))\n        num_train = int(num_all * RATIO);\n        num_val = num_all - num_train;\n        if self.mode == \"train\":\n            img_list = train_msg[:num_train]\n        elif self.mode == \"val\":\n            img_list = train_msg[num_train:num_all]\n        self.length = len(img_list)\n        self.label = img_list[\"sorghum_type\"].values\n        self.img_dir =  img_list[\"dir\"].values\n        self.img_true = img_list[\"dir_is_true\"].values\n    \n    def __len__(self):\n        return self.length\n    def __getitem__(self,item ):\n        if self.trans is None:\n                trans = transforms.Compose([\n                    transforms.Resize([IMG_WIDE, IMG_HEIGHT]),\n                    transforms.ToTensor(),\n                ])\n        else:\n            trans = self.trans\n            \n        if self.img_true[item]:\n            label = torch.tensor(self.label[item], dtype=torch.long)\n            image_path = self.img_dir[item]\n            image = Image.open(image_path)\n            #image = cv2.imread(image_path)\n            #image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n            image = trans(image)\n        else:\n            self.length -= 1\n            print(f\"loss picture {item}\")\n        return image,  label\n\nclass TestDataset(Dataset):\n    def __init__(self,test_msg,trans = tsfm):\n        self.trans = trans\n        self.length = len(test_msg)\n        self.name  =test_msg[\"filename\"].values\n        self.img_dir =  test_msg[\"dir\"].values\n        self.img_true = test_msg[\"dir_is_true\"].values\n    def __len__(self):\n        return self.length\n    def __getitem__(self,item ):\n        if self.trans is None:\n                trans = transforms.Compose([\n                    transforms.Resize([IMG_WIDE, IMG_HEIGHT]),\n                    transforms.ToTensor(),\n                ])\n        else:\n            trans = self.trans\n            \n        if self.img_true[item]:\n            image_path = self.img_dir[item]\n            image = Image.open(image_path)\n            image = trans(image)\n        else:\n            self.length -= 1\n            print(f\"loss picture {item}\")\n        return image,self.name[item]\n        ","metadata":{"execution":{"iopub.status.busy":"2022-04-26T11:46:02.321638Z","iopub.execute_input":"2022-04-26T11:46:02.322171Z","iopub.status.idle":"2022-04-26T11:46:02.340996Z","shell.execute_reply.started":"2022-04-26T11:46:02.322136Z","shell.execute_reply":"2022-04-26T11:46:02.340237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"KMP_DUPLICATE_LIB_OK\"] = \"TRUE\"\ndataset_val = MyDataset(train_msg, mode='train')\nval_loader = DataLoader(dataset_val, batch_size=40, shuffle=True)\ni = 0\n#取验证集中的40张图片显示\nfor batch in val_loader:\n    \n    if (i == 0):\n        images,labels= batch\n        print(type(images))\n        i += 1\n    else:\n        break\ngrid = torchvision.utils.make_grid(images, nrow=10)\nprint(labels)\nplt.figure(figsize=(20, 20))\nplt.imshow(np.transpose(grid, (1, 2, 0)))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-26T11:42:58.573981Z","iopub.execute_input":"2022-04-26T11:42:58.574252Z","iopub.status.idle":"2022-04-26T11:43:05.678935Z","shell.execute_reply.started":"2022-04-26T11:42:58.574224Z","shell.execute_reply":"2022-04-26T11:43:05.677165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from collections import namedtuple\n_GoogLeNetOuputs = namedtuple('GoogLeNetOuputs', ['logits', 'aux_logits2', 'aux_logits1'])\nclass GoogLeNet(nn.Module):\n\n    def __init__(self, num_classes=100, aux_logits=False, transform_input=False, init_weights=True):\n        super(GoogLeNet, self).__init__()\n        self.aux_logits = aux_logits\n        self.transform_input = transform_input\n\n        self.conv1 = BasicConv2d(3, 64, kernel_size=7, stride=2, padding=3)\n        self.maxpool1 = nn.MaxPool2d(3, stride=2, ceil_mode=True)   #向上取整\n        self.conv2 = BasicConv2d(64, 64, kernel_size=1)\n        self.conv3 = BasicConv2d(64, 192, kernel_size=3, padding=1)\n        self.maxpool2 = nn.MaxPool2d(3, stride=2, ceil_mode=True)\n\n        self.inception3a = Inception(192, 64, 96, 128, 16, 32, 32)\n        self.inception3b = Inception(256, 128, 128, 192, 32, 96, 64)\n        self.maxpool3 = nn.MaxPool2d(3, stride=2, ceil_mode=True)\n\n        self.inception4a = Inception(480, 192, 96, 208, 16, 48, 64)\n        self.inception4b = Inception(512, 160, 112, 224, 24, 64, 64)\n        self.inception4c = Inception(512, 128, 128, 256, 24, 64, 64)\n        self.inception4d = Inception(512, 112, 144, 288, 32, 64, 64)\n        self.inception4e = Inception(528, 256, 160, 320, 32, 128, 128)\n        self.maxpool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True)\n\n        self.inception5a = Inception(832, 256, 160, 320, 32, 128, 128)\n        self.inception5b = Inception(832, 384, 192, 384, 48, 128, 128)\n\n        if aux_logits:\n            self.aux1 = InceptionAux(512, num_classes)\n            self.aux2 = InceptionAux(528, num_classes)\n\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.dropout = nn.Dropout(0.2)\n        self.fc = nn.Linear(1024, num_classes)\n\n        if init_weights:\n            self._initialize_weights()\n\n    def _initialize_weights(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):\n                import scipy.stats as stats\n                X = stats.truncnorm(-2, 2, scale=0.01)\n                values = torch.as_tensor(X.rvs(m.weight.numel()), dtype=m.weight.dtype)\n                values = values.view(m.weight.size())\n                with torch.no_grad():\n                    m.weight.copy_(values)\n            elif isinstance(m, nn.BatchNorm2d):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n    def forward(self, x):\n        if self.transform_input:\n            x_ch0 = torch.unsqueeze(x[:, 0], 1) * (0.229 / 0.5) + (0.485 - 0.5) / 0.5\n            x_ch1 = torch.unsqueeze(x[:, 1], 1) * (0.224 / 0.5) + (0.456 - 0.5) / 0.5\n            x_ch2 = torch.unsqueeze(x[:, 2], 1) * (0.225 / 0.5) + (0.406 - 0.5) / 0.5\n            x = torch.cat((x_ch0, x_ch1, x_ch2), 1)\n        # N x 3 x 224 x 224\n        x = self.conv1(x)\n        # N x 64 x 112 x 112\n        x = self.maxpool1(x)\n        # N x 64 x 56 x 56\n        x = self.conv2(x)\n        # N x 64 x 56 x 56\n        x = self.conv3(x)\n        # N x 192 x 56 x 56\n        x = self.maxpool2(x)\n        # N x 192 x 28 x 28\n        x = self.inception3a(x)\n        # N x 256 x 28 x 28\n        x = self.inception3b(x)\n        # N x 480 x 28 x 28\n        x = self.maxpool3(x)\n        # N x 480 x 14 x 14\n        x = self.inception4a(x)\n        # N x 512 x 14 x 14\n        if self.training and self.aux_logits:\n            aux1 = self.aux1(x)\n\n        x = self.inception4b(x)\n        # N x 512 x 14 x 14\n        x = self.inception4c(x)\n        # N x 512 x 14 x 14\n        x = self.inception4d(x)\n        # N x 528 x 14 x 14\n        if self.training and self.aux_logits:\n            aux2 = self.aux2(x)\n\n        x = self.inception4e(x)\n        # N x 832 x 14 x 14\n        x = self.maxpool4(x)\n        # N x 832 x 7 x 7\n        x = self.inception5a(x)\n        # N x 832 x 7 x 7\n        x = self.inception5b(x)\n        # N x 1024 x 7 x 7\n        x = self.avgpool(x)\n        # N x 1024 x 1 x 1\n        x = x.view(x.size(0), -1)\n        # N x 1024\n        x = self.dropout(x)\n        x = self.fc(x)\n        # N x 100 (num_classes)\n        if self.training and self.aux_logits:\n            return _GoogLeNetOuputs(x, aux2, aux1)\n        return x\n\n\nclass Inception(nn.Module):     #Inception模块\n\n    def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):\n        super(Inception, self).__init__()\n\n        self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)\n\n        self.branch2 = nn.Sequential(\n            BasicConv2d(in_channels, ch3x3red, kernel_size=1),\n            BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1)\n        )\n\n        self.branch3 = nn.Sequential(\n            BasicConv2d(in_channels, ch5x5red, kernel_size=1),\n            BasicConv2d(ch5x5red, ch5x5, kernel_size=3, padding=1)\n        )\n\n        self.branch4 = nn.Sequential(\n            nn.MaxPool2d(kernel_size=3, stride=1, padding=1, ceil_mode=True),\n            BasicConv2d(in_channels, pool_proj, kernel_size=1)\n        )\n\n    def forward(self, x):\n        branch1 = self.branch1(x)\n        branch2 = self.branch2(x)\n        branch3 = self.branch3(x)\n        branch4 = self.branch4(x)\n\n        outputs = [branch1, branch2, branch3, branch4]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionAux(nn.Module):      #辅助分支\n\n    def __init__(self, in_channels, num_classes):\n        super(InceptionAux, self).__init__()\n        self.conv = BasicConv2d(in_channels, 128, kernel_size=1)\n\n        self.fc1 = nn.Linear(2048, 1024)\n        self.fc2 = nn.Linear(1024, num_classes)\n\n    def forward(self, x):\n        # aux1: N x 512 x 14 x 14, aux2: N x 528 x 14 x 14\n        x = F.adaptive_avg_pool2d(x, (4, 4))\n        # aux1: N x 512 x 4 x 4, aux2: N x 528 x 4 x 4\n        x = self.conv(x)\n        # N x 128 x 4 x 4\n        x = x.view(x.size(0), -1)\n        # N x 2048\n        x = F.relu(self.fc1(x), inplace=True)\n        # N x 1024\n        x = F.dropout(x, 0.7, training=self.training)\n        # N x 1024\n        x = self.fc2(x)\n        # N x num_classes\n\n        return x\n\n\nclass BasicConv2d(nn.Module):       #Conv2d+BN+Relu\n\n    def __init__(self, in_channels, out_channels, **kwargs):\n        super(BasicConv2d, self).__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)\n        self.bn = nn.BatchNorm2d(out_channels, eps=0.001)\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.bn(x)\n        return F.relu(x, inplace=True)\n\ndef test():\n    net = GoogLeNet()\n    x = torch.randn(1,3,224,224)\n    y = net(x)\n    print(y.size())\n\ntest()","metadata":{"execution":{"iopub.status.busy":"2022-04-26T10:27:55.675119Z","iopub.execute_input":"2022-04-26T10:27:55.675381Z","iopub.status.idle":"2022-04-26T10:27:57.037985Z","shell.execute_reply.started":"2022-04-26T10:27:55.675329Z","shell.execute_reply":"2022-04-26T10:27:57.037229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#model = GoogLeNet()\noptimizer = torch.optim.SGD(model.parameters(), lr=opts.lr, momentum=0.9)  # 建立优化器\ncriterion2 = nn.CrossEntropyLoss()\nif opts.use_gpu:\n    model.to(opts.device)\n\ntrain_dataset = MyDataset(train_msg, mode='train')\nval_dataset = MyDataset(train_msg, mode='val')\ntrain_loader = DataLoader(train_dataset, opts.batch_size, shuffle=False, num_workers=0, drop_last=True)\nval_loader = DataLoader(val_dataset, batch_size=1, shuffle=False, num_workers=0)\nprint(\" dateset prepare down!\")\n\nnum_train = len(train_dataset)  # 记录训练集及验证集的带训练图片标签个数\nnum_val = len(val_dataset)\n\nfor epoch in range(1, opts.epoch + 1):\n    model.train()\n    losssum = 0.\n    \n    for i, (imgs, labels) in enumerate(train_loader):\n        #print(\" have down %d%% image in epoch %d\" % (int((i * opts.batch_size / num_train) * 100), epoch),end=\"\\r\")\n        if(i%100==0):\n            print(\" have down %d%% image in epoch %d\" % (int((i * opts.batch_size / num_train) * 100), epoch))\n        #label =  torch.zeros(opts.batch_size, NUM_CLASS )\n        #print (labels.size())\n        #print (label.size())\n        #print (label);\n        if opts.use_gpu:  # 若使用GPU，则将数据转移到GPU中\n            imgs = imgs.to(opts.device)\n            labels = labels.to(opts.device)\n        preds = model(imgs)  # 前向传播\n        loss = criterion2(preds,labels ) # 计算损失\n        optimizer.zero_grad()  # 梯度清零\n        loss.backward()  # 反向传播\n        optimizer.step()  # 优化网络参数\n        losssum += float(loss.item())\n    print(\" Epoch %d/%d | avg_loss = %.3f\" % (epoch, opts.epoch, losssum / num_train))  # 统计本次epoch的数据\n    \n    model.eval()\n    with torch.no_grad():\n        num = 0\n        for i, (imgs, labels) in enumerate(val_loader):\n            if opts.use_gpu:  # 若使用GPU，则将数据转移到GPU中\n                imgs = imgs.to(opts.device)\n                labels = labels.to(opts.device)\n            preds = model(imgs)\n            ans = preds.argmax(dim=1)\n\n            if ans == labels:\n                num += 1\n        print(\" Epoch %d/%d | accurate = %.3f\" % (epoch, opts.epoch, num / num_val))  # 统计本次epoch的数据\n    \n    if epoch%10 == 0:\n        print(\" Save model\")\n        model_name = \"epoch%d.pt\" % epoch  # 保存模型命名\n        save_dir = os.path.join('./', model_name)  # 存入定好的checkpoints地址中\n        torch.save(model.state_dict(), save_dir)  # 保存结果为pt文件。\n    ","metadata":{"execution":{"iopub.status.busy":"2022-04-26T11:46:09.643517Z","iopub.execute_input":"2022-04-26T11:46:09.643773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class test_opts():\n    def __init__(self):\n        self.PRETRAIN = False  # 是否使用之前完成训练的模型\n        self.CHECKPOINTS_DIR = PATH + \"\\model\\epoch49.pt\"  # 先前保存的模型的地址和名称\n        self.DEVICE = \"cpu\"\n\ntest_opt = test_opts()\n#model = GoogLeNet()\nif test_opt.PRETRAIN:\n    model = YoloNet()  # 建立测试模型\n    model.load_state_dict(torch.load(test_opt.CHECKPOINTS_DIR, map_location='cpu')) #加载之前保存的模型参数","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_msg = pd.read_csv(PATH + \"sample_submission.csv\")\ntest_msg.dropna(inplace=True) \nprint (f\"number of train data = {len(test_msg)}\")\ntest_msg.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_msg[\"dir\"] = test_msg[\"filename\"].apply( lambda image:TEST_IMG+image )\ntest_msg[\"dir_is_true\"] = test_msg[\"dir\"].apply(lambda dir: os.path.exists(dir))\ntest_msg[\"sorghum_type\"] = test_msg[\"cultivar\"].map(lambda type:sorghum_type.index(type))\ntest_msg.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(test_msg)\ntest_loader = DataLoader(test_dataset, batch_size=1, shuffle=False, num_workers=0, drop_last=False)\nnum_test = len(test_dataset)\nprint(num_test)\n\nmodel.cuda()\nmodel.eval()\npredictions = []\nfor i, (imgs,labels) in enumerate(test_loader):\n    imgs=imgs.cuda()\n    with torch.no_grad():\n        preds = model(imgs).detach().cpu()\n        #predictions.append([preds.argmax(dim=1),labels])\n        predictions.append(preds.argmax(dim=1))\n        if i%100 == 0:\n            print(\" have down %d%% image\" % (int((i / num_test) * 100)),end=\"\\r\")\n            \n#predictions = [[sorghum_type[pred],labels] for pred,labels in predictions]\npredictions = [sorghum_type[pred] for pred in predictions]\nsub = pd.read_csv(PATH + \"sample_submission.csv\")\nsub[\"cultivar\"] = predictions\nsub.to_csv('submission.csv', index=False)\nsub.head()\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}