Разные собственные значения по градиенту nano и numpy linalg.eigh

#python #numpy #theano #eigenvalue #gradient-descent

#python #numpy #теано #собственное значение #градиентный спуск

Вопрос:

Я использовал theano.tensor.grad(), чтобы получить градиентный спуск, а затем вычислить собственные значения и собственные векторы матрицы X. Я также использовал numpy.linalg.eigh() для получения собственных значений и собственных векторов. Буквально, собственные значения из двух методов должны быть одинаковыми, в то время как я получил другой ответ. Вот код для двух методов, и я печатаю верхние 16 собственных значений из выходных данных соответственно.

 import sys
import numpy as np
import numpy.linalg as linalg
import theano
import theano.tensor as T
print theano.__version__
print np.version.version

def compute_first_eigen(X,max_iteration,rate):
    sz = 32
    cur_v = T.vector('cur_v')
    xx = T.dmatrix('xx')
    dot_xxv = T.dot(xx,cur_v)
    cost = T.dot(dot_xxv.T, dot_xxv)
    grad_ = T.grad(cost,cur_v)

    eigen_first = theano.function(
        inputs=[xx,cur_v],
        outputs=grad_,
        allow_input_downcast=True)

    v = np.random.rand(sz*sz)
    t = 1
    while t < max_iteration:
        prev_v = v
        y = v rate*eigen_first(X,v)
        v = y / linalg.norm(y)
        v_dis = linalg.norm(v-prev_v)
        if v_dis < sys.float_info.epsilon:
            break
        t = t 1
    xv = np.dot(X,v)
    value_1 = np.dot(xv.T,xv)
    return value_1,v

# set a X for testing.
sz = 32
X = np.random.rand(20,sz*sz)

rate = 0.5

# setting theano function
v = T.vector('v') 
xx = T.dmatrix('x') 
xxv = T.dot(xx,v)

coeffs = T.vector('coeffs')
vecs = T.fmatrix('vecs')
components,updates = theano.scan(fn=lambda coeffs,vecs,v:(v.dot(vecs) ** 2) * coeffs,
    outputs_info=None,
    sequences=[coeffs,vecs],
    non_sequences=v)
sum_ = components.sum()
cost = T.dot(xxv.T,xxv) - sum_

gv = T.grad(cost, v)

eigen_compute = theano.function(
  inputs=[xx,coeffs,vecs,v],
  outputs=gv,
  updates=updates,
  allow_input_downcast=True
)
val_1,vec_1 = compute_first_eigen(X, 10000, 0.5)
evals = np.array([val_1])
evecs = np.array([vec_1])
print evals

for i in range(1,16):
    t = 1

    vout = np.random.rand(sz*sz)
    while t < 10000:
        # outputs, vout = eigen_compute(X,evals,evecs)
        prev_v = vout
        y = vout   rate*eigen_compute(X,evals,evecs,vout)
        vout = y / linalg.norm(y)
        v_dis = linalg.norm(vout-prev_v)
        if v_dis < sys.float_info.epsilon:
            break
        t = t 1
    evecs = np.concatenate((evecs,vout.reshape((1,sz*sz))),axis=0)
    Xv = np.dot(X, vout)
    evals = np.append(evals,np.dot(Xv.T, Xv)) 
print evals

# numpy Linalg eigh
eigenvals,eigenvecs = linalg.eigh(np.dot(X.T,X))
idx = eigenvals.argsort()[::-1] # decreasing order of eigenvalues
eigenvals = eigenvals[idx]
D = eigenvecs[:, idx]
print eigenvals[:16]
# print sys.float_info
  

Результат 16 лучших собственных значений, как показано ниже. Первое является результатом градиента nano, последнее — из функции numpy eigh.

 [ 5185.16126103   107.55438452   103.12505677    97.43512945    96.5613719
93.96313905    93.10809773    92.42390547    89.16485977    86.65039761
84.73367931    83.0397494     81.79609393    78.64115855    76.32032247
75.24690368]

[ 5180.1757114    844.85544447   751.07308305   705.97215297   642.28619825
 611.22852835   598.26571675   568.71283447   550.16102596   538.15434055
 534.25366614   514.62884927   513.80252085   507.78943946   475.20260796
 472.42131454]
  

У меня нет идей о том, как это произошло. Я пробовал разные версии numpy, но это не помогло. Кто-нибудь знает, как это произошло?

Кстати, версия python 2.7.10, numpy 1.11.2, theano 0.9.0dev3.dev- .

Комментарии:

1. Может быть, из-за этого? X = np.random.rand(20,sz*sz)

2. @tommy.carstensen Нет, dtype не помогает.