Результат функции не является правильным массивом чисел с плавающей запятой с использованием optimize.curve_fit

Я записал экспериментальные температуры в пяти точках от поверхности твердого тела. На каждом временном шаге я хочу подогнать эти показания к теоретической кривой, определяемой моей функцией: Temp_Function_JLT (X, h).

X - это многомерный массив, который включает координаты x, а также время, начальную температуру и свойства материала (все независимые переменные). «h» - это коэффициент теплопередачи, который в данном упражнении я пытаюсь оптимизировать (оставив на мгновение физику в стороне).

Это определение моей температурной функции:

 import pandas as pd
 import numpy as np
 import matplotlib.pyplot as plt
 import pickle
 import scipy.optimize as opt
 from scipy.special import erfc


def Temp_Function_JLT(X,ht):
    # Work around the fact that only one independent variable can be passed to optimize.curve_fit
    x,t,T0,q,alpha,rho,c,k = X 

    term_a = q/ht
    term_b = erfc(x/np.sqrt(4*alpha*t))
    term_c = np.exp(((ht*x)/(np.sqrt(alpha)*np.sqrt(k*rho*c)))+((ht**2)/(k*rho*c)))
    term_d = erfc((ht*np.sqrt(t))/(np.sqrt(k*rho*c)) + (x/np.sqrt(4*alpha*t)))
    Temperature = (term_a * (term_b - term_c * term_d)) + T0 - 273

return Temperature

Функция работает. Я могу запустить его с некоторыми начальными параметрами и получить разумные значения. Что еще более важно для этого вопроса, если я вызову его со следующими данными:

t = 1
x_test = np.linspace(0.004,0.02,5) # TC locations
time_test = range(1,180,30)
T0_test = 25 + 273
q_test = 20000
h_test = 10

Я получу массив numpy как решение формы (1,), которое дает ответ на np.ndim, равный 1 (об этом упоминалось в следующих предыдущих вопросах:

Наименьшие линейные квадраты: scipy.optimize.curve_fit () выдает «Результат вызова функции не является правильным массивом чисел с плавающей запятой».

Подгонка векторной функции с помощью curve_fit в Scipy

Подгонка 2D-функции Гаусса с использованием scipy.optimize.curve_fit - ValueError и minpack.error

Проблема возникает, когда я вызываю opt.curve_fit (). indepth_temperas - это список, содержащий каждый тест в виде массива. Я перебираю его (для перебора каждого теста), а затем выполняю подгонку для каждой строки (каждый временной шаг) в соответствии со следующим кодом:

for i,test in enumerate(indepth_temperatures):

    # Iterate over every row
    for j,row in enumerate(test):
        # Define tuple that contains all independent variables
        X = (TC_depth,
             times[i][j],
             T0_temperatures[i] + 273,
             20000,
             pmma_alpha,
             pmma_rho,
             pmma_c,
             pmma_k)
        print(Temp_Function_JLT(X,h0))
        print(row)
        print('---')
        # Call function to optimize curve fit on h
        popt, pcov = opt.curve_fit(Temp_Function_JLT,X,row,h0)
        print(popt)

Для первой итерации я получаю следующий результат:

[23.2034 23.2034 23.2034 23.2034 23.2034]   # comes from print(Temp_Function_JLT(X,h0))
[23.937 22.619 22.59 24.884 21.987000000000002]  # comes from print(row)

Затем следует эта ошибка:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-67-9c4545fd257b> in <module>()
     22         print('---')
     23         # Call function to optimize curve fit on h
---> 24         popt, pcov = opt.curve_fit(Temp_Function_JLT,X,row,h0)
     25         print(popt)

~\AppData\Local\Continuum\anaconda2\envs\py36\lib\site-packages\scipy\optimize\minpack.py in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
    749         # Remove full_output from kwargs, otherwise we're passing it in twice.
    750         return_full = kwargs.pop('full_output', False)
--> 751         res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
    752         popt, pcov, infodict, errmsg, ier = res
    753         cost = np.sum(infodict['fvec'] ** 2)

~\AppData\Local\Continuum\anaconda2\envs\py36\lib\site-packages\scipy\optimize\minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    392         with _MINPACK_LOCK:
    393             retval = _minpack._lmdif(func, x0, args, full_output, ftol, xtol,
--> 394                                      gtol, maxfev, epsfcn, factor, diag)
    395     else:
    396         if col_deriv:

error: Result from function call is not a proper array of floats.

Я безуспешно пытался вернуться из моей функции np.ravel (Temperature) или Temperature.flatten (). Ошибка остается, и я не могу понять, почему она там есть. Как я уже упоминал, я проверил размеры возврата моей функции, и это 1D-массив.

Любая помощь будет оценена!

ОБНОВЛЕНИЕ: я понял, что этот код сложно воспроизвести, поэтому это упрощенная версия:

Temp_Function_JLT (X, h0): остается прежним.

pmma_rho = 1200 # kg/m3
pmma_c = 1500 # J/kgK
pmma_k = 0.16 # W/mK
pmma_alpha = pmma_k/(pmma_rho*pmma_c)
x_test = np.linspace(0.004,0.02,5) # TC locations
t = 1
T0_test = 25 + 273
q_test = 20000
h_test = 10

X = (x_test,t,T0_test,q_test,pmma_alpha,pmma_rho,pmma_c,pmma_k)
y_data = [23.937 22.619 22.59 24.884 21.987000000000002]

opt.curve_fit(Temp_Function_JLT, X, y_data, h_test)

Я не могу запустить ваш код, потому что вы не указали, что такое indepth_temperatures. Кроме того, существует множество других неизвестных переменных: h0 и все остальные, начинающиеся с pmma___.

Sheldore 10.09.2018 12:32

Спасибо за ответ! pmma_rho = 1200 pmma_c = 1500 pmma_k = 0.16 pmma_alpha = pmma_k / (pmma_rho * pmma_c) h0 = 10 indepth_temperatures - это список, который содержит показания температуры для каждого теста (всего 20 тестов). Каждый тест содержит пять показаний температуры (мои x_data) за временной шаг (около 1200 временных шагов). Вот почему я напечатал в своих результатах первую строку, которая представляет собой «y_data» для кривой, подходящей для этого первого временного шага. Другими словами, моя аппроксимация кривой использует: Temp_Function_JLT как функцию, строку (напечатанную в моем результате) как y_data и X как x_data. Упрощу свой пост.

SimonS 10.09.2018 12:43

Мммм верно. Итак, по какой-то причине моя строка (y_data) представляет собой массив numpy с dtype = object. Я думаю, что это источник проблемы. Если я напечатаю строку, то получу: array ([23.937, 22.619, 22.59, 24.884, 21.987000000000002], dtype = object)

SimonS 10.09.2018 13:21

Извините, indepth_temperatures все еще не определен для меня, хотя вы объяснили, что он содержит. В интересах экономии времени людей, пытающихся вам помочь, было бы хорошо, если бы вы определили все переменные, скопировали и вставили приведенный выше код в новый файл python и выполнили его. Только, если вы не получаете ошибку неопределенных переменных, опубликуйте код. В противном случае мы будем снова и снова спрашивать вас, что эта переменная отсутствует, а эта переменная отсутствует.

Sheldore 10.09.2018 13:33
1
4
1 752
1

Ответы 1

Я понял, что не так с моим кодом. Несмотря на то, что моя y_data (строка) была определена как одномерный массив numpy, его тип данных был object. Я еще не понимаю, почему это было причиной, но, принудительно указав тип данных с помощью np.astype (np.float), opt.curve_fit сработал.

Другие вопросы по теме