2
2
from scipy .stats import loguniform , logser #TODO: remove this dependency?
3
3
import numpy as np #TODO: remove this dependency and use scipy instead?
4
4
5
+ #function that selects selects items from a list with each having independent probability p of being selected
6
+ def select (items , p ):
7
+ selected = [item for item in items if random .random () < p ]
8
+ #if selected is empty, select one item at random
9
+ if not selected :
10
+ return [random .choice (items )]
11
+ return selected
5
12
6
13
14
+ class Trial ():
7
15
8
- #Replicating the API found in optuna: https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.Trial.html
9
- #copy-pasted some code
10
- def suggest_categorical (name , choices ):
11
- return random .choice (choices )
12
-
13
- def suggest_float (
14
- name : str ,
15
- low : float ,
16
- high : float ,
17
- * ,
18
- step = None ,
19
- log = False ,
20
- ):
21
-
22
- if log and step is not None :
23
- raise ValueError ("The parameter `step` is not supported when `log` is true." )
24
-
25
- if low > high :
26
- raise ValueError (
27
- "The `low` value must be smaller than or equal to the `high` value "
28
- "(low={}, high={})." .format (low , high )
29
- )
30
-
31
- if log and low <= 0.0 :
32
- raise ValueError (
33
- "The `low` value must be larger than 0 for a log distribution "
34
- "(low={}, high={})." .format (low , high )
35
- )
36
-
37
- if step is not None and step <= 0 :
38
- raise ValueError (
39
- "The `step` value must be non-zero positive value, " "but step={}." .format (step )
40
- )
41
-
42
- #TODO check this produces correct output
43
- if log :
44
- value = np .random .uniform (np .log (low ),np .log (high ))
45
- return np .e ** value
46
-
47
- else :
48
- if step is not None :
49
- return np .random .choice (np .arange (low ,high ,step ))
16
+ def __init__ (self , old_params = None , alpha = 1 , hyperparameter_probability = 1 ):
17
+ self ._params = dict ()
18
+
19
+ self .old_params = old_params
20
+ self .alpha = alpha
21
+ self .hyperparameter_probability = hyperparameter_probability
22
+
23
+ if old_params is not None and len (old_params ) > 0 :
24
+ self .params_to_update = select (list (old_params .keys ()), self .hyperparameter_probability )
50
25
else :
51
- return np .random .uniform (low ,high )
26
+ self .params_to_update = None
27
+
28
+
29
+ #Replicating the API found in optuna: https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.Trial.html
30
+ #copy-pasted some code
31
+ def suggest_categorical (self , name , choices ):
32
+ if self .params_to_update == None or name in self .params_to_update or name not in self .old_params : #If this parameter is selected to be changed
33
+ choice = self .suggest_categorical_ (name , choices )
34
+ else : #if this parameter is not selected to be changed
35
+ choice = self .old_params [name ]
36
+ if choice not in choices : #if the old value is not in the choices, then we need to choose a value for it
37
+ choice = self .suggest_categorical_ (name , choices )
38
+
39
+ self ._params [name ] = choice
40
+ return choice
41
+
42
+ def suggest_float (self ,
43
+ name : str ,
44
+ low : float ,
45
+ high : float ,
46
+ * ,
47
+ step = None ,
48
+ log = False ,
49
+ ):
50
+ if self .params_to_update == None or name in self .params_to_update or name not in self .old_params : #If this parameter is selected to be changed
51
+ choice = self .suggest_float_ (name , low = low , high = high , step = step , log = log )
52
+ if self .old_params is not None and name in self .old_params :
53
+ choice = self .alpha * choice + (1 - self .alpha )* self .old_params [name ]
54
+ else : #if this parameter is not selected to be changed
55
+ choice = self .old_params [name ]
56
+
57
+ self ._params [name ] = choice
58
+ return choice
59
+
60
+
61
+
62
+ def suggest_discrete_uniform (self , name , low , high , q ):
63
+ if self .params_to_update == None or name in self .params_to_update or name not in self .old_params :
64
+ choice = self .suggest_discrete_uniform_ (name , low = low , high = high , q = q )
65
+ if self .old_params is not None and name in self .old_params :
66
+ choice = self .alpha * choice + (1 - self .alpha )* self .old_params [name ]
67
+ else :
68
+ choice = self .old_params [name ]
52
69
70
+ self ._params [name ] = choice
71
+ return choice
53
72
54
- def suggest_discrete_uniform (name , low , high , q ):
55
- return suggest_float (name , low , high , step = q )
56
73
57
74
58
- def suggest_int (name , low , high , step = 1 , log = False ):
59
- if low == high : #TODO check that this matches optuna's behaviour
60
- return low
61
-
62
- if log and step > 1 :
63
- raise ValueError ("The parameter `step`>1 is not supported when `log` is true." )
75
+ def suggest_int (self , name , low , high , step = 1 , log = False ):
76
+ if self .params_to_update == None or name in self .params_to_update or name not in self .old_params :
77
+ choice = self .suggest_int_ (name , low = low , high = high , step = step , log = log )
78
+ if self .old_params is not None and name in self .old_params :
79
+ choice = int (self .alpha * choice + (1 - self .alpha )* self .old_params [name ])
80
+ else :
81
+ choice = self .old_params [name ]
64
82
65
- if low > high :
66
- raise ValueError (
67
- "The `low` value must be smaller than or equal to the `high` value "
68
- "(low={}, high={})." .format (low , high )
69
- )
83
+ self ._params [name ] = choice
84
+ return choice
70
85
71
- if log and low <= 0.0 :
72
- raise ValueError (
73
- "The `low` value must be larger than 0 for a log distribution "
74
- "(low={}, high={})." .format (low , high )
75
- )
76
86
77
- if step is not None and step <= 0 :
78
- raise ValueError (
79
- "The `step` value must be non-zero positive value, " "but step={}." .format (step )
80
- )
87
+ def suggest_uniform (self , name , low , high ):
88
+ if self .params_to_update == None or name in self .params_to_update or name not in self .old_params :
89
+ choice = self .suggest_uniform_ (name , low = low , high = high )
90
+ if self .old_params is not None and name in self .old_params :
91
+ choice = self .alpha * choice + (1 - self .alpha )* self .old_params [name ]
92
+ else :
93
+ choice = self .old_params [name ]
94
+
95
+ self ._params [name ] = choice
96
+ return choice
97
+
98
+
99
+
100
+ ####################################
101
+ #Replicating the API found in optuna: https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.Trial.html
102
+ #copy-pasted some code
103
+ def suggest_categorical_ (self , name , choices ):
104
+
105
+ choice = random .choice (choices )
106
+ return choice
107
+
108
+ def suggest_float_ (self ,
109
+ name : str ,
110
+ low : float ,
111
+ high : float ,
112
+ * ,
113
+ step = None ,
114
+ log = False ,
115
+ ):
116
+
117
+ if log and step is not None :
118
+ raise ValueError ("The parameter `step` is not supported when `log` is true." )
119
+
120
+ if low > high :
121
+ raise ValueError (
122
+ "The `low` value must be smaller than or equal to the `high` value "
123
+ "(low={}, high={})." .format (low , high )
124
+ )
125
+
126
+ if log and low <= 0.0 :
127
+ raise ValueError (
128
+ "The `low` value must be larger than 0 for a log distribution "
129
+ "(low={}, high={})." .format (low , high )
130
+ )
131
+
132
+ if step is not None and step <= 0 :
133
+ raise ValueError (
134
+ "The `step` value must be non-zero positive value, " "but step={}." .format (step )
135
+ )
136
+
137
+ #TODO check this produces correct output
138
+ if log :
139
+ value = np .random .uniform (np .log (low ),np .log (high ))
140
+ choice = np .e ** value
141
+ return choice
81
142
82
- if log :
83
- value = np .random .uniform (np .log (low ),np .log (high ))
84
- return int (np .e ** value )
85
- else :
86
- return np .random .choice (list (range (low ,high ,step )))
143
+ else :
144
+ if step is not None :
145
+ choice = np .random .choice (np .arange (low ,high ,step ))
146
+ return choice
147
+ else :
148
+ choice = np .random .uniform (low ,high )
149
+ return choice
150
+
151
+
152
+ def suggest_discrete_uniform_ (self , name , low , high , q ):
153
+ choice = self .suggest_float (name , low , high , step = q )
154
+ return choice
155
+
156
+
157
+ def suggest_int_ (self , name , low , high , step = 1 , log = False ):
158
+ if low == high : #TODO check that this matches optuna's behaviour
159
+ return low
160
+
161
+ if log and step > 1 :
162
+ raise ValueError ("The parameter `step`>1 is not supported when `log` is true." )
163
+
164
+ if low > high :
165
+ raise ValueError (
166
+ "The `low` value must be smaller than or equal to the `high` value "
167
+ "(low={}, high={})." .format (low , high )
168
+ )
169
+
170
+ if log and low <= 0.0 :
171
+ raise ValueError (
172
+ "The `low` value must be larger than 0 for a log distribution "
173
+ "(low={}, high={})." .format (low , high )
174
+ )
175
+
176
+ if step is not None and step <= 0 :
177
+ raise ValueError (
178
+ "The `step` value must be non-zero positive value, " "but step={}." .format (step )
179
+ )
180
+
181
+ if log :
182
+ value = np .random .uniform (np .log (low ),np .log (high ))
183
+ choice = int (np .e ** value )
184
+ return choice
185
+ else :
186
+ choice = np .random .choice (list (range (low ,high ,step )))
187
+ return choice
87
188
88
- def suggest_uniform ( name , low , high ):
89
- return suggest_float (name , low , high )
189
+ def suggest_uniform_ ( self , name , low , high ):
190
+ return self . suggest_float (name , low , high )
0 commit comments