{"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 timm#Pytorch image models,存放了大量的模型架构和预训练模型的参数","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"timm.list_models('swin*')#看一下swin相关的模型","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#在imagenet上训练好的1000分类的任务\nmodel=timm.create_model('swin_base_patch4_window7_224',pretrained=True)#创建模型,并且加载训练好的参数.","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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#神经网络函数库\n# from 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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path=Path('/kaggle/input/5-flowers-image-classification/train')#解析URL地址\npath","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = ImageFolder(path, transform=transform)\ndataset","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#对于模型的参数,不需要在计算中保留对应的梯度信息,即:梯度冻结\nfor param in model.parameters():\n    param.requires_grad = False\n    \nnum_classes = 5#这里进行的是五分类的任务\n#将模型的全连接层做一些改动(模型微调)\nmodel.head = nn.Linear(model.head.in_features, num_classes)","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#如果能使用GPU,就用GPU,不能使用的话用CPU\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\ndevice","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#由于是迁移学习,这里训练10次\nnum_epochs =10\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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testpath=Path('/kaggle/input/5-flowers-image-classification')#解析URL地址\ntestpath","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = ImageFolder(testpath, transform=transform)\ntest_dataset","metadata":{"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":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ans=np.array(ans).reshape(400)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def getPhoto(path_photo):\n    files_list = os.listdir(path_photo) \n    return files_list","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testfile=getPhoto('/kaggle/input/5-flowers-image-classification/test')","metadata":{"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":{"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":{"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":{"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":{"trusted":true},"execution_count":null,"outputs":[]}]}