【问题标题】:How to run a .py module?如何运行 .py 模块?
【发布时间】:2012-06-20 06:03:09
【问题描述】:

我对 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

粘贴这么长的代码很无聊,但没有其他方法可以找出我的问题。对此我很抱歉。

我根据作者website导入这个模块并传递参数:

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可以在here找到。

我的问题是:

  1. 根据代码注释,张量 X 是一个列表。我不太明白这一点,如何将列表与 Python 中的张量相关联?我能理解 Python 中的 tensor = list 吗?
  2. 是否应该先将 RDF 格式转换为三元组(主语、谓语、宾语)格式?我不确定 X 的数据结构。如何手动为 X 赋值?
  3. 那么,如何运行呢?

擅自粘贴作者代码,是否侵权?如果是这样,我很抱歉,我会尽快删除它。

这些问题可能有点无聊,但这些对我来说很重要。任何帮助将不胜感激。

[1] 马克西米利安·尼克尔、沃尔克·特雷斯普、汉斯-彼得·克里格尔、 多关系数据集体学习的三向模型, 第 28 届机器学习国际会议论文集,2011 年,美国华盛顿州贝尔维尤

【问题讨论】:

  • 运行一个模块只需执行:python modulename

标签: python numpy scipy rdf factorization


【解决方案1】:

回答问题 2:您需要转换 RDF 并保存它,然后才能从文件“us-presidents.pickle”加载它。该代码的作者可能曾经这样做过,因为 Python 本机 pickle 格式加载速度更快。由于 pickle 格式包含数据的数据类型,X 可能是一些 numpy 类实例,您需要此代码使用的示例 pickle 文件,或者执行 pickle.dump 的一些代码来弄清楚如何按照rescal 的预期从RDF 转换为这个特定的pickle 文件。

所以这可能会回答 Q1:张量由元素列表组成。从代码中您可以看到要重新缩放的X 参数有一个长度(k = len(X))并且可以被索引(T = X[i])。所以它的元素被用作一个列表(即使它可能是其他一些数据类型,也就是这样。

顺便说一句:如果您不熟悉 Python 并且只对计算结果感兴趣,您可能会获得更多帮助,请联系该软件的作者。

【讨论】:

  • cool,现在的问题是如何通过转换或承包给作者得到文件'us-presidents.pickle',我试试看。
【解决方案2】:
  1. 根据代码注释,张量 X 是一个列表。我不太明白这一点,如何将列表与 Python 中的张量相关联?我可以吗 了解 Python 中的 tensor = list 吗?

不一定,但代码作者已决定将张量数据表示为列表数据结构。正如 cmets 所示,列表 X 包含:

张量X的正面切片X_k的列表。每个X_k的形状是('N', 'N')

这意味着张量被表示为一个元组列表:[(N, N), ..., (N, N)]

  1. 我不确定 X 的数据结构。如何手动为 X 赋值?

现在我们有了 X 的数据结构,我们可以使用赋值给它赋值。下面将分配元组 (1, 3) 到列表 X 中的第一个位置(因为第一个位置在索引 0,第二个在位置 1,等等):

X[0] = (1, 3)

同样,以下将元组 (2, 4) 分配到第二个位置:

X[1] = (2, 4)

【讨论】:

  • 谢谢,但是当您分配 X[0] = (1,3) 时,会出现错误:文件“C:\Python27\rescal.py”,第 88 行,在 rescal sz = X[ 0].shape AttributeError: 'tuple' 对象没有属性 'shape'
  • 在这种情况下,X 的元素不是元组,而是不同类型的对象。在进行任何分配以检查类型是什么然后构造该类型的对象之前尝试print type(X[0])。然后,您可以将这些对象分配给 X(例如,X[0] = ...)。
  • 我在numpytutorial中找到了shape方法,非常感谢!
猜你喜欢
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2021-03-31
  • 2018-12-16
  • 2021-04-03
  • 1970-01-01
相关资源
最近更新 更多