-
Notifications
You must be signed in to change notification settings - Fork 0
/
risk.py
80 lines (67 loc) · 2.65 KB
/
risk.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import numpy as np
import torch
from utils import ones_like
def normal_cdf(value, loc=0., scale=1.):
return 0.5 * (1 + torch.erf((value - loc) / scale / np.sqrt(2)))
def normal_icdf(value, loc=0., scale=1.):
return loc + scale * torch.erfinv(2 * value - 1) * np.sqrt(2)
def normal_pdf(value, loc=0., scale=1.):
return torch.exp(-(value - loc)**2 / (2 * scale**2)) / scale / np.sqrt(2 * np.pi)
def distortion_fn(tau, mode="neutral", param=0.):
# Risk distortion function
tau = tau.clamp(0., 1.)
if param >= 0:
if mode == "neutral":
tau_ = tau
elif mode == "wang":
tau_ = normal_cdf(normal_icdf(tau) + param)
elif mode == "cvar":
tau_ = (1. / param) * tau
elif mode == "cpw":
tau_ = tau**param / (tau**param + (1. - tau)**param)**(1. / param)
return tau_.clamp(0., 1.)
else:
return 1 - distortion_fn(1 - tau, mode, -param)
def distortion_de(tau, mode="neutral", param=0., eps=1e-8):
# Derivative of Risk distortion function
tau = tau.clamp(0., 1.)
if param >= 0:
if mode == "neutral":
tau_ = ones_like(tau)
elif mode == "wang":
tau_ = normal_pdf(normal_icdf(tau) + param) / \
(normal_pdf(normal_icdf(tau)) + eps)
elif mode == "cvar":
tau_ = (1. / param) * (tau < param)
elif mode == "ncvar":
tau_ = (1. / param) * (tau >= (1 - param))
elif mode == "cpw":
g = tau**param
h = (tau**param + (1 - tau)**param)**(1 / param)
g_ = param * tau**(param - 1)
h_ = (tau**param + (1 - tau)**param)**(1 / param - 1) * \
(tau**(param - 1) - (1 - tau)**(param - 1))
tau_ = (g_ * h - g * h_) / (h**2 + eps)
return tau_.clamp(0., 5.)
else:
return distortion_de(1 - tau, mode, -param)
def muti_distortion_de(tau, mode, param, eps=1e-8):
# Derivative of Risk distortion function
tau = tau.clamp(0., 1.)
if mode == "neutral":
tau_ = ones_like(tau)
elif mode == "wang":
tau_ = normal_pdf(normal_icdf(tau) + param) / \
(normal_pdf(normal_icdf(tau)) + eps)
elif mode == "cvar":
tau_ = (1. / param) * (tau < param)
elif mode == "ncvar":
tau_ = (1. / param) * (tau >= (1 - param))
elif mode == "cpw":
g = tau**param
h = (tau**param + (1 - tau)**param)**(1 / param)
g_ = param * tau**(param - 1)
h_ = (tau**param + (1 - tau)**param)**(1 / param - 1) * \
(tau**(param - 1) - (1 - tau)**(param - 1))
tau_ = (g_ * h - g * h_) / (h**2 + eps)
return tau_.clamp(0., 5.)