まぃふぇいばりっと

退職D進して機械学習やってます.Julia大好きです.勉強したことの殴り書きです.

Julia言語 テンソルのKLダイバージェンス, αダイバージェンス

この論文の式(8)の実装になんと午前中を全て費やしてしまった...

Nonnegative Tucker decomposition with alpha-divergence - IEEE Conference Publication

テンソルの計算は慣れないなぁ. α=0,1でKLダイバージェンスになるんだけど,テンソルに対するKLダイバージェンスの定義はこの論文の式(15)を採用した.ところでなんでKLダイバージェンスのことをIダイバージェンスって読んでるの?あとLSエラーのLSってなんだ

とりあえずテンソルの足の添え字集合を用意する関数をつくっておく.こーゆのつくらずにうまいことできればいいんだけどなぁ.この関数は,こちらのWebページを参考にした.直積集合をもっと気軽につくれるようにしたい.

function get_tensor_idxs(args...)
    if length(args) == 0
        [[]]
    else
        xs = [[x,] for x = 1:args[1]]
        for i = 2 : length(args)
            xs = [[x..., y] for x = xs for y = 1:args[i]]
        end
        xs
    end
end

あとは定義にしたがって実装するだけ.

function D_KL(X, Xhat)
    # Tensor of KL-divergence is defined as
    # I-divergence in eq(15) in
    # http://mlg.postech.ac.kr/~seungjin/publications/cvpr07.pdf

    d_kl = 0.0

    input_tensor_shape = size(X)
    idxs = get_tensor_idxs(input_tensor_shape...)
    for idx in idxs
        d_kl += X[idx...] * log( X[idx...] / Xhat[idx...] )
    end
    d_kl -= sum(X)
    d_kl += sum(Xhat)

    return d_kl
end

function D_alpha(X, Xhat, alpha)
    # D_alpha(X, Xhat, 1) = D_KL(X, Xhat)
    # D_alpha(X, Xhat, 0) = D_KL(Xhat, X)
    if alpha == 1
        return D_KL(X, Xhat)
    end
    if alpha == 0
        return D_KL(Xhat, X)
    end

    d_alpha = 0.0
    d_alpha += alpha * sum(X)
    d_alpha += (1.0 - alpha) * sum(Xhat)

    input_tensor_shape = size(X)
    idxs = get_tensor_idxs(input_tensor_shape...)
    for idx in idxs
        d_alpha -= X[idx...]^alpha * Xhat[idx...]^(1.0 - alpha)
    end

    return d_alpha / (alpha - alpha^2)
end

追記

Juliaでテンソルの足のインデックスが欲しい時はCartesianIndicesを使うと良いみたい.強い人に教わった.もっと早く知りたかった..