Общие параметры, позволяющие избежать вложенных циклов for для операций с трехмерной матрицей - PullRequest
2 голосов
/ 11 июля 2019

После моих исследований о вложенных циклах я хотел бы поднять этот общий вопрос: мне нужно запускать различные функции на 3d-матрицах (многоканальных файлах изображений) с shape, например, (2500, 100, 200) или (диапазонами)., lines, cols).

Общая (медленная) процедура подхода к функциям обработки выглядит следующим образом:

import numpy as np
import time

x = np.random.random_sample([2500, 100, 200])

#  1. & 2. derivative example

def derivate(matrix):
    d1 = np.empty(shape=np.shape(matrix))
    d2 = np.empty(shape=np.shape(matrix))
    for row in range(matrix.shape[1]):
        for col in range(matrix.shape[2]):
            d1[:, row, col] = np.gradient(matrix[:, row, col])
            d2[:, row, col] = np.gradient(d1[:, row, col])
    return d1, d2


t1 = time.perf_counter()
y, z = derivate(x)
t2 = time.perf_counter()
print(t2 - t1)

>>> 4.38 seconds

Поскольку многие функции в этом стиле уже существуют в моей среде проекта, яВ поисках простейшего решения, позволяющего значительно ускорить эти вложенные функции цикла.

Я видел, что многие вопросы здесь касаются вложенных циклов for, но я не нашел ни одного общего и переносимого решения.Я был бы очень признателен, если бы было представлено много доступных подходов, ура!

1 Ответ

1 голос
/ 11 июля 2019

Вы можете реализовать это так:

import numpy as np

def derivate_vec(matrix):
    d1 = np.gradient(matrix, axis=0)
    d2 = np.gradient(d1, axis=0)
    return d1, d2

Быстрое сравнение:

import numpy as np
import time

def derivate(matrix):
    d1 = np.empty(shape=np.shape(matrix))
    d2 = np.empty(shape=np.shape(matrix))
    for row in range(matrix.shape[1]):
        for col in range(matrix.shape[2]):
            d1[:, row, col] = np.gradient(matrix[:, row, col])
            d2[:, row, col] = np.gradient(d1[:, row, col])
    return d1, d2

def derivate_vec(matrix):
    d1 = np.gradient(matrix, axis=0)
    d2 = np.gradient(d1, axis=0)
    return d1, d2

# Input data
np.random.seed(0)
x = np.random.random_sample([2500, 100, 200])

# Check results
d11, d12 = derivate(x)
d21, d22 = derivate_vec(x)
print(np.allclose(d11, d21))
# True
print(np.allclose(d12, d22))
# True

# Measure time
t1 = time.perf_counter()
derivate(x)
t2 = time.perf_counter()
derivate_vec(x)
t3 = time.perf_counter()
print(t2 - t1)
# 3.6777221
print(t3 - t2)
# 0.9414466999999997
...