stan-dev / stan

Stan development repository. The master branch contains the current release. The develop branch contains the latest stable development. See the Developer Process Wiki for details.
https://mc-stan.org
BSD 3-Clause "New" or "Revised" License
2.57k stars 368 forks source link

Optimisation writes out final parameter values in incorrect order for arrays #532

Closed JohannesBuchner closed 10 years ago

JohannesBuchner commented 10 years ago

There is a problem with the way Stan reads the initialisation values for array parameters.

I prepared a minimal example code:

data {
  int N;
  real stdev;
  real obs[N,6];
}
parameters {
  real mymean[2,3];
}
model {
  for (i in 1:N) {
    obs[i,1] ~ normal(mymean[1,1], stdev);
    obs[i,2] ~ normal(mymean[2,1], stdev);
    obs[i,3] ~ normal(mymean[1,2], stdev);
    obs[i,4] ~ normal(mymean[2,2], stdev);
    obs[i,5] ~ normal(mymean[1,3], stdev);
    obs[i,6] ~ normal(mymean[2,3], stdev);
  }
}

I generated test data from this model:

stdev <- 1e-05
obs <- structure(c(11.0000176405,11.0000040016,11.0000097874,11.0000224089,11.0000186756,10.9999902272,11.0000095009,10.9999984864,10.9999989678,11.000004106,11.0000014404,11.0000145427,11.0000076104,11.0000012168,11.0000044386,11.0000033367,11.0000149408,10.9999979484,11.0000031307,10.999991459,10.9999744701,11.0000065362,11.0000086444,10.9999925783,11.0000226975,10.9999854563,11.0000004576,10.9999981282,11.0000153278,11.0000146936,11.0000015495,11.0000037816,10.9999911221,10.999980192,10.9999965209,11.0000015635,11.0000123029,11.0000120238,10.9999961267,10.999996977,10.9999895145,10.9999857998,10.9999829373,11.0000195078,10.9999949035,10.9999956193,10.999987472,11.0000077749,10.999983861,10.9999978726,10.9999910453,11.000003869,10.9999948919,10.9999881937,10.9999997182,11.0000042833,11.0000006652,11.0000030247,10.9999936568,10.9999963726,10.9999932754,10.9999964045,10.9999918685,10.9999827372,11.0000017743,10.9999959822,10.999983698,11.0000046278,10.999990927,11.0000005195,11.0000072909,11.0000012898,11.000011394,10.9999876517,11.0000040234,10.9999931519,10.999991292,10.9999942115,10.9999968845,11.0000005617,10.9999883485,11.0000090083,11.0000046566,10.9999846376,11.0000148825,11.0000189589,11.0000117878,10.9999982008,10.9999892925,11.0000105445,10.9999959682,11.0000122245,11.0000020827,11.0000097664,11.0000035637,11.0000070657,11.000000105,11.0000178587,11.0000012691,11.0000040199,-11.9999811685,-12.0000134776,-12.0000127048,-11.999990306,-12.0000117312,-11.9999805638,-12.0000041362,-12.0000074745,-11.9999807706,-11.9999851949,-11.9999813244,-11.9999909396,-12.0000086123,-11.9999808994,-12.00000268,-11.9999919754,-11.9999905275,-12.0000015501,-11.9999938592,-11.9999907779,-11.9999962357,-12.000010994,-11.9999970176,-11.9999867361,-12.0000069457,-12.0000014963,-12.0000043515,-11.9999815074,-11.9999932771,-11.9999959254,-12.0000076992,-11.9999946075,-12.0000067433,-11.9999996817,-12.0000063585,-11.9999932357,-11.9999942341,-12.000002083,-11.9999960399,-12.0000109306,-12.0000149126,-11.9999956061,-11.9999983333,-11.9999936497,-11.9999761686,-11.9999905552,-12.0000091282,-11.9999888298,-12.0000131591,-12.0000046158,-12.0000006824,-11.9999828666,-12.0000074475,-12.0000082644,-12.0000009845,-12.0000066348,-11.9999887336,-12.0000107993,-12.0000114747,-12.0000043782,-12.0000049803,-11.9999807047,-11.9999905058,-11.9999991245,-12.0000122544,-11.9999915564,-12.0000100022,-12.0000154477,-11.9999881197,-11.9999968306,-11.9999907914,-11.9999968127,-11.9999914317,-12.0000065103,-12.0000103424,-11.9999931841,-12.0000080341,-12.0000068955,-12.0000045553,-11.9999998252,-12.0000035399,-12.0000137495,-12.0000064362,-12.000022234,-11.9999937477,-12.0000160206,-12.0000110438,-11.9999994783,-12.0000073956,-11.9999845699,-12.0000129286,-11.9999973295,-12.0000003928,-12.0000116809,-11.9999947672,-12.0000017155,-11.9999922821,-11.999991765,-11.9999783676,-11.9999866347,129.999996308,129.999997606,130.000010997,130.000006553,130.000006401,129.99998383,129.999999757,129.99999262,130.000002799,129.999999018,130.000009102,130.000003172,130.000007863,129.999995336,129.999990556,129.9999959,129.99999983,130.000003792,130.000022593,129.999999577,129.999990441,129.99999654,129.999995364,130.000004815,129.999984592,130.000000633,130.000001565,130.000002322,129.999994027,129.999997621,129.999985759,129.999995067,129.999994571,130.000004161,129.999988438,130.000007812,130.000014945,129.9999793,130.000004263,130.000006769,129.999993626,129.999996027,129.999998671,129.999997022,129.99999691,129.99998324,130.000011523,130.000010796,129.999991866,129.999985336,130.000005211,129.999994242,130.00000142,129.999996807,130.000006915,130.000006947,129.999992744,129.999986166,129.999984171,130.000006104,129.999988111,129.999994932,129.999994037,129.999999474,129.999980637,130.000001888,130.000005239,130.000000884,129.999996891,130.000000974,130.00000399,129.999972274,130.000019559,130.000003901,129.999993476,129.99999609,130.000004937,129.999998839,129.999979693,130.000020645,129.999998895,130.000010202,129.99999308,130.000015364,130.000002863,130.000006088,129.999989547,130.000012111,130.000006898,130.000013018,129.999993719,129.99999519,130.000023039,129.9999894,129.999998641,130.000011369,130.000000977,130.00000583,129.999996006,130.000003701,-210.000013065,-209.999983419,-210.000001182,-210.000006802,-209.999993336,-210.000004607,-210.000013343,-210.000013467,-209.999993062,-210.000001596,-210.000001337,-209.999989223,-210.000011268,-210.000007307,-210.000003849,-209.999999056,-210.000000422,-210.000002869,-210.000000616,-210.000001073,-210.000007196,-210.00000813,-209.999997255,-210.000008909,-210.000011574,-210.000003123,-210.000001577,-209.999977433,-210.000007047,-209.999990567,-209.999992528,-210.000011889,-209.999992267,-210.000011839,-210.000026592,-209.999993937,-210.000017559,-209.999995491,-210.00000684,-209.999983404,-209.999989315,-210.000004534,-210.000006878,-210.000012141,-210.000004409,-210.000002804,-210.000003647,-209.999998433,-209.999994215,-209.999996503,-210.000007641,-210.000014378,-209.999986355,-210.000006894,-210.000006523,-210.000005212,-210.000018431,-210.00000478,-210.000004797,-209.999993796,-209.999993015,-209.999999962,-209.999990682,-209.9999966,-210.000000157,-209.999998391,-210.000001907,-210.000003948,-210.000002677,-210.00001128,-209.999997196,-210.000009931,-209.999991584,-210.000002495,-209.999999505,-209.999995062,-209.999993567,-210.000015706,-210.000002069,-209.999991198,-210.000016981,-209.999996127,-210.000022556,-210.000010225,-209.999999614,-210.000016567,-210.000009855,-210.000014718,-209.999983519,-209.999998358,-209.999994327,-210.000002227,-210.000003534,-210.000016165,-210.000002918,-210.000007615,-209.999991421,-209.999988589,-209.999985334,-209.999991474,2.19999401346,2.19998884103,2.20000766663,2.20000356293,2.19998231462,2.20000355482,2.2000081452,2.20000058926,2.19999814946,2.19999192352,2.19998553465,2.20000800298,2.19999690886,2.19999766533,2.20001732721,2.20000684501,2.20000370825,2.20000142062,2.20001519995,2.20001719589,2.20000929505,2.20000582225,2.19997905397,2.20000123722,2.19999869893,2.20000093953,2.20000943046,2.19997260323,2.19999430688,2.20000269904,2.19999533154,2.19998583094,2.20000868963,2.20000276872,2.19999028895,2.20000314817,2.20000821586,2.20000005293,2.20000800565,2.2000007826,2.19999604771,2.19998840579,2.19999914069,2.20000194293,2.20000875833,2.19999884893,2.20000457416,2.19999035388,2.19999217371,2.19999889611,2.19998945372,2.20000820248,2.2000046313,2.20000279096,2.20000338904,2.20002021044,2.19999531136,2.19997798559,2.200001993,2.19999949396,2.19999482481,2.1999902117,2.1999956081,2.20000181338,2.19999497183,2.20002412454,2.19999039496,2.19999206883,2.1999771138,2.20000251484,2.19997983593,2.19999460545,2.19999724329,2.19999290272,2.20001738873,2.20000994394,2.20001319137,2.19999117581,2.20001128594,2.20000496001,2.20000771406,2.20001029439,2.19999091237,2.19999575682,2.20000862596,2.19997344381,2.20001513328,2.20000553132,2.19999954296,2.20000220508,2.19998970065,2.19999650057,2.20001100284,2.20001298022,2.20002696224,2.19999926075,2.19999341447,2.19999485766,2.19998981958,2.19999922145,-2.29999617268,-2.30000034242,-2.29998903653,-2.30000234216,-2.30000347451,-2.30000581268,-2.30001632635,-2.30001567768,-2.30001179158,-2.29998698572,-2.2999910474,-2.29998625036,-2.30001332212,-2.30001968625,-2.30000660056,-2.29999824181,-2.2999950131,-2.29998952028,-2.2999971572,-2.29998257331,-2.30000222606,-2.30000913079,-2.30001681218,-2.30000888971,-2.29999757882,-2.3000088872,-2.29999063258,-2.29998587672,-2.30002369587,-2.29999135948,-2.30002239604,-2.29999598501,-2.29998775129,-2.29999935144,-2.30001279689,-2.30000585431,-2.30000261645,-2.30000182245,-2.30000202897,-2.30000109883,-2.2999978652,-2.30001208574,-2.3000024202,-2.29998481739,-2.30000384645,-2.30000443836,-2.29998921803,-2.30002559185,-2.29998818621,-2.30000631904,-2.29999836071,-2.29999903679,-2.29999057532,-2.30000267595,-2.30000678026,-2.29998702154,-2.30002364174,-2.29999979666,-2.30001347925,-2.30000761573,-2.29997988743,-2.30000044595,-2.2999980493,-2.30001781563,-2.30000729045,-2.29999803443,-2.29999645242,-2.29999383113,-2.29999991372,-2.29999472996,-2.29999546218,-2.3000182974,-2.29999962994,-2.29999232098,-2.2999941012,-2.30000363859,-2.30000805627,-2.30001118312,-2.30000131054,-2.2999886692,-2.30001951804,-2.30000659892,-2.30001139802,-2.29999215042,-2.3000055431,-2.30000470638,-2.3000021695,-2.29999554607,-2.30000392389,-2.30003046143,-2.29999456688,-2.29999560957,-2.30000219541,-2.30001084037,-2.2999964822,-2.29999620764,-2.30000470033,-2.30000216731,-2.30000930157,-2.30000178589), .Dim = c(100,6))
N <- 100

