1kynwmzf0mmndnsivebprla.jpeg

Un método de optimización numérica popular y de alto rendimiento es El método de Brent.. El método de Brent es un algoritmo de búsqueda de raíces que combina varias técnicas como el método de bisección, el método de la secante y la interpolación cuadrática inversa. Se pueden encontrar más detalles de su implementación en Statsmodels. aquí.

En Python, la implementación se ve así:

def solve_power(self, effect_size=None, nobs1=None, alpha=None, power=None,
ratio=1., alternative='two-sided'):
print('--- Arguments: ---')
print('effect_size:', effect_size, 'nobs1:', nobs1, 'alpha:', alpha, 'power:', power, 'ratio:', ratio, 'alternative:', alternative, '\n')

# Check that only nobs1 is None
kwds = dict(effect_size=effect_size, nobs1=nobs1, alpha=alpha,
power=power, ratio=ratio, alternative=alternative)
key = [k for k,v in kwds.items() if v is None]
assert(key == ['nobs1'])

# Check that the effect_size is not 0
if kwds['effect_size'] == 0:
raise ValueError('Cannot detect an effect-size of 0. Try changing your effect-size.')

# Initialize the counter
self._counter = 0

# Define the function that we want to find the root of
# We want to find nobs1 s.t. current power = target power, i.e. current power - target power = 0
# So func = current power - target power
def func(x):
kwds['nobs1'] = x
target_power = kwds.pop('power') # always the same target power specified in keywords, e.g. 0.8
current_power = self.power(**kwds) # current power given the current nobs1, note that self.power does not have power as an argument
kwds['power'] = target_power # add back power to kwds

fval = current_power - target_power
print(f'Iteration {self._counter}: nobs1 = {x}, current power - target power = {fval}')
self._counter += 1
return fval

# Get the starting values for nobs1, given the brentq_expanding algorithm
# In the original code, this is the self.start_bqexp dictionary set up in the __init__ method
bqexp_fit_kwds = {'low': 2., 'start_upp': 50.}

# Solve for nobs1 using brentq_expanding
print('--- Solving for optimal nobs1: ---')
val, _ = brentq_expanding(func, full_output=True, **bqexp_fit_kwds)

return val

1.2. Escribir una versión simplificada de tt_ind_solve_power que sea una implementación exacta de la derivación estadística y produzca el mismo resultado que la función original.

El archivo fuente en Statsmodels está disponible aquí. Si bien la función original está escrita para ser más poderosa, su generalización también hace que sea más difícil tener una intuición sobre cómo funciona el código.

Por lo tanto, revisé el código fuente línea por línea y lo simplifiqué de 1600 líneas de código a 160, y de más de 10 funciones a solo 2, mientras me aseguraba de que la implementación siguiera siendo idéntica.

El código simplificado contiene solo dos funciones bajo la clase TTestIndPower, siguiendo exactamente la derivación estadística explicada en la Parte 1:

  1. fuerzaque calcula la potencia dado un tamaño de muestra
  2. resolver_poderque encuentra el tamaño de muestra mínimo que alcanza una potencia objetivo utilizando el método de Brent

Este es el código completo para la versión simplificada con una prueba para comprobar que produce el mismo resultado que la función original: