Когнитивная психология и эмоции
Субъективные заметки постдока-психолога

Как закупается оборудование для университетов в Исландии

30 октября 2015, заметки Метки: ,

Я сейчас временно работаю в Рейкьявике, постдоком в университете Исландии, так что иногда буду писать лытдыбры про это. Первый дыбр интересен будет лишь тем, кто вращается в университетской среде.

Заказывал себе на этой и прошлой неделе компьютер для работы. Поскольку значительная часть работы это анализ данных, обычный офисный компьютер мне не очень подходит. Шеф сказал, спросить у коллеги, через какую компанию универ сейчас закупается, и запросить у них цену под то, что мне нужно. Коллега назвал Компанию А и Компанию Б, обе торгуют в основном готовыми сборками с небольшими возможностями модификации. Беглый поиск показал, что цены у них выше среднерыночных. Во мне взыграла природное нежелание переплачивать, так что я также запросил предложение от обычной компании. Как и ожидалось, оно было лучше, и тот же коллега сказал, чтобы я послал нашему администратору это предложение. Администратор переслал его директору по закупкам, тот ответил, что закупать через эту компанию университет не может, так что вот вам прайс Компании А с ценами для университета, подберите себе что-нибудь. Ну, я подобрал нечто, переслал администратору с припиской. что мол все равно хуже и дороже, чем прошлое предложение. Через день мне пришел ответ, что оказывается есть еще вариант компании C, которая торгует тем же, что и найденная мной контора, и у нее закупать можно. Потратив еще часа три, подобрал себе хорошую конфигурацию, запросил цену с учетом университетской скидки. На следующее утро получил предложение, переслал его администратору. Днем и вечером получил два письма на исландском из переписки с этой конторой директора по закупкам, в последнем из которых говорилось, что компьютер будет готов третьего ноября.

Итог: времени ушло примерно неделя, цена рыночная. Конторы «по умолчанию» продают дороже. В отличие от известных мне российских вузов, закупка в таких мастшабах (около 1700-2000$) не требует тендера, хотя выбор компании ограничен, так что может что-то подобное происходит в более общем формате. Запрос цен и подборка конфигурации делается самими исследователями, но, возможно, это просто мой случай.

APA-style iniline headings in MS Word

9 октября 2015, так просто Метки: , ,

I’m writing this here so I will know where to find it. To make a proper inline headings required by APA style that are shown in Navigation pane in Microsoft Word you need to do the following:

1) select the text that should be a heading
2) add appropriate style
3) place the cursor after the heading and press Alt+Ctrl+Enter after the header to add a «style» breaker
4) format the rest of the text as usual

Online vs. Offline — new paper

18 июля 2015, наука Метки:

Наша с @konhis (Филиппом Управителевым) статья про точность оценки времени реакции в онлайн исследованиях наконец увидела свет: http://link.springer.com/article/10.3758/s13428-015-0632-x. Там же можно скачать данные и скрипты к статье. Если у кого-то нет доступа, препринт есть тут: https://www.researchgate.net/publication/280057912_Online_versus_offline_The_Web_as_a_medium_for_response_time_data_collection.

Вкратце о результатах:
1) онлайн исследованиях не хуже оффлайн по точности оценки времен реакции, но
2) слишком большая вариативность браузеров и операционных систем, большая чем наблюдается в реальности, может ухудшить результат

По сути же результаты даже лучше, чем я ожидал — я думал, что в наиболее простых задачах типа красный слева — нажми влево, красный справа — нажми вправо, разница все-таки будет. Но на выборке в 20 человек и большом количестве проб она не видна. На всякий случай уточню, что речь идет о разнице в разбросе данных. Средние отличаются, но это как раз не очень интересно, так как средние всегда отличаются. Важно то, что если у вас есть условие А и условие Б, то онлайн и оффлайн время реакции в этих условиях будет отличаться примерно на одно и то же значение. И разброс данных в условии А и условии Б будем примено одинаковым, а значит вероятность пропустить эффект онлайн и оффлайн также примерно одинакова.

В общем, исследования онлайн делать можно и нужно.

