3

私はPythonの経験がありません。チュートリアルの資料をいくつか見ましたが、高度なコードを理解するのは難しそうです。だから私はより具体的な答えを求めてここに来ました。私にとっての使命は、コンピューターのコードをやり直すことです。

シナリオは次のとおりです。

私は関係学習でテンソル因数分解を研究している大学院生です。次のように、このアルゴリズムを実行するためのコードを提供する論文[1]:

import logging, time
from numpy import dot, zeros, kron, array, eye, argmax
from numpy.linalg import qr, pinv, norm, inv 
from scipy.linalg import eigh
from numpy.random import rand

__version__ = "0.1" 
__all__ = ['rescal', 'rescal_with_random_restarts']

__DEF_MAXITER = 500
__DEF_INIT = 'nvecs'
__DEF_PROJ = True
__DEF_CONV = 1e-5
__DEF_LMBDA = 0

_log = logging.getLogger('RESCAL') 

def rescal_with_random_restarts(X, rank, restarts=10, **kwargs):
    """
    Restarts RESCAL multiple time from random starting point and 
    returns factorization with best fit.
    """
    models = []
    fits = []
    for i in range(restarts):
        res = rescal(X, rank, init='random', **kwargs)
        models.append(res)
        fits.append(res[2])
    return models[argmax(fits)]

def rescal(X, rank, **kwargs):
    """
    RESCAL 

    Factors a three-way tensor X such that each frontal slice 
    X_k = A * R_k * A.T. The frontal slices of a tensor are 
    N x N matrices that correspond to the adjecency matrices 
    of the relational graph for a particular relation.

    For a full description of the algorithm see: 
      Maximilian Nickel, Volker Tresp, Hans-Peter-Kriegel, 
      "A Three-Way Model for Collective Learning on Multi-Relational Data",
      ICML 2011, Bellevue, WA, USA

    Parameters
    ----------
    X : list
        List of frontal slices X_k of the tensor X. The shape of each X_k is ('N', 'N')
    rank : int 
        Rank of the factorization
    lmbda : float, optional 
        Regularization parameter for A and R_k factor matrices. 0 by default 
    init : string, optional
        Initialization method of the factor matrices. 'nvecs' (default) 
        initializes A based on the eigenvectors of X. 'random' initializes 
        the factor matrices randomly.
    proj : boolean, optional 
        Whether or not to use the QR decomposition when computing R_k.
        True by default 
    maxIter : int, optional 
        Maximium number of iterations of the ALS algorithm. 500 by default. 
    conv : float, optional 
        Stop when residual of factorization is less than conv. 1e-5 by default

    Returns 
    -------
    A : ndarray 
        array of shape ('N', 'rank') corresponding to the factor matrix A
    R : list
        list of 'M' arrays of shape ('rank', 'rank') corresponding to the factor matrices R_k 
    f : float 
        function value of the factorization 
    iter : int 
        number of iterations until convergence 
    exectimes : ndarray 
        execution times to compute the updates in each iteration
    """

    # init options
    ainit = kwargs.pop('init', __DEF_INIT)
    proj = kwargs.pop('proj', __DEF_PROJ)
    maxIter = kwargs.pop('maxIter', __DEF_MAXITER)
    conv = kwargs.pop('conv', __DEF_CONV)
    lmbda = kwargs.pop('lmbda', __DEF_LMBDA)
    if not len(kwargs) == 0:
        raise ValueError( 'Unknown keywords (%s)' % (kwargs.keys()) )

    sz = X[0].shape
    dtype = X[0].dtype 
    n = sz[0]
    k = len(X) 

    _log.debug('[Config] rank: %d | maxIter: %d | conv: %7.1e | lmbda: %7.1e' % (rank, 
        maxIter, conv, lmbda))
    _log.debug('[Config] dtype: %s' % dtype)

    # precompute norms of X 
    normX = [norm(M)**2 for M in X]
    Xflat = [M.flatten() for M in X]
    sumNormX = sum(normX)

    # initialize A
    if ainit == 'random':
        A = array(rand(n, rank), dtype=dtype)
    elif ainit == 'nvecs':
        S = zeros((n, n), dtype=dtype)
        T = zeros((n, n), dtype=dtype)
        for i in range(k):
            T = X[i]
            S = S + T + T.T
        evals, A = eigh(S,eigvals=(n-rank,n-1))
    else :
        raise 'Unknown init option ("%s")' % ainit

    # initialize R
    if proj:
        Q, A2 = qr(A)
        X2 = __projectSlices(X, Q)
        R = __updateR(X2, A2, lmbda)
    else :
        R = __updateR(X, A, lmbda)

    # compute factorization
    fit = fitchange = fitold = f = 0
    exectimes = []
    ARAt = zeros((n,n), dtype=dtype)
    for iter in xrange(maxIter):
        tic = time.clock()
        fitold = fit
        A = __updateA(X, A, R, lmbda)
        if proj:
            Q, A2 = qr(A)
            X2 = __projectSlices(X, Q)
            R = __updateR(X2, A2, lmbda)
        else :
            R = __updateR(X, A, lmbda)

        # compute fit value
        f = lmbda*(norm(A)**2)
        for i in range(k):
            ARAt = dot(A, dot(R[i], A.T))
            f += normX[i] + norm(ARAt)**2 - 2*dot(Xflat[i], ARAt.flatten()) + lmbda*(R[i].flatten()**2).sum()
        f *= 0.5

        fit = 1 - f / sumNormX
        fitchange = abs(fitold - fit)

        toc = time.clock()
        exectimes.append( toc - tic )
        _log.debug('[%3d] fit: %.5f | delta: %7.1e | secs: %.5f' % (iter, 
            fit, fitchange, exectimes[-1]))
        if iter > 1 and fitchange < conv:
            break
    return A, R, f, iter+1, array(exectimes)

