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

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

""" 

scikit-learn is an excellent library for training linear models and provides a 

large number of useful tools. 

 

This module provides simplified interfaces for vaiours linear model regression 

methods. These methods are set up in a way that work out of the box for typical 

problems in cluster expansion and force constant potential construction. This 

includes slight adjustments scitkit-learn default values. 

 

If you would like more flexibility or extended functionality or ability to 

fine-tune parameters that are not included in this interface, it is of course 

possible to use scikit-learn directly. 

More information about the sklearn linear models can be found at 

http://scikit-learn.org/stable/modules/linear_model.html 

""" 

 

import numpy as np 

from ..io.logging import logger 

from collections import OrderedDict 

from .split_bregman import fit_split_bregman 

try: 

from sklearn.linear_model import (Lasso, 

LassoCV, 

ElasticNet, 

ElasticNetCV, 

BayesianRidge, 

ARDRegression) 

from sklearn.preprocessing import StandardScaler 

# arrangement of logger assignments is owed to pep8 requirements 

logger = logger.getChild('fit_methods') 

except Exception: 

logger = logger.getChild('fit_methods') 

logger.warning('Failed to import scitkit-learn;' 

' several optimizers will fail') 

 

 

def fit(X, y, fit_method, standardize=True, **kwargs): 

""" Wrapper function for all available fit methods. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

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 

 

Returns 

---------- 

results : dict 

dict containing parameters and possibly pther information obtained by 

the fit_method 

""" 

 

59 ↛ 60line 59 didn't jump to line 60, because the condition on line 59 was never true if fit_method not in available_fit_methods: 

msg = ['Fit method not available'] 

msg += ['Please choose one of the following:'] 

for key in available_fit_methods: 

msg += [' * ' + key] 

raise ValueError('\n'.join(msg)) 

 

66 ↛ 73line 66 didn't jump to line 73, because the condition on line 66 was never false if standardize: 

ss = StandardScaler(copy=False, with_mean=False, with_std=True) 

ss.fit_transform(X) # change in place 

results = fit_methods[fit_method](X, y, **kwargs) 

ss.inverse_transform(X) # change in place 

ss.transform(results['parameters'].reshape(1, -1)).reshape(-1,) 

else: 

results = fit_methods[fit_method](X, y, **kwargs) 

return results 

 

 

def _fit_least_squares(X, y): 

""" 

Return the least-squares solution `a` to the linear problem `Xa=y`. 

 

This function is a wrapper to the `linalg.lstsq` function in NumPy. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

 

Returns 

---------- 

results : dict 

dict containing parameters 

""" 

results = dict() 

results['parameters'] = np.linalg.lstsq(X, y, rcond=-1)[0] 

return results 

 

 

