2017-02-07 67 views
13

iki vektör v ve w ve onları bu şekilde dışında bir matris m olmak için: Diğer bir deyişleGereksiz boyutlarda boyut kaybı olmadan tensörler için dış ürün nasıl uygulanır?

m[i, j] = v[i] * w[j] 

I dış ürün bunların hesaplamak istiyoruz. Bunu theano.tensor.outer kullanarak veya v ve v'a yeni dizinler ekleyerek ve dot ürününü kullanarak yapabilirim.

m = T.dot(v[:,numpy.newaxis], w[numpy.newaxis,:]) 

Şimdi biraz daha genel bir sorunu çözmeye çalışıyorum. Iki vektör yerine v ve w Ben iki matrisler (Ben onlarıve w olarak adlandırıyorum) matris v matris w (birinci satırdaki i_th satır karşılık gelen satırı ile her satırın bir dış ürün hesaplamak istiyorum) ikinci matrisin i_th satırı ile çarpılır). Yani, böyle bir şey yapmak istiyorum:

başka deyişle
m1 = T.tensordot(v[:,:, numpy.newaxis], w[:,:,numpy.newaxis], axes = [[2],[2]]) 
m[i, j, k] = m1[i, k, j, k] 

, m[:,:,k] matrisin v ve matrisin w ait k_th satırdan k_th sıranın dış ürüne tekabül matristir.

Yukarıdaki "çözüm" ile ilgili iki sorun görüyorum. İlk olarak, bu gerçekten bir çözüm değildir, çünkü kodun ikinci satırı uygun bir teano kodu değildir. Yani, ilk sorum, bazı dizinlerin eşit olmasını zorlayarak bu "gelişmiş dilimleme" yi nasıl yapacağız. Örneğin m[i, k] = a[i, k, i, i, k]. İkincisi, ilk olarak iki 2D tensörden bir 4D tesnor (m1) oluşturduğumu ve daha sonra bir 3D tensörüne indirgemeyi sevmiyorum. Çok hafıza tüketen olabilir. Sanırım bundan kurtulabiliriz.

cevap

1

Böyle bir şey mi arıyorsunuz?

>>> a = b = np.arange(8).reshape([2,4]) 
>>> a[:,None,:]*b[:,:,None] 
array([[[ 0, 0, 0, 0], 
     [ 0, 1, 2, 3], 
     [ 0, 2, 4, 6], 
     [ 0, 3, 6, 9]], 

     [[16, 20, 24, 28], 
     [20, 25, 30, 35], 
     [24, 30, 36, 42], 
     [28, 35, 42, 49]]]) 
4

Biz dimshuffle ile iki giriş matrisleri içine broadcastable boyutlarını tanıtmak ve daha sonra bunların satırları coresponding arasındaki dış yan ürün ile sonuçlanan elementwise çarpım broadcasting icabına izin gerekiyor. Theano matrisleri gibi V ve W ile Böylece

, sadece yapılacak - NumPy olarak

V.dimshuffle(0, 1, 'x')*W.dimshuffle(0, 'x', 1) 

, boyutları permutasyonu için boyutları ve np.transpose() uzatmak np.newaxis sahiptir. theno ile, bu görevlerin her ikisini de listeleme boyutu kimlikleri ve x 'lerinin yeni yayınlanabilir eksenlerini tanıtmak için kullanması için vardır.

Örnek çalıştırma

1) Girişler:

# Numpy arrays 
In [121]: v = np.random.randint(11,99,(3,4)) 
    ...: w = np.random.randint(11,99,(3,5)) 
    ...: 

# Perform outer product on corresponding rows in inputs 
In [122]: for i in range(v.shape[0]): 
    ...:  print(np.outer(v[i],w[i])) 
    ...:  
[[2726 1972 1740 2117 1972] 
[8178 5916 5220 6351 5916] 
[7520 5440 4800 5840 5440] 
[8648 6256 5520 6716 6256]] 
[[8554 3458 8918 4186 4277] 
[1786 722 1862 874 893] 
[8084 3268 8428 3956 4042] 
[2444 988 2548 1196 1222]] 
[[2945 2232 1209 372 682] 
[2565 1944 1053 324 594] 
[7125 5400 2925 900 1650] 
[6840 5184 2808 864 1584]] 

2) Theano kısmı:

# Get to theano : Get the theano matrix versions 
In [123]: V = T.matrix('v') 
    ...: W = T.matrix('w') 
    ...: 

# Use proposed code 
In [124]: OUT = V.dimshuffle(0, 1, 'x')*W.dimshuffle(0, 'x', 1) 

# Create a function out of it and then use on input NumPy arrays 
In [125]: f = function([V,W], OUT) 

3) doğrulama sonuçları:

In [126]: f(v,w) # Verify results against the earlier loopy results 
Out[126]: 
array([[[ 2726., 1972., 1740., 2117., 1972.], 
     [ 8178., 5916., 5220., 6351., 5916.], 
     [ 7520., 5440., 4800., 5840., 5440.], 
     [ 8648., 6256., 5520., 6716., 6256.]], 

     [[ 8554., 3458., 8918., 4186., 4277.], 
     [ 1786., 722., 1862., 874., 893.], 
     [ 8084., 3268., 8428., 3956., 4042.], 
     [ 2444., 988., 2548., 1196., 1222.]], 

     [[ 2945., 2232., 1209., 372., 682.], 
     [ 2565., 1944., 1053., 324., 594.], 
     [ 7125., 5400., 2925., 900., 1650.], 
     [ 6840., 5184., 2808., 864., 1584.]]]) 
1

Kimsenin np.einsum'u kullanmayı denediğine inanamıyorum. Bu eşdeğer Theano fonksiyonu benziyor

w 
array([[1, 8, 9, 2], 
     [1, 2, 9, 0], 
     [5, 8, 7, 3], 
     [2, 9, 8, 2]]) 

v 
array([[1, 4, 5, 9], 
     [9, 1, 3, 7], 
     [9, 6, 1, 5], 
     [4, 9, 7, 0]]) 

for i in range(w.shape[0]): 
    print(np.outer(w[i], v[i])) 

[[ 1 4 5 9] 
[ 8 32 40 72] 
[ 9 36 45 81] 
[ 2 8 10 18]] 
[[ 9 1 3 7] 
[18 2 6 14] 
[81 9 27 63] 
[ 0 0 0 0]] 
[[45 30 5 25] 
[72 48 8 40] 
[63 42 7 35] 
[27 18 3 15]] 
[[ 8 18 14 0] 
[36 81 63 0] 
[32 72 56 0] 
[ 8 18 14 0]] 

np.einsum('ij,ik->ijk', w, v) 

array([[[ 1, 4, 5, 9], 
     [ 8, 32, 40, 72], 
     [ 9, 36, 45, 81], 
     [ 2, 8, 10, 18]], 

     [[ 9, 1, 3, 7], 
     [18, 2, 6, 14], 
     [81, 9, 27, 63], 
     [ 0, 0, 0, 0]], 

     [[45, 30, 5, 25], 
     [72, 48, 8, 40], 
     [63, 42, 7, 35], 
     [27, 18, 3, 15]], 

     [[ 8, 18, 14, 0], 
     [36, 81, 63, 0], 
     [32, 72, 56, 0], 
     [ 8, 18, 14, 0]]]) 

(daha hızlı einsum daha olması gerekiyordu) theano.tensor.batched_dot, ama Theano ile hiçbir deneyimim var.

+0

Mükemmel bir DSL uygulaması ... bu durumda Einstein notasyonu/toplama kuralı :) –