- 定义自己的数据集
第一种方法:ImageFolder函数,具体参考官方文档:https://pytorch-cn.readthedocs.io/zh/latest/torchvision/torchvision-datasets/
第二种方法:定义数据类继承Dataset
My code :
class SkData(Dataset): def __init__(self,img_path,transforms=None): self.imgs = pd.read_csv(img_path) self.transforms = data_transforms def __len__(self): return len(self.imgs) def __getitem__(self,index): # if self.way == 'sk_class': img_paths = self.imgs.loc[index].values[0] label1 = np.array(int(img_paths.split('/')[-2].split('A')[-1])-1) label1 = torch.from_numpy(label1) label2 = np.array(np.random.randint(0,2)) label2 = torch.from_numpy(label2) img = cv2.imread(img_paths) img = Image.fromarray(img) if self.transforms: img = self.transforms(img) return img,label1,label2
__init__中主要进行数据路径的读取和定义一些操作
__getitem__中主要进行opencv或者其他库对图片的读取和标签制作,最后一般返回的是图片与标签(可以定义成字典)
- 定义自己的网络反向传播与正向传播,以GRL(梯度反置层)为例
class ReverseLayerF(torch.autograd.Function): @staticmethod def forward(ctx, x, alpha): ctx.alpha = alpha return x @staticmethod def backward(ctx, grad_output): output = grad_output.neg() * ctx.alpha return output, None
继承Function,后使用修饰器定义自己的forward和backward
- 定义网络结构
一种可以使用堆叠的方式nn.Sequential方式,此种方式可以定义简单网络
另一种是继承nn.Module类定义自己的网络
class DiffNet(nn.Module): def __init__(self): super(DiffNet,self).__init__() self.base_model = torchvision.models.resnet50(pretrained=True) # self.base_model.aux_logits = False self.flatten = nn.Flatten() self.base_model = nn.Sequential(*list(self.base_model.children())[:-2]) self.avgpooling = nn.AdaptiveAvgPool2d((1,1)) self.fc1 = nn.Linear(2048,1024) self.fc2 = nn.Linear(1024,512) self.output1 = nn.Linear(512,2) self.output2 = nn.Linear(512,60) self.dropout = nn.Dropout(p=0.5) def forward(self,x): output_feature = self.base_model(x) output_feature = self.avgpooling(output_feature) output_feature = self.flatten(output_feature) output_feature_reverse = ReverseLayerF.apply(output_feature,0.9) # output_feature_reverse = output_feature dropout1 = self.dropout(output_feature_reverse) fc1 = F.relu(self.fc1(dropout1)) dropout2 = self.dropout(fc1) fc2 = F.relu(self.fc2(dropout2)) output1 = self.output1(fc2) # output1 = nn.LogSoftmax(output1)#rota_class dropout3 = self.dropout(output_feature) fc3 = self.fc1(dropout3) dropout4 = self.dropout(fc3) fc4 = self.fc2(dropout4) output2 = self.output2(fc4)#sk_class # output2 = nn.LogSoftmax(output2) return output1,output2
Note:在定义loss的时候注意torch.nn.NLLLoss与torch.nn.CrossEntropyLoss的区别
- 冻结某些层的参数
1 for child in model.children(): 2 ct += 1 3 if ct == 1: 4 for param in childs.parameters(): 5 param.requires_grad = False
注意在定义优化器的时候过滤掉冻结的参数
1 optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=lr_init)