Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * Copyright (C) 2021 Parichay Kapoor <pk.kapoor@samsung.com>
4 : *
5 : * @file lr_scheduler_step.cpp
6 : * @date 09 December 2021
7 : * @brief This is Step Learning Rate Scheduler class
8 : * @see https://github.com/nnstreamer/nntrainer
9 : * @author Parichay Kapoor <pk.kapoor@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : *
12 : * @details given the iteration range [it_0, it_1, ... it_n], learning rates
13 : * [lr_0, lr_1 ... lr_n_1], and iteration iter, find index i such that
14 : * it_i_1 < iter <= it_i and return lr_i_1.
15 : */
16 :
17 : #include <cmath>
18 :
19 : #include <common_properties.h>
20 : #include <lr_scheduler_step.h>
21 : #include <nntrainer_error.h>
22 : #include <nntrainer_log.h>
23 : #include <node_exporter.h>
24 :
25 : namespace nntrainer {
26 :
27 16 : StepLearningRateScheduler::StepLearningRateScheduler() : lr_props({}, {}) {}
28 :
29 11 : void StepLearningRateScheduler::finalize() {
30 13 : NNTR_THROW_IF(std::get<std::vector<props::LearningRate>>(lr_props).empty(),
31 : std::invalid_argument)
32 : << "[StepLearningRateScheduler] Learning rates are not set";
33 11 : NNTR_THROW_IF(std::get<std::vector<props::Iteration>>(lr_props).empty(),
34 : std::invalid_argument)
35 : << "[StepLearningRateScheduler] Step iterations are not set";
36 :
37 : auto const &[learning_rates, iterations] = lr_props;
38 7 : if (learning_rates.size() != iterations.size() + 1)
39 : throw std::invalid_argument("[StepLearningRateScheduler] learning rates "
40 2 : "and step iterations count mismatch");
41 :
42 : /**
43 : * provided step iterations must contain monotonically increasing values,
44 : * and all values must be unique
45 : */
46 5 : std::vector<unsigned int> sorted_iterations(iterations.size());
47 : std::transform(iterations.begin(), iterations.end(),
48 : sorted_iterations.begin(),
49 11 : [](auto const &val) { return val.get(); });
50 5 : std::sort(sorted_iterations.begin(), sorted_iterations.end());
51 5 : auto iter = std::unique(sorted_iterations.begin(), sorted_iterations.end());
52 6 : NNTR_THROW_IF(iter != sorted_iterations.end(), std::invalid_argument)
53 : << "[StepLearningRateScheduler] step iterations should contain unique "
54 : "values";
55 11 : for (unsigned int idx = 0; idx < sorted_iterations.size(); idx++)
56 9 : NNTR_THROW_IF(iterations[idx].get() != sorted_iterations[idx],
57 : std::invalid_argument)
58 : << "[StepLearningRateScheduler] step iterations should be in "
59 : "monotonically increasing order";
60 5 : }
61 :
62 37 : void StepLearningRateScheduler::setProperty(
63 : const std::vector<std::string> &values) {
64 37 : auto left = loadProperties(values, lr_props);
65 39 : NNTR_THROW_IF(left.size(), std::invalid_argument)
66 : << "[StepLearningRateScheduler] There are unparsed properties";
67 36 : }
68 :
69 0 : void StepLearningRateScheduler::exportTo(
70 : Exporter &exporter, const ml::train::ExportMethods &method) const {
71 0 : exporter.saveResult(lr_props, method, this);
72 0 : }
73 :
74 106 : double StepLearningRateScheduler::getLearningRate(size_t iteration) {
75 : auto const &[learning_rates, iterations] = lr_props;
76 : auto upper =
77 106 : std::lower_bound(iterations.begin(), iterations.end(), iteration);
78 106 : if (upper != iterations.end())
79 102 : return learning_rates[upper - iterations.begin()];
80 : else
81 4 : return learning_rates.back().get();
82 : }
83 :
84 : } // namespace nntrainer
|