Нелинейная подгонка удельного сопротивления в Python

Я пытаюсь подогнать приближение Эйнштейна удельного сопротивления в твердом теле к набору экспериментальных данных. У меня есть удельное сопротивление против температуры (от 200 до 4 К)

import xlrd as xd
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import scipy as sp
from scipy.optimize import curve_fit

#retrieve data from file
data = pl.loadtxt('salita.txt')
Temp = data[:, 1]
Res = data[:, 2]

#define fitting function
def einstein_func( T, ro0, AE, TE):
    nl = np.sinh(TE/(2*T))
    return ro0 + AE*nl*T

p0 = sp.array([1 , 1, 1])

coeffs, cov = curve_fit(einstein_func, Temp, Res, p0)

Но я получаю эти предупреждения

crio.py:14: RuntimeWarning: divide by zero encountered in divide
  nl = np.sinh(TE/(2*T))
crio.py:14: RuntimeWarning: overflow encountered in sinh
  nl = np.sinh(TE/(2*T))
crio.py:15: RuntimeWarning: divide by zero encountered in divide
  return ro0 + AE*np.sinh(TE/(2*T))*T
crio.py:15: RuntimeWarning: overflow encountered in sinh
  return ro0 + AE*np.sinh(TE/(2*T))*T
crio.py:15: RuntimeWarning: invalid value encountered in multiply
  return ro0 + AE*np.sinh(TE/(2*T))*T
Traceback (most recent call last):
  File "crio.py", line 19, in <module>
    coeffs, cov = curve_fit(einstein_func, Temp, Res, p0)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 511, in curve_fit
    raise RuntimeError(msg)
RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 800.

Я не понимаю, почему он продолжает говорить, что в sinh есть деление на ноль, ведь у меня строго положительные значения. Изменение моего начального предположения не повлияет на это.

РЕДАКТИРОВАТЬ: мой набор данных организован следующим образом:

4.39531E+0  1.16083E-7
4.39555E+0  -5.92258E-8
4.39554E+0  -3.79045E-8
4.39525E+0  -2.13213E-8
4.39619E+0  -4.02736E-8
4.43130E+0  -1.42142E-8
4.45900E+0  -2.60594E-8
4.46129E+0  -9.00232E-8
4.46181E+0  1.42142E-7
4.46195E+0  -2.13213E-8
4.46225E+0  4.26426E-8
4.46864E+0  -2.60594E-8
4.47628E+0  1.37404E-7
4.47747E+0  9.47612E-9
4.48008E+0  2.84284E-8
4.48795E+0  1.35035E-7
4.49804E+0  1.39773E-7
4.51151E+0  -1.75308E-7
4.54916E+0  -1.63463E-7
4.59176E+0  -2.36902E-9

где первый столбец — температура, а второй — удельное сопротивление (отрицательные значения обусловлены шумом пробного тока, так как образец представляет собой сплав PbIn, который становится сверхпроводящим при температуре ниже 6,7-6,9 К, здесь мы при 4,5 К).

Аргумент, который я предоставляю sinh, - это массивы Numpy, с линейной функцией ro0 + AE*T мой код работает. Я пробовал с scipy.optimize.minimize, но результат тот же. Теперь я вижу, что у меня в файле почти девятьсот значений, может в этом проблема?

Я отредактировал свой набор данных, удалив несколько строк, и теперь отображается единственное предупреждение:

RuntimeWarning: overflow encountered in sinh

Как я могу обойти это?


person iacolippo    schedule 12.05.2015    source источник
comment
Это может помочь опубликовать образец строк из salita.txt   -  person xnx    schedule 12.05.2015
comment
Это не деление на ноль, а скорее переполнение/недостаточное значение в функции sinh. Убедитесь, что аргументы, которые вы ему приводите, разумны. Если у вас все еще есть проблемы, попробуйте другой решатель из scipy.optimize.minimize, который является более гибким, чем scipy.optimize.curve_fit.   -  person rth    schedule 13.05.2015
comment
Теперь я заметил, что минимизация дает мне другую ошибку: np.array has no attribute 'lower'. Я думаю, это означает, что я привожу неверный аргумент, но я не могу понять, как я мог это написать. Я смог выполнить подгонку в MATLAB, но теперь мне просто интересно, как это сделать в Python.   -  person iacolippo    schedule 14.05.2015


