Как перебрать трехмерный тензор - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть тензор:

y_true = np.array([[[1.], [0.], [3.]], [[5.], [0.], [0.]]])

Я хочу перебрать y_true для доступа ко всем независимым значениям. Я хочу сделать что-то вроде следующего в Java:

for(i=0;i<y_true.length;i++){
    arr2 = y_true[i];
    for(j=0;j<arr2.length;j++){
        print(arr2[j][0])
    }
}. 

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

Есть 2 случая:

  1. Вы знаете ранг (размерность) вашего созданного массива numpy в примере * Массив y_true имеет ранг 3, и вы можете проверить свойство y_true.shape, которое должно дать вам точный размер каждого измерения y_true, тогда вы можете написать столько циклов for для ранга y_true и вывести каждый элемент отдельно, например:

    import numpy as np
    
    y_true = np.array([[[1.], [0.], [3.]], [[5.], [0.], [0.]]])
    dims = y_true.shape
    for i in range(dims[0]):
        for j in range(dims[1]):
            for k in range(dims[2]):
                print("Element of np array with indices {} is equal to {}".format([i, j, k], y_true[i, j, k]))
    
  2. Если вы не знаете ранг тензора, который хотите распечатать, вы можете написать рекурсивную функцию, которая будет печатать все элементы, например:

    import numpy as np    
    
    
    def recursively_print_elems(np_arr, idx, pos):
        if pos >= len(np_arr.shape):
            print("Element of np array with indeces {} is equal to: {}".format(idx, np_arr[tuple(idx)]))
            return
        for i in range(np_arr.shape[pos]):
            idx[pos] = i
            recursively_print_elems(np_arr, idx, pos + 1)
    
    
    def print_elems(np_arr):
        idx = [0] * len(np_arr.shape)
        recursively_print_elems(np_arr, idx, 0)
    
    
    y_true = np.array([[[1.], [0.], [3.]], [[5.], [0.], [0.]]])
    print_elems(y_true)
    

Второй подход является более общим, он будет работать для любого размерного тензора.


0 голосов
/ 29 апреля 2018

Ваш массив:

In [19]: y_true
Out[19]: 
array([[[1.],
        [0.],
        [3.]],

       [[5.],
        [0.],
        [0.]]])
In [20]: y_true.shape
Out[20]: (2, 3, 1)

С последним размером 1, мы можем изменить его

In [21]: y_true.reshape(2,3)
Out[21]: 
array([[1., 0., 3.],
       [5., 0., 0.]])

Выбор по этому индексу также хорош.

Но вы можете получить доступ ко всем значениям по порядку, просто расправившись / уплощаясь:

In [22]: y_true.ravel()
Out[22]: array([1., 0., 3., 5., 0., 0.])

Или получите 1 итератор:

In [23]: yiter = y_true.flat
In [24]: yiter?
Type:            flatiter
String form:     <numpy.flatiter object at 0x1fdd200>
Length:          6
File:            ~/.local/lib/python3.6/site-packages/numpy/__init__.py
Docstring:       <no docstring>
Class docstring:
Flat iterator object to iterate over arrays.

A `flatiter` iterator is returned by ``x.flat`` for any array `x`.
It allows iterating over the array as if it were a 1-D array,
either in a for-loop or by calling its `next` method.
...

Таким образом, вместо создания итератора для каждого измерения мы можем выполнить итерацию для этого плоского:

In [25]: for item in yiter:print(item)
1.0
0.0
3.0
5.0
0.0
0.0

ndenumerate использует этот плоский итератор и возвращает координаты и значения:

In [26]: list(np.ndenumerate(y_true))
Out[26]: 
[((0, 0, 0), 1.0),
 ((0, 1, 0), 0.0),
 ((0, 2, 0), 3.0),
 ((1, 0, 0), 5.0),
 ((1, 1, 0), 0.0),
 ((1, 2, 0), 0.0)]

Разновидностью этого является ndindex:

In [27]: indexs = np.ndindex(y_true.shape)
In [28]: for ijk in indexs:
    ...:     print(ijk, y_true[ijk])
    ...:     
(0, 0, 0) 1.0
(0, 1, 0) 0.0
(0, 2, 0) 3.0
(1, 0, 0) 5.0
(1, 1, 0) 0.0
(1, 2, 0) 0.0

Но там, где это возможно, лучше работать со всем массивом, чем с итерациями. Эти операции с целым массивом выполняют итерацию в скомпилированном коде.

0 голосов
/ 29 апреля 2018

Вы ищете нарезку с [:,:,0]?

>>> y_true[:,:,0]
array([[1., 0., 3.],
       [5., 0., 0.]])
...