Использование функции, определенной в функции

#python #numpy #scipy

#Python #numpy #scipy

Вопрос:

Я пытаюсь использовать функцию внутри функции, которую я уже написал, и она работает с list comprehension и частичными функциями, но не с lambda функциями.

Итак, моя функция:

 import numpy as np
from scipy.optimize import minimize
from _functools import partial
from sklearn.metrics import mean_squared_error

arpdau = np.random.randint(0,100,15)

def fitARPDAU(arpdau, max_cohortday, method, par=None):

  valid = {'log', 'power', 'all'}
  if method not in valid:
      raise ValueError("results: method must be one of %r." % valid)

  values = par

  if method == 'log':

    if values == None:
      a = 1
      b = 0
      c = 1
      values = [a, b, c]
      bounds = [(1e-10, None), (1e-10, None), (None, None)]

    def getArpdauFunction(x, values):
      return values[0] * np.log(x   values[1])   values[2]
  elif method == 'power':

    if values == None:
      a = 1
      b = 0
      c = .5
      d = 0
      values = [a, b, c, d]
      bounds = [(1e-10, None), (None, None), (1e-10, 1), (None, None)]


    def getArpdauFunction(x, values):
      return values[0] * (x   values[1]) ** values[2]  values[3]

  elif method == 'all':

    log_loss = fitARPDAU(arpdau, max_cohortday, method='log', par=par)
    power_loss = fitARPDAU(arpdau, max_cohortday, method='power', par=par)

    combined_models = [log_loss, power_loss]
    losses = map(lambda x: x[0].fun, combined_models)
    return combined_models[np.argmin(losses)]

  def getLossOptim(values):

    # import ipdb; ipdb.set_trace()
    # arpdau_pred = [getArpdauFunction(x, values) for x in range(max_cohortday)]
    arpdau_pred_1 = map(lambda x: getArpdauFunction(x, values), range(max_cohortday))
    # arpdau_pred_2 = partial(getArpdauFunction, values=values)(range(271))
    return mean_squared_error(arpdau, arpdau_pred_1[:len(arpdau)])

  result = minimize(getLossOptim, values, method='L-BFGS-B', bounds=bounds)

  return result, [getArpdauFunction(x, result.x) for x in range(max_cohortday)], result.x, method, getArpdauFunction

print fitARPDAU(arpdau, 100, method='all', par=None)
 

Есть ли какая-либо причина в getLossOptim, по которой работает частичное понимание и понимание списка, а функция lambda — нет?

lambda Функция возвращает

 NameError: global name 'getArpdauFunction' is not defined
 

Спасибо!


Комментарии:

1. Что вы подразумеваете под «не работает»?

2. Нет ничего особенного в том, что функция определяется внутри другой функции, причина, по которой у вас возникает эта ошибка, заключается в том, что функция может быть не определена. Например, если method не является ни 'log' тем, ни 'power' другим , то getArpdauFunction не определено.

3. Действительно, к чему привязана функция getArpdauFunction(), если метод = ‘all’ ?

4. В вашем опубликованном коде нет основной программы. Вы не проследили код, чтобы показать, что getArpdauFunction он действительно определен во время выполнения.

5. Кстати, в Python мощность — это ** . Это ^ XOR .

Ответ №1:

Это не имеет ничего общего с функцией, определенной внутри другой функции. Если method нет 'log' или 'power' , то getArpdauFunction() никогда не определяется.

Вероятно, вам следует определить ее для всего, а затем перегрузить ее, если метод равен 'log' или 'power' .

Это не имеет отношения к вашей проблеме, но вы также никогда не должны использовать if x == None . Поскольку None это одноэлементный, он более эффективен и удобен в использовании if x is None

Ответ №2:

Как я уже сказал в своем комментарии, ваша проблема не имеет ничего общего с функцией, определенной внутри другой функции. Причина, по которой вы получаете сообщение об ошибке, заключается в том, что функция иногда не определена; если method не является ни 'log' nor 'power' , то getArpdauFunction() никогда не определяется.

Это легко исправить. Самый чистый метод, который я вижу на данный момент, — это объявить несколько функций, а затем динамически выбрать одну:

 def identity(x): return x
def pp(x): return x 1
def mm(x): return x-1

functions = {
  "  ": pp,
  "--": mm
}

default_function = identity

print(functions.get("  ", default_function)(2)) # 3
print(functions.get("--", default_function)(2)) # 1
print(functions.get("non existing function name", default_function)(2)) # 2
 

Если ваши функции очень короткие (как в этом примере, то вы можете напрямую написать:

 functions = {
  "  ": lambda x: x 1,
  "--": lambda x: x-1
}