Как векторизовать функцию уменьшения масштаба с NumPY? - PullRequest
1 голос
/ 30 октября 2019

Учитывая матрицу NxM в NumPY, я хочу уменьшить частоту дискретизации до матрицы NxO (O <<< M), чтобы значения в матрице NxO были линейно интерполированы из одинаково разнесенных выборок в исходной матрице. </p>

В качестве примера рассмотрим матрицу 3x10:

[
    [1  2  3  4  5  6  7  8  9  10]
    [10 9  8  7  6  5  4  3  2  1 ]
    [4  6  4  6  4  6  4  6  4  6 ]
]

Если бы мне пришлось уменьшить частоту дискретизации до матрицы 3x4, значения могли бы выровняться следующим образом:

1   2   3   4   5   6   7   8   9   10
|---|---|---|---|---|---|---|---|---|
       *      *       *      *      
       1      2       3      4

В целом, учитывая, что М исходных элементов подвергается понижающей дискретизации до O новых элементов, первый элемент должен быть выбран из (M-1)/(O+1) с дополнительными выборками, взятыми с шагом (M-1)/(O+1). Это можно увидеть на изображении выше, где 10 оригинальных элементов дают 9 «промежутков» между элементами. Мы хотим разделить это расстояние в 9 «промежутков» на 5 равных частей (оставляя равное пространство слева и справа с равным интервалом между каждым из элементов). Таким образом, каждый новый элемент находится на расстоянии 9/5 = 1,8 "пробелов" друг от друга:

  • Новый элемент 0 = Старый элемент 1,8
  • Новый элемент 1 = Старый элемент 3,6
  • Новый элемент 2 = Старый элемент 5.4
  • Новый элемент 3 = Старый элемент 7.2

Используя базовую линейную интерполяцию, мы можем сказать, что «элемент 1.8» равен 80% элемента 2 плюс 20% от элемента 1

Поэтому моя окончательная матрица будет выглядеть так:

[
    [2.8 4.6 6.4 8.2]
    [8.2 6.4 4.6 2.8]
    [4.4 4.8 5.2 5.6]
]

Я подумал просто написать функцию для вычисления выходных значений и использовать метод np.apply_along_axis(), но потом я увидел в этом посте StackOverflow , в котором говорится, что это просто хрупкая обертка для цикла for, и вам лучше векторизовать вашу функцию.

Так как же векторизовать это? Можно ли это сделать?

1 Ответ

1 голос
/ 30 октября 2019

Попробуйте эту функцию

def downsample(m, samples):
    weights = np.zeros((m.shape[1], samples))
    for n in range(samples):
        pos = ((m.shape[1] - 1) / (samples + 1)) * (n + 1)
        if pos == np.floor(pos):
            weights[int(np.floor(pos)), n] = 1
        else:
            weights[int(np.ceil(pos)), n] = pos - int(np.floor(pos))
            weights[int(np.floor(pos)), n] = int(np.ceil(pos)) - pos
    return np.matmul(m, weights)

Она создает матрицу весов на основе описанной вами интерполяции, а затем применяет этот вес ко всей матрице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...