blob: 0499c4be329cb328f9544f9bb3e4d54511b32211 [file] [log] [blame]
/************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef SINGA_NEURALNET_INPUT_LAYER_H_
#define SINGA_NEURALNET_INPUT_LAYER_H_
#include <string>
#include <vector>
#include <thread>
#include "singa/io/store.h"
#include "singa/io/kvfile.h"
#include "singa/neuralnet/layer.h"
namespace singa {
/**
* Base class for loading data from Store.
*/
class StoreInputLayer : virtual public InputLayer {
public:
~StoreInputLayer();
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
protected:
/**
* Helper method for doing the prefetching, basically read (key,value) pairs
* to buf_keys and buf_vals_ vector of size batchsize_.
*/
void fetch_data();
/**
* Parsing the (key, val) tuple to get feature (and label).
* Subclasses must implment this function.
* @param[in] k parse this tuple as the k-th instance of one mini-batch.
* @param[in] flag used to guide the parsing, e.g., kDeploy phase should not
* parse labels from the tuple.
* @param[in] key
* @param[in] val
*/
virtual bool Parse(int k, int flag, const string& key, const string& val) = 0;
protected:
int batchsize_ = 1;
int random_skip_ = 0;
io::Store* store_ = nullptr;
vector<std::string> buf_keys_, buf_vals_;
std::thread *thread_ = nullptr; // prefetching thread
};
/**
* Base layer for parsing a key-value tuple as a feature vector with fixed
* length. The feature shape is indicated by users in the configuration.
* Each tuple may has a label.
*/
class SingleLabelRecordLayer : public StoreInputLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
protected:
/**
* Load a single record (tuple), e.g., the mean or standard variance vector.
*/
virtual void LoadRecord(const string& backend, const string& path,
Blob<float>* to) = 0;
protected:
/**
* Feature standardization by processing each feature dimension via
* @f$ y = (x - mu)/ std @f$
* <a href= "http://ufldl.stanford.edu/wiki/index.php/Data_Preprocessing">
* UFLDL</a>
*/
Blob<float> mean_, std_;
};
/**
* Specific layer that parses the value string loaded by Store as a line from
* a CSV file.
*
* It assumes the first column is the label except that has_label_ is configured
* to false. Or the data is used in deploy mode.
*/
class CSVInputLayer : public SingleLabelRecordLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
protected:
bool Parse(int k, int flag, const string& key, const string& val) override;
void LoadRecord(const string& backend,
const string& path,
Blob<float>* to) override;
private:
std::string sep_;
bool has_label_;
};
/**
* Specific layer that parses the value string loaded by Store into a
* RecordProto.
*/
class RecordInputLayer : public SingleLabelRecordLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
protected:
/**
* Parse key as instance ID and val into RecordProto.
* @copydetails StoreInputLayer::Parse()
*/
bool Parse(int k, int flag, const string& key, const string& val) override;
void LoadRecord(const string& backend,
const string& path,
Blob<float>* to) override;
private:
// TODO(wangwei) decode the image
bool encoded_;
};
/**
* Do preprocessing for images, including cropping, mirroring, resizing.
*/
class ImagePreprocessLayer : public InputLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers);
private:
bool mirror_ = false;
int cropsize_ = 0;
int resize_ = 0;
float scale_ = 1;
};
class OneHotLayer : public InputLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers);
private:
int batchsize_, dim_;
};
/**
* * Read the ASCII file as a large string used for RNN model where each character
* * is a single input to the unrolled RNN layer.
* * max string length is string::max_size();
* */
class CharRNNInputLayer : public InputLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers);
private:
int batchsize_ = 0, unroll_len_ = 1;
unsigned offset_ = 0;
string path_, vocab_path_;
string buf_;
vector<int> start_;
std::unordered_map<char, int> char2index_;
};
/**
* Label layer for fetching labels from the src input layer for RNN models.
* The i-th unrolled layer fetch label from the input layer via data(i+1).
* Particularly, it shares data_ Blob with data(i+1) of its src layer.
*/
class RNNLabelLayer : public InputLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers);
void ComputeFeature(int flag, const vector<Layer*>& srclayers);
};
/****************Deprecated layers******************/
/**
* @deprecated please use the StoreInputLayer.
*
* Base layer for reading ::Record from local Shard, HDFS, lmdb, etc.
*/
class DataLayer: virtual public InputLayer {
public:
Blob<float>* mutable_data(const Layer* layer) override { return nullptr; }
ConnectionType dst_layer_connection() const override {
return kOneToMany;
}
inline int batchsize() const { return batchsize_; }
virtual const Record& sample() const {
return sample_;
}
/**
* @return the loaded records
*/
virtual const std::vector<Record>& records() const {
return records_;
}
protected:
int random_skip_;
int batchsize_;
Record sample_;
std::vector<Record> records_;
};
/**
* @deprecated Please use the subclasses of StoreInputLayer.
*
* Layer for loading Record from DataShard.
*/
class ShardDataLayer : public DataLayer {
public:
~ShardDataLayer();
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
private:
DataShard* shard_;
};
/**
* @deprecated please use the subclasses of StoreInputLayer.
*
* Layer for loading Record from LMDB.
*/
#ifdef USE_LMDB
#include <lmdb.h>
class LMDBDataLayer : public DataLayer {
public:
~LMDBDataLayer();
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void OpenLMDB(const std::string& path);
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ConvertCaffeDatumToRecord(const CaffeDatum& datum,
SingleLabelImageRecord* record);
private:
MDB_env* mdb_env_;
MDB_dbi mdb_dbi_;
MDB_txn* mdb_txn_;
MDB_cursor* mdb_cursor_;
MDB_val mdb_key_, mdb_value_;
};
#endif
/******************Parser layers***************/
/**
* @deprecated Please use the subclasses of StoreInputLayer which load and parse
* data in a single layer.
*
* Base layer for parsing the input records into Blobs.
*/
class ParserLayer : public InputLayer {
public:
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override {}
ConnectionType dst_layer_connection() const override {
return kOneToMany;
}
/**
* Parse records from DataLayer into blob.
*/
virtual void ParseRecords(int flag, const std::vector<Record>& records,
Blob<float>* blob) = 0;
};
/**
*
* @deprecated Please use the SingleLabelRecordLayer which parses both feature
* and label for each record. Its aux_data() function returns the parsed labels.
*
* Derived from ParserLayer to parse label in SingaleLabelImageRecord loaded by
* ShardDataLayer.
*/
class LabelLayer : public ParserLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ParseRecords(int flag, const std::vector<Record>& records,
Blob<float>* blob) override;
};
/**
* @deprecated Please use the subclasses of StoreInputLayer.
*
* Derived from ParserLayer to parse MNIST feature from SingaleLabelImageRecord.
*/
class MnistLayer : public ParserLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ParseRecords(int flag, const std::vector<Record>& records,
Blob<float>* blob) override;
protected:
float norm_a_, norm_b_;
};
/**
* @deprecated please use the ImagePreprocessLayer which preprocess image
* feature from data Blob of source layers.
*
* Derived from ParserLayer to parse RGB image feature from
* SingaleLabelImageRecord.
*/
class RGBImageLayer : public ParserLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ParseRecords(int flag, const std::vector<Record>& records,
Blob<float>* blob) override;
private:
float scale_;
int cropsize_;
bool mirror_;
Blob<float> mean_;
};
} // namespace singa
#endif // SINGA_NEURALNET_INPUT_LAYER_H_