Skip to content

Commit

Permalink
upd: contents
Browse files Browse the repository at this point in the history
  • Loading branch information
jindongwang committed Oct 29, 2019
1 parent 9c79048 commit 17e8b65
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 20 deletions.
4 changes: 3 additions & 1 deletion src/chaps/ch00_prefix.tex
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ \section*{说明}

第6章到第8章,介绍了领域自适应的3大类基本的方法,分别是:数据分布自适应法、特征选择法、子空间学习法。

第9章重点介绍了目前持续最火的深度迁移学习方法
第9章重点介绍了目前主流的深度迁移学习方法

第10章提供了简单的上手实践教程。

Expand All @@ -90,6 +90,8 @@ \section*{说明}

\textbf{手册的相关资源:}

我们在Github上持续维护了迁移学习的资源仓库,包括论文、代码、文档、比赛等,请读者持续关注:\url{https://github.com/jindongwang/transferlearning},配合本手册更香哦!

网站(内含勘误表):\url{http://t.cn/RmasEFe}

开发维护地址: \url{http://github.com/jindongwang/transferlearning-tutorial}
Expand Down
205 changes: 202 additions & 3 deletions src/chaps/ch10_practice.tex
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ \section{上手实践}

在众多的非深度迁移学习方法中,我们选择最经典的迁移方法之一、发表于IEEE TNN 2011的TCA(Transfer Component Analysis)~\cite{pan2011domain}方法进行实践。为了便于学习,我们同时用Matlab和Python实现了此代码。代码的链接为\url{https://github.com/jindongwang/transferlearning/tree/master/code/traditional/TCA}。下面我们对代码进行简单讲解。

\subsection{TCA方法代码实现}

\subsubsection{Matlab}

\textbf{1. 数据获取}
Expand Down Expand Up @@ -254,7 +256,7 @@ \subsubsection{Python}

与Matlab代码类似,我们也可以用Python对TCA进行实现,其主要依赖于Numpy和Scipy两个强大的科学计算库。Python版本的TCA代码如下:

\begin{lstlisting}[title=TCA方法的Matlab实现, frame=shadowbox]
\begin{lstlisting}[title=TCA方法的Python实现, frame=shadowbox]

import numpy as np
import scipy.io
Expand Down Expand Up @@ -355,8 +357,205 @@ \subsubsection{Python}

通过以上过程,我们分别使用Matlab代码和Python代码对经典的TCA方法进行了实验,完成了一个迁移学习任务。其他的非深度迁移学习方法,均可以参考上面的过程。值得庆幸的是,许多论文的作者都公布了他们的文章代码,以方便我们进行接下来的研究。读者可以从Github~\footnote{\url{https://github.com/jindongwang/transferlearning/tree/master/code}}或者相关作者的网站上获取其他许多方法的代码。

%\subsection{深度网络的finetune}
\subsection{深度网络的finetune代码实现}

本小节我们用Pytorch实现一个深度网络的finetune。Pytorch是一个较为流行的深度学习工具包,由Facebook进行开发,在Github~\footnote{\url{https://github.com/pytorch/pytorch}}上也进行了开源。

Finetune指的是训练好的深度网络,拿来在新的目标域上进行微调。因此,我们假定读者具有基本的Pytorch知识,直接给出finetune的代码。完整的代码可以在这里~\footnote{\url{https://github.com/jindongwang/transferlearning/tree/master/code/deep/finetune_AlexNet_ResNet}}找到。

我们定义一个叫做finetune的函数,它接受输入的一个已有模型,从目标数据中进行微调,输出最好的模型其结果。其代码如下:

\begin{lstlisting}[title=深度网络的finetune代码实现, frame=shadowbox]

def finetune(model, dataloaders, optimizer):
since = time.time()
best_acc = 0.0
acc_hist = []
criterion = nn.CrossEntropyLoss()
for epoch in range(1, N_EPOCH + 1):
# lr_schedule(optimizer, epoch)
print('Learning rate: {:.8f}'.format(optimizer.param_groups[0]['lr']))
print('Learning rate: {:.8f}'.format(optimizer.param_groups[-1]['lr']))
for phase in ['src', 'val', 'tar']:
if phase == 'src':
model.train()
else:
model.eval()
total_loss, correct = 0, 0
for inputs, labels in dataloaders[phase]:
inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)
optimizer.zero_grad()
with torch.set_grad_enabled(phase == 'src'):
outputs = model(inputs)
loss = criterion(outputs, labels)
preds = torch.max(outputs, 1)[1]
if phase == 'src':
loss.backward()
optimizer.step()
total_loss += loss.item() * inputs.size(0)
correct += torch.sum(preds == labels.data)
epoch_loss = total_loss / len(dataloaders[phase].dataset)
epoch_acc = correct.double() / len(dataloaders[phase].dataset)
acc_hist.append([epoch_loss, epoch_acc])
print('Epoch: [{:02d}/{:02d}]---{}, loss: {:.6f}, acc: {:.4f}'.format(epoch, N_EPOCH, phase, epoch_loss,
epoch_acc))
if phase == 'tar' and epoch_acc > best_acc:
best_acc = epoch_acc
print()
fname = 'finetune_result' + model_name + \
str(LEARNING_RATE) + str(args.source) + \
'-' + str(args.target) + '.csv'
np.savetxt(fname, np.asarray(a=acc_hist, dtype=float), delimiter=',',
fmt='%.4f')
time_pass = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(
time_pass // 60, time_pass % 60))

return model, best_acc, acc_hist

\end{lstlisting}

其中,model可以是由任意深度网络训练好的模型,如Alexnet、Resnet等。

另外,有很多任务也需要用到深度网络来提取深度特征以便进一步处理。我们也进行了实现,代码在\url{https://github.com/jindongwang/transferlearning/blob/master/code/feature_extractor}中。

%
%\subsection{深度网络自适应}
\subsection{深度网络自适应代码}

我们仍然以Pytorch为例,实现深度网络的自适应。具体地说,实现经典的DDC (Deep Domain Confusion)~\cite{tzeng2014deep}方法和与其类似的DCORAL (Deep CORAL)~\cite{sun2016deep}方法。

此网络实现的核心是:如何正确计算DDC中的MMD损失、以及DCORAL中的CORAL损失,并且与神经网络进行集成。此部分对于初学者难免有一些困惑。如何输入源域和目标域、如何进行判断?因此,我们认为此部分应该是深度迁移学习的基础代码,读者应该努力地进行学习和理解。

\textbf{网络结构}

首先我们要定义好网络的架构,其应该是来自于已有的网络结构,如Alexnet和Resnet。但不同的是,由于要进行深度迁移适配,因此,输出层要和finetune一样,和目标的类别数相同。其二,由于要进行距离的计算,我们需要加一个叫做bottleneck的层,用来将最高维的特征进行降维,然后进行距离计算。当然,bottleneck层不加尚可。

我们的网络结构如下所示:

\begin{lstlisting}[title=深度迁移网络代码实现, frame=shadowbox]
import torch.nn as nn
import torchvision
from Coral import CORAL
import mmd
import backbone


class Transfer_Net(nn.Module):
def __init__(self, num_class, base_net='resnet50', transfer_loss='mmd', use_bottleneck=True, bottleneck_width=256, width=1024):
super(Transfer_Net, self).__init__()
self.base_network = backbone.network_dict[base_net]()
self.use_bottleneck = use_bottleneck
self.transfer_loss = transfer_loss
bottleneck_list = [nn.Linear(self.base_network.output_num(
), bottleneck_width), nn.BatchNorm1d(bottleneck_width), nn.ReLU(), nn.Dropout(0.5)]
self.bottleneck_layer = nn.Sequential(*bottleneck_list)
classifier_layer_list = [nn.Linear(self.base_network.output_num(), width), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(width, num_class)]
self.classifier_layer = nn.Sequential(*classifier_layer_list)

self.bottleneck_layer[0].weight.data.normal_(0, 0.005)
self.bottleneck_layer[0].bias.data.fill_(0.1)
for i in range(2):
self.classifier_layer[i * 3].weight.data.normal_(0, 0.01)
self.classifier_layer[i * 3].bias.data.fill_(0.0)

def forward(self, source, target):
source = self.base_network(source)
target = self.base_network(target)
source_clf = self.classifier_layer(source)
if self.use_bottleneck:
source = self.bottleneck_layer(source)
target = self.bottleneck_layer(target)
transfer_loss = self.adapt_loss(source, target, self.transfer_loss)
return source_clf, transfer_loss

def predict(self, x):
features = self.base_network(x)
clf = self.classifier_layer(features)
return clf

\end{lstlisting}

其中Transfer Net是整个网络的模型定义。它接受参数有:

\begin{itemize}
\item num class: 目标域类别数
\item base net: 主干网络,例如Resnet等,也可以是自己定义的网络结构
\item Transfer loss: 迁移的损失,比如MMD和CORAL,也可以是自己定义的损失
\item use bottleneck: 是否使用bottleneck
\item bottleneck width: bottleneck的宽度
\item width: 分类器层的width
\end{itemize}

\textbf{迁移损失定义}

迁移损失是核心。其定义如下:

\begin{lstlisting}[title=深度迁移网络代码实现, frame=shadowbox]

def adapt_loss(self, X, Y, adapt_loss):
"""Compute adaptation loss, currently we support mmd and coral
Arguments:
X {tensor} -- source matrix
Y {tensor} -- target matrix
adapt_loss {string} -- loss type, 'mmd' or 'coral'. You can add your own loss
Returns:
[tensor] -- adaptation loss tensor
"""
if adapt_loss == 'mmd':
mmd_loss = mmd.MMD_loss()
loss = mmd_loss(X, Y)
elif adapt_loss == 'coral':
loss = CORAL(X, Y)
else:
loss = 0
return loss
\end{lstlisting}

其中的MMD和CORAL是自己实现的两个loss,MMD对应DDC方法,CORAL对应DCORAL方法。其代码在上述github中可以找到,我们不再赘述。

\textbf{训练}

训练时,我们一次输入一个batch的源域和目标域数据。为了方便,我们使用pytorch自带的dataloader。

\begin{lstlisting}[title=深度迁移网络代码实现, frame=shadowbox]
def train(source_loader, target_train_loader, target_test_loader, model, optimizer, CFG):
len_source_loader = len(source_loader)
len_target_loader = len(target_train_loader)
train_loss_clf = utils.AverageMeter()
train_loss_transfer = utils.AverageMeter()
train_loss_total = utils.AverageMeter()
for e in range(CFG['epoch']):
model.train()
iter_source, iter_target = iter(
source_loader), iter(target_train_loader)
n_batch = min(len_source_loader, len_target_loader)
criterion = torch.nn.CrossEntropyLoss()
for i in range(n_batch):
data_source, label_source = iter_source.next()
data_target, _ = iter_target.next()
data_source, label_source = data_source.to(
DEVICE), label_source.to(DEVICE)
data_target = data_target.to(DEVICE)

optimizer.zero_grad()
label_source_pred, transfer_loss = model(data_source, data_target)
clf_loss = criterion(label_source_pred, label_source)
loss = clf_loss + CFG['lambda'] * transfer_loss
loss.backward()
optimizer.step()
train_loss_clf.update(clf_loss.item())
train_loss_transfer.update(transfer_loss.item())
train_loss_total.update(loss.item())
if i % CFG['log_interval'] == 0:
print('Train Epoch: [{}/{} ({:02d}%)], cls_Loss: {:.6f}, transfer_loss: {:.6f}, total_Loss: {:.6f}'.format(
e + 1,
CFG['epoch'],
int(100. * i / n_batch), train_loss_clf.avg, train_loss_transfer.avg, train_loss_total.avg))

# Test
test(model, target_test_loader)
\end{lstlisting}

%
%\subsection{深度对抗网络迁移}
1 change: 1 addition & 0 deletions src/chaps/ch13_appendix.tex
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ \subsection{迁移学习相关的期刊和会议}
9 & ECCV & European Conference on Computer Vision & 计算机视觉 \\ \hline
10 & WWW & International World Wide Web Conferences & 文本、互联网 \\ \hline
11 & CIKM & International Conference on Information and Knowledge Management & 文本分析 \\ \hline
12 & ACMMM & ACM International Conference on Multimedia & 多媒体 \\ \hline
\end{tabular}
}
\end{table}
Expand Down
5 changes: 3 additions & 2 deletions src/main.tex
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@
\renewcommand{\today}{\number\year\number\month\number\day 日}


\title{{\Huge 迁移学习简明手册{\large\linebreak\\}}{\Large 一点心得体会\\版本号:v1.0\linebreak\linebreak
\title{{\Huge 迁移学习简明手册{\large\linebreak\\}}{\Large 一点心得体会\\版本号:v1.1\linebreak\linebreak
}}
\author{\\
王晋东\\中国科学院计算技术研究所\\\href{http://tutorial.transferlearning.xyz}{tutorial.transferlearning.xyz}}
\date{2018年4月}
\date{2018年4月初稿\\
2019年10月最新修改}
\maketitle
\thispagestyle{empty}

Expand Down
32 changes: 18 additions & 14 deletions src/main.toc
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,21 @@
\contentsline {subsubsection}{\numberline {9.4.2}核心方法}{52}{subsubsection.9.4.2}%
\contentsline {subsubsection}{\numberline {9.4.3}小结}{55}{subsubsection.9.4.3}%
\contentsline {section}{\numberline {10}上手实践}{56}{section.10}%
\contentsline {subsubsection}{\numberline {10.0.1}Matlab}{56}{subsubsection.10.0.1}%
\contentsline {section}{\numberline {11}迁移学习前沿}{61}{section.11}%
\contentsline {subsection}{\numberline {11.1}机器智能与人类经验结合迁移}{61}{subsection.11.1}%
\contentsline {subsection}{\numberline {11.2}传递式迁移学习}{61}{subsection.11.2}%
\contentsline {subsection}{\numberline {11.3}终身迁移学习}{62}{subsection.11.3}%
\contentsline {subsection}{\numberline {11.4}在线迁移学习}{63}{subsection.11.4}%
\contentsline {subsection}{\numberline {11.5}迁移强化学习}{64}{subsection.11.5}%
\contentsline {subsection}{\numberline {11.6}迁移学习的可解释性}{64}{subsection.11.6}%
\contentsline {section}{\numberline {12}总结语}{65}{section.12}%
\contentsline {section}{\numberline {13}附录}{66}{section.13}%
\contentsline {subsection}{\numberline {13.1}迁移学习相关的期刊和会议}{66}{subsection.13.1}%
\contentsline {subsection}{\numberline {13.2}迁移学习研究学者}{66}{subsection.13.2}%
\contentsline {subsection}{\numberline {13.3}迁移学习资源汇总}{69}{subsection.13.3}%
\contentsline {subsection}{\numberline {13.4}迁移学习常用算法及数据资源}{70}{subsection.13.4}%
\contentsline {subsection}{\numberline {10.1}TCA方法代码实现}{56}{subsection.10.1}%
\contentsline {subsubsection}{\numberline {10.1.1}Matlab}{56}{subsubsection.10.1.1}%
\contentsline {subsubsection}{\numberline {10.1.2}Python}{60}{subsubsection.10.1.2}%
\contentsline {subsection}{\numberline {10.2}深度网络的finetune代码实现}{62}{subsection.10.2}%
\contentsline {subsection}{\numberline {10.3}深度网络自适应代码}{63}{subsection.10.3}%
\contentsline {section}{\numberline {11}迁移学习前沿}{66}{section.11}%
\contentsline {subsection}{\numberline {11.1}机器智能与人类经验结合迁移}{66}{subsection.11.1}%
\contentsline {subsection}{\numberline {11.2}传递式迁移学习}{66}{subsection.11.2}%
\contentsline {subsection}{\numberline {11.3}终身迁移学习}{67}{subsection.11.3}%
\contentsline {subsection}{\numberline {11.4}在线迁移学习}{68}{subsection.11.4}%
\contentsline {subsection}{\numberline {11.5}迁移强化学习}{69}{subsection.11.5}%
\contentsline {subsection}{\numberline {11.6}迁移学习的可解释性}{69}{subsection.11.6}%
\contentsline {section}{\numberline {12}总结语}{70}{section.12}%
\contentsline {section}{\numberline {13}附录}{71}{section.13}%
\contentsline {subsection}{\numberline {13.1}迁移学习相关的期刊和会议}{71}{subsection.13.1}%
\contentsline {subsection}{\numberline {13.2}迁移学习研究学者}{71}{subsection.13.2}%
\contentsline {subsection}{\numberline {13.3}迁移学习资源汇总}{74}{subsection.13.3}%
\contentsline {subsection}{\numberline {13.4}迁移学习常用算法及数据资源}{75}{subsection.13.4}%

0 comments on commit 17e8b65

Please sign in to comment.