-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define constants with specific type #3189
Comments
The code is class Kernel {
constexpr T LOG_THRESHOLD() const { return static_cast<T>(1e-20); }
void compute() {
for (int i = 0; i < batch_size; ++i) {
Y_data[i] = -std::log(
std::max(X_data[i * class_num + label_data[i]], LOG_THRESHOLD()));
}
}
}
3, In our case ,T may be float, float16 and float32, and will not be int because crossentropy is the next layer of softmax, and the output of softmax is probability of each label, it should be floatxx. 4, According to google code style of const name, I will rename it to |
@jacquesqiao Thanks for the plot and detailed explanation! It looks to me it is like you are doing log to a small value. I cannot see the full context, but it sounds like the log-sum-exp trick might help: https://www.xarg.org/2016/06/the-log-sum-exp-trick-in-machine-learning/. Hopefully, we can reformulate the problem using this trick so that we don't take log to a small value at all. Even if the trick doesn't help and we'd just have to compute log to a small value, a template function might not be what we want, because the small-enough-value differs with types -- double and float. Please see the following code snippet: #include <iostream>
#include <cmath>
int main()
{
const double kSmall = 1e-60;
std::cout << "log(kSmall) = " << std::log(kSmall) << "\n";
const float kSmallFloat = 1e-60;
std::cout << "log(kSmallFloat) = " << std::log(kSmallFloat) << "\n";
} It runs and prints
It looks to me that we can check-and-change the result value from log instead of the input. This would save us from defining a global const value: #include <iostream>
#include <cmath>
#include <type_traits>
template <typename T>
T tolerable_log(T x) {
static_assert(std::is_floating_point<T>::value,
"tolerable_log works only on float, double and double double.");
T ret = std::log(x);
if (ret == - INFINITY) {
const T kApproxNegativeInf = -300;
return kApproxNegativeInf;
}
return ret;
}
int main()
{
const double kSmall = 1e-60;
std::cout << "log(kSmall) = " << std::log(kSmall) << "\n";
const float kSmallFloat = 1e-60;
std::cout << "log(kSmall) = " << std::log(kSmallFloat) << "\n";
std::cout << tolerable_log(kSmall) << "\n";
std::cout << tolerable_log(kSmallFloat) << "\n";
} Please be aware that the const value The outputs shows that
|
the purpose of check is to handle INFINITY, and there are another situation like: T a = x/y; // y is very small so I check the ret value and return a tolerable one with tolerable_value |
As stated in #3186 (review), we have code snippets like
The snippet has two problems -- 1. the naming violates code style, 2. a constant should be define with specific type as it is obvious that 1e-20 cannot be casted into any integral type.
The text was updated successfully, but these errors were encountered: