Объект слишком глубокий для желаемого массива - scipy.integrate.odeint

Я только вчера начал работать с Python и получаю сообщение об ошибке при использовании scipy.integrate.odeint.

Я определил функцию

def SIR(x, t, beta, gamma, mu, M):

который принимает numpy.array объекты x, t и M; а скалярные числа с плавающей точкой beta, gamma и mu.

M имеет (60,60) размер, но я не думаю, что это имеет значение.

x и t оба не одноэлементные, причем x.shape - это (180,), а t.shape - (5000,). Я пробовал дать им одноэлементное измерение, чтобы они имели формы (180,1) и (5000,1) соответственно, но все равно получаю ту же ошибку:

In [1]: run measles_age.py
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/IPython/utils/py3compat.py in execfile(fname, *where)
    173             else:
    174                 filename = fname
--> 175             __builtin__.execfile(filename, *where)

/Users/qcaudron/Documents/SIR/measles_age.py in <module>()
    111 
    112 
--> 113         x = integrate.odeint(SIR, x0, t, args=(beta, gamma, mu, M));
    114 
    115 #       plot(t, x);


/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/scipy/integrate/odepack.py in odeint(func, y0, t, args, Dfun, col_deriv, full_output, ml, mu, rtol, atol, tcrit, h0, hmax, hmin, ixpr, mxstep, mxhnil, mxordn, mxords, printmessg)
    141     output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
    142                              full_output, rtol, atol, tcrit, h0, hmax, hmin,
--> 143                              ixpr, mxstep, mxhnil, mxordn, mxords)
    144     if output[-1] < 0:
    145         print _msgs[output[-1]]

Я получаю эту ошибку, даже когда SIR просто возвращает x, и если я убираю из него все аргументы, кроме x и t:

def SIR(x, t):
    return x;

Как видите, строка, вызывающая ошибку, выглядит так:

x = integrate.odeint(SIR, x0, t, args=(beta, gamma, mu, M));

РЕДАКТИРОВАТЬ :

Меня попросили добавить полный код для метода SIR. Поскольку он относительно длинный, я поместил полный скрипт .py в pastebin: http://pastebin.com/RphJbCHN

Еще раз спасибо.


person Quentin    schedule 29.03.2013    source источник
comment
Добро пожаловать в Python! Большинство этих точек с запятой не нужны в вашем коде.   -  person askewchan    schedule 29.03.2013
comment
Спасибо. Я понимаю, что они не нужны - я просто думаю, что с ними все выглядит чище :) Спасибо за правку выше.   -  person Quentin    schedule 29.03.2013
comment
Из документации SIR должен вернуть dx/dt в 3_. Это то, что делает SIR?   -  person askewchan    schedule 29.03.2013
comment
Да, в полном коде это так. Если он немедленно возвращает x, это не совсем актуально - уравнение, которое мы решаем, вполне может быть dx/dt = x, и в этом случае да, оно возвращает правильный расчет. Я не уверен, почему объект слишком глубокий для того, чтобы возвращалась ошибка желаемого массива.   -  person Quentin    schedule 29.03.2013
comment
Источник находится в fortran. Вы пробовали использовать integrate.ode?   -  person askewchan    schedule 29.03.2013
comment
В вашем урезанном случае подпись SIR должна быть SIR(x, t). Аргумент t является обязательным.   -  person Warren Weckesser    schedule 30.03.2013


Ответы (2)


Я могу воспроизвести вашу ошибку несколькими способами.

Ошибка возникает немедленно, если аргумент y0 или аргумент t для odeint не является одномерным массивом. В примере кода, опубликованном на pastebin (упоминаемом в комментарии), t изменен следующим образом:

t = np.arange(0, 520, 1);
t = t.reshape(len(t),1);

Удалите линию, изменяющую форму t. t должен быть одномерным массивом, а не двухмерным массивом с формой (len (t), 1).

Например...

In [177]: def SIR(x, t):
   .....:     return x
   .....: 

Это работает...

In [178]: x0 = [0.1, 0.2]

In [179]: odeint(SIR, x0, t=[0, 0.5, 1])
Out[179]: 
array([[ 0.1       ,  0.2       ],
       [ 0.16487213,  0.32974426],
       [ 0.27182822,  0.54365643]])

Это приводит к ошибке:

In [180]: x0 = [[0.1, 0.2]]  # wrong shape

In [181]: odeint(SIR, x0, t=[0, 0.5, 1])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-181-a37878f92395> in <module>()
----> 1 odeint(SIR, x0, t=[0, 0.5, 1])

/home/warren/anaconda/lib/python2.7/site-packages/scipy/integrate/odepack.pyc in odeint(func, y0, t, args, Dfun, col_deriv, full_output, ml, mu, rtol, atol, tcrit, h0, hmax, hmin, ixpr, mxstep, mxhnil, mxordn, mxords, printmessg)
    142     output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
    143                              full_output, rtol, atol, tcrit, h0, hmax, hmin,
--> 144                              ixpr, mxstep, mxhnil, mxordn, mxords)
    145     if output[-1] < 0:
    146         print _msgs[output[-1]]

ValueError: object too deep for desired array

Убедитесь, что начальное условие, которое вы даете odeint (второй аргумент), является массивом 1-D numpy (а не 2-мерным массивом с формой (1, 180) или (180, 1)) .

Я также получаю ошибку «объект слишком глубоко ...», если SIR возвращает массив неправильной формы. Он должен возвращать массив 1-D с той же формой, что и его первый аргумент. Убедитесь, что он действительно 1-D, а не 2-D с формой (1, 180) или (180, 1).

person Warren Weckesser    schedule 29.03.2013
comment
Спасибо, но я это проверил. SIR возвращает numpy-массив размером (180,), а аргумент y0 для odeint также имеет форму (180,). - person Quentin; 30.03.2013
comment
@Quentin: Если можете, добавьте в вопрос свой код для SIR вместе с автономным способом его запуска, чтобы мы могли воспроизвести полученную вами ошибку. - person Warren Weckesser; 30.03.2013
comment
Я обновил свой ответ, добавив комментарий о том, что t является 1-D. Не переделывайте его в двумерный массив. - person Warren Weckesser; 31.03.2013
comment
Большое вам спасибо, Уоррен. Не знаю, как я это пропустил. Я исправил это, и, похоже, он работает. - person Quentin; 31.03.2013

Из учебника кажется как и первый аргумент integrate.odeint(), должен быть функцией для работы (в вашем случае) x0 и t. Поскольку ваша функция SIR() принимает только один аргумент, операция завершается ошибкой. Возможно, что размер и / или форма результатов, возвращаемых SIR(), важны по отношению к остальным аргументам.

person MattDMo    schedule 29.03.2013
comment
Извините, возможно, я не понял. Я сократил его до этого, чтобы увидеть, была ли проблема в функции SIR. Это было не так. Я получил ту же ошибку, что и когда SIR взял пять аргументов: def SIR(x, t, beta, gamma, mu): return x; и был вызван с использованием x = integrate.odeint(SIR, x0, t, args=(beta, gamma, mu)); - person Quentin; 29.03.2013