ajwills72 / catlearn

Formal Psychological Models of Categorization and Learning
GNU General Public License v3.0
23 stars 3 forks source link

model running but not updating #10

Closed troyhouser closed 1 month ago

troyhouser commented 1 month ago

Hi,

I am trying to run slpSUSTAIN and it seems to be running smoothly, but the model's outputs show that no updating is happening (e.g., every trial, response probabilities for both categories is 50%, weights are always 0, lambdas are unchanged, etc.).

results = matrix(nrow = length(files),ncol = 10)
cn = c("d1x","d1y","d2x","d2y","d3x","d3y","d4x","d4y")
non_optimized_pars = list(lambda = c(1, 1, 1, 1),tau = 0.0,dims = c(2,2,2,2),w = NA,cluster = NA,colskip = 1) 
inits=list(r = 1,beta = 1, d = 1, eta = .1)

fitSUSTAIN = function(par, non_opt_par, data) {
  st = c(non_opt_par,par)
  sustain = slpSUSTAIN(st, data.matrix(data), xtdo = TRUE)
  assign("sustain", sustain,envir = .GlobalEnv)
  return((sum(data[,"c1"] - sustain$xtdo[,1])^2)^.5)
}

weights = clusters = list()
for(file in 1:length(files)){
  dat = read.csv(files[file])
  train = dat[is.na(dat$isold),]
  stims = train[,3:6]
  ctrl = c(1,rep(0,nrow(stims)-1))
  c1 = ifelse(train$corresp==1,1,0)
  c2 = ifelse(train$corresp==2,1,0)
  d = as.data.frame(cbind(ctrl,convertSUSTAIN(stims,dims = rep(2,4)),c1,c2))
  colnames(d)[2:9] = cn
  param = optim(par = inits, fitSUSTAIN, non_opt_par = non_optimized_pars, data = d, lower = c(0,0,0,0),method="L-BFGS-B")
  #print(sustain)
  results[file,] = c(param$par,sustain$lambda,nrow(sustain$cluster),param$value)
  weights[[file]] = sustain$w
  clusters[[file]] = sustain$clusters
  print(file)
}

This is my code and i attached one example datafile. thus, setting:

files = "101_Rulex_2023-11-20-08h50.19.527.csv"

should make the code executable.

Any help at all is very appreciated!

Love this package btw!!

101_Rulex_2023-11-20_08h50.19.527.csv

lenarddome commented 1 month ago

Hi,

Great to hear you love the package! It's always great to hear from people using it.

I managed to replicate it, but when I looked at the parameters, the best-fitting learning rate was 0, which makes me think it might have been an optimisation problem. And in fact, when I run SUSTAIN with the un-optimised paramerets inits=list(r = 1,beta = 1, d = 1, eta = .1), it exhibits a more sensible behaviour.

It could potentially be because of (sum(data[,"c1"] - sustain$xtdo[,1])^2)^.5. You need to use the absolute value of the differences.

I personally recommend to either use ssecl() from catlearn or use a Negative Log Likelihood for Bernoulli distributions.

If you use the built-in catlearn function ssecl(), then you would have something like this:


fitSUSTAIN = function(par, non_opt_par, data) {
  st = c(non_opt_par, par)
  sustain = slpSUSTAIN(st, data.matrix(data), xtdo = TRUE)
  assign("sustain", sustain,envir = .GlobalEnv)
  ## calculate error between predictions and observations
  error = ssecl(data[,"c1"], sustain$xtdo[,1])
  ## control for out-of-bounds parameters
  if (is.infinite(error) || is.nan(error)) {
    error = 1e+10
  }
  return(error)
}

It works perfectly fine, but some people might prefer to use Negative Log Likelihood. Let me know if any of it works for you, I only tested it on my machine.

It seems like it is not a bug in catlearn, but I will leave the issue open until we make sure it works for you too 😃

lenarddome commented 1 month ago

I would also recommend to set some upper bounds in optim, such that upper=c(20, 20, 20, 1), see the Notes in the slpSUSTAIN documentation.

troyhouser commented 1 month ago

Thank you so much for your help and speedy response! It seems to be working well and I tried with both the ssecl function and negative log likelihood. I am getting a convergence issue from optim (code 52, abnormal termination), but it seems this will be resolved outside of catlearn.

Many thanks!

lenarddome commented 1 month ago

Great to hear! I will close the issue then.