#include "gpu/intel/conv/jit/v2/planner/model_fit.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
namespace conv {
namespace jit {
namespace v2 {
namespace planner {
namespace {
float r2_score(
model_kind_t kind, const vec2d &X, const vec1d &y, const vec1d &coef) {
std::vector<float> y_true, y_pred;
for (size_t i = 0; i < X.size(); i++) {
y_true.push_back(y[i]);
y_pred.push_back(model_t::predict(kind, X[i], coef));
}
float u = 0;
float v = 0;
float y_mean = 0;
int n = (int)y_true.size();
for (int i = 0; i < n; i++)
y_mean += y_true[i];
y_mean /= n;
for (int i = 0; i < n; i++) {
u += (y_true[i] - y_pred[i]) * (y_true[i] - y_pred[i]);
v += (y_true[i] - y_mean) * (y_true[i] - y_mean);
}
return 1 - u / v;
}
struct model_params_t {
struct param_t {
std::string name;
float val = 0;
float lo = 0;
float hi = 0;
float step = 0;
param_t(const std::string &name, float val, float lo, float hi)
: name(name), val(val), lo(lo), hi(hi), step((hi - lo) / 5) {}
void set(float v) { val = std::min(hi, std::max(lo, v)); }
float operator()() const { return val; }
};
model_params_t() = default;
model_params_t(model_kind_t kind) : kind(kind) {}
void add(const std::string &name, float val, float lo, float hi) {
vec.emplace_back(name, val, lo, hi);
}
param_t &operator[](int idx) { return vec[idx]; }
const param_t &operator[](int idx) const { return vec[idx]; }
int size() const { return (int)vec.size(); }
std::string str() const {
ostringstream_t oss;
bool is_first = true;
oss << "(";
for (auto &p : vec) {
if (!is_first) oss << ", ";
oss << p.val;
is_first = false;
}
oss << ")";
return oss.str();
}
model_kind_t kind = model_kind_t::undef;
std::vector<param_t> vec;
};
float r2_score(const vec2d &X, const vec1d &y, const model_params_t ¶ms) {
vec1d coef;
for (int i = 0; i < params.size(); i++)
coef.push_back(params[i].val);
return r2_score(params.kind, X, y, coef);
}
void find_optimal_param(
model_params_t ¶ms, int idx, const vec2d &X, const vec1d &y) {
auto &p = params[idx];
float step = p.step;
for (int iter = 0; iter < 10; iter++) {
float p_val = p.val;
float p_val_best = p_val;
float r2_best = r2_score(X, y, params);
for (int sign : {-1, 1}) {
p.set(p_val + sign * step);
float r2 = r2_score(X, y, params);
if (r2 > r2_best) {
p_val_best = p.val;
r2_best = r2;
}
}
p.val = p_val_best;
step /= 2;
}
p.step /= 2;
}
}
model_t model_fit(
model_params_t ¶ms, const vec2d &X, const vec1d &y, bool verbose) {
int nparams = params.size();
int niters = 10 * nparams;
for (int i = 0; i < niters; i++) {
find_optimal_param(params, i % nparams, X, y);
}
if (verbose) {
std::cout << "R2: " << r2_score(X, y, params) << " (cases: " << X.size()
<< ") model params = " << params.str() << std::endl;
}
vec1d coef;
for (int i = 0; i < params.size(); i++)
coef.push_back(params[i].val);
return model_t(params.kind, coef);
}
model_t model_fit(model_kind_t kind, const vec2d &X, const vec1d &y,
bool verbose = false) {
model_params_t params(kind);
std::vector<std::string> param_names;
std::vector<float> param_values;
std::vector<float> param_min;
std::vector<float> param_max;
model_t::coef_ranges(
kind, X, y, param_names, param_values, param_min, param_max);
for (size_t i = 0; i < param_names.size(); i++) {
params.add(param_names[i], param_values[i], param_min[i], param_max[i]);
}
return model_fit(params, X, y, verbose);
}
model_t model_fit(model_kind_t kind, const bench_data_t &bd) {
vec2d X;
vec1d y;
to_model_data(kind, bd, X, y);
auto model = model_fit(kind, X, y);
vec2d X_adjusted;
vec1d y_adjusted;
for (size_t i = 0; i < X.size(); i++) {
float pred = model.predict(X[i]);
if ((pred - y[i]) > 0.25 * y[i]) continue;
X_adjusted.push_back(X[i]);
y_adjusted.push_back(y[i]);
}
model = model_fit(kind, X_adjusted, y_adjusted, true);
dump_csv(bd, model);
dump_model_params(bd.kernel_desc, model);
return model;
}
void model_fit(const bench_data_t &bd, model_set_t &model_set) {
if (!bd) {
std::cout << "Warning: empty bench_data." << std::endl;
return;
}
if (bd.kernel_desc.use_stream_k) {
auto model = model_fit(model_kind_t::stream_k, bd);
model_set.add(model);
} else {
auto model = model_fit(model_kind_t::data_parallel, bd);
model_set.add(model);
}
}
} } } } } } } }