The first block of code shown below works; my issue is in trying to adapt that block of code to my problem (defined just below it).
I am trying to use SCIPY to minimize the function chisq
below. The entire code is basically a chain of functions (such as expectperbin
, which calls a distribution function to integrate over); the code below has obsperbin
, parameterguess
, countperbin
, and initial parameters, all of which are pre-defined. Only the top of the function chain is shown:
from scipy.optimize import minimize
from scipy.stats import chisquare
def chisq( args ):
## first subscript [0] gives chi-squared value, [1] gives 0 ≤ p-value ≤ 1
return chisquare( obsperbin , expectperbin( args ))[0]
def miniz( chisq , parameterguess ):
## optimization routine to minimize Chi Square (or negative p-value)
globmin = minimize( chisq , parameterguess)
while globmin.success == False:
## self-correcting mechanism if 'success test' fails
try:
globmin = minimize( chisq , parameterguess)
print("ERROR: MINIMIZE LOOPING AGAIN")
break
except globmin.success == True:
print("TA DAA")
break
return globmin
res = miniz( chisq, [initial_mu , initial_sigma] ) ## FULL OPTIMIZED RESULT
print(res)
The code above finds optimized values of mu
and sigma
(given an initial guess for each) that minimizes chisq
, and it works as expected. So I am now trying to generalize the code for the case when multiple distributions are defined. I use an unchangeable function input pickdist
to choose which pre-defined distribution to calculate expectperbin
. My attempt is below:
def chisq( pickdist , args ):
obsperbin = countperbin( pickdist = pickdist )
expperbin = expectperbin( pickdist , args )
return chisquare( obsperbin , expectperbin( pickdist , args ))[0]
def miniz( pickdist ):
if pickdist == 1:
parameterguess = paramguess1
elif pickdist == 2:
parameterguess = paramguess2
elif pickdist == 3:
parameterguess = paramguess3
else:
raise ValueError(errmsg)
globmin = minimize( chisq , parameterguess, args = (pickdist))
return globmin
Running that code creates the error message
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
and finds the bug in the line of code that reads obsperbin = countperbin ...
(from above, under chisq
) and in a line of code from below that reads if pickdist == 1:
def countperbin( pickdist ):
## counts multiplicity of observed values per bin via dataset
if pickdist == 1:
dataset = data
elif pickdist == 2:
dataset = logdata
elif pickdist == 3:
dataset = logdata
else:
raise ValueError(errmsg)
## I can delete the code below if it's too long
bincount = []
subintervals = binbounder( pickdist )
for jndex in range(len( subintervals )):
if jndex != len( subintervals ) - 1:
summ = 0
for value in dataset:
if value > subintervals [ jndex ] and value <= subintervals [ jndex + 1 ]:
summ += 1
bincount.append(summ)
if jndex == len( subintervals ) - 1:
pass
return bincount
obsperbin1 = countperbin( 1 )
... ## rest not shown to keep post short but can add if requested
I tried debugging this code after reading this post on SO but without success. How do I apply what the error message is telling me to my functions?