Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

 

""" 

BaseOptimizer serves as base for all optimizers. 

""" 

 

import numpy as np 

from .fit_methods import available_fit_methods 

 

 

class BaseOptimizer: 

""" 

BaseOptimizer class. 

 

Serves as base class for all Optimizers solving `Ax = y`. 

 

Parameters 

---------- 

fit_data : tuple of NumPy (N, M) array and NumPy (N) array 

the first element of the tuple represents the fit matrix `A` 

whereas the second element represents the vector of target 

values `y`; here `N` (=rows of `A`, elements of `y`) equals the number 

of target values and `M` (=columns of `A`) equals the number of 

parameters 

fit_method : string 

method to be used for training; possible choice are 

"least-squares", "lasso", "elasticnet", "bayesian-ridge", "ardr" 

standardize : bool 

whether or not to standardize the fit matrix before fitting 

seed : int 

seed for pseudo random number generator 

""" 

 

def __init__(self, fit_data, fit_method, standardize=True, seed=42): 

""" 

Attributes 

---------- 

_A : NumPy (N, M) array 

fit matrix 

_y : NumPy (N) array 

target values 

""" 

 

if fit_method not in available_fit_methods: 

raise ValueError('Unknown fit_method: {}'.format(fit_method)) 

 

if fit_data[0].shape[0] != fit_data[1].shape[0]: 

raise ValueError('Invalid fit data; shapes of fit matrix' 

' and target vector do not match') 

 

50 ↛ 51line 50 didn't jump to line 51, because the condition on line 50 was never true if len(fit_data[0].shape) != 2: 

raise ValueError('Invalid fit matrix; must have two dimensions') 

 

self._A, self._y = fit_data 

self._n_rows = self._A.shape[0] 

self._n_cols = self._A.shape[1] 

self._fit_method = fit_method 

self._standarize = standardize 

self._seed = seed 

self._fit_results = {'parameters': None} 

 

def compute_rmse(self, A, y): 

""" 

Compute the root mean square error using the `A`, `y`, and the 

vector of fitted parameters `x` corresponding to `||Ax-y||_2`. 

 

Parameters 

---------- 

A : NumPy (N, M) array 

fit matrix where `N` (=rows of `A`, elements of `y`) equals the 

number of target values and `M` (=columns of `A`) equals the number 

of parameters (=elements of `x`) 

y : NumPy (N) array 

vector of target values 

 

Returns 

------- 

float 

root mean squared error 

""" 

y_predicted = self.predict(A) 

delta_y = y_predicted - y 

rmse = np.sqrt(np.mean(delta_y**2)) 

return rmse 

 

def predict(self, A): 

""" 

Predict data given an input matrix `A`, i.e., `Ax`, where `x` is 

the vector of the fitted parameters. 

 

Parameters 

---------- 

A : NumPy (N, M) array or NumPy (M, ) 

fit matrix where `N` (=rows of `A`, elements of `y`) equals the 

number of target values and `M` (=columns of `A`) equals the number 

of parameters 

 

Returns 

------- 

NumPy (N) array, or float if single row is inputed 

vector of predicted values 

""" 

return np.dot(A, self.parameters) 

 

def get_contributions(self, A): 

""" 

Compute the average contribution to the predicted values from each 

element of the parameter vector. 

 

Parameters 

---------- 

A : NumPy (N, M) array 

fit matrix where `N` (=rows of `A`, elements of `y`) equals the 

number of target values and `M` (=columns of `A`) equals the number 

of parameters 

 

Returns 

------- 

NumPy (N, M) array 

average contribution for each row of `A` from each parameter 

""" 

return np.mean(np.abs(np.multiply(A, self.parameters)), axis=0) 

 

@property 

def summary(self): 

""" dict : Comprehensive information about the optimizer. """ 

info = dict() 

info['fit_method'] = self.fit_method 

info['standardize'] = self.standardize 

info['number_of_target_values'] = self.number_of_target_values 

info['number_of_parameters'] = self.number_of_parameters 

info['number_of_nonzero_parameters'] = \ 

self.number_of_nonzero_parameters 

return {**info, **self._fit_results} 

 

def __str__(self): 

width = 54 

s = [] 

s.append(' {} '.format(self.__class__.__name__).center(width, '=')) 

for key in sorted(self.summary.keys()): 

value = self.summary[key] 

if isinstance(value, (str, int)): 

s.append('{:30} : {}'.format(key, value)) 

143 ↛ 144line 143 didn't jump to line 144, because the condition on line 143 was never true elif isinstance(value, (float)): 

s.append('{:30} : {:.7g}'.format(key, value)) 

s.append(''.center(width, '=')) 

return '\n'.join(s) 

 

def __repr__(self): 

return 'BaseOptimizer((A, y), {}, {}'.format( 

self.fit_method, self.seed) 

 

@property 

def fit_method(self): 

""" string : fit method. """ 

return self._fit_method 

 

@property 

def parameters(self): 

""" NumPy array : copy of parameter vector. """ 

if self._fit_results['parameters'] is None: 

return None 

else: 

return self._fit_results['parameters'].copy() 

 

@property 

def number_of_nonzero_parameters(self): 

""" int : number of non-zero parameters """ 

if self.parameters is None: 

return None 

else: 

return np.count_nonzero(self.parameters) 

 

@property 

def number_of_target_values(self): 

""" int : number of target values (=rows in `A` matrix). """ 

return self._n_rows 

 

@property 

def number_of_parameters(self): 

""" int : number of parameters (=columns in `A` matrix). """ 

return self._n_cols 

 

@property 

def standardize(self): 

""" bool : whether or not to standardize the fit matrix before 

fitting. 

""" 

return self._standarize 

 

@property 

def seed(self): 

""" int : seed used to initialize pseudo random number generator.""" 

return self._seed