Ответы (1)


Вот несколько наблюдений, которые могут помочь:

  • Вы можете попробовать использовать метод наименьших квадратов напрямую с leastsq, предоставив якобиан, который может помочь укротить его.

  • Я предполагаю, что вам вообще не нужны температуры сверхпроводимости в вашем наборе данных, если вы подходите к модели Эйнштейна (кстати, у вас есть источник для этого уравнения?)

  • Убедитесь, что ваши первоначальные догадки настолько хороши, насколько это возможно (ro0=AE=TE=1, вероятно, не сработает).

  • Постройте свои данные и убедитесь, что нет никаких странных артефактов

  • Кажется, вы неправильно индексируете свой массив данных в своем примере кода: если данные структурированы, как вы говорите, вы хотите:

    Темп = данные[:, 0] Рез = данные[:, 1]

(Индексы Python начинаются с 0).

person xnx    schedule 14.05.2015
comment
У меня есть другие столбцы в моем файле, но они мне не нужны для этой конкретной подгонки. Мой источник для уравнения — Solid State Physics, Mermin & Ashcroft. Точки под переходами обязательно нужно убрать, в Матлабе сделал, а здесь забыл. В данных нет артефактов, как только приду домой, попробую исправить свой набор данных. Я думаю, что я мог бы использовать значения Pb в качестве исходного предположения, поскольку мой образец представляет собой сплав PbIn. - person iacolippo; 14.05.2015
comment
Я пробовал с leastsq и якобианом, но там написано too many values to unpack. Даже с начальным предположением, очень похожим на те, которые я нашел в Matlab. Я не думаю, что мне требуется такая сложная подгонка, возможно, я совершаю какую-то ошибку, поскольку я новичок в Python, но я думаю, что с опытом я улучшусь. - person iacolippo; 14.05.2015
comment
Возвращаемые значения из leastsq немного отличаются и сложнее, чем curve_fit: [документы](docs.scipy.org/doc/scipy-0.14.0/reference/generated/} содержит более подробную информацию. - person xnx; 14.05.2015
comment
Можете ли вы опубликовать весь salita.txt и исходные параметры предположения где-нибудь, например pastebin.com? - person xnx; 14.05.2015
comment
Я получаю предупреждение: /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py:393: RuntimeWarning: Number of calls to function has reached maxfev = 800. warnings.warn(errors[info][0], RuntimeWarning) (array([ 9.18063198e-04, -1.82655707e-04, 9.56012732e+00]), 5) (возвращает последнюю итерацию). Начальные параметры предположения: 10*10^(-6) для остаточного удельного сопротивления, 10*10^(-8) для электрон-фононной связи AE, 50 для температуры Эйнштейна. - person iacolippo; 14.05.2015
comment
Мой текстовый файл находится здесь ссылка. В этой версии он состоит из 7 колонок, первая - температура, третья - удельное сопротивление в этой версии (у меня есть несколько версий, и они имеют разный порядок столбцов, не моя вина...). Спасибо - person iacolippo; 14.05.2015
comment
Хммм... ваша целевая функция монотонно убывает, но данные растут (почти линейно): вы уверены в своем einstein_func? - person xnx; 14.05.2015
comment
Ах да, это всплытие пробы из Дьюара с жидким He, может надо инвертировать векторы данных. Линейный рост правильный, так как при высокой температуре удельное сопротивление линейно по температуре, так называемое колено есть только при промежуточных температурах, но здесь оно не столь очевидно, так как имеет место сверхпроводящий переход. Я, конечно, совершал глупые ошибки, но никто никогда не объяснял мне, как сделать подгонку данных. - person iacolippo; 14.05.2015
comment
Я сделал глупую ошибку: einstein_func неверен, как вы сказали. Правильная функция: ro0+AE*T*((TE/2T)/sinh(TE/2T))^2... Прямо сейчас я чувствую себя таким глупым. я пытаюсь это - person iacolippo; 15.05.2015
comment
Я СДЕЛАЛ ЭТО! Большое спасибо - person iacolippo; 15.05.2015
comment
@IacopoPoli Рад помочь коллеге-ученому! - person xnx; 15.05.2015