【论文笔记】Domain Adaptation via Transfer Component Analysis

论文题目:《Domain Adaptation via Transfer Component Analysis》

论文作者:Sinno Jialin Pan, Ivor W. Tsang, James T. Kwok and Qiang Yang

论文链接https://www.cse.ust.hk/~qyang/Docs/2009/TCA.pdf

会议期刊:IJCAI 2009 / IEEE Transactions on Neural Networks 2010

简介

领域自适应(Domain Adaptation)的一个主要问题是如何减少源域和目标域之间的差异.

一个好的特征表示应该尽可能地减少域间分布差异, 同时保持原始数据重要的特性(如几何/统计特性等).

本文提出一个新的特征提取方式, 叫做迁移成分分析(transfer component analysis, TCA).

TCA学习所有域的公共迁移成分(即不会引起域间分布变化保持原始数据固有结构的成分), 使得不同域在投影后的子空间中分布差异减少.

预备知识

问题设定

源域(source domain)中有带标签数据 \(\mathcal{D}_{S}\), 目标域(target domain)中只有大量无标签数据 \(\mathcal{D}_{T}\).

  • \(\mathcal{D}_{S}=\left\{\left(x_{S_{1}}, y_{S_{1}}\right), \ldots,\left(x_{S_{n}}, y_{S_{n}}\right)\right\}\), \(x_{S_{i}} \in \mathcal{X}\) 为输入数据, \(y_{S_{i}} \in \mathcal{Y}\)为对应的标签.

  • \(\mathcal{D}_{T}=\left\{x_{T_{1}}, \ldots, x_{T_{n_{2}}}\right\}\), \(x_{T_{i}} \in \mathcal{X}\).

  • \(\mathcal{P(X_{S})}\)\(\mathcal{Q(X_{T})}\) 分别为 \(X_S\)\(X_T\) 的边缘分布.

设定: 边缘分布不同 \(\mathcal{P} \ne \mathcal{Q}\), 但类条件概率分布相同 \(P(Y_{S} | X_{S}) = P(Y_{T} | X_{T})\).

任务: 在目标域中预测输入数据 \(x_{T_{i}}\) 对应的标签 \(y_{T_{i}}\).

最大均值差异

我们知道, 存在很多准则可以度量不同分布之间的差异, 如, KL散度等.

但这些方法通常都需要对分布的概率密度进行估计, 因而是参数化的方法. 为了避免引入额外的参数, 我们希望寻找一种非参数化的方法来度量分布的差异.

在2006年, Borgwardt等人[1]提出了一种基于再生核希尔伯特空间(Reproducing Kernel Hilbert Space, RKHS)的分布度量准则 最大均值差异(Maximum Mean Discrepancy, MMD).

\(X = \{ x_1, \cdots, x_{n1}\}\)\(Y = \{ y_1, \cdots, y_{n2}\}\) 为两个分布 \(\mathcal{P}\)\(\mathcal{Q}\) 的随机变量集合, 根据MMD的定义, 两个分布的经验估计距离为:

\[\operatorname{Dist}(\mathrm{X}, \mathrm{Y})=\left\|\frac{1}{n_{1}} \sum_{i=1}^{n_{1}} \phi\left(x_{i}\right)-\frac{1}{n_{2}} \sum_{i=1}^{n_{2}} \phi\left(y_{i}\right)\right\|_{\mathcal{H}} \tag{1} \]

其中, \(\mathcal{H}\) 是再生核希尔伯特空间, \(\phi : \mathcal{X} \to \mathcal{H}\) 为核函数映射.

迁移成分分析

\(\phi : \mathcal{X} \to \mathcal{H}\) 为非线性映射, \(X^{\prime}_{S} = \{ x^{\prime}_{S_{i}} \} = \{ \phi(x_{S_{i}}) \}\), \(X^{\prime}_{T} = \{ x^{\prime}_{T_{i}} \} = \{ \phi(x_{T_{i}}) \}\), \(X^{\prime} = X^{\prime}_{S} \cup X^{\prime}_{T}\) 分别为源域/目标域/结合域映射后的数据.

我们希望找到这样一个映射, 使得映射后的数据分布一致, 即 \(\mathcal{P^{\prime}}(X^{\prime}_{S}) = \mathcal{Q^{\prime}}(X^{\prime}_{T})\).

根据MMD的定义, 我们可以通过度量两个域之间的经验均值的距离平方作为分布的距离.

\[\operatorname{Dist}\left(X_{S}^{\prime}, X_{T}^{\prime}\right)=\left\|\frac{1}{n_{1}} \sum_{i=1}^{n_{1}} \phi\left(x_{S_{i}}\right)-\frac{1}{n_{2}} \sum_{i=1}^{n_{2}} \phi\left(x_{T_{i}}\right)\right\|_{\mathcal{H}}^{2} \tag{2} \]