I optimize and the file written correctly contains:

lp__,mymean.1.1,mymean.2.1,mymean.1.2,mymean.2.2,mymean.1.3,mymean.2.3
-298.317,11.000000598079,129.99999940768,2.1999998743578,-11.99999917987,-210.00000196798,-2.3000020293099

I create the following initialisation file:

mymean <- structure(c(11.0000005981,129.999999408,2.19999987436,-11.9999991799,-210.000001968,-2.30000202931), .Dim = c(2,3))

If I use this in R, it gives:

> mymean <- structure(c(11.0000005981,129.999999408,2.19999987436,-11.9999991799,-210.000001968,-2.30000202931), .Dim = c(2,3))
> mymean
     [,1]  [,2]        [,3]
[1,]   11   2.2 -210.000002
[2,]  130 -12.0   -2.300002

This is exactly what the output file describes.

Now I use this as a initialisation file for sampling.

The problem is that init_log_prob is then extremely low (-1.64101e+17). (For debugging, I inserted a line into command.hpp to print out init_log_prob). The correct log_probability (-303.011) is only given if I re-order the array in the initialisation:

mymean <- structure(c(11,-12,130,-210,2.2,-2.3), .Dim = c(2,3))

Such that

> mymean
     [,1] [,2] [,3]
[1,]   11  130  2.2
[2,]  -12 -210 -2.3
>#mymean.1.1,mymean.2.1,mymean.1.2,mymean.2.2,mymean.1.3,mymean.2.3
> c(mymean[1,1], mymean[2,1], mymean[1,2], mymean[2,2], mymean[1,3], mymean[2,3])
[1]   11.0  -12.0  130.0 -210.0    2.2   -2.3