def _fit_lasso(X, y, alpha=None, fit_intercept=False, **kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

the LASSO method as implemented in scitkit-learn. 

 

LASSO optimizes the following problem:: 

 

(1 / (2 * n_samples)) * ||y - Xw||^2_2 + alpha * ||w||_1 

 

If `alpha` is `None` this function will call the fit_lassoCV which attempts 

to find the optimal alpha via sklearn LassoCV class. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

alpha : float 

alpha value 

fit_intercept : bool 

center data or not, forwarded to sklearn 

 

Returns 

---------- 

results : dict 

dictionary containing parameters 

""" 

if alpha is None: 

return _fit_lassoCV(X, y, fit_intercept=fit_intercept, **kwargs) 

else: 

lasso = Lasso(alpha=alpha, fit_intercept=fit_intercept, **kwargs) 

lasso.fit(X, y) 

results = dict() 

results['parameters'] = lasso.coef_ 

return results 

 

 

def _fit_lassoCV(X, y, alphas=None, fit_intercept=False, cv=10, n_jobs=-1, 

**kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

the LassoCV method as implemented in scitkit-learn. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

alphas : list / array 

list of alpha values to be evaluated during regularization path 

fit_intercept : bool 

center data or not, forwarded to sklearn 

cv : int 

how many folds to carry out in cross-validation 

 

Returns 

------- 

results : dict 

dictionary containing parameters, 

alpha_optimal (alpha value that yields the lowest validation rmse), 

alpha_path (all tested alpha values), 

mse_path (mse for validation set for each alpha) 

""" 

 

166 ↛ 169line 166 didn't jump to line 169, because the condition on line 166 was never false if alphas is None: 

alphas = np.logspace(-8, -0.3, 100) 

 

lassoCV = LassoCV(alphas=alphas, fit_intercept=fit_intercept, cv=cv, 

n_jobs=n_jobs, **kwargs) 

lassoCV.fit(X, y) 

results = dict() 

results['parameters'] = lassoCV.coef_ 

results['alpha_optimal'] = lassoCV.alpha_ 

results['alpha_path'] = lassoCV.alphas_ 

results['mse_path'] = lassoCV.mse_path_.mean(axis=1) 

return results 

 

 

def _fit_elasticnet(X, y, alpha=None, fit_intercept=False, **kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

the ElasticNet method as implemented in scitkit-learn. 

 

If `alpha` is `None` this function will call the fit_lassoCV which attempts 

to find the optimal alpha via sklearn ElasticNetCV class. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

alpha : float 

alpha value 

fit_intercept : bool 

center data or not, forwarded to sklearn 

 

Returns 

---------- 

results : dict 

dictionary containing parameters 

""" 

if alpha is None: 

return _fit_elasticnetCV(X, y, fit_intercept=fit_intercept, **kwargs) 

else: 

elasticnet = ElasticNet(alpha=alpha, fit_intercept=fit_intercept, 

**kwargs) 

elasticnet.fit(X, y) 

results = dict() 

results['parameters'] = elasticnet.coef_ 

return results 

 

 

def _fit_elasticnetCV(X, y, alphas=None, l1_ratio=None, fit_intercept=False, 

cv=10, n_jobs=-1, **kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

the ElasticNetCV method as implemented in scitkit-learn. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

alphas : list / array 

list of alpha values to be evaluated during regularization path 

l1_ratio : float or list of floats 

l1_ratio values to be evaluated during regularization path 

fit_intercept : bool 

center data or not, forwarded to sklearn 

cv : int 

how many folds to carry out in cross-validation 

 

Returns 

------- 

results : dict 

dictionary containing parameters, 

alpha_optimal (alpha value that yields the lowest validation rmse), 

alpha_path (all tested alpha values), 

l1_ratio_optmal (alpha value that yields the lowest validation rmse), 

l1_ratio_pathh (all tested l1_ratio values) 

mse_path (mse for validation set for each alpha and l1_ratio) 

""" 

 

247 ↛ 249line 247 didn't jump to line 249, because the condition on line 247 was never false if alphas is None: 

alphas = np.logspace(-8, -0.3, 100) 

249 ↛ 253line 249 didn't jump to line 253, because the condition on line 249 was never false if l1_ratio is None: 

l1_ratio = [1.0, 0.995, 0.99, 0.98, 0.97, 0.95, 0.925, 0.9, 0.85, 

0.8, 0.75, 0.65, 0.5, 0.4, 0.25, 0.1] 

 

elasticnetCV = ElasticNetCV(alphas=alphas, l1_ratio=l1_ratio, cv=cv, 

fit_intercept=fit_intercept, n_jobs=n_jobs, 

**kwargs) 

elasticnetCV.fit(X, y) 

results = dict() 

results['parameters'] = elasticnetCV.coef_ 

results['alpha_optimal'] = elasticnetCV.alpha_ 

results['alpha_path'] = elasticnetCV.alphas_ 

results['l1_ratio_path'] = elasticnetCV.l1_ratio 

results['l1_ratio_optimal'] = elasticnetCV.l1_ratio_ 

results['mse_path'] = elasticnetCV.mse_path_.mean(axis=2) 

return results 

 

 

def _fit_bayesian_ridge(X, y, fit_intercept=False, **kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

Bayesian ridge regression as implemented in scitkit-learn. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

fit_intercept : bool 

center data or not, forwarded to sklearn 

 

Returns 

---------- 

results : dict 

dict containing parameters 

""" 

brr = BayesianRidge(fit_intercept=fit_intercept, **kwargs) 

brr.fit(X, y) 

results = dict() 

results['parameters'] = brr.coef_ 

return results 

 

 

def _fit_ardr(X, y, threshold_lambda=1e6, fit_intercept=False, **kwargs): 

""" 

Return the solution `a` to the linear problem `Xa=y` obtained by using 

the automatic relevance determination regression (ARDR) method as 

implemented in scitkit-learn. 

 

Parameters 

----------- 

X : matrix / array 

fit matrix 

y : array 

target array 

threshold_lambda : float 

threshold lambda parameter forwarded to sklearn 

fit_intercept : bool 

center data or not, forwarded to sklearn 

 

Returns 

---------- 

results : dict 

dictionary containing parameters 

""" 

ardr = ARDRegression(threshold_lambda=threshold_lambda, 

fit_intercept=fit_intercept, **kwargs) 

ardr.fit(X, y) 

results = dict() 

results['parameters'] = ardr.coef_ 

return results 

 

 

fit_methods = OrderedDict([ 

('least-squares', _fit_least_squares), 

('lasso', _fit_lasso), 

('elasticnet', _fit_elasticnet), 

('bayesian-ridge', _fit_bayesian_ridge), 

('ardr', _fit_ardr), 

('split-bregman', fit_split_bregman) 

]) 

available_fit_methods = list(fit_methods.keys())