核心代码
dmlc/data.h
RowBlock
:把样本矩阵X转换成一维向量存储。可以结合spmv.h中的矩阵乘法理解。
此外,offset
起始可以不为0,这样可以把输入的样本切割为很多个RowBlock
。
template<typename IndexType>
struct RowBlock {
/*! \brief batch size */
size_t size; // 样本数量
/*! \brief array[size+1], row pointer to beginning of each rows */
const size_t *offset; // 每个样本的偏移位置,搭配index和label使用
/*! \brief array[size] label of each instance */
const real_t *label; // 样本label
/*! \brief With weight: array[size] label of each instance, otherwise nullptr */
const real_t *weight; // 该样本自身权重,一般不设置(adaboost有用?)
/*! \brief feature index */
const IndexType *index; // 样本的特征id,是一种稀疏化表示
/*! \brief feature value, can be NULL, indicating all values are 1 */
const real_t *value; // 样本各特征的值,NULL则均为1,比如one-hot之后
// ....
}
示例:
size = 2
该RowBlock包含两个样本,样本类型是Row<IndexType>
offset = 4, 7, 8
第一个样本3个特征,第二个样本1个特征,且offset起始为4,说明这不是第一个RowBlocklabel = 1, 0
第一个样本label:1,第二个样本label:0index = 0, 1, 3, 1
第一个样本包含特征id:0、1、3,第二个样本包含特征id:1value = 1, 0, 0, 1
第一个样本对应特征值:1、0、0,第二个样本对应特征值:1
src/data/row_block.h
RowBlockContainer
搭配RowBlock
使用,是实际保存数据的结构。
RowBlock
里只是一些指针,指向RowBlockContainer
的动态内存。
两个Push()
函数,用于填充Row
和RowBlock
。
同时实现了Load()
和Save()
用于序列化。
dmlc/io.h
InputSplit
基类,从各种dataset读取记录。
SingleFileSplit
stdinLineSplitter
text类型,逐行读取RecordIOSplitter
recordio类型ThreadedInputSplit
使用c++11编译,支持thread预读取CachedInputSplit
uri里带 # 指定cache文件
Create()
工厂方法,根据uri、part index、文件类型(text或者recordio)创建InputSplit
实例。
参考
- https://github.com/dmlc/dmlc-core