我想用一个共享分类器创建3个不同的VGG。基本上,这些体系结构中的每一个都只有卷积,然后我将所有的网结合在一起,用一个分类器。
为了得到更好的解释,让我们看看这个图像:

我不知道如何在毕道尔做这件事。你有什么我可以学习的例子吗?这是一个重量分享的例子吗?
编辑:我的实际代码。你认为是对的吗?
class VGGBlock(nn.Module):
def __init__(self, in_channels, out_channels,batch_norm=False):
super(VGGBlock,self).__init__()
conv2_params = {'kernel_size': (3, 3),
'stride' : (1, 1),
'padding' : 1
}
noop = lambda x : x
self._batch_norm = batch_norm
self.conv1 = nn.Conv2d(in_channels=in_channels,out_channels=out_channels , **conv2_params)
self.bn1 = nn.BatchNorm2d(out_channels) if batch_norm else noop
self.conv2 = nn.Conv2d(in_channels=out_channels,out_channels=out_channels, **conv2_params)
self.bn2 = nn.BatchNorm2d(out_channels) if batch_norm else noop
self.max_pooling = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))
@property
def batch_norm(self):
return self._batch_norm
def forward(self,x):
x = self.conv1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.conv2(x)
x = self.bn2(x)
x = F.relu(x)
x = self.max_pooling(x)
return xclass VGG16(nn.Module):
def __init__(self, input_size, num_classes=1,batch_norm=False):
super(VGG16, self).__init__()
self.in_channels,self.in_width,self.in_height = input_size
self.block_1 = VGGBlock(self.in_channels,64,batch_norm=batch_norm)
self.block_2 = VGGBlock(64, 128,batch_norm=batch_norm)
self.block_3 = VGGBlock(128, 256,batch_norm=batch_norm)
self.block_4 = VGGBlock(256,512,batch_norm=batch_norm)
@property
def input_size(self):
return self.in_channels,self.in_width,self.in_height
def forward(self, x):
x = self.block_1(x)
x = self.block_2(x)
x = self.block_3(x)
x = self.block_4(x)
x = torch.flatten(x,1)
return xclass VGG16Classifier(nn.Module):
def __init__(self, num_classes=1,classifier = None,batch_norm=False):
super(VGG16Classifier, self).__init__()
self._vgg_a = VGG16((1,32,32),batch_norm=True)
self._vgg_b = VGG16((1,32,32),batch_norm=True)
self._vgg_star = VGG16((1,32,32),batch_norm=True)
self.classifier = classifier
if (self.classifier is None):
self.classifier = nn.Sequential(
nn.Linear(2048, 2048),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(2048, 512),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(512, num_classes)
)
def forward(self, x1,x2,x3):
op1 = self._vgg_a(x1)
op2 = self._vgg_b(x2)
op3 = self._vgg_star(x3)
x1 = self.classifier(op1)
x2 = self.classifier(op2)
x3 = self.classifier(op3)
return x1,x2,x3
return xcmodel1 = VGG16((1,32,32),batch_norm=True)
model2 = VGG16((1,32,32),batch_norm=True)
model_star = VGG16((1,32,32),batch_norm=True)
model_combo = VGG16Classifier(model1,model2,model_star)编辑:我更改了VGG16Classifier的前向,因为以前我使用了3 VGG的输出,我做了一个接口,然后传递给分类器。相反,现在我们对每个VGG都有相同的分类器。
现在,我的问题是,我想实施这一损失:

以下是我实施的尝试:
class CombinedLoss(nn.Module):
def __init__(self, loss_a, loss_b, loss_star, _lambda=1.0):
super().__init__()
self.loss_a = loss_a
self.loss_b = loss_b
self.loss_star = loss_star
self.register_buffer('_lambda',torch.tensor(float(_lambda),dtype=torch.float32))
def forward(self,y_hat,y):
return (self.loss_a(y_hat[0],y[0]) +
self.loss_b(y_hat[1],y[1]) +
self.loss_combo(y_hat[2],y[2]) +
self._lambda * torch.sum(model_star.weight - torch.pow(torch.cdist(model1.weight+model2.weight), 2)))也许lamba*和的部分是错误的,但是,我的问题是,用这种方式,我必须将我的数据集分成3部分,才能得到y0,y1和y2,对吗?如果不能在这篇文章中提问,我会提出一个新的问题。
发布于 2021-06-14 12:40:15
一切似乎都很好,但您没有从model1、model2和model_star获得任何输出?
这是我如何编码这个东西-
import torch
import torch.nn as nn
import torch.nn.functional as F
class VGGBlock(nn.Module):
def __init__(self, in_channels, out_channels,batch_norm=False):
super(VGGBlock,self).__init__()
conv2_params = {'kernel_size': (3, 3),
'stride' : (1, 1),
'padding' : 1}
noop = lambda x : x
self.conv1 = nn.Conv2d(in_channels=in_channels,out_channels=out_channels , **conv2_params)
self.bn1 = nn.BatchNorm2d(out_channels) if batch_norm else noop
self.conv2 = nn.Conv2d(in_channels=out_channels,out_channels=out_channels, **conv2_params)
self.bn2 = nn.BatchNorm2d(out_channels) if batch_norm else noop
self.max_pooling = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))
def forward(self,x):
x = self.conv1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.conv2(x)
x = self.bn2(x)
x = F.relu(x)
x = self.max_pooling(x)
return x
class VGG16(nn.Module):
def __init__(self, input_size, num_classes=1,batch_norm=False):
super(VGG16, self).__init__()
self.in_channels,self.in_width,self.in_height = input_size
self.block_1 = VGGBlock(self.in_channels,64,batch_norm=batch_norm)
self.block_2 = VGGBlock(64, 128,batch_norm=batch_norm)
self.block_3 = VGGBlock(128, 256,batch_norm=batch_norm)
self.block_4 = VGGBlock(256,512,batch_norm=batch_norm)
@property
def input_size(self):
return self.in_channels,self.in_width,self.in_height
def forward(self, x):
x = self.block_1(x)
x = self.block_2(x)
x = self.block_3(x)
x = self.block_4(x)
x = torch.flatten(x,1)
return x
class VGG16Classifier(nn.Module):
def __init__(self, num_classes=1, classifier=None, batch_norm=False):
super(VGG16Classifier, self).__init__()
self._vgg_a = VGG16((1,32,32),batch_norm=True)
self._vgg_b = VGG16((1,32,32),batch_norm=True)
self._vgg_c = VGG16((1,32,32),batch_norm=True)
self.classifier = classifier
if (self.classifier is None):
self.classifier = nn.Sequential(
nn.Linear(2048, 2048),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(2048, 512),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(512, num_classes)
)
def forward(self,x1,x2,x3):
op1 = self._vgg_a(x1)
op2 = self._vgg_b(x2)
op3 = self._vgg_c(x3)
xc = torch.cat((op1,op2,op3),0)
xc = self.classifier(xc)
return xc
model = VGG16Classifier()
ip1 = torch.randn([1, 1, 32, 32])
ip2 = torch.randn([1, 1, 32, 32])
ip3 = torch.randn([1, 1, 32, 32])
# Model inference
print(model(ip1,ip2,ip3).shape) # torch.Size([3, 1])训练也变得直截了当,你可以做到,就像我们对任何其他网络一样。例如定义优化器,比如-
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)同样的损失和优化步骤也是一样的-
loss.backward()
optimizer.step()https://datascience.stackexchange.com/questions/96567
复制相似问题