{"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":"markdown","source":"Accoding to this article:\n    https://www.kaggle.com/code/neupane9sujal/flower-classification-resnet50","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"<font size=6><b>1.Import related Libraries.</b></font>","metadata":{}},{"cell_type":"code","source":"import pandas as pd#导入csv文件的库\nimport numpy as np#进行矩阵运算的库\nimport matplotlib.pyplot as plt#作图的库\nimport torch #一个深度学习的库Pytorch\nimport torch.nn as nn#neural network,神经网络\nfrom torch.autograd import Variable#从自动求导中引入变量\nimport torch.optim as optim#一个实现了各种优化算法的库\nimport torch.nn.functional as F#神经网络函数库\nfrom torchvision import models#进行迁移学习导入模型\nimport torchvision.transforms as transforms#Pytorch下面的图像处理库,用于对图像进行数据增强\nfrom torch.utils.data import DataLoader, random_split#数据加载和随机划分训练集和验证集\nfrom torchvision.datasets import ImageFolder#数据加载器\nimport os\nfrom pathlib import Path#提供表示文件系统路径的类\nimport pathlib#对文件进行处理,应用于不同的操作系统\nplt.style.use('ggplot')#ggplot是基于R的ggplot 2和Python的绘图系统。它的构建是为了用最少的代码快速绘制既专业又美观的图表\nimport warnings#避免一些可以忽略的报错\nwarnings.filterwarnings('ignore')#filterwarnings()方法是用于设置警告过滤器的方法，它可以控制警告信息的输出方式和级别。","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:12:59.713618Z","iopub.execute_input":"2023-04-25T08:12:59.714679Z","iopub.status.idle":"2023-04-25T08:13:03.427705Z","shell.execute_reply.started":"2023-04-25T08:12:59.714641Z","shell.execute_reply":"2023-04-25T08:13:03.425852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font size=6><b>2.Data enhancement.</b></font>","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:03:52.698258Z","iopub.execute_input":"2023-04-25T08:03:52.698723Z","iopub.status.idle":"2023-04-25T08:03:52.706681Z","shell.execute_reply.started":"2023-04-25T08:03:52.698681Z","shell.execute_reply":"2023-04-25T08:03:52.704805Z"}}},{"cell_type":"code","source":"path=Path('/kaggle/input/5-flowers-image-classification/train')#解析URL地址\npath","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:03.429807Z","iopub.execute_input":"2023-04-25T08:13:03.430390Z","iopub.status.idle":"2023-04-25T08:13:03.445424Z","shell.execute_reply.started":"2023-04-25T08:13:03.430337Z","shell.execute_reply":"2023-04-25T08:13:03.443559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((224, 224)),#将图像调整成224*224的大小,\n    transforms.RandomHorizontalFlip(),#随机水平翻转\n    transforms.ToTensor(),#转换成Pytorch可以处理的Tensor类型的数据\n    #定义正则化的标准，3个颜色通道的均值和方差,这是从ImageNet数据集上得出的数值\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                 std=[0.229, 0.224, 0.225]),\n])","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:03.449679Z","iopub.execute_input":"2023-04-25T08:13:03.450433Z","iopub.status.idle":"2023-04-25T08:13:03.462467Z","shell.execute_reply.started":"2023-04-25T08:13:03.450370Z","shell.execute_reply":"2023-04-25T08:13:03.461134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = ImageFolder(path, transform=transform)\ndataset","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:03.465451Z","iopub.execute_input":"2023-04-25T08:13:03.465943Z","iopub.status.idle":"2023-04-25T08:13:04.752614Z","shell.execute_reply.started":"2023-04-25T08:13:03.465896Z","shell.execute_reply":"2023-04-25T08:13:04.751610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font size=6><b>3.Divide training and validation sets.</b></font>","metadata":{}},{"cell_type":"code","source":"#将训练集和验证集按照8:2的比例划分\ntrain_size = int(0.8 * len(dataset))\nval_size = len(dataset) - train_size\ntrain_dataset, val_dataset = random_split(dataset, [train_size, val_size])","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:04.754056Z","iopub.execute_input":"2023-04-25T08:13:04.754927Z","iopub.status.idle":"2023-04-25T08:13:04.783355Z","shell.execute_reply.started":"2023-04-25T08:13:04.754885Z","shell.execute_reply":"2023-04-25T08:13:04.782421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64#一批次为64个\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)#将训练集按批次加载,并打乱\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)#将验证集按批次加载,不用打乱","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:04.784820Z","iopub.execute_input":"2023-04-25T08:13:04.785294Z","iopub.status.idle":"2023-04-25T08:13:04.791796Z","shell.execute_reply.started":"2023-04-25T08:13:04.785241Z","shell.execute_reply":"2023-04-25T08:13:04.790385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font size=6><b>4.import the model and train.</b></font>","metadata":{}},{"cell_type":"code","source":"#如果能使用GPU,就用GPU,不能使用的话用CPU\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\ndevice","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:04.793555Z","iopub.execute_input":"2023-04-25T08:13:04.794241Z","iopub.status.idle":"2023-04-25T08:13:04.877750Z","shell.execute_reply.started":"2023-04-25T08:13:04.794205Z","shell.execute_reply":"2023-04-25T08:13:04.876742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#下载模型resnet101,并且将训练好的参数加载进来\nmodel = models.resnet101(pretrained=True)\n\n#对于模型的参数,不需要在计算中保留对应的梯度信息,即:梯度冻结\nfor param in model.parameters():\n    param.requires_grad = False\n    \nnum_classes = 5#这里进行的是五分类的任务\n#将模型的全连接层做一些改动(模型微调)\nmodel.fc = nn.Linear(model.fc.in_features, num_classes)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:04.880249Z","iopub.execute_input":"2023-04-25T08:13:04.881773Z","iopub.status.idle":"2023-04-25T08:13:07.075487Z","shell.execute_reply.started":"2023-04-25T08:13:04.881733Z","shell.execute_reply":"2023-04-25T08:13:07.074399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\n#优化器\noptimizer=optim.Adam(model.parameters(),lr=0.0002,betas=(0.5,0.999))","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:07.077265Z","iopub.execute_input":"2023-04-25T08:13:07.077667Z","iopub.status.idle":"2023-04-25T08:13:07.084709Z","shell.execute_reply.started":"2023-04-25T08:13:07.077628Z","shell.execute_reply":"2023-04-25T08:13:07.083443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#由于是迁移学习,这里训练20次\nnum_epochs =20\n\n#用GPU去训练模型\nmodel.to(device)\n\n#用字典来存储训练集和测试集的评价指标\ntrain_metrics = {'loss': [], 'accuracy': []}\ntest_metrics = {'loss': [], 'accuracy': []}\n\nfor epoch in range(num_epochs):\n    running_loss = 0.0\n    correct = 0#预测准确了多少张图片\n    total = 0#统计本次训练已经传入了多少张图片\n    \n    for images, labels in train_loader:\n        #取出一批次的图片和标签,并在GPU上进行训练\n        images = images.to(device)\n        labels = labels.to(device)\n\n        #清空梯度\n        optimizer.zero_grad()\n\n        #传入图片让模型去预测\n        outputs = model(images)\n        #对比输出结果和标签去计算损失\n        loss = criterion(outputs, labels)\n        #将损失反向传播回去\n        loss.backward()\n        #更新参数\n        optimizer.step()\n\n        running_loss += loss.item() * images.size(0)\n        _, predicted = torch.max(outputs.data, axis=1)#将输出结果按行求最大值\n        total += labels.size(0)#统计传入了多少张图片\n        correct += (predicted == labels).sum().item()#.item():预测准的个数,将整数取出,并保持原张量不变.\n\n    # Calculate training metrics and store them in dictionary\n    epoch_loss = running_loss / len(train_loader.dataset)\n    epoch_acc = correct / total\n    train_metrics['loss'].append(epoch_loss)\n    train_metrics['accuracy'].append(epoch_acc)\n    print(f'Epoch {epoch + 1} training loss: {epoch_loss:.4f} accuracy: {epoch_acc:.4f}')\n\n    #在验证集上进行相同的操作\n    running_loss = 0.0\n    correct = 0\n    total = 0\n    with torch.no_grad():#验证集这里是不更新参数的\n        for images, labels in val_loader:\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            running_loss += loss.item() * images.size(0)\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n\n    epoch_loss = running_loss / len(val_loader.dataset)\n    epoch_acc = correct / total#计算本次的准确率,预测正确的张数/总共的张数\n    test_metrics['loss'].append(epoch_loss)\n    test_metrics['accuracy'].append(epoch_acc)\n    print(f'Valid loss: {epoch_loss:.4f} accuracy: {epoch_acc:.4f}')","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:13:07.088644Z","iopub.execute_input":"2023-04-25T08:13:07.089018Z","iopub.status.idle":"2023-04-25T08:23:46.250907Z","shell.execute_reply.started":"2023-04-25T08:13:07.088981Z","shell.execute_reply":"2023-04-25T08:23:46.249707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font size=6><b>5.Visualization of resultsVisualization of results.</b></font>","metadata":{}},{"cell_type":"code","source":"#metrics:衡量指标\nplt.plot(train_metrics['loss'], label='Training Loss')\nplt.plot(test_metrics['loss'], label='Testing Loss')\nplt.xlabel('Epoch')#x轴是迭代次数\nplt.ylabel('Loss')#y轴是损失\nplt.legend()#画出网格\nplt.show()#显示出来\n\n# Plot training and testing accuracy\nplt.plot(train_metrics['accuracy'], label='Training Accuracy')\nplt.plot(test_metrics['accuracy'], label='Testing Accuracy')\nplt.xlabel('Epoch')#x轴是迭代次数\nplt.ylabel('Accuracy')#y轴是正确率\nplt.legend()#画出网格\nplt.show()#显示出来","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:23:46.252543Z","iopub.execute_input":"2023-04-25T08:23:46.253184Z","iopub.status.idle":"2023-04-25T08:23:46.728557Z","shell.execute_reply.started":"2023-04-25T08:23:46.253144Z","shell.execute_reply":"2023-04-25T08:23:46.727432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font size=6><b>6.Predict.</b></font>","metadata":{}},{"cell_type":"code","source":"testpath=Path('/kaggle/input/5-flowers-image-classification')#解析URL地址\ntestpath","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:23:46.730351Z","iopub.execute_input":"2023-04-25T08:23:46.730724Z","iopub.status.idle":"2023-04-25T08:23:46.738159Z","shell.execute_reply.started":"2023-04-25T08:23:46.730686Z","shell.execute_reply":"2023-04-25T08:23:46.736908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = ImageFolder(testpath, transform=transform)\ntest_dataset","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:23:51.031665Z","iopub.execute_input":"2023-04-25T08:23:51.032188Z","iopub.status.idle":"2023-04-25T08:23:51.146675Z","shell.execute_reply.started":"2023-04-25T08:23:51.032143Z","shell.execute_reply":"2023-04-25T08:23:51.145441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size=10\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)#将测试集按批次加载,不用打乱","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:23:57.755629Z","iopub.execute_input":"2023-04-25T08:23:57.756009Z","iopub.status.idle":"2023-04-25T08:23:57.761802Z","shell.execute_reply.started":"2023-04-25T08:23:57.755976Z","shell.execute_reply":"2023-04-25T08:23:57.760725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ans=[]\nfor images in test_loader:\n    images = torch.Tensor(images[0]).to(device)\n    outputs = model(images)\n    _, predicted = torch.max(outputs.data, axis=1)\n    ans.append(predicted.detach().cpu().numpy().tolist())\n    if len(ans)*batch_size==400:\n        break","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:23:59.255750Z","iopub.execute_input":"2023-04-25T08:23:59.256880Z","iopub.status.idle":"2023-04-25T08:24:05.047969Z","shell.execute_reply.started":"2023-04-25T08:23:59.256835Z","shell.execute_reply":"2023-04-25T08:24:05.046850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ans=np.array(ans).reshape(400)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:07.043999Z","iopub.execute_input":"2023-04-25T08:24:07.044991Z","iopub.status.idle":"2023-04-25T08:24:07.050791Z","shell.execute_reply.started":"2023-04-25T08:24:07.044935Z","shell.execute_reply":"2023-04-25T08:24:07.049801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Due to the fact that the predicted results obtained are not arranged in image order, some adjustments need to be made here","metadata":{}},{"cell_type":"code","source":"def getPhoto(path_photo):\n    files_list = os.listdir(path_photo) \n    return files_list","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:08.604209Z","iopub.execute_input":"2023-04-25T08:24:08.604595Z","iopub.status.idle":"2023-04-25T08:24:08.611087Z","shell.execute_reply.started":"2023-04-25T08:24:08.604564Z","shell.execute_reply":"2023-04-25T08:24:08.609006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testfile=getPhoto('/kaggle/input/5-flowers-image-classification/test')","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:13.631773Z","iopub.execute_input":"2023-04-25T08:24:13.632157Z","iopub.status.idle":"2023-04-25T08:24:13.638255Z","shell.execute_reply.started":"2023-04-25T08:24:13.632124Z","shell.execute_reply":"2023-04-25T08:24:13.636947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index=[]\nfor i in range(len(testfile)):\n    index.append((testfile[i].split('.')[0]))","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:15.061222Z","iopub.execute_input":"2023-04-25T08:24:15.062134Z","iopub.status.idle":"2023-04-25T08:24:15.068275Z","shell.execute_reply.started":"2023-04-25T08:24:15.062083Z","shell.execute_reply":"2023-04-25T08:24:15.067131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index=sorted(index)\nfor i in range(len(index)):\n    index[i]=int(index[i])-1","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:16.926538Z","iopub.execute_input":"2023-04-25T08:24:16.927639Z","iopub.status.idle":"2023-04-25T08:24:16.933489Z","shell.execute_reply.started":"2023-04-25T08:24:16.927600Z","shell.execute_reply":"2023-04-25T08:24:16.932344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred=[0 for i in range(len(ans))]\nfor i in range(len(ans)):\n    pred[index[i]]=ans[i]","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:21.577247Z","iopub.execute_input":"2023-04-25T08:24:21.577941Z","iopub.status.idle":"2023-04-25T08:24:21.583903Z","shell.execute_reply.started":"2023-04-25T08:24:21.577905Z","shell.execute_reply":"2023-04-25T08:24:21.582595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#写入文件\nimport csv\nhead=[\"id\",\"label\"]\ndata=[]\nfor i in range(len(pred)):\n    data.append([(i+1),pred[i]])\nwith open(\"prediction.csv\",'w',newline='') as f:\n    writer=csv.writer(f)\n    writer.writerow(head)\n    writer.writerows(data)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T08:24:23.114685Z","iopub.execute_input":"2023-04-25T08:24:23.115290Z","iopub.status.idle":"2023-04-25T08:24:23.123215Z","shell.execute_reply.started":"2023-04-25T08:24:23.115253Z","shell.execute_reply":"2023-04-25T08:24:23.122079Z"},"trusted":true},"execution_count":null,"outputs":[]}]}