{"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\nfor 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":{"execution":{"iopub.status.busy":"2022-05-07T15:14:10.733725Z","iopub.execute_input":"2022-05-07T15:14:10.734326Z","iopub.status.idle":"2022-05-07T15:14:42.360043Z","shell.execute_reply.started":"2022-05-07T15:14:10.734227Z","shell.execute_reply":"2022-05-07T15:14:42.359335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cd /kaggle/input\n","metadata":{"execution":{"iopub.status.busy":"2022-05-08T11:13:00.189784Z","iopub.execute_input":"2022-05-08T11:13:00.190545Z","iopub.status.idle":"2022-05-08T11:13:00.216046Z","shell.execute_reply.started":"2022-05-08T11:13:00.190447Z","shell.execute_reply":"2022-05-08T11:13:00.215248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 树叶分类练习\n```\n/kaggle/input/classify-leaves/sample_submission.csv\n/kaggle/input/classify-leaves/train.csv\n/kaggle/input/classify-leaves/test.csv\n/kaggle/input/classify-leaves/images/19812.jpg\n/kaggle/input/classify-leaves/images/22735.jpg\n/kaggle/input/classify-leaves/images/16916.jpg\n/kaggle/input/classify-leaves/images/7981.jpg\n/kaggle/input/classify-leaves/images/22706.jpg\n```","metadata":{}},{"cell_type":"markdown","source":"# 引入相关依赖\n","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torch import nn\nfrom PIL import Image\nfrom torchvision.io import read_image\nimport matplotlib.pyplot  as plot\nfrom torch.nn import functional as F","metadata":{"execution":{"iopub.status.busy":"2022-05-07T15:14:42.363296Z","iopub.execute_input":"2022-05-07T15:14:42.36352Z","iopub.status.idle":"2022-05-07T15:14:43.867317Z","shell.execute_reply.started":"2022-05-07T15:14:42.363492Z","shell.execute_reply":"2022-05-07T15:14:43.866533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"csv = pd.read_csv('/kaggle/input/classify-leaves/train.csv')\nu_labels = np.unique(csv.iloc[:,[1]].values.flatten())\nsorted(u_labels)\nlabel_map = dict(zip(u_labels,range(len(u_labels))))","metadata":{"execution":{"iopub.status.busy":"2022-05-07T15:14:43.868771Z","iopub.execute_input":"2022-05-07T15:14:43.869063Z","iopub.status.idle":"2022-05-07T15:14:43.94868Z","shell.execute_reply.started":"2022-05-07T15:14:43.869027Z","shell.execute_reply":"2022-05-07T15:14:43.947937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 创建DataLoader","metadata":{}},{"cell_type":"code","source":"class LeafDataset(torch.utils.data.Dataset):\n    \n    def __init__(self,annotation_file, image_dir, transform=None,):\n        self.image_lables = pd.read_csv(annotation_file)\n        self.image_dir = image_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.image_lables)\n    \n    def __getitem__(self,idx):\n        image_file_path = os.path.join(self.image_dir,self.image_lables.iloc[idx,0])\n        image = read_image(image_file_path).to(torch.uint8)\n        label = self.image_lables.iloc[idx,1]\n        # 需要把label 转成 对应的数字\n        if self.transform:\n            image = self.transform(image)\n        return image, label_map[label]\n    \ntraning_data = LeafDataset('/kaggle/input/classify-leaves/train.csv','/kaggle/input/classify-leaves/')\ntest_data = LeafDataset('/kaggle/input/classify-leaves/test.csv','/kaggle/input/classify-leaves/')\n\ntrain_loader = torch.utils.data.DataLoader(traning_data,batch_size = 64,shuffle=True)\ntest_loader = torch.utils.data.DataLoader(test_data,batch_size = 64,shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-07T15:34:21.213271Z","iopub.execute_input":"2022-05-07T15:34:21.213523Z","iopub.status.idle":"2022-05-07T15:34:21.245213Z","shell.execute_reply.started":"2022-05-07T15:34:21.213496Z","shell.execute_reply":"2022-05-07T15:34:21.244464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoader测试\n","metadata":{}},{"cell_type":"code","source":"train_features, train_labels = next(iter(train_loader))\nprint(train_features.shape)\nplot.figure(figsize=(16,16))\nfor j in range(64):\n    plot.subplot(8,8,j+1)\n    plot.imshow(train_features[j].permute(1,2,0))\n    plot.axis(\"off\")\nplot.show()","metadata":{"execution":{"iopub.status.busy":"2022-05-07T15:34:30.49625Z","iopub.execute_input":"2022-05-07T15:34:30.496534Z","iopub.status.idle":"2022-05-07T15:34:33.647927Z","shell.execute_reply.started":"2022-05-07T15:34:30.496505Z","shell.execute_reply":"2022-05-07T15:34:33.647286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 定义Resnet基本块","metadata":{}},{"cell_type":"code","source":"class Residual(nn.Module):\n    def __init__(self,input_channels, output_channels, use_1x1conv=False, strides=1):\n        super().__init__()\n        self.conv1 = nn.Conv2d(input_channels,output_channels,kernel_size=3, stride = strides, padding=1) \n        self.conv2 = nn.Conv2d(output_channels,output_channels,kernel_size=3, padding=1)\n        if use_1x1conv:\n            self.conv3 = nn.Conv2d(input_channels, output_channels, kernel_size=1, stride=strides)\n        else:\n            self.conv3 = None\n        self.BN1 = nn.BatchNorm2d(output_channels)\n        self.BN2 = nn.BatchNorm2d(output_channels)\n    \n    def forward(self,X):\n        out = F.relu(self.BN1(self.conv1(X)))\n        out= self.BN2(self.conv2(out))\n        if self.conv3:\n            X = self.conv3(X)\n#         print(f\"x shape:{X.shape}, out shape:{out.shape}\")\n        out+=X\n        return F.relu(out)\n\n        ","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:44.617894Z","iopub.execute_input":"2022-05-07T12:22:44.618296Z","iopub.status.idle":"2022-05-07T12:22:44.626839Z","shell.execute_reply.started":"2022-05-07T12:22:44.618257Z","shell.execute_reply":"2022-05-07T12:22:44.626103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 残差块测试","metadata":{}},{"cell_type":"code","source":"blk = Residual(3,3)\nX = torch.rand(64,3,224,224)\nY = blk(X)\nY.shape","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:44.62797Z","iopub.execute_input":"2022-05-07T12:22:44.628246Z","iopub.status.idle":"2022-05-07T12:22:45.381773Z","shell.execute_reply.started":"2022-05-07T12:22:44.62821Z","shell.execute_reply":"2022-05-07T12:22:45.381069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 定义Resnet18模型\n","metadata":{}},{"cell_type":"code","source":"def resnet_block(input_channels, num_channels, num_residuals, first_block=False):\n    blk = []\n    for i in range(num_residuals):\n        if i==0 and not first_block:\n            blk.append(Residual(input_channels,num_channels, use_1x1conv=True, strides=2))\n        else:\n            blk.append(Residual(num_channels,num_channels))\n    return blk\nb1 = nn.Sequential(nn.Conv2d(3, 64,kernel_size=7,stride = 2, padding = 3),\n                    nn.BatchNorm2d(64), nn.ReLU(),\n                    nn.MaxPool2d(kernel_size=3,stride =2 ,padding=1))\nb2 = nn.Sequential(*resnet_block(64,64,2,first_block=True))\nb3 = nn.Sequential(*resnet_block(64,128,2))\nb4 = nn.Sequential(*resnet_block(128,256,2))\nb5 = nn.Sequential(*resnet_block(256,512,2))","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:45.383113Z","iopub.execute_input":"2022-05-07T12:22:45.383512Z","iopub.status.idle":"2022-05-07T12:22:45.48873Z","shell.execute_reply.started":"2022-05-07T12:22:45.383473Z","shell.execute_reply":"2022-05-07T12:22:45.488093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 设备相关","metadata":{}},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:45.490006Z","iopub.execute_input":"2022-05-07T12:22:45.490278Z","iopub.status.idle":"2022-05-07T12:22:45.564615Z","shell.execute_reply.started":"2022-05-07T12:22:45.490243Z","shell.execute_reply":"2022-05-07T12:22:45.563669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 定义网络","metadata":{}},{"cell_type":"code","source":"net = nn.Sequential(b1,b2,b3,b4,b5,\n                    nn.AdaptiveAvgPool2d((1,1)),\n                    nn.Flatten(),nn.Linear(512,176)\n                   )\nnet.to(device)","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:45.567911Z","iopub.execute_input":"2022-05-07T12:22:45.568495Z","iopub.status.idle":"2022-05-07T12:22:48.350648Z","shell.execute_reply.started":"2022-05-07T12:22:45.568455Z","shell.execute_reply":"2022-05-07T12:22:48.349932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# X = torch.rand(size=(64, 3, 224, 224))\n# for layer in net:\n#     X = layer(X)\n#     print(layer.__class__.__name__,'output shape:\\t', X.shape)","metadata":{"execution":{"iopub.status.busy":"2022-05-07T12:22:48.351958Z","iopub.execute_input":"2022-05-07T12:22:48.352228Z","iopub.status.idle":"2022-05-07T12:22:48.355255Z","shell.execute_reply.started":"2022-05-07T12:22:48.352199Z","shell.execute_reply":"2022-05-07T12:22:48.354415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 开始训练","metadata":{}},{"cell_type":"code","source":"lr, num_epochs, batch_size = 5e-2, 10, 128\ncriterion = nn.CrossEntropyLoss()\nnn.\noptimizer = torch.optim.SGD(net.parameters(),lr=lr)\n\nfor i in range(num_epochs):\n    net.train()\n    # These are used to record information in validation.\n    train_loss = []\n    train_accs = []\n    for data in train_loader:\n        imgs, labels = data\n        imgs = imgs.to(device)\n        labels = labels.to(device)\n        outputs = net(imgs)\n        loss = criterion(outputs, labels)\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        train_acc = (outputs.argmax(-1) == labels).float().mean()\n        # Record the loss and accuracy.\n        train_loss.append(loss.item())\n        train_accs.append(train_acc)\n        # The average loss and accuracy for entire validation set is the average of the recorded values.\n    # The average loss and accuracy of the training set is the average of the recorded values.\n    train_loss = sum(train_loss) / len(train_loss)\n    train_acc = sum(train_accs) / len(train_accs)\n    # Print the information.\n    print(f\"[ Valid | {i + 1:03d}/{num_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}\")\n#     net.eval()\n#     with torch.no_grad():\n#         for data in test_loader:\n#             imgs, lables = data\n#             outputs = net(imgs)\n#             l2 = loss(nn.step, lables)\n#     print(f\"epoch {i}, train loss: {l1}, test loss: {l2}\")\n","metadata":{"execution":{"iopub.status.busy":"2022-06-24T08:49:14.022683Z","iopub.status.idle":"2022-06-24T08:49:14.023764Z","shell.execute_reply.started":"2022-06-24T08:49:14.023478Z","shell.execute_reply":"2022-06-24T08:49:14.023518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}