通过最小化公式\((2)\), 我们可以找到想要的非线性映射 \(\phi\).

然而, 对公式\((2)\)直接优化是十分困难的, 通常会陷入局部极值点. 因此, 必须另辟蹊径.

核学习

为了避免显式地直接寻找非线性变换 \(\phi\), Pan等人[2]将该问题转化为核学习(kernel learning)问题.

通过利用核技巧 \(k(x_i, x_j) = \phi(x_i)^{\prime}\phi(x_j)\), 公式\((2)\)中两个域之间的经验均值距离可以被写为:

\[\begin{aligned} \operatorname{Dist}\left(X_{S}^{\prime}, X_{T}^{\prime}\right) &= \frac{1}{n^{2}_{1}} \sum_{i=1}^{n_1} \sum_{j=1}^{n_1} k\left(x_{S_i}, x_{S_j}\right)+\frac{1}{n^{2}_{2}} \sum_{i=1}^{n_2} \sum_{j=1}^{n_2} k\left(x_{T_i}, x_{T_j}\right)-\frac{2}{n_1 n_2} \sum_{i=1}^{n_1} \sum_{j=1}^{n_2} k\left(x_{S_i}, x_{T_j}\right) \\ &= \operatorname{tr}(K L) \\ \end{aligned} \tag{3} \]

其中,

\[K=\left[ \begin{array}{ll}{K_{S, S}} & {K_{S, T}} \\ {K_{T, S}} & {K_{T, T}}\end{array}\right] \tag{4} \]

\((n_1 + n_2) \times (n_1 + n_2)\) 大小的核矩阵, \(K_{S,S}\), \(K_{T,T}\), \(K_{S,T}\) 分别为由 \(k\) 定义在源域/目标域/跨域的核矩阵.

\(L = [ L_{ij} ] \succeq 0\) 为半正定矩阵, 其中

