Niedawno zacząłem uczyć się Julii, kodując prostą implementację samoorganizujących się map. Chcę, aby rozmiar i wymiary mapy były określone przez użytkownika, co oznacza, że naprawdę nie mogę używać pętli do pracy na macierzach map, ponieważ nie wiem z góry, ile warstw pętli będę potrzebować. Tak więc absolutnie potrzebuję funkcji rozgłaszania i cięcia, które działają na tablicach o dowolnych wymiarach.Krojenie i rozgłaszanie wielowymiarowych tablic w Julii: meshgrid example
Teraz muszę zbudować tablicę wskaźników mapy. Powiedzmy, że moja mapa jest zdefiniowana przez tablicę o rozmiarze mapsize = (5, 10, 15)
, potrzebuję skonstruować tablicę indices
o rozmiarze (3, 5, 10, 15)
, gdzie indices[:, a, b, c]
powinien zwrócić .
Pochodzę z Python/Numpy tle, w których rozwiązanie jest już podany przez konkretnego „funkcje”, mgrid:
indices = numpy.mgrid[:5, :10, :15]
print indices.shape # gives (3, 5, 10, 15)
print indices[:, 1, 2, 3] gives [1, 2, 3]
Nie spodziewałem Julia mieć taką funkcję get -go, więc zwróciłem się do nadawania. W NumPy emisja jest oparta na zbiorze reguł, które uważam za dość jasne i logiczne. Można używać tablic o różnych wymiarach w tym samym wyrażeniu tak długo, jak rozmiary w każdym meczu wymiar lub jeden z nich jest 1:
(5, 10, 15) broadcasts to (5, 10, 15)
(10, 1)
(5, 1, 15) also broadcasts to (5, 10, 15)
(1, 10, 1)
Aby w tym pomóc, można również użyć numpy.newaxis albo żaden z łatwością dodaj nowy wymiar do swojej tablicy:
array = numpy.zeros((5, 15))
array[:,None,:] has shape (5, 1, 15)
pomaga tablice broadcast prościej:
A = numpy.arange(5)
B = numpy.arange(10)
C = numpy.arange(15)
bA, bB, bC = numpy.broadcast_arrays(A[:,None,None], B[None,:,None], C[None,None,:])
bA.shape == bB.shape == bC.shape = (5, 10, 15)
Używanie tego, tworząc tablicę indices
jest raczej straightfo rward:
indices = numpy.array(numpy.broadcast_arrays(A[:,None,None], B[None,:,None], C[None,None,:]))
(indices == numpy.mgrid[:5,:10,:15]).all() returns True
ogólnym przypadku jest oczywiście nieco bardziej skomplikowane, ale można obejść stosując listowych i plasterki:
arrays = [ numpy.arange(i)[tuple([None if m!=n else slice(None) for m in range(len(mapsize))])] for n, i in enumerate(mapsize) ]
indices = numpy.array(numpy.broadcast_arrays(*arrays))
Wracając do Julii. Próbowałem zastosować ten sam rodzaj uzasadnienia i ostatecznie osiągnąłem ekwiwalent listy kodów powyżej arrays
. To okazało się być raczej prostsze niż NumPy CPF dzięki składni wyrażeń złożonych:
arrays = [ (idx = ones(Int, length(mapsize)); idx[n] = i;reshape([1:i], tuple(idx...))) for (n,i)=enumerate(mapsize) ]
Teraz utknąłem tutaj, a ja naprawdę nie wiem, jak zastosować nadawanie na mojej liście generowania tablic tutaj ... Funkcje broadcast[!]
wymagają podania funkcji f, a ja nie mam żadnych. Próbowałem za pomocą pętli for spróbować zmuszając nadawanie:
indices = Array(Int, tuple(unshift!([i for i=mapsize], length(mapsize))...))
for i=1:length(mapsize)
A[i] = arrays[i]
end
Ale to daje mi błąd: ERROR: convert has no method matching convert(::Type{Int64}, ::Array{Int64,3})
robię to we właściwy sposób? Czy przeoczyłem coś ważnego? Każda pomoc jest doceniana.
Awesome! Zmodyfikowałem trochę kod, aby uzyskać wynik jednego tensora: Druga linia: 'X = Array (Int, tuple (unshift! ([I for i = dims], length (dims)) ...))'; 8. linia: 'X [d, cur_idx ...] = i' – Nathan