Running Julia’s MixedModels from R

30 июня 2015, анализ данных Метки: , , , ,

Today I had to rerun some scripts to test additional factors with mixed regression. For those of you who haven’t been using it, mixed regression (aka mixed effects regression, hierarchical modeling, or multilevel modeling) is a new sexy way to analyze your data when you have repeated measures (see this or this for some intro). Despite its awesomeness, mixed regression have one major drawback: computations are difficult and your average PC would be a bit slow. I am used to doing statistics interactively, and leaving R to do its stuff even for 10 minutes is frustrating. Leaving it for a couple of hours is definitely too much. So today while lme4 was doing its work, I decided that it’s finally time to test Julia’s magic powers. If mixed models are new and sexy, then Julia is a kind of uncombed but smart and agile teenager (I hope my attempts at metaphors would not be devastated by my «far from perfect» English and you would get the point). It is a three years old programming language made to be a bit like R, but much faster. What’s more interesting, Douglas Bates, one of the main authors of lme4 package in R, have been working for quite some time on a MixedModels package for Julia. The package is still quite underdeveloped and lacks some features of lme4 but the speed, the speed is already amazing. Given that you can run Julia from R with rjulia, one can use the best from both worlds. I made some tests on how fast MixedModels are when compared to lme4. So here are some results:

> ptm <- proc.time()
> lmer_with_julia(lrt~poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf+(1|participant),ds_data[correct==1&dsdf==15,])
 
                                     Estimate   StdError           Z
(Intercept)                        6.69235953 0.03986305 167.8837895
poly(targetDist, 2)1              -0.93507318 0.49478109  -1.8898725
poly(targetDist, 2)2               0.67376146 0.45051646   1.4955313
poly(distr_shift, 2)1             -0.13266734 0.63263396  -0.2097063
poly(distr_shift, 2)2              3.86257519 0.68643291   5.6270251
prev_dsdf10                        0.02124134 0.02187113   0.9712045
poly(distr_shift, 2)1:prev_dsdf10 -0.40239178 0.94527044  -0.4256896
poly(distr_shift, 2)2:prev_dsdf10 -0.59574970 1.10967725  -0.5368675
> proc.time() - ptm
   user  system elapsed 
   0.27    0.07    0.33 
> 
> ptm <- proc.time()
> mod_fit<-lmer(lrt~poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf+(1+poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf|participant),ds_data[correct==1&dsdf==15,])
Warning messages:
1: In commonArgs(par, fn, control, environment()) :
  maxfun < 10 * length(par)^2 is not recommended.
