dataset.cpp 4.68 KB
Newer Older
Guolin Ke's avatar
Guolin Ke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <LightGBM/dataset.h>

#include <LightGBM/feature.h>
#include <LightGBM/network.h>

#include <omp.h>

#include <cstdio>
#include <unordered_map>
#include <limits>
#include <vector>
#include <utility>
#include <string>
Guolin Ke's avatar
Guolin Ke committed
14
#include <sstream>
Guolin Ke's avatar
Guolin Ke committed
15
16
17
18

namespace LightGBM {


Guolin Ke's avatar
Guolin Ke committed
19
20
21
22
Dataset::Dataset() {
  num_class_ = 1;
  num_data_ = 0;
  is_loading_from_binfile_ = false;
Guolin Ke's avatar
Guolin Ke committed
23
24
25
26
27
28
29
30
31
32
}

Dataset::~Dataset() {
  for (auto& feature : features_) {
    delete feature;
  }
  features_.clear();
}


Guolin Ke's avatar
Guolin Ke committed
33
34
35
36
37
38
void Dataset::CopyFeatureMetadataTo(Dataset *dataset, bool is_enable_sparse) const {
  dataset->features_.clear();
  // copy feature bin mapper data
  for (Feature* feature : features_) {
    dataset->features_.push_back(new Feature(feature->feature_index(),
      new BinMapper(*feature->bin_mapper()), dataset->num_data_, is_enable_sparse));
Guolin Ke's avatar
Guolin Ke committed
39
  }
Guolin Ke's avatar
Guolin Ke committed
40
41
42
43
  dataset->used_feature_map_ = used_feature_map_;
  dataset->num_features_ = static_cast<int>(dataset->features_.size());
  dataset->num_total_features_ = num_total_features_;
  dataset->feature_names_ = feature_names_;
Guolin Ke's avatar
Guolin Ke committed
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
}

std::vector<const BinMapper*> Dataset::GetBinMappers() const {
  std::vector<const BinMapper*> ret(num_total_features_, nullptr);
  for (const auto feature : features_) {
    ret[feature->feature_index()] = feature->bin_mapper();
  }
  return ret;
}

void Dataset::SetField(const char* field_name, const void* field_data, data_size_t num_element, int type) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    if (type != 0) {
      Log::Fatal("type of label should be float");
    }
    metadata_.SetLabel(static_cast<const float*>(field_data), num_element);
Guolin Ke's avatar
Guolin Ke committed
62
  } else if (name == std::string("weight") || name == std::string("weights")) {
Guolin Ke's avatar
Guolin Ke committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    if (type != 0) {
      Log::Fatal("type of weights should be float");
    }
    metadata_.SetWeights(static_cast<const float*>(field_data), num_element);
  } else if (name == std::string("init_score")) {
    if (type != 0) {
      Log::Fatal("type of init_score should be float");
    }
    metadata_.SetInitScore(static_cast<const float*>(field_data), num_element);
  } else if (name == std::string("query") || name == std::string("group")) {
    if (type != 1) {
      Log::Fatal("type of init_score should be int");
    }
    metadata_.SetQueryBoundaries(static_cast<const data_size_t*>(field_data), num_element);
  } else {
    Log::Fatal("unknow field name: %s", field_name);
  }
}

Guolin Ke's avatar
Guolin Ke committed
82
void Dataset::SaveBinaryFile(const char* bin_filename) {
Guolin Ke's avatar
Guolin Ke committed
83

Guolin Ke's avatar
Guolin Ke committed
84
  if (!is_loading_from_binfile_) {
Guolin Ke's avatar
Guolin Ke committed
85
86
87
88
89
90
    // if not pass a filename, just append ".bin" of original file
    if (bin_filename == nullptr || bin_filename[0] == '\0') {
      std::string bin_filename_str(data_filename_);
      bin_filename_str.append(".bin");
      bin_filename = bin_filename_str.c_str();
    }
Guolin Ke's avatar
Guolin Ke committed
91
    FILE* file;
Guolin Ke's avatar
Guolin Ke committed
92
#ifdef _MSC_VER
Guolin Ke's avatar
Guolin Ke committed
93
    fopen_s(&file, bin_filename, "wb");
Guolin Ke's avatar
Guolin Ke committed
94
#else
Guolin Ke's avatar
Guolin Ke committed
95
    file = fopen(bin_filename, "wb");
Guolin Ke's avatar
Guolin Ke committed
96
#endif
Guolin Ke's avatar
Guolin Ke committed
97
    if (file == NULL) {
Guolin Ke's avatar
Guolin Ke committed
98
      Log::Fatal("Cannot write binary data to %s ", bin_filename);
Guolin Ke's avatar
Guolin Ke committed
99
100
    }

101
    Log::Info("Saving data to binary file %s", data_filename_);
Guolin Ke's avatar
Guolin Ke committed
102
103

    // get size of header
Guolin Ke's avatar
Guolin Ke committed
104
105
    size_t size_of_header = sizeof(num_data_) + sizeof(num_features_) + sizeof(num_total_features_) 
      + sizeof(size_t) + sizeof(int) * used_feature_map_.size();
106
107
108
109
    // size of feature names
    for (int i = 0; i < num_total_features_; ++i) {
      size_of_header += feature_names_[i].size() + sizeof(int);
    }
Guolin Ke's avatar
Guolin Ke committed
110
111
112
113
    fwrite(&size_of_header, sizeof(size_of_header), 1, file);
    // write header
    fwrite(&num_data_, sizeof(num_data_), 1, file);
    fwrite(&num_features_, sizeof(num_features_), 1, file);
114
    fwrite(&num_total_features_, sizeof(num_features_), 1, file);
Guolin Ke's avatar
Guolin Ke committed
115
116
117
118
    size_t num_used_feature_map = used_feature_map_.size();
    fwrite(&num_used_feature_map, sizeof(num_used_feature_map), 1, file);
    fwrite(used_feature_map_.data(), sizeof(int), num_used_feature_map, file);

119
120
121
122
123
124
125
126
    // write feature names
    for (int i = 0; i < num_total_features_; ++i) {
      int str_len = static_cast<int>(feature_names_[i].size());
      fwrite(&str_len, sizeof(int), 1, file);
      const char* c_str = feature_names_[i].c_str();
      fwrite(c_str, sizeof(char), str_len, file);
    }

Guolin Ke's avatar
Guolin Ke committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    // get size of meta data
    size_t size_of_metadata = metadata_.SizesInByte();
    fwrite(&size_of_metadata, sizeof(size_of_metadata), 1, file);
    // write meta data
    metadata_.SaveBinaryToFile(file);

    // write feature data
    for (int i = 0; i < num_features_; ++i) {
      // get size of feature
      size_t size_of_feature = features_[i]->SizesInByte();
      fwrite(&size_of_feature, sizeof(size_of_feature), 1, file);
      // write feature
      features_[i]->SaveBinaryToFile(file);
    }
    fclose(file);
  }
}

}  // namespace LightGBM