Получение ValueError при попытке использовать np.piecewise для многомерной функции - PullRequest
0 голосов
/ 05 февраля 2019

Я пытаюсь определить многомерную кусочную функцию, используя np.piecewise следующим образом:

X = np.array([
    [1, 2],
    [3, 4], 
    [5, 6]
])

pw = np.piecewise(
    X,
    [
        np.abs(X[:, 0] - X[:, 1]) < 1,
        np.abs(X[:, 0] - X[:, 1]) >= 1
    ],
    [
        lambda X: 1 + 2 * X[:, 0] + 3 * X[:, 1],
        lambda X: 1.5 + 2.5 * X[:, 0] + 3.5 * X[:, 1]
    ]
)

Запуск этого фрагмента дает следующую ошибку:

ValueError: shape mismatch: value array of shape (3,) could not be broadcast to indexing result of shape (3,2)

Для контекста, яПытаюсь представить карту f: R ^ 2 -> R в этом примере, оценивая ее по каждой из строк X одновременно.

Есть идеи?Нужно ли определять конечный параметр по-другому, чтобы индексирование транслировалось правильно?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Используя структурированный массив, я мог бы преобразовать 2d формулировку в 1d:

In [76]: X = np.array([(1,2),(3,4),(5,6)],'f,f')
In [77]: X
Out[77]: array([(1., 2.), (3., 4.), (5., 6.)], dtype=[('f0', '<f4'), ('f1', '<f4')])
In [78]: pw = np.piecewise(
    ...:     X,
    ...:     [
    ...:         np.abs(X['f0'] - X['f1']) < 1,
    ...:         np.abs(X['f0'] - X['f1']) >= 1
    ...:     ],
    ...:     [
    ...:         lambda X: 1 + 2 * X['f0'] + 3 * X['f1'],
    ...:         lambda X: 1.5 + 2.5 * X['f0'] + 3.5 * X['f1']
    ...:     ]
    ...: )
In [79]: pw
Out[79]: 
array([(11., 11.), (23., 23.), (35., 35.)],
      dtype=[('f0', '<f4'), ('f1', '<f4')])

Числа повторяются в pw, потому что piecewise возвращает массив с такой же формой и типом d, какX, хотя lambdas возвращает только скалярные значения.

0 голосов
/ 05 февраля 2019

IMO np.piecewise больше подходит, если у вас есть два массива из np.meshgrid, так что np.piecewise может сопоставить размерность условия с размером вашего массива.

В вашем случае, для представления кусочной карты $ f: R ^ 2 \ to R $ с входными данными, имеющими форму (n,2) и вычисляемыми строка за строкой (каждый столбец представляет переменную), самый простой способгенерировать векторизованный код будет просто с помощью np.select:

def pw(X):
    return np.select([np.abs(X[:,0] - X[:,1]) < 1, np.abs(X[:,0] - X[:,1]) >= 1], 
            [1 + 2 * X[:, 0] + 3 * X[:, 1], 1.5 + 2.5 * X[:, 0] + 3.5 * X[:, 1]])

, а pw(X) даст желаемый ответ.

...