Either the order the array is read or written incorrectly. I use Stan commit 65ceb15f5f1b.

JohannesBuchner commented 10 years ago

The problem is that the output column values are actually written last index fastest, while the header claims first index fastest indexing!

bob-carpenter commented 10 years ago

I'm not quite following the problem here. I tried to create a slightly simpler example.

parameters {
  real y[2,2];
}
model {
  print("y=",y);
  y[1,1] ~ normal(1,1);
  y[2,1] ~ normal(100,1);
  y[1,2] ~ normal(10000,1);
  y[2,2] ~ normal(1000000,1);
}

I then create the init file in R:

> y <- matrix(NA,2,2)
> y[1,1] <- 1
> y[2,1] <- 100
> y[1,2] <- 10000
> y[2,2] <- 1000000

> y
     [,1]  [,2]
[1,]    1 1e+04
[2,]  100 1e+06

> stan_rdump(c('y'),"init.init.R")

which produces a file init.init.R with content

y <- 
structure(c(1, 100, 10000, 1e+06),
.Dim = c(2, 2))

And then I compile and run from CmdStan, turning warmup off:

~/temp2/init$ ./init sample num_warmup=0 num_samples=5 init=init.init.R

and what I get is what I'd expect with no warmup:

Iteration: 1 / 10 [ 10%]  (Sampling)
y=[[1,10000],[100,1e+06]]
y=[[1.93513,10001.1],[100.572,1e+06]]
y=[[0.0648746,9998.93],[99.4284,1e+06]]
y=[[0.0648746,9998.93],[99.4284,1e+06]]
y=[[1.93513,10001.1],[100.572,1e+06]]
y=[[2.09643,9999.64],[99.1611,1e+06]]