2: In optwrap(optimizer, devfun, getStart(start, rho$lower, rho$pp),  :
  convergence code 1 from bobyqa: bobyqa -- maximum number of function evaluations exceeded
3: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge with max|grad| = 5.46484 (tol = 0.002, component 15)
4: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge: degenerate  Hessian with 1 negative eigenvalues
> data.frame(Estimate=fixef(mod_fit), StdError = sqrt(diag(vcov(mod_fit))), Z = fixef(mod_fit)/sqrt(diag(vcov(mod_fit))))
                                     Estimate   StdError           Z
(Intercept)                        6.69229926 0.04190106 159.7167138
poly(targetDist, 2)1              -0.94220751 0.49613863  -1.8990811
poly(targetDist, 2)2               0.67036440 0.45581822   1.4706837
poly(distr_shift, 2)1             -0.13513381 0.63298649  -0.2134861
poly(distr_shift, 2)2              3.86885453 0.71171753   5.4359410
prev_dsdf10                        0.02137927 0.02213446   0.9658818
poly(distr_shift, 2)1:prev_dsdf10 -0.38675995 0.98129074  -0.3941339
poly(distr_shift, 2)2:prev_dsdf10 -0.58599673 1.11212726  -0.5269152
> proc.time() - ptm
   user  system elapsed 
  23.68    0.03   23.99

So here MixedModels takes 0.33 s and lme4 takes 23.99 s. Not bad. In addition, lme4 is having troubles with convergence while MixedModels seemingly don’t (I sent a question to r-sig-mixed-models about this, but there’s no answer yet).

> ptm <- proc.time()
> lmer_with_julia(lrt~poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf+(1|participant),ds_data[correct==1,])
 
                                     Estimate   StdError           Z
(Intercept)                        6.64043269 0.03552565 186.9193793
poly(targetDist, 2)1              -1.13069412 0.45134566  -2.5051623
poly(targetDist, 2)2               1.06636970 0.51338074   2.0771517
poly(distr_shift, 2)1              0.07246496 0.68719409   0.1054505
poly(distr_shift, 2)2              5.96863602 0.88864270   6.7165757
prev_dsdf10                       -0.04445310 0.01722907  -2.5801220
prev_dsdf15                       -0.03616479 0.02084635  -1.7348263
poly(distr_shift, 2)1:prev_dsdf10 -1.04818681 0.94317549  -1.1113380
poly(distr_shift, 2)2:prev_dsdf10 -1.22641312 0.94836666  -1.2931846
poly(distr_shift, 2)1:prev_dsdf15 -0.68364579 1.08519143  -0.6299771
poly(distr_shift, 2)2:prev_dsdf15 -1.06375276 1.00142954  -1.0622343
> proc.time() - ptm
   user  system elapsed 
   1.06    0.88    1.59 
> 
> ptm <- proc.time()
> mod_fit<-lmer(lrt~poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf+(1+poly(targetDist,2)+poly(distr_shift,2)*prev_dsdf|participant),ds_data[correct==1,])
Warning messages:
1: In commonArgs(par, fn, control, environment()) :
  maxfun < 10 * length(par)^2 is not recommended.
2: In optwrap(optimizer, devfun, getStart(start, rho$lower, rho$pp),  :
  convergence code 1 from bobyqa: bobyqa -- maximum number of function evaluations exceeded
3: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge with max|grad| = 17.0124 (tol = 0.002, component 58)
4: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge: degenerate  Hessian with 12 negative eigenvalues
> data.frame(Estimate=fixef(mod_fit), StdError = sqrt(diag(vcov(mod_fit))), Z = fixef(mod_fit)/sqrt(diag(vcov(mod_fit))))
                                     Estimate   StdError            Z
(Intercept)                        6.64061439 0.03584556 185.25625436
poly(targetDist, 2)1              -1.10335265 0.43205622  -2.55372471
poly(targetDist, 2)2               1.07790118 0.47686934   2.26037008
poly(distr_shift, 2)1              0.05756552 0.64110292   0.08979139
poly(distr_shift, 2)2              5.98318507 0.75230028   7.95318738
prev_dsdf10                       -0.04464860 0.01754927  -2.54418516
prev_dsdf15                       -0.03645163 0.02094288  -1.74052671
poly(distr_shift, 2)1:prev_dsdf10 -1.01415019 0.90588970  -1.11950736
poly(distr_shift, 2)2:prev_dsdf10 -1.24803222 0.90816160  -1.37424024
poly(distr_shift, 2)1:prev_dsdf15 -0.65142933 0.92908060  -0.70115480
poly(distr_shift, 2)2:prev_dsdf15 -1.12188710 0.89307721  -1.25620393
> proc.time() - ptm
   user  system elapsed 
 152.00    0.03  152.43

Again, MixedModels wins hands down, and the difference is considerable.

 
> ptm <- proc.time()
> lmer_with_julia(lrt~poly(targetDist,2)*dsdf+poly(distr_shift,2)*prev_dsdf+(1|participant),ds_data[correct==1,])
[1] "mod_fit = fit(lmm(lrt~a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+(a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p|participant),mm))"
                                  Estimate StdError      Z
(Intercept)                           6.47     0.03 211.68
poly(targetDist, 2)1                 -0.40     0.66  -0.61
poly(targetDist, 2)2                  0.66     0.62   1.06
dsdf10                                0.12     0.02   6.41
dsdf15                                0.22     0.02   9.80
poly(distr_shift, 2)1                 0.12     0.69   0.18
poly(distr_shift, 2)2                 5.87     0.90   6.50
prev_dsdf10                           0.02     0.02   1.22
prev_dsdf15                           0.07     0.02   3.27
poly(targetDist, 2)1:dsdf10          -0.57     1.02  -0.56
poly(targetDist, 2)2:dsdf10           0.77     1.06   0.72
poly(targetDist, 2)1:dsdf15          -1.38     0.93  -1.47
poly(targetDist, 2)2:dsdf15           0.47     0.95   0.49
poly(distr_shift, 2)1:prev_dsdf10    -1.08     0.93  -1.16
poly(distr_shift, 2)2:prev_dsdf10    -1.15     1.04  -1.11
poly(distr_shift, 2)1:prev_dsdf15    -0.76     1.10  -0.70
poly(distr_shift, 2)2:prev_dsdf15    -0.95     0.98  -0.97
> proc.time() - ptm
   user  system elapsed 
  10.12    5.72   11.89 
> 
> ptm <- proc.time()
> mod_fit<-lmer(lrt~poly(targetDist,2)*dsdf+poly(distr_shift,2)*prev_dsdf+(1+poly(targetDist,2)*dsdf+poly(distr_shift,2)*prev_dsdf|participant),ds_data[correct==1,])
Warning messages:
1: In commonArgs(par, fn, control, environment()) :
  maxfun < 10 * length(par)^2 is not recommended.
2: In optwrap(optimizer, devfun, getStart(start, rho$lower, rho$pp),  :
  convergence code 1 from bobyqa: bobyqa -- maximum number of function evaluations exceeded
3: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge with max|grad| = 18.1075 (tol = 0.002, component 132)
4: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv,  :
  Model failed to converge: degenerate  Hessian with 39 negative eigenvalues
> res<-data.frame(Estimate=fixef(mod_fit), StdError = sqrt(diag(vcov(mod_fit))), Z = fixef(mod_fit)/sqrt(diag(vcov(mod_fit))))
> round(res, 2)
                                  Estimate StdError      Z
(Intercept)                           6.47     0.03 216.25
poly(targetDist, 2)1                 -0.40     0.62  -0.65
poly(targetDist, 2)2                  0.67     0.63   1.06
dsdf10                                0.12     0.02   6.52
dsdf15                                0.22     0.02  10.16
poly(distr_shift, 2)1                 0.10     0.62   0.16
poly(distr_shift, 2)2                 5.91     0.68   8.73
prev_dsdf10                           0.02     0.02   1.29
prev_dsdf15                           0.07     0.02   3.50
poly(targetDist, 2)1:dsdf10          -0.60     0.87  -0.69
poly(targetDist, 2)2:dsdf10           0.79     0.87   0.91
poly(targetDist, 2)1:dsdf15          -1.34     0.89  -1.52
poly(targetDist, 2)2:dsdf15           0.55     0.88   0.62
poly(distr_shift, 2)1:prev_dsdf10    -1.03     0.87  -1.18
poly(distr_shift, 2)2:prev_dsdf10    -1.16     0.87  -1.33
poly(distr_shift, 2)1:prev_dsdf15    -0.73     0.88  -0.83
poly(distr_shift, 2)2:prev_dsdf15    -1.02     0.88  -1.17
> proc.time() - ptm
   user  system elapsed 
1030.20    0.18 1036.91

And now there’s really a huge difference. Note that the effects are more or less the same, which is good, because it shows that the results provided by MixedModels can be trusted. I added the lmer_with_julia to my functions on github, if you want to test it. It’s not very elaborated: currently, it uses right hand side of the formula to create maximal random effects structure and it also assumes that you’re using data.table.

R functions for formatting results «APA style» and other stuff

13 апреля 2015, анализ данных Метки:

For those of you using R and writing papers in APA style: I’ve uploaded some of the functions I commonly use for describing the results in Markdown to Github: https://github.com/ralfer/apa_format_and_misc/. I find them quite time-saving during initial stages of writing the manuscript. See some examples here: https://github.com/ralfer/apa_format_and_misc/blob/master/example/example.md.