{"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":"is_train = True\nbasic_epochs = 260\nmodel_layer = 18\nlocal = 1\nif (local):\n    log_dir = '/home/zyp/w/d2l/classify_leave/log'\n    data_dir = '/home/zyp/w/d2l/classify_leave/data'\n    history_dir = '/home/zyp/w/d2l/classify_leave/history'\n    model_file = '/home/zyp/w/d2l/classify_leave/log/epochs'+str(basic_epochs)+'.model'\nelse:\n    log_dir = '/content/log'\n    data_dir = '/content/data'\n    history_dir = '/content/history'\n    model_file = '/content/history/epochs'+str(basic_epochs)+'.model'\n    drive_log_dir = '/content/drive/MyDrive/colab/classify_leave/log'\n    drive_model_file = '/content/drive/MyDrive/colab/classify_leave/log/epochs'+str(basic_epochs)+'.model'\n    \n!mkdir -p $log_dir\n!mkdir -p $data_dir\n!mkdir -p $history_dir\n\ntotal_epochs = basic_epochs\n\nrecord = []","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:28.219801Z","start_time":"2022-05-25T06:49:27.792136Z"},"id":"ReaZwkzQSzxX","outputId":"81f47796-800a-46f8-e143-e76f73877184"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#显示运行时间\n!pip install ipython-autotime\n%load_ext autotime\n\n# 挂载 drive\nfrom google.colab import drive\ndrive.mount('/content/drive')\n\n# 准备数据集\n!cp /content/drive/MyDrive/colab/classify_leave/classify-leaves.zip /content/data\n!unzip /content/data/classify-leaves.zip -d /content/data/\n!ls /content/data/images/ | wc -l\n\n!cp $drive_model_file /content/history/\n\n!nvidia-smi","metadata":{"ExecuteTime":{"end_time":"2022-05-24T12:49:07.104824Z","start_time":"2022-05-24T12:49:04.517271Z"},"id":"Tv4Ip1AYMNT4","outputId":"3c9775bd-a747-4914-cdef-66d397f4364b"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\nimport torch\nimport torch.nn as nn\nimport pandas as pd\nimport numpy as np\nfrom torch.utils.data import Dataset, DataLoader\nimport matplotlib.pyplot as plt\nimport torchvision.models as models\nfrom torchvision.io import read_image\nimport torchvision.transforms as transforms\nimport json","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:33.021991Z","start_time":"2022-05-25T06:49:33.019187Z"},"id":"fe3c458e","outputId":"533844b2-dded-4699-cf1e-18bf079205bf"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:35.439458Z","start_time":"2022-05-25T06:49:35.436127Z"},"id":"s1sb0pS2oX2c","outputId":"e4c9588b-fd34-43fc-cebb-bd9763414acc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_train_label = pd.read_csv(data_dir + '/train.csv')\nprint(all_train_label)","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:37.898511Z","start_time":"2022-05-25T06:49:37.875477Z"},"id":"ff417cdf","outputId":"62b13adc-3c70-4bf9-bd62-461e460b3972"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"leave_class = sorted(list(set(all_train_label['label'])))\nclass_to_idx = dict(zip(leave_class, range(len(leave_class)))) \nidx_to_class = {v:k for k, v in class_to_idx.items()}\n\nprint(list(class_to_idx.items())[0:4])\nprint(list(idx_to_class.items())[0:4])\nprint(len(leave_class))","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:40.456505Z","start_time":"2022-05-25T06:49:40.451979Z"},"id":"fa97f8a0","outputId":"ec2c5df6-402a-406b-919a-70749ebc250b","scrolled":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LeaveDataset(Dataset):\n    \n    all_train_label = pd.read_csv(data_dir + '/train.csv')\n    test_label = pd.read_csv(data_dir + '/test.csv')\n    offset = math.floor(len(all_train_label) * 0.8)\n    train_mode = \"train\"\n    validation_mode = \"validation\"\n    \n    def __init__(self, mode):\n        self.mode = mode\n        \n    def __getitem__(self, idx):\n        all_train_label = LeaveDataset.all_train_label.copy(deep=False)\n        test_label = LeaveDataset.test_label.copy(deep=False)\n\n        if self.mode == LeaveDataset.train_mode:\n            img_file, label = all_train_label.iloc[idx][0], all_train_label.iloc[idx][1]\n        elif self.mode == LeaveDataset.validation_mode:\n            idx = LeaveDataset.offset + idx\n            img_file, label = all_train_label.iloc[idx][0], all_train_label.iloc[idx][1]\n        else:\n            img_file = test_label.iloc[idx][0]\n            \n        img = read_image(str(data_dir + '/' + img_file))\n        if self.mode == LeaveDataset.train_mode:\n            t = transforms.Compose([\n                transforms.RandomHorizontalFlip(p=0.5),\n                transforms.RandomVerticalFlip(p=0.5),\n                transforms.RandomResizedCrop(size=(224, 224), scale=(0.5, 1)),\n                transforms.ConvertImageDtype(torch.float),\n            ])\n        else:\n            t = transforms.Compose([\n                transforms.Resize((224, 224)),\n                transforms.ConvertImageDtype(torch.float),\n            ])         \n        \n        img = t(img)\n        if 'label' in locals():\n            label = class_to_idx[label]\n            return img, label\n        else:\n            return img\n\n    def __len__(self):\n        test_label = LeaveDataset.test_label.copy(deep=False)\n\n        if self.mode == LeaveDataset.train_mode:\n            return LeaveDataset.offset\n        elif self.mode == LeaveDataset.validation_mode:\n            return len(all_train_label) - LeaveDataset.offset \n        else:\n            return len(test_label)\n\n        \ntraining_data = LeaveDataset(\"train\")\nvalidation_data = LeaveDataset(\"validation\")\ntest_data = LeaveDataset(\"test\")\nprint(len(training_data), len(validation_data), len(test_data))\n\ntrain_dataloader = DataLoader(training_data, batch_size=64)\nvalidation_dataloader = DataLoader(validation_data, batch_size=64)\ntest_dataloader = DataLoader(test_data, batch_size=64)\n","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:42.17396Z","start_time":"2022-05-25T06:49:42.149989Z"},"id":"d60d5081","outputId":"840d1e5b-b9f9-4057-b170-b9ddcb64dc5b"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_resnet(model_layer, model_file=None):\n    pretained = (basic_epochs == 0)\n    if model_layer == 18:\n        model = models.resnet18(pretrained=pretained)\n    else:\n        model = models.resnet50(pretrained=pretained)\n    \n    model.fc = nn.Linear(model.fc.in_features, len(leave_class))\n    if pretained:\n        nn.init.xavier_uniform_(model.fc.weight)\n    else:\n        model.load_state_dict(torch.load(model_file, map_location=torch.device(device)))\n    return model\n    \n\nmodel = get_resnet(model_layer, model_file=model_file)\nprint(f'model: restnet{model_layer}, load from:{model_file}')\nmodel.train(is_train)\n\nmodel = model.to(device)","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:45.328651Z","start_time":"2022-05-25T06:49:45.203293Z"},"id":"RJzal83n8KF_","outputId":"3db2ba0e-fa99-4a96-e2d3-ae61e883c763"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64\nepochs = 5\n\n# Initialize the loss function / optimizer\nloss_fn = nn.CrossEntropyLoss()\n\nlearning_rate = 3e-5\nweight_decay = 1e-3\n#optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay)\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n#optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:49:54.768212Z","start_time":"2022-05-25T06:49:54.764926Z"},"id":"5caca424","outputId":"8cc9452b-1582-4a65-ca39-b9edf784fbd3"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for batch, (X, y) in enumerate(train_dataloader):\n    X, y = X.to(device), y.to(device)\n    pred = model(X)\n    loss = loss_fn(pred, y)\n    optimizer.zero_grad()\n    loss.backward()\n    optimizer.step()\n    break\n\n","metadata":{"ExecuteTime":{"end_time":"2022-05-24T03:20:25.536017Z","start_time":"2022-05-24T03:20:22.907031Z"},"id":"ce6e0a1b","outputId":"7d28bd7c-7362-4414-f77b-2f05a9bcbaf6"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_loop(dataloader, model, loss_fn, optimizer):\n    size = len(dataloader.dataset)\n    correct = 0\n    for batch, (X, y) in enumerate(dataloader):\n        # Compute prediction and loss\n        X, y = X.to(device), y.to(device)\n        pred = model(X)\n        loss = loss_fn(pred, y)\n        correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n\n        # Backpropagation\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n            \n    correct /= size\n    print(f\"[Train] Accuracy: {(100*correct):>0.1f}%, Avg loss: {loss.item():>8f} \\n\")\n    return round(100*correct, 1), round(loss.item(), 6)\n\n\ndef validation_loop(dataloader, model, loss_fn):\n    size = len(dataloader.dataset)\n    num_batches = len(dataloader)\n    test_loss, correct = 0, 0\n\n    with torch.no_grad():\n        for X, y in dataloader:\n            X, y = X.to(device), y.to(device)\n            pred = model(X)\n            test_loss += loss_fn(pred, y).item()\n            correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n\n    test_loss /= num_batches\n    correct /= size\n    print(f\"[Test] Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \\n\")\n    return round(100*correct, 1), round(test_loss, 6)\n","metadata":{"ExecuteTime":{"end_time":"2022-05-24T03:39:02.774128Z","start_time":"2022-05-24T03:39:02.768823Z"},"id":"be5d5ffd","outputId":"0fa91910-aada-4fc6-b8a2-910e5787b78b"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_loop(validation_dataloader, model, loss_fn)\ntrain_loop(train_dataloader, model, loss_fn, optimizer)","metadata":{"ExecuteTime":{"end_time":"2022-05-24T03:37:17.228201Z","start_time":"2022-05-24T03:36:12.374717Z"},"id":"31df4083","outputId":"80f76ffa-4a89-4c71-df59-b00f8ff40f06"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_state(model, record):\n    print(\"save model at epochs \" + str(total_epochs))\n    torch.save(model.state_dict(), log_dir+'/epochs' + str(total_epochs) + '.model')\n    with open(log_dir + \"/acc\" + str(total_epochs) + \".log\", 'a') as f:\n        json.dump(record, f)","metadata":{"id":"ltuEEmLFDrJS","outputId":"fa5de696-0611-4966-82df-b41a07495a2b"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 10\nprint(optimizer)\nfor t in range(epochs):\n    total_epochs+=1\n    print(f\"Epoch {total_epochs}\\n-------------------------------\")\n    l1, acc1 = train_loop(train_dataloader, model, loss_fn, optimizer)\n    l2, acc2 = validation_loop(validation_dataloader, model, loss_fn)\n    record.append([total_epochs, l1, acc1, l2, acc2])\n    if total_epochs % 20 == 0:\n        save_state(model, record)\nprint(\"Done!\")","metadata":{"ExecuteTime":{"end_time":"2022-05-20T01:36:22.756525Z","start_time":"2022-05-20T01:25:16.091883Z"},"id":"925f1360","outputId":"5fb3d969-1a52-4c9c-8fff-dff433eb4543","collapsed":true,"jupyter":{"outputs_hidden":true}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls -alh $log_dir\n\n!mv /content/log/*.model $drive_log_dir\n!mv /content/log/*.log $drive_log_dir","metadata":{"id":"IxYEY0rDuuxR","outputId":"69380450-ee33-45ab-817d-b0a3d65a185e"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---\n## 测试\n","metadata":{"id":"d0b3ee47"}},{"cell_type":"code","source":"# 测试集预测\ntest_pred = torch.tensor([], dtype=torch.int64)\n\nwith torch.no_grad():\n    for X in test_dataloader:\n        X = X.to(device)\n        pred = model(X)\n        test_pred = torch.hstack((test_pred, pred.argmax(1)))\n        \nprint(test_pred.shape)\n\ntest_class = []\nfor i in enumerate(test_pred.numpy()):\n    test_class.append(idx_to_class[i[1]])\nprint(len(test_class))\ntest_class2 = pd.DataFrame(test_class, columns=['label'])\n\nresult = pd.concat([LeaveDataset.test_label, test_class2], axis=1)\nresult.to_csv(log_dir + \"/result.csv\", index=False)\nresult","metadata":{"ExecuteTime":{"end_time":"2022-05-25T06:53:04.434867Z","start_time":"2022-05-25T06:50:19.219587Z"},"id":"99cd3a9f","outputId":"c66044e0-bc71-44fc-d3cd-28d78915415c"},"execution_count":null,"outputs":[]}]}