\[l_{i j}=\left\{\begin{array}{ll}{\frac{1}{n_{1}^{2}}} & {x_{i}, x_{j} \in \mathcal{D}_{s}} \\ {\frac{1}{n_{2}^{2}}} & {x_{i}, x_{j} \in \mathcal{D}_{t}} \\ {-\frac{1}{n_{1} n_{2}}} & {\text { otherwise }}\end{array}\right. \tag{5} \]

在直推学习的设置下(直推学习即假设未标记的数据就是最终要用来测试的数据, 学习的目的即为在这些数据上取得最佳泛化能力), 核函数 \(k(\cdot, \cdot)\) 可以通过求解核矩阵 \(K\) 替代.

Pan等人[2:1]将核矩阵学习问题形式化为半定规划(semi-definite program, SDP)问题. 然后, 对学习到的核矩阵使用PCA方法得到跨域的低维隐空间.

参数化核映射

MMDE[2:2]的方法存在如下局限性:

  • 它是直推式的, 不能泛化到未见的样本中
  • 公式\((3)\)中的\(K\)需要是半正定的, 且求解SDP问题十分耗时
  • 为了构造低维表示, 需要对\(K\)进行PCA处理, 这会损失\(K\)中的信息

本文提出一种基于核特征提取来寻找非线性映射 \(\phi\) 的高效方法.

  • 避免求解SDP问题, 减轻计算负担
  • 学习到的核函数\(k\)可以泛化到未见的样本
  • 利用显式的低秩表示得到统一的核学习方法

首先, 公式\((4)\)中的核矩阵 \(K\) 可以被分解为 \(K = (KK^{-1/2})(K^{-1/2}K)\), 这通常称为经验核映射(empirical kernel map)[3].

★注: 这个分解可由矩阵的特征分解得到, 即令 \(K = Q^{-1}\Lambda Q\) 代入.
至于为什么要对核矩阵 \(K\) 进行分解, 可以这样理解, 核矩阵给出的是映射后数据的内积, 即 \(K_{ij} = k(x_i, x_j)\), 但我们只想知道映射后的数据 \(\phi(x)\) 该怎么办? 便可以将矩阵分解成 \(K=A^TA\) 的形式, 使得 \(A = [ \phi(x_1), \cdots, \phi(x_{n_1 + n_2}) ]\), 即 \(A\) 中的每个元素都是映射后的数据.
在上述的分解中, \(A\) 即为 \(K^{-1/2}K\). 注意到 \(K\) 为对称半正定矩阵, 因此 \(A^T = (K^{-1/2}K)^T = KK^{-1/2}\).

考虑使用 \((n_1 + n_2) \times m\) 维的矩阵 \(\widetilde{W}\) 将特征变化到 \(m\) 维空间 (通常 \(m \ll n_1 + n_2\)), 则得到的核矩阵为:

\[\widetilde{K} = (KK^{-1/2}\widetilde{W})(\widetilde{W}^TK^{-1/2}K) = KWW^TK \tag{6} \]

其中, \(W = K^{-1/2}\widetilde{W} \in \mathbb{R}^{(n_1 + n_2) \times m}\). 特别地, 任意两个数据 \(x_i\)\(x_j\) 的核函数为:

\[\tilde{k}(x_i, x_j) = k^{T}_{x_i}WW^Tk_{x_j} \tag{7} \]

其中, \(k_x = [ k(x_1, x), \cdots, k(x_{n_1 + n_2}, x)]^T \in \mathbb{R}^{n_1 + n_2}\). 因此, 公式\((7)\)中的核函数给出了未见样本的参数化核估计表示.

此外, 根据公式\((6)\)\(\widetilde{K}\)的定义, 两个域之间的经验均值距离可重新写为:

\[\begin{aligned} \operatorname{Dist}\left(X_{S}^{\prime}, X_{T}^{\prime}\right) &=\operatorname{tr}\left(\left(K W W^{\top} K\right) L\right) \\ &=\operatorname{tr}\left(W^{\top} K L K W\right) \\ & {\scriptsize //利用迹循环性质:tr(ABC)=tr(BCA)=tr(CAB)} \end{aligned} \tag{8} \]

迁移成分提取

在最小化公式\((8)\)的时候, 通常需要加一个正则项 \(tr(W^TW)\) (即矩阵二范数 \(\Vert W \Vert_{2}\))来控制参数 \(W\) 的复杂度.

从而, 领域自适应的核学习问题可变为:

\[\begin{array}{cl} {\min \limits_{W}} & {\operatorname{tr}\left(W^{\top} W\right)+\mu \operatorname{tr}\left(W^{\top} K L K W\right)} \\ {\text { s.t. }} & {W^{\top} K H K W=I} \end{array} \tag{9} \]

其中, \(\mu\) 为权衡参数, \(I \in \mathbb{R}^{m \times m}\) 为单位阵, \(H = I_{n_1 + n_2} - \frac{1}{n_1 + n_2} \mathrm{1}\mathrm{1}^T\)中心矩阵(centering matrix), \(\mathrm{1} \in \mathbb{R}^{n_1 + n_2}\) 为全1列向量, \(I_{n_1 + n_2} \in \mathbb{R}^{(n_1 + n_2) \times (n_1 + n_)}\) 为单位阵.

★注: 添加 \(W^{\top} K H K W=I\) 限制条件一方面是为了避免平凡解(即\(W = 0\)), 另一方面是为了保持数据的散度(\(W^{\top} K H K W\)为投影后数据\(W^{\top} K\)的散度矩阵), 即前面简介中所说的保持原始数据固有结构.

尽管公式\((9)\)为非凸优化问题, 但其可以转化为迹优化问题:

\[\min _{W} \operatorname{tr}\left(\left(W^{\top} K H K W\right)^{\dagger} W^{\top}(I+\mu K L K) W\right) \tag{10} \]

或者

\[\max _{W} \operatorname{tr}\left(\left(W^{\top}(I+\mu K L K) W\right)^{-1} W^{\top} K H K W\right) \tag{11} \]

上述转化可由拉格朗日乘子法得到, 具体证明略...

类似于核Fisher判别, 公式\((11)\)\(W\) 的解为 \((I + \mu KLK)^{-1}KHK\) 的前 \(m\) 个特征值对应的特征向量.

因此, 本文提出的方法命名为迁移成分分析(Transfer Component Analysis, TCA).

实验结果

toy dataset

(左) toy dataset   (中) PCA   (右) TCA

跨域WiFi定位

跨域文本分类

代码

via: jindongwang/transferlearning

# encoding=utf-8
"""
    Created on 21:29 2018/11/12 
    @author: Jindong Wang
"""
import numpy as np
import scipy.io
import scipy.linalg
import sklearn.metrics
import sklearn.neighbors


def kernel(ker, X, X2, gamma):
    if not ker or ker == 'primal':
        return X
    elif ker == 'linear':
        if not X2:
            K = np.dot(X.T, X)
        else:
            K = np.dot(X.T, X2)
    elif ker == 'rbf':
        n1sq = np.sum(X ** 2, axis=0)
        n1 = X.shape[1]
        if not X2:
            D = (np.ones((n1, 1)) * n1sq).T + \
            np.ones((n1, 1)) * n1sq - 2 * np.dot(X.T, X)
        else:
            n2sq = np.sum(X2 ** 2, axis=0)
            n2 = X2.shape[1]
            D = (np.ones((n2, 1)) * n1sq).T + \
            np.ones((n1, 1)) * n2sq - 2 * np.dot(X.T, X)
        K = np.exp(-gamma * D)
    elif ker == 'sam':
        if not X2:
            D = np.dot(X.T, X)
        else:
            D = np.dot(X.T, X2)
        K = np.exp(-gamma * np.arccos(D) ** 2)
    return K


class TCA:
    def __init__(self, kernel_type='primal', dim=30, lamb=1, gamma=1):
        '''
        Init func
        :param kernel_type: kernel, values: 'primal' | 'linear' | 'rbf' | 'sam'
        :param dim: dimension after transfer
        :param lamb: lambda value in equation
        :param gamma: kernel bandwidth for rbf kernel
        '''
        self.kernel_type = kernel_type
        self.dim = dim
        self.lamb = lamb
        self.gamma = gamma

    def fit(self, Xs, Xt):
        '''
        Transform Xs and Xt
        :param Xs: ns * n_feature, source feature
        :param Xt: nt * n_feature, target feature
        :return: Xs_new and Xt_new after TCA
        '''
        X = np.hstack((Xs.T, Xt.T))
        X /= np.linalg.norm(X, axis=0)
        m, n = X.shape
        ns, nt = len(Xs), len(Xt)
        e = np.vstack((1 / ns * np.ones((ns, 1)), -1 / nt * np.ones((nt, 1))))
        M = e * e.T
        M = M / np.linalg.norm(M, 'fro')
        H = np.eye(n) - 1 / n * np.ones((n, n))
        K = kernel(self.kernel_type, X, None, gamma=self.gamma)
        n_eye = m if self.kernel_type == 'primal' else n
        a, b = np.linalg.multi_dot([K, M, K.T]) + self.lamb * \
               np.eye(n_eye), np.linalg.multi_dot([K, H, K.T])
        w, V = scipy.linalg.eig(a, b)
        ind = np.argsort(w)
        A = V[:, ind[:self.dim]]
        Z = np.dot(A.T, K)
        Z /= np.linalg.norm(Z, axis=0)
        Xs_new, Xt_new = Z[:, :ns].T, Z[:, ns:].T
        return Xs_new, Xt_new

    def fit_predict(self, Xs, Ys, Xt, Yt):
        '''
        Transform Xs and Xt, then make predictions on target using 1NN
        :param Xs: ns * n_feature, source feature
        :param Ys: ns * 1, source label
        :param Xt: nt * n_feature, target feature
        :param Yt: nt * 1, target label
        :return: Accuracy and predicted_labels on the target domain
        '''
        Xs_new, Xt_new = self.fit(Xs, Xt)
        clf = sklearn.neighbors.KNeighborsClassifier(n_neighbors=1)
        clf.fit(Xs_new, Ys.ravel())
        y_pred = clf.predict(Xt_new)
        acc = sklearn.metrics.accuracy_score(Yt, y_pred)
        return acc, y_pred


if __name__ == '__main__':
    domains = ['caltech.mat', 'amazon.mat', 'webcam.mat', 'dslr.mat']
    for i in range(4):
        for j in range(4):
            if i != j:
                src, tar = 'data/' + domains[i], 'data/' + domains[j]
                src_domain, tar_domain = scipy.io.loadmat(src), scipy.io.loadmat(tar)
                Xs, Ys, Xt, Yt = src_domain['feas'], src_domain['label'], \
                                 tar_domain['feas'], tar_domain['label']
                tca = TCA(kernel_type='primal', dim=30, lamb=1, gamma=1)
                acc, ypre = tca.fit_predict(Xs, Ys, Xt, Yt)
                print(acc)

参考文献


  1. Karsten M. Borgwardt, Arthur Gretton, Malte J. Rasch, Hans-Peter Kriegel, Bernhard Scholkopf, and Alexander J. Smola. Integrating structured biological data by kernel maximum mean discrepancy. In ISMB, pages 49–57, Fortaleza, Brazil, 2006 ↩︎

  2. Sinno Jialin Pan, James T. Kwok, and Qiang Yang. Transfer learning via dimensionality reduction. In Proceedings of AAAI, pages 677–682, Chicago, Illinois, USA, 2008. ↩︎ ↩︎ ↩︎

  3. Bernhard Scholkopf, Alexander Smola, and Klaus-Robert Muller. Nonlinear component analysis as a kernel eigenvalue problem. Neural Computation, 10(5):1299–1319,1998. ↩︎

posted @ 2019-03-28 12:27  orzyt  阅读(3807)  评论(2编辑  收藏  举报