Esempio n. 1
0
void Net::Train(const mxArray *mx_data, const mxArray *mx_labels) {  
  
  //mexPrintMsg("Start training...");  
  ReadData(mx_data);
  ReadLabels(mx_labels);
  InitNorm();
  
  std::srand(params_.seed_);  
  
  size_t train_num = labels_.size1();
  size_t numbatches = (size_t) ceil((ftype) train_num/params_.batchsize_);
  trainerror_.resize(params_.numepochs_, numbatches);
  for (size_t epoch = 0; epoch < params_.numepochs_; ++epoch) {    
    std::vector<size_t> randind(train_num);
    for (size_t i = 0; i < train_num; ++i) {
      randind[i] = i;
    }
    if (params_.shuffle_) {
      std::random_shuffle(randind.begin(), randind.end());
    }
    std::vector<size_t>::const_iterator iter = randind.begin();
    for (size_t batch = 0; batch < numbatches; ++batch) {
      size_t batchsize = std::min(params_.batchsize_, (size_t)(randind.end() - iter));
      std::vector<size_t> batch_ind = std::vector<size_t>(iter, iter + batchsize);
      iter = iter + batchsize;      
      Mat data_batch = SubMat(data_, batch_ind, 1);      
      Mat labels_batch = SubMat(labels_, batch_ind, 1);      
      UpdateWeights(epoch, false);      
      InitActiv(data_batch);
      Mat pred_batch;
      Forward(pred_batch, 1);      
      InitDeriv(labels_batch, trainerror_(epoch, batch));
      Backward();
      CalcWeights();      
      UpdateWeights(epoch, true); 
      if (params_.verbose_ == 2) {
        std::string info = std::string("Epoch: ") + std::to_string(epoch+1) +
                           std::string(", batch: ") + std::to_string(batch+1);
        mexPrintMsg(info);
      }      
    } // batch    
    if (params_.verbose_ == 1) {
      std::string info = std::string("Epoch: ") + std::to_string(epoch+1);
      mexPrintMsg(info);
    }
  } // epoch
  //mexPrintMsg("Training finished");
}
Esempio n. 2
0
void Net::Train(const mxArray *mx_data, const mxArray *mx_labels) {  
  
  //mexPrintMsg("Start training...");
  LayerFull *lastlayer = static_cast<LayerFull*>(layers_.back());
  std::vector<size_t> labels_dim = mexGetDimensions(mx_labels);  
  mexAssert(labels_dim.size() == 2, "The label array must have 2 dimensions");    
  mexAssert(labels_dim[0] == lastlayer->length_,
    "Labels and last layer must have equal number of classes");  
  size_t train_num = labels_dim[1];  
  Mat labels(labels_dim);
  mexGetMatrix(mx_labels, labels);
  classcoefs_.assign(labels_dim[0], 1);
  if (params_.balance_) {  
    Mat labels_mean(labels_dim[0], 1);
    labels.Mean(2, labels_mean);
    for (size_t i = 0; i < labels_dim[0]; ++i) {
      mexAssert(labels_mean(i) > 0, "Balancing impossible: one of the classes is not presented");  
      (classcoefs_[i] /= labels_mean(i)) /= labels_dim[0];      
    }
  }
  if (lastlayer->function_ == "SVM") {
    (labels *= 2) -= 1;    
  }
  
  size_t mapnum = 1;  
  if (mexIsCell(mx_data)) {
    mapnum = mexGetNumel(mx_data);    
  }
  mexAssert(mapnum == layers_.front()->outputmaps_,
    "Data must have the same number of cells as outputmaps on the first layer");
  std::vector< std::vector<Mat> > data(mapnum);  
  for (size_t map = 0; map < mapnum; ++map) {
    const mxArray *mx_cell;  
    if (mexIsCell(mx_data)) {
      mx_cell = mxGetCell(mx_data, map);
    } else {
      mx_cell = mx_data;
    }
    std::vector<size_t> data_dim = mexGetDimensions(mx_cell);  
    mexAssert(data_dim.size() == 3, "The data array must have 3 dimensions");  
    mexAssert(data_dim[0] == layers_.front()->mapsize_[0] && 
              data_dim[1] == layers_.front()->mapsize_[1],
             "Data and the first layer must have equal sizes");    
    mexAssert(data_dim[2] == train_num, "All data maps and labels must have equal number of objects");    
    mexGetMatrix3D(mx_cell, data[map]);
  }
  
      
  
  size_t numbatches = ceil((double) train_num/params_.batchsize_);
  trainerror_.assign(params_.numepochs_ * numbatches, 0);
  for (size_t epoch = 0; epoch < params_.numepochs_; ++epoch) {    
    std::vector<size_t> randind(train_num);
    for (size_t i = 0; i < train_num; ++i) {
      randind[i] = i;
    }
    if (params_.shuffle_) {
      std::random_shuffle(randind.begin(), randind.end());
    }
    std::vector<size_t>::const_iterator iter = randind.begin();
    for (size_t batch = 0; batch < numbatches; ++batch) {
      size_t batchsize = std::min(params_.batchsize_, (size_t)(randind.end() - iter));
      std::vector<size_t> batch_ind = std::vector<size_t>(iter, iter + batchsize);
      iter = iter + batchsize;
      std::vector< std::vector<Mat> > data_batch(mapnum);
      for (size_t map = 0; map < mapnum; ++map) {
        data_batch[map].resize(batchsize);
        for (size_t i = 0; i < batchsize; ++i) {        
          data_batch[map][i] = data[map][batch_ind[i]];
        }
      }      
      Mat labels_batch(labels_dim[0], batchsize);
      Mat pred_batch(labels_dim[0], batchsize);
      labels.SubMat(batch_ind, 2 ,labels_batch);
      UpdateWeights(false);      
      Forward(data_batch, pred_batch, true);
      Backward(labels_batch, trainerror_[epoch * numbatches + batch]);      
      UpdateWeights(true);
      if (params_.verbose_ == 2) {
        std::string info = std::string("Epoch: ") + std::to_string(epoch+1) +
                           std::string(", batch: ") + std::to_string(batch+1);
        mexPrintMsg(info);
      }
    } // batch    
    if (params_.verbose_ == 1) {
      std::string info = std::string("Epoch: ") + std::to_string(epoch+1);                         
      mexPrintMsg(info);
    }
  } // epoch
  //mexPrintMsg("Training finished");
}
void mexFunction(int nLhs, mxArray* pLhs[], int nRhs, const mxArray* pRhs[]) {

  mexAssert(NARGIN_MIN <= nRhs && nRhs <= NARGIN_MAX, "Number of input arguments in wrong!");
  mexAssert(nLhs == NARGOUT, "Number of output arguments is wrong!" );  
  mexAssert(mexIsCell(IN_L), "Layers must be the cell array");
  mexAssert(mexGetNumel(IN_L) == 2, "Layers array must contain 2 cells");
  mexAssert(mexIsCell(IN_W), "Weights must be the cell array");
  mexAssert(mexGetNumel(IN_W) == 2, "Weights array must contain 2 cells");
  
  Net net;
  mxArray *mx_weights;
  net.InitLayers(mexGetCell(IN_L, 1));
  net.InitWeights(mexGetCell(IN_W, 1), mx_weights);  
  net.InitParams(IN_P);
  net.ReadLabels(IN_Y);

  const mxArray *mx_imweights = mexGetCell(IN_W, 0);  
  size_t train_num = net.labels_.size1();
  mexAssert(train_num == mexGetNumel(mx_imweights),
    "Weights and labels number must coincide");
  bool is_multicoords = false;
  if (mexIsCell(IN_X)) {    
    mexAssert(train_num == mexGetNumel(IN_X),
    "Coordinates and labels number must coincide");
    is_multicoords = true;
  }
  Params params_ = net.params_;
  size_t numbatches = (size_t) ceil((ftype) train_num/params_.batchsize_);  
  Mat trainerror_(params_.numepochs_, numbatches);
  Mat trainerror2_(params_.numepochs_, numbatches);
  trainerror2_.assign(0);
  
  std::vector<Net> imnets;
  imnets.resize(params_.batchsize_);
  for (size_t i = 0; i < params_.batchsize_; ++i) {
    imnets[i].InitLayers(mexGetCell(IN_L, 0));        
    if (!is_multicoords) {
      imnets[i].ReadData(IN_X);    
    } else {
      imnets[i].ReadData(mexGetCell(IN_X, i)); // just to get pixels_num
    }
  }
  size_t pixels_num = imnets[0].data_.size1();
  Layer *firstlayer = net.layers_[0];
  size_t dimens_num = firstlayer->outputmaps_;
  mexAssert(imnets[0].layers_.back()->length_ == dimens_num,
            "Final layer length must coincide with the number of outputmaps");   
  mexAssert(pixels_num == firstlayer->mapsize_[0] * firstlayer->mapsize_[1],
            "Pixels number must coincide with the first layer elements number");   
  
  std::vector<size_t> pred_size(2);
  pred_size[0] = 1; pred_size[1] = pixels_num * dimens_num;    
  Mat images_mat, labels_batch, pred_batch, pred_pixels;      
  std::vector< std::vector<Mat> > images, images_der;
  for (size_t epoch = 0; epoch < params_.numepochs_; ++epoch) {    
    std::vector<size_t> randind(train_num);
    for (size_t i = 0; i < train_num; ++i) {
      randind[i] = i;
    }
    if (params_.shuffle_) {
      std::random_shuffle(randind.begin(), randind.end());
    }
    std::vector<size_t>::const_iterator iter = randind.begin();
    for (size_t batch = 0; batch < numbatches; ++batch) {
      size_t batchsize = std::min(params_.batchsize_, (size_t)(randind.end() - iter));
      std::vector<size_t> batch_ind = std::vector<size_t>(iter, iter + batchsize);
      iter = iter + batchsize;      
      labels_batch = SubMat(net.labels_, batch_ind, 1);
      net.UpdateWeights(epoch, false);
      images_mat.resize(batchsize, pred_size[1]);
      InitMaps(images_mat, pred_size, images);        
      // first pass
      for (size_t m = 0; m < batchsize; ++m) {        
        imnets[m].InitWeights(mexGetCell(mx_imweights, batch_ind[m]));
        if (is_multicoords) {
          imnets[m].ReadData(mexGetCell(IN_X, batch_ind[m]));
        }
        imnets[m].InitActiv(imnets[m].data_);                
        imnets[m].Forward(pred_pixels, 1);        
        images[m][0].copy(Trans(pred_pixels).reshape(pred_size[0], pred_size[1]));
      }
      net.InitActiv(images_mat);  
      net.Forward(pred_batch, 1);
      /*
      for (int i = 0; i < 5; ++i) {
        mexPrintMsg("pred_batch1", pred_batch(0, i)); 
      }*/
      // second pass
      net.InitDeriv(labels_batch, trainerror_(epoch, batch));
      net.Backward();
      net.CalcWeights();
      InitMaps(firstlayer->deriv_mat_, pred_size, images_der);
      
      for (size_t m = 0; m < batchsize; ++m) {
        imnets[m].layers_.back()->deriv_mat_ = Trans(images_der[m][0].reshape(dimens_num, pixels_num));        
        imnets[m].Backward();        
      }
      
      // third pass      
      ftype loss2 = 0, curloss = 0, invind = 0; 
      std::vector<size_t> invalid;
      for (size_t m = 0; m < batchsize; ++m) {        
        imnets[m].InitDeriv2(curloss);
        if (curloss > 0) {
          imnets[m].Forward(pred_pixels, 3);        
          images[m][0].copy(Trans(pred_pixels).reshape(pred_size[0], pred_size[1]));        
          loss2 += curloss;
        } else {
          invalid.push_back(m);          
        }
      }
      if (invalid.size() < batchsize) {
        loss2 /= (batchsize - invalid.size());
        trainerror2_(epoch, batch) = loss2;
        net.InitActiv(images_mat);  
        net.Forward(pred_batch, 3);
      }        
      net.CalcWeights2(invalid);      
      // weights update      
      net.UpdateWeights(epoch, true);      
      if (params_.verbose_ == 2) {
        std::string info = std::string("Epoch: ") + std::to_string(epoch+1) +
                           std::string(", batch: ") + std::to_string(batch+1);
        mexPrintMsg(info);
      }      
    } // batch    
    if (params_.verbose_ == 1) {
      std::string info = std::string("Epoch: ") + std::to_string(epoch+1);
      mexPrintMsg(info);
    }
  } // epoch
  //mexPrintMsg("Training finished");
  
  //net.weights_.get().copy(net.weights_.der());
    
  OUT_W = mexSetCellMat(1, 2);  
  mexSetCell(OUT_W, 0, mexDuplicateArray(mx_imweights));
  mexSetCell(OUT_W, 1, mx_weights);
  
  OUT_E = mexSetCellMat(1, 2);  
  mexSetCell(OUT_E, 0, mexSetMatrix(trainerror_));  
  mexSetCell(OUT_E, 1, mexSetMatrix(trainerror2_));
}
Esempio n. 4
0
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");
    }
  }
} 
Esempio n. 5
0
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);
  }
}