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

#include <LightGBM/feature.h>

#include <omp.h>

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

namespace LightGBM {


Guolin Ke's avatar
Guolin Ke committed
18
19
20
21
Dataset::Dataset() {
  num_class_ = 1;
  num_data_ = 0;
  is_loading_from_binfile_ = false;
Guolin Ke's avatar
Guolin Ke committed
22
23
}

24
25
Dataset::Dataset(data_size_t num_data, int num_class) {
  num_class_ = num_class;
Guolin Ke's avatar
Guolin Ke committed
26
27
  num_data_ = num_data;
  is_loading_from_binfile_ = false;
28
  metadata_.Init(num_data_, num_class_, -1, -1);
Guolin Ke's avatar
Guolin Ke committed
29
30
}

Guolin Ke's avatar
Guolin Ke committed
31
Dataset::~Dataset() {
Guolin Ke's avatar
Guolin Ke committed
32

Guolin Ke's avatar
Guolin Ke committed
33
34
}

Guolin Ke's avatar
Guolin Ke committed
35
36
37
38
39
40
void Dataset::FinishLoad() {
#pragma omp parallel for schedule(guided)
  for (int i = 0; i < num_features_; ++i) {
    features_[i]->FinishLoad();
  }
}
Guolin Ke's avatar
Guolin Ke committed
41

Guolin Ke's avatar
Guolin Ke committed
42
43
void Dataset::CopyFeatureMapperFrom(const Dataset* dataset, bool is_enable_sparse) {
  features_.clear();
Guolin Ke's avatar
Guolin Ke committed
44
  // copy feature bin mapper data
Guolin Ke's avatar
Guolin Ke committed
45
46
47
48
49
50
51
  for (const auto& feature : dataset->features_) {
    features_.emplace_back(std::unique_ptr<Feature>(
      new Feature(feature->feature_index(), 
        new BinMapper(*feature->bin_mapper()), 
        num_data_, 
        is_enable_sparse)
      ));
Guolin Ke's avatar
Guolin Ke committed
52
  }
Guolin Ke's avatar
Guolin Ke committed
53
  features_.shrink_to_fit();
Guolin Ke's avatar
Guolin Ke committed
54
55
56
57
58
  num_class_ = dataset->num_class_;
  used_feature_map_ = dataset->used_feature_map_;
  num_features_ = static_cast<int>(features_.size());
  num_total_features_ = dataset->num_total_features_;
  feature_names_ = dataset->feature_names_;
Guolin Ke's avatar
Guolin Ke committed
59
60
}

61
bool Dataset::SetFloatField(const char* field_name, const float* field_data, data_size_t num_element) {
Guolin Ke's avatar
Guolin Ke committed
62
63
64
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
65
    metadata_.SetLabel(field_data, num_element);
Guolin Ke's avatar
Guolin Ke committed
66
  } else if (name == std::string("weight") || name == std::string("weights")) {
67
    metadata_.SetWeights(field_data, num_element);
Guolin Ke's avatar
Guolin Ke committed
68
  } else if (name == std::string("init_score")) {
69
    metadata_.SetInitScore(field_data, num_element);
Guolin Ke's avatar
Guolin Ke committed
70
  } else {
71
    return false;
Guolin Ke's avatar
Guolin Ke committed
72
  }
73
  return true;
Guolin Ke's avatar
Guolin Ke committed
74
75
}

76
77
78
79
80
81
82
83
84
85
86
87
bool Dataset::SetIntField(const char* field_name, const int* field_data, data_size_t num_element) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
    metadata_.SetQueryBoundaries(field_data, num_element);
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetFloatField(const char* field_name, int64_t* out_len, const float** out_ptr) {
88
89
90
91
92
93
94
95
96
97
98
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    *out_ptr = metadata_.label();
    *out_len = num_data_;
  } else if (name == std::string("weight") || name == std::string("weights")) {
    *out_ptr = metadata_.weights();
    *out_len = num_data_;
  } else if (name == std::string("init_score")) {
    *out_ptr = metadata_.init_score();
    *out_len = num_data_;
99
100
101
102
103
104
105
106
107
108
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetIntField(const char* field_name, int64_t* out_len, const int** out_ptr) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
109
110
111
    *out_ptr = metadata_.query_boundaries();
    *out_len = num_data_;
  } else {
112
    return false;
113
  }
114
  return true;
115
116
}

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

Guolin Ke's avatar
Guolin Ke committed
119
  if (!is_loading_from_binfile_) {
120
    std::string bin_filename_str(data_filename_);
Guolin Ke's avatar
Guolin Ke committed
121
122
123
124
125
    // if not pass a filename, just append ".bin" of original file
    if (bin_filename == nullptr || bin_filename[0] == '\0') {
      bin_filename_str.append(".bin");
      bin_filename = bin_filename_str.c_str();
    }
Guolin Ke's avatar
Guolin Ke committed
126
    FILE* file;
Guolin Ke's avatar
Guolin Ke committed
127
#ifdef _MSC_VER
Guolin Ke's avatar
Guolin Ke committed
128
    fopen_s(&file, bin_filename, "wb");
Guolin Ke's avatar
Guolin Ke committed
129
#else
Guolin Ke's avatar
Guolin Ke committed
130
    file = fopen(bin_filename, "wb");
Guolin Ke's avatar
Guolin Ke committed
131
#endif
Guolin Ke's avatar
Guolin Ke committed
132
    if (file == NULL) {
Guolin Ke's avatar
Guolin Ke committed
133
      Log::Fatal("Cannot write binary data to %s ", bin_filename);
Guolin Ke's avatar
Guolin Ke committed
134
    }
135
    Log::Info("Saving data to binary file %s", bin_filename);
Guolin Ke's avatar
Guolin Ke committed
136
137

    // get size of header
Guolin Ke's avatar
Guolin Ke committed
138
    size_t size_of_header = sizeof(num_data_) + sizeof(num_class_) + sizeof(num_features_) + sizeof(num_total_features_) 
Guolin Ke's avatar
Guolin Ke committed
139
      + sizeof(size_t) + sizeof(int) * used_feature_map_.size();
140
141
142
143
    // 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
144
145
146
    fwrite(&size_of_header, sizeof(size_of_header), 1, file);
    // write header
    fwrite(&num_data_, sizeof(num_data_), 1, file);
Guolin Ke's avatar
Guolin Ke committed
147
    fwrite(&num_class_, sizeof(num_class_), 1, file);
Guolin Ke's avatar
Guolin Ke committed
148
    fwrite(&num_features_, sizeof(num_features_), 1, file);
149
    fwrite(&num_total_features_, sizeof(num_features_), 1, file);
Guolin Ke's avatar
Guolin Ke committed
150
151
152
153
    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);

154
155
156
157
158
159
160
161
    // 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    // 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