Índice
Este artículo va a ser uno corto, pero creo que va a resolver el problema a muchas personas, igual que me lo resolvió a mi.
Haciendo una práctica de Aprendizaje Automático, en concreto implementando Gradiente Descendente Estocástico (Stochastic Gradient Descent) o SGD para Regresión Logística e intentando hacer el código lo más eficiente posible (Y eso en R significa evitar el uso de for a toda costa) me encontré con la siguiente situación:
SGD <- function(...) {
# Stochastic gradient descent
#
w <- matrix(rep(0,3))
# ...
update <- function(x) {
# Aqui dentro se necesita modificar w, y modificarla
}
while (above.tolerance) {
w.old <- w
apply(data, 1, update)
# ...
}
w
}
Bien, tal y como está el código de arriba no funciona, ya que aunque la función update
puede ver el valor de w
, que está en el ámbito de la función SGD
, pero no puede modificar su valor, lo que modifica es una copia local, en el ámbito de update
. Para que Gradiente Descendente Estocástico funcione se necesita que para cada punto se actualice el vector de pesos w
y quede reflejado en el ámbito de la función SGD
.
Para lograr este comportamiento, al principio pensé en declarar w
como variable global con el operador <<-
, lo cual es una terrible idea, porque w
sería global a todo el programa. En este caso solo necesitamos que w
pueda modificarse desde update
. Así que buscando un poco encontré la forma de crear un entorno local a la función SGD
, y luego usarlo dentro de update
, aquí está el código:
SGD <- function(...) {
# Stochastic gradient descent
#
w.env <- new.env()
w.env$w <- matrix(rep(0,3))
# ...
update <- function(x) {
# Aqui dentro se necesita modificar w, y modificarla
# Se usa la variable w.env$w
}
while (above.tolerance) {
w.old <- w.env$w
apply(data, 1, update)
# ...
}
w.env$w
}
Con este sencillo cambio, dentro de update
se está accediendo y modificando la variable w
, actualizándola correctamente en cada iteración de apply
.
Espero que os sea útil.
Referencias
- Entornos Avanzados en R | adv-r.had.co.nz
¿Has visto algún error?: Por favor, ayúdame a corregirlo contactando conmigo o comentando abajo.