def __updateA(X, A, R, lmbda):
    n, rank = A.shape
    F = zeros((n, rank), dtype=X[0].dtype)
    E = zeros((rank, rank), dtype=X[0].dtype)

    AtA = dot(A.T,A)
    for i in range(len(X)):
        F += dot(X[i], dot(A, R[i].T)) + dot(X[i].T, dot(A, R[i]))
        E += dot(R[i], dot(AtA, R[i].T)) + dot(R[i].T, dot(AtA, R[i]))
    A = dot(F, inv(lmbda * eye(rank) + E))
    return A

def __updateR(X, A, lmbda):
    r = A.shape[1]
    R = []
    At = A.T    
    if lmbda == 0:
        ainv = dot(pinv(dot(At, A)), At)
        for i in range(len(X)):
            R.append( dot(ainv, dot(X[i], ainv.T)) )
    else :
        AtA = dot(At, A)
        tmp = inv(kron(AtA, AtA) + lmbda * eye(r**2))
        for i in range(len(X)):
            AtXA = dot(At, dot(X[i], A)) 
            R.append( dot(AtXA.flatten(), tmp).reshape(r, r) )
    return R

def __projectSlices(X, Q):
    q = Q.shape[1]
    X2 = []
    for i in range(len(X)):
        X2.append( dot(Q.T, dot(X[i], Q)) )
    return X2

こんなに長いコードを貼り付けるのは退屈ですが、問題を解決する方法は他にありません。申し訳ありません。

このモジュールをインポートし、作成者のWeb サイトに従って引数を渡します。

import pickle, sys
from rescal import rescal

rank = sys.argv[1]
X = pickle.load('us-presidents.pickle')
A, R, f, iter, exectimes = rescal(X, rank, lmbda=1.0)

データセット us-presidents.rdf はこちらにあります

私の質問は次のとおりです。

  1. コードノートによると、テンソル X はリストです。私はこれをよく理解していません.Pythonでリストをテンソルに関連付けるにはどうすればよいですか? Python の tensor = list を理解できますか?
  2. 最初に RDF 形式をトリプル (主語、述語、目的語) 形式に変換する必要がありますか? X のデータ構造がよくわかりません。手動で X に値を代入するにはどうすればよいですか?
  3. 次に、それを実行する方法は?

作者の許可なく作者のコードを貼り付けますが、それは侵害行為ですか? もしそうなら、申し訳ありませんが、すぐに削除します。

問題は少し退屈かもしれませんが、これらは私にとって重要です。どんな助けでも大歓迎です。

[1] Maximilian Nickel, Volker Tresp, Hans-Peter Kriegel, A Three-Way Model for Collective Learning on Multi-Relational Data, in Proceedings of the 28th International Conference on Machine Learning, 2011 , Bellevue, WA, USA

4

2 に答える 2

1

Q2に答えるには:ファイル'us-presidents.pickle'からロードする前に、RDFを変換して保存する必要があります。そのコードの作者は、Pythonのネイティブピクルス形式の読み込みが速いため、おそらく一度それを実行しました。pickle形式にはデータのデータ型が含まれているため、Xnumpyクラスのインスタンスである可能性があり、このコードで使用されるサンプルのpickleファイル、またはからの変換方法を理解するためにpickle.dumpを実行するコードが必要になります。rescal予想通り、この特定のピクルスファイルへのRDF 。

したがって、これはQ1に答えるかもしれません:テンソルは要素のリストで構成されています。コードから、再スケーリングするXパラメーターの長さが(k = len(X))であり、インデックスを付けることができる()ことがわかりますT = X[i]。したがって、要素はリストとして使用されます(他のデータ型であっても、そのように動作します。

余談ですが、Pythonに精通しておらず、計算結果に関心がある場合は、ソフトウェアの作成者に連絡することでさらにサポートが得られる可能性があります。

于 2012-06-20T06:50:39.380 に答える
1
  1. コードノートによると、テンソル X はリストです。私はこれをよく理解していません.Pythonでリストをテンソルに関連付けるにはどうすればよいですか? Python の tensor = list を理解できますか?

必ずというわけではありませんが、コードの作成者は、テンソル データをリスト データ構造として表現することを決定しました。コメントが示すように、リスト X には以下が含まれます。

テンソル X の正面スライス X_k のリスト。各 X_k の形状は ('N', 'N') です。

つまり、テンソルはタプルのリストとして表されます: [(N, N), ..., (N, N)].

  1. X のデータ構造がよくわかりません。手動で X に値を代入するにはどうすればよいですか?

X のデータ構造ができたので、代入を使用してそれに値を割り当てることができます。次の例では、タプル(1, 3)をリスト X の最初の位置に割り当てます (最初の位置はインデックス 0、2 番目の位置は 1 など)。

X[0] = (1, 3)

同様に、次はタプル(2, 4)を 2 番目の位置に割り当てます。

X[1] = (2, 4)
于 2012-06-20T06:54:50.323 に答える