class SVDLinear(link.Link):
    """
        U x V
    """
    def __init__(self, in_size, out_size=None, nobias=False,
                 initialV=None, initialU=None, initial_bias=None,
                 k=16):
        super(SVDLinear, self).__init__()

        if out_size is None:
            in_size, out_size = None, in_size
        self.out_size = out_size
        self.k = k
        with self.init_scope():
            U_initializer = initializers._get_initializer(initialU)
            V_initializer = initializers._get_initializer(initialV)

            # Is it dirty code?
            self.U = Parameter(V_initializer)
            self.U.to_gpu()
            self.V = Parameter(U_initializer)
            self.V.to_gpu()

            self.register_persistent('U')

            if in_size is not None:
                self._initialize_params(in_size)

            if nobias:
                self.b = None
            else:
                if initial_bias is None:
                    initial_bias = 0
                bias_initializer = initializers._get_initializer(initial_bias)
                self.b = Parameter(bias_initializer, out_size)

    def _initialize_params(self, in_size):
        self.U.initialize((self.k, in_size))
        self.V.initialize((self.out_size, self.k))

    def __call__(self, x):
        """Applies the linear layer. However, I checked this code for simple data, It does not work...
        Args:
            x (~chainer.Variable): Batch of input vectors.
        Returns:
            ~chainer.Variable: Output of the linear layer.
        """
        if self.U.data is None or self.V.data is not None:
            in_size = x.shape[1]
            self._initialize_params(in_size)

        # x: (batch_size, CxHxW)
        # V: (CxHxW, k)
        # W: (k, CxHxW)
        # (V*(U*x))+b = Wx + b
        W1 = linear.linear(x, self.U)
        return linear.linear(W1, self.V, self.b)
Ejemplo n.º 2
0
class PCA(Chain):
    """
    extract: (batch, in_channel, H, W, D) -> (batch, hidden_channel)
    reverse: (batch, hidden_channel) -> (batch, in_channel * H * W * D)
    """
    def __init__(self, hidden_channel, initialW=None, initial_bias=None):
        super().__init__()
        self.hidden_channel = hidden_channel
        self.initial_bias = initial_bias
        self.initialW = initialW

    def __call__(self, x):
        original_shape = x.shape
        if not hasattr(self, "W"):
            with self.init_scope():
                self.W = Parameter(
                    _get_initializer(self.initialW),
                    (self.hidden_channel,
                     int(self.xp.prod(self.xp.array(original_shape[1:])))))
                self.W.to_gpu()
        if not hasattr(self, "bias"):
            self.bias = Parameter(
                _get_initializer(self.initial_bias),
                (int(self.xp.prod(self.xp.array(original_shape[1:]))), ))
            self.bias.to_gpu()

        if x.ndim > 2:
            x = x.reshape(len(x), -1)

        h = x - broadcast_to(self.bias, x.shape)
        h = linear(h, self.W)
        h = linear(h, self.W.T)
        h = h + broadcast_to(self.bias, h.shape)
        h = reshape(h, original_shape)
        return h

    def to_gpu(self, device=None):
        if hasattr(self, "W"):
            self.W.to_gpu(device)
        if hasattr(self, "bias"):
            self.bias.to_gpu(device)