在深度学习领域,编程的复杂性常常让初学者和经验丰富的数据科学家都感到畏惧。复杂的代码和不完善的文档使得理解代码变得困难。因此,推荐使用Pytorch Lightning,这是一个继承自Pytorch的开源库。Pytorch Lightning自动化了许多深度学习和神经网络的编码工作,让可以专注于模型构建。此外,Pytorch Lightning还有助于编写更清晰、更易于复现的代码。想要了解更多信息,请访问。
将使用的数据集是Kaggle上的。该数据集已经以一种简化模型构建的方式进行了结构化。数据集包含两个主要文件夹“Train”和“Test”,每个文件夹下有5个子文件夹,这些子文件夹包含图像,每个图像的类别就是子文件夹的名称。与其它图像数据集相比,这个数据集相对较小,因此将使用数据增强进行预处理。建议在远程笔记本上运行,如Kaggle笔记本,因为在当地笔记本上运行任何图像识别模型都可能计算成本较高。现在,让开始编码。
前提条件:如果想跟随本教程进行编码,需要安装Pytorch Lightning。如果在本地环境中运行,而Kaggle或Colab上运行的所有笔记本应该已经安装了它。在本地Python环境中安装命令为pip install pytorch-lightning
,在本地conda环境中安装命令为conda install -c conda-forge pytorch-lightning
。还建议安装torchvision和cv2,以便轻松预处理图像数据。
让运行所有必要的导入操作来开始。
import torch
from torch.nn import functional as F
from torch import nn
import pytorch_lightning as pl
from pytorch_lightning.core.lightning import LightningModule
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
import pandas as pd
import torchvision
import cv2
import torchvision.transforms as transforms
import os
from random import randint
!jupyter nbextension enable --py widgetsnbextension
如果无法运行这个单元格,说明环境中有一个或多个库尚未安装。
声明训练和测试文件夹的路径。
train_path = "../input/yoga-poses-dataset/DATASET/TRAIN"
test_path = "../input/yoga-poses-dataset/DATASET/TEST"
classes_dir_data = os.listdir(base_path)
num_of_classes = len(classes_dir_data)
print("Total Number of Classes :" , num_of_classes)
num = 0
classes_dict = {}
num_dict = {}
for c in classes_dir_data:
classes_dict[c] = num
num_dict[num] = c
num = num +1
num_dict包含一个按数值分类的字典及其对应的类别。classes_dict包含一个类别字典及其对应的数值。
接下来,将创建数据集。
class Image_Dataset(Dataset):
"""
classes:The classes in the dataset
image_base_dir:The directory of the folders containing the images
transform:The transformations for the Images
Target_transform:The transformations for the target
"""
def __init__(self,classes,image_base_dir,transform = None, target_transform = None):
self.img_labels = classes
self.imge_base_dir = image_base_dir
self.transform = transform
self.target_transform = target_transform
def __len__(self):
return len(self.img_labels)
def __getitem__(self,idx):
img_dir_list = os.listdir(os.path.join(self.imge_base_dir,self.img_labels[idx]))
image_path = img_dir_list[randint(0,len(img_dir_list)-1)]
image_path = os.path.join(self.imge_base_dir,self.img_labels[idx],image_path)
image = cv2.imread(image_path)
if self.transform:
image = self.transform(image)
if self.transform:
label = self.target_transform(self.img_labels[idx])
return image,label
所有将在此数据集上运行的转换。
basic_transformations = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((size,size)),
transforms.Grayscale(1),
transforms.ToTensor()])
training_transformations = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((size,size)),
transforms.RandomRotation(degrees = 45),
transforms.RandomHorizontalFlip(p = 0.005),
transforms.Grayscale(1),
transforms.ToTensor()])
def target_transformations(x):
return torch.tensor(classes_dict.get(x))
这个Pytorch Lightning模块将使向模型传递值变得更容易。
class YogaDataModule(pl.LightningDataModule):
def __init__(self):
super().__init__()
def prepare_data(self):
self.train = Image_Dataset(classes_dir_data,train_path,training_transformations,target_transformations)
self.valid = Image_Dataset(classes_dir_data,test_path,basic_transformations,target_transformations)
self.test = Image_Dataset(classes_dir_data,test_path,basic_transformations,target_transformations)
def train_dataloader(self):
return DataLoader(self.train,batch_size = 64,shuffle = True)
def val_dataloader(self):
return DataLoader(self.valid,batch_size = 64,shuffle = True)
def test_dataloader(self):
return DataLoader(self.test,batch_size = 64,shuffle = True)
class YogaModel(LightningModule):
def __init__(self):
super().__init__()
self.layer_1 = nn.Conv2d(in_channels = 1,out_channels = 3,kernel_size = (3,3),padding = (1,1),stride = (1,1))
self.layer_2 = nn.Conv2d(in_channels = 3,out_channels = 6,kernel_size = (3,3),padding = (1,1),stride = (1,1))
self.layer_3 = nn.Conv2d(in_channels = 6,out_channels = 12,kernel_size = (3,3),padding = (1,1),stride = (1,1))
self.pool = nn.MaxPool2d(kernel_size = (3,3),padding = (1,1),stride = (1,1))
self.layer_5 = nn.Linear(12*50*50,1000)
self.layer_6 = nn.Linear(1000,100)
self.layer_7 = nn.Linear(100,50)
self.layer_8 = nn.Linear(50,10)
self.layer_9 = nn.Linear(10,5)
def forward(self,x):
x = self.layer_1(x)
x = self.pool(x)
x = self.layer_2(x)
x = self.pool(x)
x = self.layer_3(x)
x = self.pool(x)
x = x.view(x.size(0),-1)
print(x.size())
x = self.layer_5(x)
x = self.layer_6(x)
x = self.layer_7(x)
x = self.layer_8(x)
x = self.layer_9(x)
return x
def configure_optimizers(self):
optimizer = torch.optim.Adam(self.parameters(),lr = 1e-7)
return optimizer
def training_step(self,batch,batch_idx):
x,y = batch
y_pred = self(x)
loss = F.cross_entropy(y_pred,y)
return loss
def validation_step(self,batch,batch_idx):
x,y = batch
y_pred = self(x)
loss = F.cross_entropy(y_pred,y)
return loss
def test_step(self,batch,batch_idx):
x,y = batch
y_pred = self(x)
loss = F.cross_entropy(y_pred,y)
self.log("loss",loss)
return loss
from pytorch_lightning import Trainer
model = YogaModel()
module = YogaDataModule()
trainer = Trainer(max_epochs=1 , cpu = 1)
trainer.fit(model,module)
trainer.test()