У меня возникла проблема, при которой значения в массиве Numpy изменяются после копирования с помощью copy.deepcopy или numpy.copy. Фактически, я получаю разные значения, если я просто напечатаю массив перед его копированием.Почему значение глубины изменения значения numpy массива?
Я использую Python 3.5, Numpy 1.11.1, 0.18.0 SciPy
Мой исходный массив содержится в списке кортежей; каждый кортеж пара: поплавок (время точка) и массив NumPy (решение ОДЫ в этот момент времени), например:
[(0.0, array([ 0., ... 0.])), ...
(3.0, array([ 0., ... 0.]))]
В этом случае, я хочу, чтобы массив для последней точки времени ,
Когда я вызываю следующее:
tandy = c1.IntegrateColony(3)
ylast = copy.deepcopy(tandy[-1][1])
print(ylast)
я получаю что-то, что имеет смысл для системы Я пытаюсь моделировать:
[7.14923891e-07 7.14923891e-07 ... 8.26478813e-01 8.85589634e-01]
Однако, следующее:
tandy = c1.IntegrateColony(3)
print(tandy[-1][1])
ylast = copy.deepcopy(tandy[-1][1])
print(ylast)
Я получаю все нули:
[0.00000000e+00 0.00000000e+00 ... 0.00000000e+00 0.00000000e+00]
[ 0. 0. ... 0. 0.]
Я должен добавить с большими системами и различными параметрами отображение tandy [k] [1] (либо с помощью print(), либо просто путем вызова его в командной строке) показывает все ненулевые значения, которые все очень близко к нулю, то есть < 1e-70, но это все еще неразумно для системы.
С:
tandy = c1.IntegrateColony(3)
ylast = np.copy(tandy[-1][1])
print(ylast)
я получаю разумный выход снова:
[7.14923891e-07 7.14923891e-07 ... 8.26478813e-01 8.85589634e-01]
Функция, которая генерирует 'Тэнди' заключается в следующем (под редакцией для ясности), который использует scipy.integrate.ode, и метод set_solout для получения решения в промежуточных временных точках:
def IntegrateColony(self, tmax=1):
# I edited out initialization of dCdt & first_step for clarity.
y = ode(dCdt)
y.set_integrator('dopri5', first_step=dt0, nsteps=2000)
sol = []
def solout(tcurrent, ytcurrent):
sol.append((tcurrent, ytcurrent))
y.set_solout(solout)
y.set_initial_value(y=C0, t=0)
yfinal = y.integrate(tmax)
return sol
Хотя я сотрудничаю uld получить последнюю точку времени, вернув yfinal, я бы хотел получить все время курса, как только я выясню, почему он ведет себя так, как есть.
Спасибо за ваши предложения!
Микки
Edit: Если я печатаю все золе (print(tandy)
или print(IntegrateColony...
), то выходит, как показано выше (со значениями в массивах, как 0), то есть:
[(0.0, array([ 0., ... 0.])), ...
(3.0, array([ 0., ... 0.]))]
Однако, если я скопирую его (y = copy.deepcopy(tandy); print(y)
), массивы берут значения между 1е-7 и 1е + 1.
Если я делаю print(tandy[-1][1])
два раза подряд, они заполняются нулями, но формат изменяется (от 0.0000
до 0.
).
Еще одна особенность, которую я заметил при выполнении предложений в комментариях LutzL и hpaulj: если я запустил tandy = c1.IntegrateColony(3)
в консоли (работает Spyder), массивы заполняются нулями в проводнике переменных. Тем не менее, если я запускаю следующее в консоли:
tandy = c1.IntegrateColony(3); ylast=copy.deepcopy(tandy)
Оба массивы в Тэнди и в ylast заполнены значениями в диапазоне я бы ожидать, и print(tandy[-1][1])
теперь дает:
[7.14923891e-07 7.14923891e-07 ... 8.26478813e-01 8.85589634e-01]
Даже если я найду решение, которое остановит это поведение, я буду признателен за чье-либо понимание того, что происходит, поэтому я не повторю те же ошибки.
Спасибо!
Edit: Вот простой пример, который дает такое поведение:
import numpy as np
from scipy.integrate import ode
def testODEint(tmax=1):
C0 = np.ones((3,))
# C0 = 1 # This seems to behave the same
def dCdt_simpleinputs(t, C):
return C
y = ode(dCdt_simpleinputs)
y.set_integrator('dopri5')
sol = []
def solout(tcurrent, ytcurrent):
sol.append((tcurrent, ytcurrent)) # Behaves oddly
# sol.append((tcurrent, ytcurrent.copy())) # LutzL's idea: Works
y.set_solout(solout)
y.set_initial_value(y=C0, t=0)
yfinal = y.integrate(tmax)
return sol
tandy = testODEint(1)
ylast = np.copy(tandy[-1][1])
print(ylast) # Expect same values as tandy[-1][1] below
tandy = testODEint(1)
tandy[-1][1]
print(tandy[-1][1]) # Expect same values as ylast above
Когда я запускаю это, я получаю следующий результат для ylast
и tandy[-1][1]
:
[ 2.71828196 2.71828196 2.71828196]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
Код Я работал над тем, когда я столкнулся с этой проблемой, это смущающий беспорядок, но если вы хотите взглянуть, здесь находится старая версия: https://github.com/mvondassow/BryozoanModel2
Если вы печатаете весь зонд, измените ли строки или все равно? Возможно, вам придется использовать 'sol.append ((tcurrent, ytcurrent.copy()))', чтобы избежать сохранения всегда одного и того же указателя на вектор состояния интегратора. – LutzL
Не утруждайте себя 'deepcopy', когда вы знаете, что объект является массивом. 'x.copy()' достаточно. Но я думаю, что есть что-то смешное в отношении «tandy». Это не просто список независимых значений. Что происходит, когда вы выполняете 'print (tandy [-1] [1])' дважды подряд? – hpaulj
Я попробую, LutzL. –