and so is the output

~/temp2/init$ cat output.csv
...
lp__,accept_stat__,stepsize__,treedepth__,n_leapfrog__,n_divergent__,y.1.1,y.2.1,y.1.2,y.2.2
...
0,0.725398,1,2,3,0,1,100,10000,1e+06
-0.669897,0.845798,1,2,3,0,0.16092,99.3665,10000.5,1e+06
-1.52923,0.807111,1,2,3,0,0.495168,101.343,9999.68,999999
-2.36202,0.75204,1,2,3,0,0.724809,101.193,9998.79,1e+06
-2.36202,0.458734,1,2,3,0,1.27519,98.8069,10001.2,999999

That is, I get y.1.1 equal to 1, y.2.1 equal to 100, y.1.2 equal to 10000, and y.2.2. equal to 1000000.

mbrubake commented 10 years ago

I can confirm this with CmdStan on current develop. It also is only in issue with arrays. If mymean is a matrix, the ordering is correct and consistent. The bug is in how the write_array/write_csv/etc orders its loops for arrays which is inconsistent with write_csv_header.

@bob-carpenter @syclik I think we should just to everything column major since that's also how things are read in. Thoughts?

bob-carpenter commented 10 years ago

I guess I'm still being too dense to see what the problem is. @Marcus --- can you create a simpler example for me to follow?

Or is it somehow just a problem with optimization?

mbrubake commented 10 years ago

