
sum 을 할 경우 clip 혹은 max 등 넘칠 경우에 문제가 발생할 수 있다고 생각했다.
inf 를 만나서 훈련 중 끊어지는 상황을 본 적이 있다.다시 생각해보면, nn.Conv2d 를 사용할 경우, torch framework 안에서 놀기 때문에 문제는 없다.
self.conv = nn.Conv2d(c1, 1, 1, bias=False).requires_grad_(False)
이와 같이 requires_grad 로 backprop 시에 gradient 를 하지 않아서 문제는 없다.
허나, 저 당시 좀 더 다루지 못했던 부분을 다루어볼 생각이다.
inf앞에서 체크된 range 를 다시 보자.
>>> torch.log(torch.tensor([1e-45]))
tensor([-103.2789])
>>> torch.log(torch.tensor([1e-46]))
tensor([-inf])
실제 activation 때 이렇게 되었는데,
>>> torch.tensor([1e-200])
tensor([0.])

하지만 를 에 가까워지면-inf 가 나오는건 당연하지만..
numeric limits 정의 참고. (cpp-reference)
float max_value = std::numeric_limits<float>::max();
std::cout << "max_value: " << max_value << std::endl;
float max_value_2nd = 3.40283e+38;
std::cout << "max_value_2nd: " << max_value_2nd << std::endl;
float min_value = std::numeric_limits<float>::min();
std::cout << "min_value: " << min_value << std::endl;
float min_value_2nd = 1.17548e-38;
std::cout << "min_value_2nd: " << min_value_2nd << std::endl;
float lowest_value = std::numeric_limits<float>::lowest();
std::cout << "lowest_value: " << lowest_value << std::endl;
result
max_value: 3.40282e+38
max_value_2nd: inf
min_value: 1.17549e-38
min_value_2nd: 1.17548e-38
lowest_value: -3.40282e+38
min() 는 생각해보면 0 에 가까워질 뿐, positive value 로 아주 작게 가능하다.
실제 모든 numeric 에 관해서 이런 limitation 이 존재한다.
/usr/include/limits.h 참고
// ...
/* Minimum and maximum values a `signed short int' can hold. */
# define SHRT_MIN (-32768)
# define SHRT_MAX 32767
/* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */
# define USHRT_MAX 65535
/* Minimum and maximum values a `signed int' can hold. */
# define INT_MIN (-INT_MAX - 1)
# define INT_MAX 2147483647
/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
# define UINT_MAX 4294967295U
/* Minimum and maximum values a `signed long int' can hold. */
# if __WORDSIZE == 64
# define LONG_MAX 9223372036854775807L
# else
# define LONG_MAX 2147483647L
# endif
# define LONG_MIN (-LONG_MAX - 1L)
// ...
그럼 의문이 드는 것은 set 의 정의가 으로 0 의 boundary 가 열린 집합일 때, 어디까지 가능할까? 가 의문이 든다.
max_value: 3.40282e+38
min_value: 1.17549e-38
로 되어 있지만 min_value 는 더 내려갈 수 있다. 0 에 더 가까워 질 수 있다는 말이 맞다.
>>> torch.log(torch.tensor([1e-45]))
tensor([-103.2789])
>>> torch.log(torch.tensor([1e-46]))
tensor([-inf])
>>> torch.tensor(1e-45)
tensor(1.4013e-45)
>>> torch.tensor(1e-46)
tensor(0.)
비교 값 코드
// compare_f1
float compare_f1 = 1e-45;
std::cout << "compare_f1: " << compare_f1 << std::endl;
// compare_f2
float compare_f2 = 1e-46;
std::cout << "compare_f2: " << compare_f2 << std::endl;
// compare_d1
double compare_d1 = 1e-45;
std::cout << "compare_d1: " << compare_d1 << std::endl;
// compare_d1 :
double compare_d2 = 1e-46;
std::cout << "compare_d2: " << compare_d2 << std::endl;
compare_f1: 1.4013e-45
compare_f2: 0
compare_d1: 1e-45
compare_d2: 1e-46
// STL/stl/inc/limits
static constexpr int digits = FLT_MANT_DIG;
static constexpr int digits10 = FLT_DIG;
static constexpr int max_digits10 = 9;
static constexpr int max_exponent = FLT_MAX_EXP;
static constexpr int max_exponent10 = FLT_MAX_10_EXP; // 38
static constexpr int min_exponent = FLT_MIN_EXP;
static constexpr int min_exponent10 = FLT_MIN_10_EXP; // -37
max_value: 3.40282e+38
min_value: 1.17549e-38
로도 확인 할 수 있다.
torch framework 에서 사용할 경우, torch 안의 함수를 사용하여 quantized (clip, clamp) 을 적용하게 받거나, 실제 만들어서 적용하려면 이와 같은 numeric limitation 을 신경 써서 작업해야 문제가 없다.
현재는 GPU 가 중심이고, 미분 계산기에 의존 하지만, 이런 체계들이 근본이다.