Улучшение копирования элементов массива numpy - PullRequest
1 голос
/ 08 мая 2020

У меня вопрос относительно присвоения переменных и выделения памяти в простом случае.

Представьте, что я инициализирую вектор состояния x с начальным значением x0. Затем я выполняю итеративные обновления этого вектора состояния с помощью буферного массива X, и после каждой итерации я сохраняю новый вектор состояния в списке хранения L. Набросок моей первоначальной реализации можно найти в следующем фрагменте:

import numpy as np

np.random.seed(11)

x0 = 1
L = [x0]
x = x0

X = np.zeros((3,1))

for i in range(10):
    X[-1, :] = np.random.normal() # To simulate operations on X
    x = X[-1, :]
    L.append(x)

print(L)

который выведет, что L содержит

[1 array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
 array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
 array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
 array([-1.06560298])]

Потому что, когда x добавляется к L, только добавляется ссылка на X[-1, :], а не на фактическое значение.

Решение, которое я мог найти, - использовать np.copy для копирования значений последней строки X в x, а затем добавить его, как показано в следующем фрагменте.

import numpy as np

np.random.seed(11)

x0 = 1
L = [x0]
x = x0

X = np.zeros((3,1))

for i in range(10):
    X[-1, :] = np.random.normal() # To simulate operations on X
    x = np.copy(X[-1, :])
    L.append(x)

print(L)

Вывод показывает, что действительно изменения в состоянии x записаны правильно.

[1 array([1.74945474]) array([-0.286073]) array([-0.48456513])
 array([-2.65331856]) array([-0.00828463]) array([-0.31963136])
 array([-0.53662936]) array([0.31540267]) array([0.42105072])
 array([-1.06560298])]

Интересно, есть ли более элегантный или эффективный способ решить эту проблему?

Спасибо!

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Не смешивайте numpy массивы и python списки, если можете этого избежать. Если вы знаете количество итераций, предварительно выделите буфер для всего этого (например, с np.empty):

import numpy as np

np.random.seed(11)

N = 10

L = np.empty(N)
L[0] = 1

X = np.zeros(3)

for i in range(N):
    L[i] = X[-1] = np.random.normal()

print(L)

С другой стороны, если все вы нужно получить скаляр из 1-элементного массива, вы можете использовать метод item:

x = X[:, -1].item()
1 голос
/ 08 мая 2020

Я не совсем уверен, что понимаю, что вы хотите сделать, но, возможно, numpy.append() - это то, что вы ищете:

import numpy as np

np.random.seed(11)

x = np.array([1.])

for i in range(10):
    x = np.append(x, np.random.normal())

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