コード例 #1
0
ファイル: layer_s.cpp プロジェクト: andylulu/ConvNet
void LayerScal::Init(const mxArray *mx_layer, Layer *prev_layer) {
  
  mexAssert(prev_layer->type_ != "f", "The 's' type layer cannot be after 'f' type layer");
  mexAssert(mexIsField(mx_layer, "scale"), "The 's' type layer must contain the 'scale' field");
  mapsize_.resize(prev_layer->mapsize_.size());
  std::vector<double> scale = mexGetVector(mexGetField(mx_layer, "scale"));  
  mexAssert(scale.size() == mapsize_.size(), "Length of scale vector and maps dimensionality must coincide");
  scale_.resize(scale.size());
  for (size_t i = 0; i < mapsize_.size(); ++i) {
    scale_[i] = (size_t) scale[i];
    mexAssert(1 <= scale_[i], "Scale size on the 's' layer must be greater or equal to 1");
    mapsize_[i] = ceil((double) prev_layer->mapsize_[i] / scale_[i]);
  }    
  outputmaps_ = prev_layer->outputmaps_;
  if (!mexIsField(mx_layer, "function")) {
    function_ = "mean";
  } else {
    function_ = mexGetString(mexGetField(mx_layer, "function"));
  }
  std::string errmsg = function_ + " - unknown function for the layer";    
  mexAssert(function_ == "max" || function_ == "mean", errmsg);
  activ_.resize(outputmaps_);
  deriv_.resize(outputmaps_);  
  
}
コード例 #2
0
ファイル: layer_f.cpp プロジェクト: mwoodson1/NeuroPhi
void LayerFull::Init(const mxArray *mx_layer, Layer *prev_layer) {
  mexAssert(mexIsField(mx_layer, "length"), "The 'f' type layer must contain the 'length' field");
  ftype length = mexGetScalar(mexGetField(mx_layer, "length"));
  mexAssert(1 <= length, "Length on the 'f' layer must be greater or equal to 1");
  length_ = (size_t) length;  
  mapsize_.assign(prev_layer->numdim_, 0);  
  length_prev_ = prev_layer->length_;
  if (mexIsField(mx_layer, "function")) {
    function_ = mexGetString(mexGetField(mx_layer, "function"));
    mexAssert(function_ == "soft" || function_ == "sigm" || function_ == "relu",
      "Unknown function for the 'f' layer");
  }
  if (mexIsField(mx_layer, "dropout")) {
    dropout_ = mexGetScalar(mexGetField(mx_layer, "dropout"));
    mexAssert(0 <= dropout_ && dropout_ < 1, "Dropout must be in the range [0, 1)");  
  }
  if (mexIsField(mx_layer, "initstd")) {
    init_std_ = mexGetScalar(mexGetField(mx_layer, "initstd"));
    mexAssert(0 <= init_std_, "initstd must be non-negative");  
  }  
  if (mexIsField(mx_layer, "biascoef")) {
    bias_coef_ = mexGetScalar(mexGetField(mx_layer, "biascoef"));
    mexAssert(0 <= bias_coef_, "biascoef must be non-negative");  
  }
}
コード例 #3
0
ファイル: params.cpp プロジェクト: yuanpu/ConvNet
void Params::Init(const mxArray *mx_params) {
  
  if (mexIsField(mx_params, "batchsize")) {    
    batchsize_ = (size_t) mexGetScalar(mexGetField(mx_params, "batchsize"));    
    mexAssert(batchsize_ > 0, "Batchsize must be positive");
  }
  if (mexIsField(mx_params, "numepochs")) {    
    numepochs_ = (size_t) mexGetScalar(mexGetField(mx_params, "numepochs"));    
    mexAssert(numepochs_ > 0, "Numepochs must be positive");
  }
  if (mexIsField(mx_params, "alpha")) {    
    alpha_ = mexGetVector(mexGetField(mx_params, "alpha"));
    mexAssert(alpha_.size() == 1 || alpha_.size() == numepochs_,
      "Wrong length of the alpha vector");
    for (size_t i = 0; i < alpha_.size(); ++i) {
      mexAssert(alpha_[i] >= 0, "alpha must be nonnegative");
    }
  }
  if (mexIsField(mx_params, "momentum")) {    
    momentum_ = mexGetVector(mexGetField(mx_params, "momentum"));
    mexAssert(momentum_.size() == 1 || momentum_.size() == numepochs_,
      "Wrong length of the momentum vector");
    for (size_t i = 0; i < momentum_.size(); ++i) {
      mexAssert(0 <= momentum_[i] && momentum_[i] < 1, "Momentum is out of range [0, 1)");
    }    
  }
  if (mexIsField(mx_params, "adjustrate")) {    
    adjustrate_ = mexGetScalar(mexGetField(mx_params, "adjustrate"));    
    mexAssert(0 <= adjustrate_, "Adjustrate must be non-negative");
  }
  if (mexIsField(mx_params, "maxcoef")) {    
    maxcoef_ = mexGetScalar(mexGetField(mx_params, "maxcoef"));
    mexAssert(1 <= maxcoef_ , "Maxcoef must be larger or equal to 1");
    mincoef_ = 1 / maxcoef_;    
  }
  if (mexIsField(mx_params, "balance")) {    
    balance_ = (bool) mexGetScalar(mexGetField(mx_params, "balance"));    
  }
  if (mexIsField(mx_params, "shuffle")) {    
    shuffle_ = (bool) mexGetScalar(mexGetField(mx_params, "shuffle"));    
  }
  if (mexIsField(mx_params, "verbose")) {    
    verbose_ = (size_t) mexGetScalar(mexGetField(mx_params, "verbose"));    
  }
  if (mexIsField(mx_params, "seed")) {    
    seed_ = (size_t) mexGetScalar(mexGetField(mx_params, "seed"));    
  }
}
コード例 #4
0
ファイル: layer_t.cpp プロジェクト: mrgloom/ConvNet
void LayerTrim::Init(const mxArray *mx_layer, Layer *prev_layer) {
  
  mexAssert(prev_layer->type_ != "f", "The 't' type layer cannot be after 'f' type layer");
  numdim_ = prev_layer->numdim_;
  outputmaps_ = prev_layer->outputmaps_;  
  length_prev_ = prev_layer->outputmaps_;
  mexAssert(mexIsField(mx_layer, "mapsize"), "The 't' type layer must contain the 'mapsize' field");
  std::vector<ftype> mapsize = mexGetVector(mexGetField(mx_layer, "mapsize"));  
  mexAssert(mapsize.size() == numdim_, "Length of the trim vector and maps dimensionality must coincide");
  mapsize_.resize(numdim_);
  length_ = outputmaps_;
  for (size_t i = 0; i < numdim_; ++i) {
    mexAssert(mapsize[i] <= prev_layer->mapsize_[i], "In 't' layer new mapsize cannot be larger than the old one");    
    mapsize_[i] = (size_t) mapsize[i];    
    length_ *= mapsize_[i];
  }  
}
コード例 #5
0
ファイル: layer_c.cpp プロジェクト: mwoodson1/NeuroPhi
void LayerConv::Init(const mxArray *mx_layer, Layer *prev_layer) {
  
  mexAssert(prev_layer->type_ != "f", "The 'c' type layer cannot be after 'f' type layer");
  numdim_ = prev_layer->numdim_;
  length_prev_ = prev_layer->outputmaps_;
  mexAssert(mexIsField(mx_layer, "outputmaps"), "The 'c' type layer must contain the 'outputmaps' field");
  ftype outputmaps = mexGetScalar(mexGetField(mx_layer, "outputmaps"));
  mexAssert(1 <= outputmaps, "Outputmaps on the 'i' layer must be greater or equal to 1");
  outputmaps_ = (size_t) outputmaps;  
  if (mexIsField(mx_layer, "function")) {
    function_ = mexGetString(mexGetField(mx_layer, "function"));
    mexAssert(function_ == "relu" || function_ == "sigm", 
      "Unknown function for the 'c' layer");
  }
  mexAssert(mexIsField(mx_layer, "filtersize"), "The 'c' type layer must contain the 'filtersize' field");
  std::vector<ftype> filtersize = mexGetVector(mexGetField(mx_layer, "filtersize"));
  mexAssert(filtersize.size() == numdim_, "Filters and maps must be the same dimensionality");
  filtersize_.resize(numdim_);    
  for (size_t i = 0; i < numdim_; ++i) {
    mexAssert(1 <= filtersize[i], "Filtersize on the 'c' layer must be positive");
    filtersize_[i] = (size_t) filtersize[i];    
  }
  #if COMP_REGIME == 2	// GPU
    mexAssert(filtersize_[0] == filtersize_[1], "In the GPU version the filtersize should be squared on all layers");
  #endif
  padding_.assign(numdim_, 0);
  if (mexIsField(mx_layer, "padding")) {
    std::vector<ftype> padding = mexGetVector(mexGetField(mx_layer, "padding"));
    mexAssert(padding.size() == numdim_, "Padding vector has the wrong length");
    for (size_t i = 0; i < numdim_; ++i) {
      mexAssert(0 <= padding[i] && padding[i] <= filtersize_[i] - 1, "Padding on the 'c' layer must be in the range [0, filtersize-1]");
      padding_[i] = (size_t) padding[i];
    }
    #if COMP_REGIME == 2	// GPU
      mexAssert(padding_[0] == padding_[1], "In the GPU version the padding should be squared on all layers");
    #endif    
  }
  mapsize_.resize(numdim_);
  length_ = outputmaps_;
  size_t minsize_ = prev_layer->mapsize_[0] + 2*padding_[0] - filtersize_[0] + 1;
  for (size_t i = 0; i < numdim_; ++i) {
    mapsize_[i] = prev_layer->mapsize_[i] + 2*padding_[i] - filtersize_[i] + 1;
    mexAssert(1 <= mapsize_[i], "Mapsize on the 'c' layer must be greater than 1");
    if (mapsize_[i] < minsize_) minsize_ = mapsize_[i];
    length_ *= mapsize_[i];
  }
  if (mexIsField(mx_layer, "sumwidth")) {
    ftype sum_width = mexGetScalar(mexGetField(mx_layer, "sumwidth"));
    mexAssert(1 <= sum_width && sum_width <= minsize_, "Sumwidth must be in the range [0, min(mapsize)]");
    sum_width_ = (size_t) sum_width;
  } else {
    if (sum_width_ > minsize_) sum_width_ = minsize_;
  }
  if (mexIsField(mx_layer, "initstd")) {
    init_std_ = mexGetScalar(mexGetField(mx_layer, "initstd"));
    mexAssert(0 <= init_std_, "initstd must be non-negative");  
  }
  if (mexIsField(mx_layer, "biascoef")) {
    bias_coef_ = mexGetScalar(mexGetField(mx_layer, "biascoef"));
    mexAssert(0 <= bias_coef_, "biascoef must be non-negative");  
  }
  if (mexIsField(mx_layer, "unshared")) {
    unshared_ = (mexGetScalar(mexGetField(mx_layer, "unshared")) > 0);    
    if (unshared_) sum_width_ = 1;
  }
}
コード例 #6
0
ファイル: layer_j.cpp プロジェクト: jiminliang/ConvNet
void LayerJitt::Init(const mxArray *mx_layer, Layer *prev_layer) {
  //mexAssert(prev_layer->type_ == "i", "The 'j' type layer must be after the input one");
  numdim_ = prev_layer->numdim_;
  outputmaps_ = prev_layer->outputmaps_;
  length_prev_ = prev_layer->length_prev_;
  mexAssert(mexIsField(mx_layer, "mapsize"), "The 'j' type layer must contain the 'mapsize' field");
  std::vector<ftype> mapsize = mexGetVector(mexGetField(mx_layer, "mapsize"));  
  mexAssert(mapsize.size() == numdim_, "Length of jitter mapsize vector and maps dimensionality must coincide");
  mapsize_.resize(numdim_);
  length_ = outputmaps_;
  for (size_t i = 0; i < numdim_; ++i) {
    mexAssert(1 <= mapsize[i], "In 'j' layer mapsize must be positive");    
    mapsize_[i] = (size_t) mapsize[i];
    length_ *= mapsize_[i];
  }
  shift_.assign(numdim_, 0);
  if (mexIsField(mx_layer, "shift")) {
    shift_ = mexGetVector(mexGetField(mx_layer, "shift"));  
    mexAssert(shift_.size() == numdim_, "Length of jitter shift vector and maps dimensionality must coincide");
    for (size_t i = 0; i < numdim_; ++i) {      
      mexAssert(0 <= shift_[i] && shift_[i] < mapsize_[i], "Shift in 'j' layer is out of range");
    }
  }
  scale_.assign(numdim_, 1);
  if (mexIsField(mx_layer, "scale")) {
    scale_ = mexGetVector(mexGetField(mx_layer, "scale"));  
    mexAssert(scale_.size() == numdim_, "Length of jitter scale vector and maps dimensionality must coincide");
    for (size_t i = 0; i < numdim_; ++i) {      
      mexAssert(1 <= scale_[i] && scale_[i] < mapsize_[i], "Scale in 'j' layer is out of range");
    }
  }
  mirror_.assign(numdim_, false);
  if (mexIsField(mx_layer, "mirror")) {
    std::vector<ftype> mirror = mexGetVector(mexGetField(mx_layer, "mirror"));  
    mexAssert(mirror.size() == numdim_, "Length of jitter scale vector and maps dimensionality must coincide");
    for (size_t i = 0; i < numdim_; ++i) {      
      mirror_[i] = (mirror[i] > 0);      
    }
  }
  angle_ = 0;
  if (mexIsField(mx_layer, "angle")) {
    angle_ = mexGetScalar(mexGetField(mx_layer, "angle"));    
    mexAssert(0 <= angle_ && angle_ <= 1, "Angle in 'j' layer must be between 0 and 1");    
  }  
  defval_ = 0;
  if (mexIsField(mx_layer, "defval")) {
    defval_ = mexGetScalar(mexGetField(mx_layer, "defval"));    
  } else {  
    // check that the transformed image is always inside the original one
    std::vector<ftype> maxsize(numdim_, 0);    
    for (size_t i = 0; i < numdim_; ++i) {
      maxsize[i] = (ftype) (mapsize_[i] - 1) * scale_[i];      
    }
    if (angle_ > 0) {
      ftype angle_inn = atan2((ftype) mapsize_[0], (ftype) mapsize_[1]) / kPi;    
      ftype maxsin = 1;
      if (angle_inn + angle_ < 0.5) {
        maxsin = sin(kPi * (angle_inn + angle_));        
      }    
      ftype maxcos = 1;
      if (angle_inn > angle_) {
        maxcos = cos(kPi * (angle_inn - angle_));
      }    
      ftype maxrad = sqrt(maxsize[0]*maxsize[0] + maxsize[1]*maxsize[1]);  
      maxsize[0] = maxrad * maxsin;
      maxsize[1] = maxrad * maxcos;    
    }
    std::vector<ftype> oldmapsize(numdim_, 0);
    for (size_t i = 0; i < numdim_; ++i) { 
      oldmapsize[i] = (ftype) prev_layer->mapsize_[i];
    }
    ftype min0 = (oldmapsize[0]/2 - 0.5) - maxsize[0]/2 - shift_[0];
    ftype max0 = (oldmapsize[0]/2 - 0.5) + maxsize[0]/2 + shift_[0];
    ftype min1 = (oldmapsize[1]/2 - 0.5) - maxsize[1]/2 - shift_[1];
    ftype max1 = (oldmapsize[1]/2 - 0.5) + maxsize[1]/2 + shift_[1];
    if (!(0 <= min0 && max0 < oldmapsize[0] && 0 <= min1 && max1 < oldmapsize[1])) {
      mexPrintMsg("min1", min0); mexPrintMsg("max1", max0);
      mexPrintMsg("min2", min1); mexPrintMsg("max2", max1);    
      mexAssert(false, "For these jitter parameters the new image is out of the original image");
    }
  }
} 
コード例 #7
0
ファイル: layer.cpp プロジェクト: chybhao666/ConvNet
void Layer::InitGeneral(const mxArray *mx_layer) {
  type_ = mexGetString(mexGetField(mx_layer, "type"));
  if (mexIsField(mx_layer, "function")) {
    function_ = mexGetString(mexGetField(mx_layer, "function"));
    mexAssertMsg(function_ == "relu" ||
              function_ == "sigm" ||
              function_ == "soft" ||
              function_ == "none",
              "Unknown function code");
  }
  if (mexIsField(mx_layer, "add_bias")) {
    // actual value if defined
    add_bias_ = (mexGetScalar(mexGetField(mx_layer, "add_bias")) > 0);
  }
  if (mexIsField(mx_layer, "mapsize")) {
    std::vector<ftype> mapsize = mexGetVector(mexGetField(mx_layer, "mapsize"));
    mexAssertMsg(mapsize.size() == 2, "Input mapsize length must be 2");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(1 <= mapsize[i] && mapsize[i] < INT_MAX, "Mapsize must be >= 1");
      dims_[i+2] = (int) mapsize[i];
    }
  }
  if (mexIsField(mx_layer, "channels")) {
    ftype channels = mexGetScalar(mexGetField(mx_layer, "channels"));
    mexAssertMsg(1 <= channels && channels < INT_MAX, "Channels num must be >= 1");
    dims_[1] = (int) channels;
    filters_.dims(0) = dims_[1];
    if (add_bias_) { // using actual value here
      biases_.dims() = {1, dims_[1], 1, 1};
    }
  }
  if (mexIsField(mx_layer, "filtersize")) {
    std::vector<ftype> filtersize = mexGetVector(mexGetField(mx_layer, "filtersize"));
    mexAssertMsg(filtersize.size() == 2, "Filtersize must contain 2 values");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(1 <= filtersize[i] && filtersize[i] < INT_MAX, "Filtersize must be >= 1");
      filters_.dims(i+2) = (int) filtersize[i];
    }
  }
  if (mexIsField(mx_layer, "padding")) {
    std::vector<ftype> padding = mexGetVector(mexGetField(mx_layer, "padding"));
    mexAssertMsg(padding.size() == 2, "Padding vector must have 2 values");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(0 <= padding[i] && padding[i] < INT_MAX, "Padding must be non-negative");
      padding_[i] = (int) padding[i];
    }
  }
  if (mexIsField(mx_layer, "stride")) {
    std::vector<ftype> stride = mexGetVector(mexGetField(mx_layer, "stride"));
    mexAssertMsg(stride.size() == 2, "Stride vector has the wrong length");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(1 <= stride[i] && stride[i] < INT_MAX, "Stride must be >= 1");
      stride_[i] = (int) stride[i];
    }
  }
  if (mexIsField(mx_layer, "init_std")) {
    init_std_ = mexGetScalar(mexGetField(mx_layer, "init_std"));
    mexAssertMsg(0 <= init_std_, "init_std must be non-negative");
  }
  if (mexIsField(mx_layer, "bias_coef")) {
    bias_coef_ = mexGetScalar(mexGetField(mx_layer, "bias_coef"));
    mexAssertMsg(0 <= bias_coef_, "bias_coef must be non-negative");
  }
  if (mexIsField(mx_layer, "lr_coef")) {
    lr_coef_ = mexGetScalar(mexGetField(mx_layer, "lr_coef"));
    mexAssertMsg(0 <= lr_coef_, "lr_coef must be non-negative");
  }
  if (mexIsField(mx_layer, "dropout")) {
    dropout_ = mexGetScalar(mexGetField(mx_layer, "dropout"));
    mexAssertMsg(0 <= dropout_ && dropout_ < 1, "dropout must be in the range [0, 1)");
  }
}
コード例 #8
0
ファイル: layer_full.cpp プロジェクト: chybhao666/ConvNet
void LayerFull::Init(const mxArray *mx_layer, const Layer *prev_layer) {
  mexAssertMsg(mexIsField(mx_layer, "channels"), "The 'full' type layer must contain the 'channels' field");
  filters_.dims(1) = prev_layer->length();
}
コード例 #9
0
ファイル: layer_jitt.cpp プロジェクト: chybhao666/ConvNet
void LayerJitt::Init(const mxArray *mx_layer, const Layer *prev_layer) {
  dims_[1] = prev_layer->dims_[1];

  std::vector<ftype> shift(2);
  shift[0] = 0; shift[1] = 0;
  if (mexIsField(mx_layer, "shift")) {
    shift = mexGetVector(mexGetField(mx_layer, "shift"));
    mexAssertMsg(shift.size() == 2, "Length of jitter shift vector and maps dimensionality must coincide");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(0 <= shift[i] && shift[i] < dims_[i+2], "Shift in 'jitt' layer is out of range");
    }
    MatCPU shift_cpu(1, 2);
    shift_cpu.assign(shift);
    shift_ = shift_cpu;
  }

  std::vector<ftype> scale(2);
  scale[0] = 1; scale[1] = 1;
  if (mexIsField(mx_layer, "scale")) {
    scale = mexGetVector(mexGetField(mx_layer, "scale"));
    mexAssertMsg(scale.size() == 2, "Length of jitter scale vector and maps dimensionality must coincide");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(1 <= scale[i] && scale[i] < dims_[i+2], "Scale in 'j' layer is out of range");
    }
    MatCPU scale_cpu(1, 2);
    scale_cpu.assign(scale);
    scale_ = scale_cpu;
    scale_.Log();
  }

  if (mexIsField(mx_layer, "mirror")) {
    std::vector<ftype> mirror = mexGetVector(mexGetField(mx_layer, "mirror"));
    mexAssertMsg(mirror.size() == 2, "Length of jitter scale vector and maps dimensionality must coincide");
    for (size_t i = 0; i < 2; ++i) {
      mexAssertMsg(mirror[i] == 0 || mirror[i] == 1, "Mirror must be either 0 or 1");
    }
    MatCPU mirror_cpu(1, 2);
    mirror_cpu.assign(mirror);
    mirror_ = mirror_cpu;
  }

  if (mexIsField(mx_layer, "angle")) {
    angle_ = mexGetScalar(mexGetField(mx_layer, "angle"));
    mexAssertMsg(0 <= angle_ && angle_ <= 1, "Angle in 'j' layer must be between 0 and 1");
  }

  if (mexIsField(mx_layer, "defval")) {
    defval_ = mexGetScalar(mexGetField(mx_layer, "defval"));
  } else {
    // check that the transformed image is always inside the original one
    std::vector<ftype> maxsize(2, 0);
    for (size_t i = 0; i < 2; ++i) {
      maxsize[i] = (ftype) (dims_[i+2] - 1) * scale[i];
    }
    if (angle_ > 0) {
      ftype angle_inn = atan2((ftype) dims_[2], (ftype) dims_[3]) / kPi;
      ftype maxsin = 1;
      if (angle_inn + angle_ < 0.5) {
        maxsin = sin(kPi * (angle_inn + angle_));
      }
      ftype maxcos = 1;
      if (angle_inn > angle_) {
        maxcos = cos(kPi * (angle_inn - angle_));
      }
      ftype maxrad = (ftype) sqrt((double) (maxsize[0]*maxsize[0] + maxsize[1]*maxsize[1]));
      maxsize[0] = maxrad * maxsin;
      maxsize[1] = maxrad * maxcos;
    }
    std::vector<ftype> oldmapsize(2, 0);
    for (size_t i = 0; i < 2; ++i) {
      oldmapsize[i] = (ftype) prev_layer->dims_[i+2];
    }
    ftype min0 = ((ftype) oldmapsize[0] / 2 - (ftype) 0.5) - (ftype) maxsize[0] / 2 - shift[0];
    ftype max0 = ((ftype) oldmapsize[0] / 2 - (ftype) 0.5) + (ftype) maxsize[0] / 2 + shift[0];
    ftype min1 = ((ftype) oldmapsize[1] / 2 - (ftype) 0.5) - (ftype) maxsize[1] / 2 - shift[1];
    ftype max1 = ((ftype) oldmapsize[1] / 2 - (ftype) 0.5) + (ftype) maxsize[1] / 2 + shift[1];
    if (!(0 <= min0 && max0 < oldmapsize[0] && 0 <= min1 && max1 < oldmapsize[1])) {
      mexPrintMsg("min1", min0); mexPrintMsg("max1", max0);
      mexPrintMsg("min2", min1); mexPrintMsg("max2", max1);
      mexAssertMsg(false, "For these jitter parameters the new image is out of the original image");
    }
  }
  if (mexIsField(mx_layer, "eigenvectors")) {
    const mxArray* mx_ev = mexGetField(mx_layer, "eigenvectors");
    std::vector<size_t> ev_dim = mexGetDimensions(mx_ev);
    mexAssertMsg(ev_dim.size() == 2, "The eigenvectors array must have 2 dimensions");
    mexAssertMsg(ev_dim[0] == dims_[1] && ev_dim[1] == dims_[1],
      "The eigenvector matrix size is wrong");
    MatCPU ev_cpu(dims_[1], dims_[1]);
    mexGetMatrix(mx_ev, ev_cpu);
    eigenvectors_.resize(dims_[1], dims_[1]);
    eigenvectors_ = ev_cpu;
    if (mexIsField(mx_layer, "noise_std")) {
      noise_std_ = mexGetScalar(mexGetField(mx_layer, "noise_std"));
      mexAssertMsg(noise_std_ >= 0, "noise_std must be nonnegative");
    } else {
      mexAssertMsg(false, "noise_std is required with eigenvalues");
    }
  }
  if (mexIsField(mx_layer, "randtest")) {
    randtest_ = (mexGetScalar(mexGetField(mx_layer, "randtest")) > 0);
  }
}