@bob-carpenter Look in the generated cpp file for the original model. You'll find this:

    void write_csv_header(std::ostream& o__) const {
        stan::io::csv_writer writer__(o__);
        for (int k_1__ = 1; k_1__ <= 3; ++k_1__) {
            for (int k_0__ = 1; k_0__ <= 2; ++k_0__) {
                writer__.comma();
                o__ << "mymean" << '.' << k_0__ << '.' << k_1__;
            }
        }
        writer__.newline();
    }

    template <typename RNG>
    void write_csv(RNG& base_rng__,
                   std::vector<double>& params_r__,
                   std::vector<int>& params_i__,
                   std::ostream& o__,
                   std::ostream* pstream__ = 0) const {
...
        size_t dim_mymean_0__ = 2;
        mymean.resize(dim_mymean_0__);
        for (size_t k_0__ = 0; k_0__ < dim_mymean_0__; ++k_0__) {
            size_t dim_mymean_1__ = 3;
            for (size_t k_1__ = 0; k_1__ < dim_mymean_1__; ++k_1__) {
                mymean[k_0__].push_back(in__.scalar_constrain());
                writer__.write(mymean[k_0__][k_1__]);
            }
        }
...

Note that the loop ordering is different between write_csv_header() and write_csv().

JohannesBuchner commented 10 years ago

The problem seems to only appear when running "optimize", not "sample". I think.

bob-carpenter commented 10 years ago

Thanks for the clarification --- I see the problem. I'd like to get rid of the dependencies on write_csv and write_csv_header so that the generated model code doesn't need to do anything with formatting.

@mbrubake Would you mind changing optimization so that it uses constrained_param_names() and write_array(), both of which are last-index fastest?

@maverickg Does RStan use write_csv or write_csv_header?

@ariddell Does PyStan use write_csv or write_csv_header?

mbrubake commented 10 years ago

Ok, changing now. When did those functions become deprecated? It's also somewhat of a shame as we now have duplicated code between command.hpp and in mcmc_writer.hpp because we're not using functions like write_csv or write_csv_header. Perhaps we should simply rewrite the write_csv* functions in terms of write_array?

JohannesBuchner commented 10 years ago

Could you please help me: How can I print out the current model parameters? I would like to insert some debugging code into command.hpp after the initialisation is loaded. In another test code, I get -inf values in cont_params after loading. I don't know the actual model parameter values. Can I dump them somehow?

betanalpha commented 10 years ago

write_csv is only used in the optimization — it’s in the process of being deprecated, a process which was put on hold due to the upcoming refactor of command.

On Feb 4, 2014, at 5:52 PM, Marcus Brubaker notifications@github.com wrote:

Ok, changing now. When did those functions become deprecated? It's also somewhat of a shame as we now have duplicated code between command.hpp and in mcmc_writer.hpp because we're not using functions like write_csv or write_csv_header. Perhaps we should simply rewrite the write_csv* functions in terms of write_array?

— Reply to this email directly or view it on GitHub.

bob-carpenter commented 10 years ago

@JohannesBuchner Current in what sense? And on the constrained or unconstrained scale? You can print the constrained versions using a print statement in the model. Those will print during each leapfrog step during sampling. I'm not sure what happens during optimization.

We're not going to add general printing to the Stan C++ API.

bob-carpenter commented 10 years ago

I'd rather not have the compiled model have anything built in to do printing.

I'd be OK with a write_csv-like utility function on the outside to use in CmdStan. PyStan and RStan both need to get the values as C++ data structures.

On 2/4/14, 6:52 PM, Marcus Brubaker wrote:

Ok, changing now. When did those functions become deprecated? It's also somewhat of a shame as we now have duplicated code between command.hpp and in mcmc_writer.hpp because we're not using functions like write_csv or write_csv_header. Perhaps we should simply rewrite the write_csv* functions in terms of write_array?

— Reply to this email directly or view it on GitHub https://github.com/stan-dev/stan/issues/532#issuecomment-34087102.

JohannesBuchner commented 10 years ago

Oh this worked:

        std::cout << "initial log-probability: " << init_log_prob << std::endl;
        std::cout << "values: " << std::endl;
        for (unsigned int i = 0; i < model.num_params_r(); i++) {
          std::cout << "  " << cont_params[i] << std::endl;
        }
        model.write_csv(base_rng, cont_params, disc_params, std::cout, &std::cout);
JohannesBuchner commented 10 years ago

You're right, using print in the model is much simpler.