没错,我就是那个为了勋章不择手段的屑(手动狗头)。快乐的假期结束了哭哭...
DANN 对抗迁移学习
域适应Domain Adaption-迁移学习;把具有不同分布的源域(Source Domain)和目标域(Target Domain)中的数据,映射到同一个特征空间。
GAN:生成对抗网络,包含生成器和判别器,有点类似博弈论的做法。
GAN+迁移学习:生成器不再是生成样本,而是进行特征提取工作。目标:从源域和目标域中提取特征,使得判别器无法区别提取的特征是来自哪个域。
好的可迁移特征:1-Domain-invariance,2.Discriminativeness
损失loss:训练损失和域判别损失
这里有一个疑惑,就是梯度反转层gradient reversal layer的作用?论文原文称之为GRL。
部分源码
下面对DANN的一个pytorch实现代码进行简要的分析。仅对网络的搭建代码进行说明。
1-梯度反转层的构建(GRL)
from torch.autograd import Function
class ReverseLayerF(Function):
@staticmethod
def forward(ctx, x, alpha):
ctx.alpha = alpha
return x.view_as(x)
@staticmethod
def backward(ctx, grad_output):
output = grad_output.neg() * ctx.alpha
return output, None
2-整体模型的搭建
这一版的写法很像keras,完成了结构图中的模型搭建,各个网络的意义如论文中的那个图一样。
import torch.nn as nn
from functions import ReverseLayerF
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
self.feature = nn.Sequential()
self.feature.add_module('f_conv1', nn.Conv2d(3, 64, kernel_size=5))
self.feature.add_module('f_bn1', nn.BatchNorm2d(64))
self.feature.add_module('f_pool1', nn.MaxPool2d(2))
self.feature.add_module('f_relu1', nn.ReLU(True))
self.feature.add_module('f_conv2', nn.Conv2d(64, 50, kernel_size=5))
self.feature.add_module('f_bn2', nn.BatchNorm2d(50))
self.feature.add_module('f_drop1', nn.Dropout2d())
self.feature.add_module('f_pool2', nn.MaxPool2d(2))
self.feature.add_module('f_relu2', nn.ReLU(True))
self.class_classifier = nn.Sequential()
self.class_classifier.add_module('c_fc1', nn.Linear(50 * 4 * 4, 100))
self.class_classifier.add_module('c_bn1', nn.BatchNorm1d(100))
self.class_classifier.add_module('c_relu1', nn.ReLU(True))
self.class_classifier.add_module('c_drop1', nn.Dropout())
self.class_classifier.add_module('c_fc2', nn.Linear(100, 100))
self.class_classifier.add_module('c_bn2', nn.BatchNorm1d(100))
self.class_classifier.add_module('c_relu2', nn.ReLU(True))
self.class_classifier.add_module('c_fc3', nn.Linear(100, 10))
self.class_classifier.add_module('c_softmax', nn.LogSoftmax(dim=1))
self.domain_classifier = nn.Sequential()
self.domain_classifier.add_module('d_fc1', nn.Linear(50 * 4 * 4, 100))
self.domain_classifier.add_module('d_bn1', nn.BatchNorm1d(100))
self.domain_classifier.add_module('d_relu1', nn.ReLU(True))
self.domain_classifier.add_module('d_fc2', nn.Linear(100, 2))
self.domain_classifier.add_module('d_softmax', nn.LogSoftmax(dim=1))
def forward(self, input_data, alpha):
input_data = input_data.expand(input_data.data.shape[0], 3, 28, 28)
feature = self.feature(input_data)
feature = feature.view(-1, 50 * 4 * 4)
reverse_feature = ReverseLayerF.apply(feature, alpha)
class_output = self.class_classifier(feature)
domain_output = self.domain_classifier(reverse_feature)
return class_output, domain_output
本文分析的源码是github上源文件的一个子集,欢迎各位一起来交流学习。GitHub - fungtion/DANN_py3: python 3 pytorch implementation of DANN
原文的链接贴在这里,方便各位朋友细看。