2013-11-23 5 views
1

Я очень, очень новичок в python, поэтому, пожалуйста, несите меня и прощайте мою наивность. Я использую Spyder Python 2.7 на своем ноутбуке Windows. Как следует из названия, у меня есть некоторые данные, теоретическое уравнение, и я пытаюсь подгонять мои данные, и я считаю, что это хи-квадрат. Теоретическое уравнение я использую enter image description hereПодгонка теоретического уравнения к моим данным

import math 

import numpy as np 

import scipy.optimize as optimize 

import matplotlib.pylab as plt 

import csv 

#with open('1.csv', 'r') as datafile: 
# datareader = csv.reader(datafile) 
# for row in datareader: 
    #  print ', '.join(row) 

t_y_data = np.loadtxt('exerciseball.csv', dtype=float, delimiter=',', usecols=(1,4), skiprows = 1) 


print(t_y_data) 

t = t_y_data[:,0] 

y = t_y_data[:,1] 

gamma0 = [.1] 

sigma = [(0.345366)/2]*(len(t)) 

#len(sigma) 

#print(sigma) 

#print(len(sigma)) 

#sigma is the error in our measurements, which is the radius of the object 


# Dragfunction is the theoretical equation of the position as a function of time when the thing falling experiences a drag force 
# This is the function we are trying to fit to our data 
# t is the independent variable time, m is the mass, and D is the Diameter 

#Gamma is the value of which python will vary, until chi-squared is a minimum 



def Dragfunction(x, gamma): 
    print x 
    g = 9.8 
    D = 0.345366 
    m = 0.715 
# num = math.sqrt(gamma)*D*g*x 
# den = math.sqrt(m*g) 
# frac = num/den 
# print "frac", frac 

    return ((m)/(gamma*D**2))*math.log(math.cosh(math.sqrt(gamma/m*g)*D*g*t)) 


optimize.curve_fit(Dragfunction, t, y, gamma0, sigma) 

Это сообщение об ошибке я получаю:

return ((m)/(gamma*D**2))*math.log(math.cosh(math.sqrt(gamma/m*g)*D*g*t)) 
TypeError: only length-1 arrays can be converted to Python scalars 

Мой профессор и я провел около трех или четырех часов, пытаясь исправить это. Он помог мне решить много проблем, но это мы, похоже, не можем решить.

Не могли бы вы помочь? Если вам нужна какая-либо другая информация, пожалуйста, дайте мне знать.

+1

Я думаю, вы можете решить это просто с помощью 'np.log' и' np.sqrt' и 'np.cosh', которые действуют только на массивы, а не только на скаляры. – askewchan

+1

Кроме того, не связанный с вашим вопросом, но 'gamma/m * g' совпадает с' gamma * g/m', поскольку умножение и деление выполняется только слева направо в python. Вы хотите «gamma/(m * g)» в соответствии с вашим уравнением сверху. – askewchan

+0

askewchan, поэтому, когда вы говорите, что эти функции действуют на массивы, вы имеете в виду, что он выполняет функцию через каждое значение в массиве? – Mack

ответ

2

Ваше сообщение об ошибке исходит из того, что эти math функции принимают только скаляр, поэтому для вызова функций на массиве, используйте numpy версии:

In [82]: a = np.array([1,2,3]) 

In [83]: np.sqrt(a) 
Out[83]: array([ 1.  , 1.41421356, 1.73205081]) 

In [84]: math.sqrt(a) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
----> 1 math.sqrt(a) 

TypeError: only length-1 arrays can be converted to Python scalars 

В процессе я случайно укажите математическую ошибку в коде. Ваше уравнение на вершине говорит, что g находится в нижней части квадратного корня внутри log(cosh()), но ты его на вершину, потому что a/b*c == a*c/b в питоне, не a/(b*c)

log(cosh(sqrt(gamma/m*g)*D*g*t)) 

вместо этого должен быть какой-либо один из них:

log(cosh(sqrt(gamma/m/g)*D*g*t)) 
log(cosh(sqrt(gamma/(m*g))*D*g*t)) 
log(cosh(sqrt(gamma*g/m)*D*t))  # the simplest, by canceling with the g from outside sqrt 

Вторая ошибка в том, что в определении функции, то есть параметр с именем x, который вы никогда не использовать, но вместо этого вы используете t, который в данный момент является глобальной переменной (от ваших данных), так вы не увидите ошибку. Вы не увидите эффект, используя curve_fit, так как он будет передавать ваши данные t в любом случае, но если вы попытались позвонить Dragfunction на другой набор данных, он все равно даст вам результаты из значений t. Возможно, вы имели в виду это:

def Dragfunction(t, gamma): 
    print t 
    ... 
    return ... D*g*t ... 

пару других нот, как непрошеные советы, так как вы сказали, что вы новичок в Python:

Вы можете загрузить и «распаковать» в t и y переменные сразу с:

t, y = np.loadtxt('exerciseball.csv', dtype=float, delimiter=',', usecols=(1,4), skiprows = 1, unpack=True) 

Если ошибка постоянна, то sigma не оказывает никакого влияния на curve_fit, как это влияет только на Относительный вес весит для подгонки, так что вам это действительно не нужно.

Ниже приведена моя версия вашего кода со всеми перечисленными выше изменениями.

import numpy as np 
from scipy import optimize   # simplified syntax 
import matplotlib.pyplot as plt # pylab != pyplot 

# `unpack` lets you split the columns immediately: 
t, y = np.loadtxt('exerciseball.csv', dtype=float, delimiter=',', 
        usecols=(1, 4), skiprows=1, unpack=True) 

gamma0 = .1 # does not need to be a list 

def Dragfunction(x, gamma): 
    g = 9.8 
    D = 0.345366 
    m = 0.715 
    gammaD_m = gamma*D*D/m # combination is used twice, only calculate once for (small) speedup 
    return np.log(np.cosh(np.sqrt(gammaD_m*g)*t))/gammaD_m 

gamma_best, gamma_var = optimize.curve_fit(Dragfunction, t, y, gamma0) 
+0

Итак, когда я запускаю этот код, я получаю [2.17284808] и [[3.63752744]]. Я предполагаю, что первым массивом является значение гаммы, а второе - панель ошибок на нем? – Mack

+0

Более или менее, да. Первое является наилучшим подходящим значением для 'gamma', но второе - это дисперсия (на самом деле это не ошибка). Я считаю, что одной оценкой ошибки будет 'sqrt (variance/t.size)'. – askewchan

+0

У меня есть одна проблема с этим кодом. Чем меньше я делаю гамма, тем меньше установленное значение гаммы. В конце концов, когда gamma0 = .0000000000000001, я получаю в качестве вывода [1.00000000e-16] inf. Что-то кажется неправильным. Я знаю, что гамма, которую мы пытаемся найти, должна быть около 0.025 – Mack