dquant 1.2.0__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dquant-1.2.0/src/DQuant.egg-info → dquant-1.2.2}/PKG-INFO +1 -1
- {dquant-1.2.0 → dquant-1.2.2}/pyproject.toml +1 -1
- {dquant-1.2.0 → dquant-1.2.2/src/DQuant.egg-info}/PKG-INFO +1 -1
- dquant-1.2.2/src/dquant/metrics.py +8 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/dquant/models.py +152 -325
- {dquant-1.2.0 → dquant-1.2.2}/src/dquant/visual.py +3 -9
- dquant-1.2.0/src/dquant/metrics.py +0 -10
- {dquant-1.2.0 → dquant-1.2.2}/LICENSE +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/README.md +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/setup.cfg +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/DQuant.egg-info/SOURCES.txt +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/DQuant.egg-info/dependency_links.txt +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/DQuant.egg-info/requires.txt +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/DQuant.egg-info/top_level.txt +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/__init__.py +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/dquant/__init__.py +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/src/dquant/get_data.py +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/test/test.py +0 -0
- {dquant-1.2.0 → dquant-1.2.2}/test/test_load.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dquant
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: DQuant is an open-source Python library for automated volatility forecasting of financial time series. It handles all stages of model construction, from raw prices to the final forecast.
|
|
5
5
|
Author: Denis Makarov
|
|
6
6
|
Project-URL: Homepage, https://dquant.space
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dquant
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: DQuant is an open-source Python library for automated volatility forecasting of financial time series. It handles all stages of model construction, from raw prices to the final forecast.
|
|
5
5
|
Author: Denis Makarov
|
|
6
6
|
Project-URL: Homepage, https://dquant.space
|
|
@@ -12,7 +12,7 @@ import numpy as np
|
|
|
12
12
|
import xgboost
|
|
13
13
|
from sklearn.ensemble import GradientBoostingRegressor
|
|
14
14
|
from sklearn.model_selection import train_test_split
|
|
15
|
-
from sklearn.metrics import mean_squared_error, r2_score
|
|
15
|
+
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
|
|
16
16
|
from .metrics import qlike_score
|
|
17
17
|
from sklearn.preprocessing import StandardScaler
|
|
18
18
|
from typing import Tuple
|
|
@@ -33,7 +33,6 @@ class FichEn:
|
|
|
33
33
|
eps = 1e-8
|
|
34
34
|
y_pred = np.clip(y_pred, eps, None)
|
|
35
35
|
|
|
36
|
-
# Градиент (оставляем истинный)
|
|
37
36
|
grad = 1.0 / y_pred - y_true / (y_pred ** 2)
|
|
38
37
|
|
|
39
38
|
hess_approx = 1.0 / (y_pred ** 2)
|
|
@@ -44,16 +43,13 @@ class FichEn:
|
|
|
44
43
|
if self.output == False:
|
|
45
44
|
return
|
|
46
45
|
if file is None:
|
|
47
|
-
file = sys.stdout
|
|
46
|
+
file = sys.stdout
|
|
48
47
|
|
|
49
|
-
# Преобразуем все аргументы в строки и соединяем через sep
|
|
50
48
|
output = sep.join(str(arg) for arg in args)
|
|
51
|
-
output += end
|
|
49
|
+
output += end
|
|
52
50
|
|
|
53
|
-
# Записываем в файловый объект
|
|
54
51
|
file.write(output)
|
|
55
52
|
|
|
56
|
-
# Принудительно сбрасываем буфер, если нужно
|
|
57
53
|
if flush:
|
|
58
54
|
file.flush()
|
|
59
55
|
|
|
@@ -71,14 +67,14 @@ class FichEn:
|
|
|
71
67
|
|
|
72
68
|
for col in required:
|
|
73
69
|
if col not in data.columns:
|
|
74
|
-
raise ValueError(f"
|
|
70
|
+
raise ValueError(f"Column '{col}' is not found")
|
|
75
71
|
|
|
76
72
|
raw_windows_X = []
|
|
77
73
|
raw_windows_y = []
|
|
78
74
|
|
|
79
|
-
for i in range(window_in + 1, len(data) - window_out +
|
|
75
|
+
for i in range(window_in + 1, len(data) - (window_out + 2)):
|
|
80
76
|
x_window = data.iloc[i - window_in: i]
|
|
81
|
-
y_window = data.iloc[i
|
|
77
|
+
y_window = data.iloc[i: i + window_out+1]
|
|
82
78
|
|
|
83
79
|
raw_windows_X.append(x_window)
|
|
84
80
|
raw_windows_y.append(y_window)
|
|
@@ -95,13 +91,12 @@ class FichEn:
|
|
|
95
91
|
|
|
96
92
|
for col in required:
|
|
97
93
|
if col not in data.columns:
|
|
98
|
-
raise ValueError(f"
|
|
94
|
+
raise ValueError(f"Column '{col}' is not found")
|
|
99
95
|
|
|
100
96
|
feature_list_final = []
|
|
101
97
|
single_feature_list_final = []
|
|
102
98
|
single_feature_dict = {}
|
|
103
99
|
|
|
104
|
-
# Сначала рассчитываем TR, так как он нужен для ATR
|
|
105
100
|
if 'TR' in feature_list or any(f.startswith('atr_') for f in feature_list) or any(
|
|
106
101
|
f.startswith('roll_atr_') for f in feature_list):
|
|
107
102
|
prev_close = data['close'].shift(1).fillna(data['close'])
|
|
@@ -145,7 +140,6 @@ class FichEn:
|
|
|
145
140
|
feature_list_final.append(i)
|
|
146
141
|
|
|
147
142
|
elif i == 'abs_returns':
|
|
148
|
-
# Используем уже рассчитанные returns
|
|
149
143
|
if 'returns' in data.columns:
|
|
150
144
|
data[i] = data['returns'].abs()
|
|
151
145
|
else:
|
|
@@ -265,7 +259,7 @@ class FichEn:
|
|
|
265
259
|
f'Not enough data to calculate BB: max BB period is {len(close_values)} and yours {window}')
|
|
266
260
|
sma = close_values.mean()
|
|
267
261
|
std = close_values.std()
|
|
268
|
-
single_feature_dict[f'bb_{window}'] = (4 * std) / (sma + epsilon)
|
|
262
|
+
single_feature_dict[f'bb_{window}'] = (4 * std) / (sma + epsilon)
|
|
269
263
|
single_feature_list_final.append(f'bb_{window}')
|
|
270
264
|
|
|
271
265
|
elif i[:9] == 'roll_rsi_':
|
|
@@ -316,7 +310,7 @@ class FichEn:
|
|
|
316
310
|
window = int(window)
|
|
317
311
|
sma = data['close'].rolling(window=window, min_periods=window).mean()
|
|
318
312
|
std = data['close'].rolling(window=window, min_periods=window).std()
|
|
319
|
-
data[f'roll_bb_{window}'] = (4 * std) / (sma + epsilon)
|
|
313
|
+
data[f'roll_bb_{window}'] = (4 * std) / (sma + epsilon)
|
|
320
314
|
feature_list_final.append(f'roll_bb_{window}')
|
|
321
315
|
|
|
322
316
|
else:
|
|
@@ -327,14 +321,6 @@ class FichEn:
|
|
|
327
321
|
|
|
328
322
|
data = data.fillna(0)
|
|
329
323
|
|
|
330
|
-
"""feature_vector = []
|
|
331
|
-
for i in range(1, len(data)):
|
|
332
|
-
for feat in existing_features:
|
|
333
|
-
feature_vector.append(data[feat].iloc[i])
|
|
334
|
-
|
|
335
|
-
for i in single_feature_list_final:
|
|
336
|
-
feature_vector.append(single_feature_dict[i])"""
|
|
337
|
-
|
|
338
324
|
feature_vector = data[existing_features].iloc[1:].to_numpy(dtype=np.float64).ravel()
|
|
339
325
|
single_vals = np.array([single_feature_dict[f] for f in single_feature_list_final], dtype=np.float64)
|
|
340
326
|
feature_vector = np.concatenate([feature_vector, single_vals])
|
|
@@ -352,20 +338,7 @@ class FichEn:
|
|
|
352
338
|
|
|
353
339
|
for col in required:
|
|
354
340
|
if col not in data.columns:
|
|
355
|
-
raise ValueError(f"
|
|
356
|
-
|
|
357
|
-
"""tr_values = []
|
|
358
|
-
|
|
359
|
-
for i in range(1, len(data)):
|
|
360
|
-
if i == 0:
|
|
361
|
-
tr = (data['high'].iloc[i] - data['low'].iloc[i]) / data['close'].iloc[i]
|
|
362
|
-
else:
|
|
363
|
-
hl = data['high'].iloc[i] - data['low'].iloc[i]
|
|
364
|
-
hc = abs(data['high'].iloc[i] - data['close'].iloc[i - 1])
|
|
365
|
-
lc = abs(data['low'].iloc[i] - data['close'].iloc[i - 1])
|
|
366
|
-
tr = max(hl/data['close'].iloc[i], hc/data['close'].iloc[i], lc/data['close'].iloc[i])
|
|
367
|
-
|
|
368
|
-
tr_values.append(tr)"""
|
|
341
|
+
raise ValueError(f"Column '{col}' is not found")
|
|
369
342
|
|
|
370
343
|
high = data['high']
|
|
371
344
|
low = data['low']
|
|
@@ -419,35 +392,32 @@ class FichEn:
|
|
|
419
392
|
bar = '█' * filled_chars + '░' * (50 - filled_chars)
|
|
420
393
|
time_per = time.time() - startt
|
|
421
394
|
if percent < 10:
|
|
422
|
-
self.dquantprint(f'\
|
|
395
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
423
396
|
elif percent >= 10 and percent < 100:
|
|
424
|
-
self.dquantprint(f'\
|
|
397
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
425
398
|
else:
|
|
426
|
-
self.dquantprint(f'\
|
|
399
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
427
400
|
|
|
428
401
|
self.dquantprint()
|
|
429
402
|
x = np.array(XX)
|
|
430
403
|
y = np.array(YY)
|
|
431
404
|
|
|
432
|
-
|
|
433
|
-
train_window_size = input_bars # сколько последних окон использовать для обучения
|
|
434
|
-
# Минимальный индекс, с которого можно начинать валидацию (должен быть >= train_window_size)
|
|
405
|
+
train_window_size = input_bars
|
|
435
406
|
start_val_idx = train_window_size
|
|
436
407
|
|
|
437
408
|
total_iterations = len(x) - start_val_idx
|
|
438
409
|
if total_iterations <= 0:
|
|
439
|
-
raise ValueError(f"
|
|
410
|
+
raise ValueError(f"Too little data: total windows {len(x)}, and train_window_size={train_window_size}")
|
|
440
411
|
|
|
441
|
-
self.dquantprint(f"
|
|
442
|
-
self.dquantprint(f"
|
|
443
|
-
self.dquantprint(f"
|
|
412
|
+
self.dquantprint(f"Total windows: {len(x)}")
|
|
413
|
+
self.dquantprint(f"Training window size: {train_window_size}")
|
|
414
|
+
self.dquantprint(f"Validation steps: {total_iterations}")
|
|
444
415
|
|
|
445
416
|
all_train_errors = []
|
|
446
417
|
all_val_errors = []
|
|
447
418
|
all_train_r2 = []
|
|
448
419
|
all_val_r2 = []
|
|
449
420
|
|
|
450
|
-
# horizon может быть числом или списком, приведём к списку индексов
|
|
451
421
|
if isinstance(horizon, int):
|
|
452
422
|
horizon_list = list(range(horizon))
|
|
453
423
|
else:
|
|
@@ -457,16 +427,15 @@ class FichEn:
|
|
|
457
427
|
start_it = time.time()
|
|
458
428
|
iter_num = val_idx - start_val_idx + 1
|
|
459
429
|
|
|
460
|
-
# === Обучающая выборка: последние train_window_size окон перед val_idx ===
|
|
461
430
|
train_indices = list(range(val_idx - train_window_size, val_idx))
|
|
462
431
|
X_train = x[train_indices]
|
|
463
432
|
y_train = y[train_indices]
|
|
464
433
|
|
|
465
|
-
# ===
|
|
466
|
-
X_val = x[val_idx:val_idx + 1] #
|
|
467
|
-
y_val_true = y[val_idx] #
|
|
434
|
+
# === Validation window ===
|
|
435
|
+
X_val = x[val_idx:val_idx + 1] # form (1, n_features)
|
|
436
|
+
y_val_true = y[val_idx] # form (horizon,)
|
|
468
437
|
|
|
469
|
-
# ===
|
|
438
|
+
# === Normalization ===
|
|
470
439
|
scaler_X = StandardScaler()
|
|
471
440
|
scaler_y_local = StandardScaler()
|
|
472
441
|
|
|
@@ -475,46 +444,40 @@ class FichEn:
|
|
|
475
444
|
|
|
476
445
|
X_val_scaled = scaler_X.transform(X_val)
|
|
477
446
|
|
|
478
|
-
# ===
|
|
447
|
+
# === training for each horizon ===
|
|
479
448
|
model_ex = self.base_model.__class__(**self.base_model.get_params())
|
|
480
449
|
model_ex.set_params(n_estimators=trees)
|
|
481
450
|
models_temp = []
|
|
482
451
|
for h_idx in horizon_list:
|
|
483
452
|
if h_idx >= y_train_scaled.shape[1]:
|
|
484
|
-
continue
|
|
453
|
+
continue
|
|
485
454
|
|
|
486
455
|
y_h = y_train_scaled[:, h_idx]
|
|
487
456
|
|
|
488
|
-
# Создаём модель с параметрами, как у self.base_model
|
|
489
457
|
model = model_ex
|
|
490
|
-
# При желании можно задать n_estimators из self.trees_count, но для чистоты
|
|
491
|
-
# walk-forward оставим обучение до конца (или фиксированное число деревьев).
|
|
492
|
-
# Если нужен early_stopping по числу деревьев - можно добавить.
|
|
493
458
|
model.fit(X_train_scaled, y_h)
|
|
494
459
|
models_temp.append(model)
|
|
495
460
|
|
|
496
|
-
# ===
|
|
497
|
-
# На тренировочных данных
|
|
461
|
+
# === Foracesting train ===
|
|
498
462
|
train_preds_list = []
|
|
499
463
|
for model in models_temp:
|
|
500
464
|
train_preds_list.append(model.predict(X_train_scaled))
|
|
501
465
|
train_preds = np.column_stack(train_preds_list) # (train_windows, horizon)
|
|
502
466
|
|
|
503
|
-
#
|
|
467
|
+
# Forecasting on validation data
|
|
504
468
|
val_preds_list = []
|
|
505
469
|
for model in models_temp:
|
|
506
470
|
val_preds_list.append(model.predict(X_val_scaled))
|
|
507
471
|
val_preds = np.array(val_preds_list).flatten() # (horizon,)
|
|
508
472
|
|
|
509
|
-
|
|
473
|
+
|
|
510
474
|
y_train_inv = scaler_y_local.inverse_transform(y_train_scaled)
|
|
511
475
|
train_preds_inv = scaler_y_local.inverse_transform(train_preds)
|
|
512
476
|
|
|
513
|
-
y_val_true_inv = y_val_true
|
|
477
|
+
y_val_true_inv = y_val_true
|
|
514
478
|
val_preds_inv = scaler_y_local.inverse_transform(val_preds.reshape(1, -1)).flatten()
|
|
515
479
|
|
|
516
|
-
# ===
|
|
517
|
-
# Усредняем MSE по всем горизонтам
|
|
480
|
+
# === Metrics ===
|
|
518
481
|
train_error = mean_squared_error(y_train_inv.flatten(), train_preds_inv.flatten())
|
|
519
482
|
val_error = mean_squared_error(y_val_true_inv, val_preds_inv)
|
|
520
483
|
train_r2 = r2_score(y_train_inv.flatten(), train_preds_inv.flatten())
|
|
@@ -525,7 +488,7 @@ class FichEn:
|
|
|
525
488
|
all_train_r2.append(train_r2)
|
|
526
489
|
all_val_r2.append(val_r2)
|
|
527
490
|
|
|
528
|
-
# ===
|
|
491
|
+
# === Progress bar ===
|
|
529
492
|
percent = (iter_num / total_iterations) * 100
|
|
530
493
|
filled = int(percent / 2)
|
|
531
494
|
bar = '█' * filled + '░' * (50 - filled)
|
|
@@ -533,11 +496,11 @@ class FichEn:
|
|
|
533
496
|
f'\rWalk-Forward: |{bar}| {percent:.1f}% - Iteration {iter_num}/{total_iterations} - Val MSE: {val_error:.6f} - need time: {(time.time()-start_it)*(total_iterations-iter_num)} seconds',
|
|
534
497
|
end='', flush=True)
|
|
535
498
|
|
|
536
|
-
|
|
537
|
-
self.dquantprint(f"
|
|
538
|
-
self.dquantprint(f"
|
|
539
|
-
self.dquantprint(f"
|
|
540
|
-
self.dquantprint(f"
|
|
499
|
+
|
|
500
|
+
self.dquantprint(f"Mean validation error (MSE): {np.mean(all_val_errors):.6f} +/- {np.std(all_val_errors):.6f}")
|
|
501
|
+
self.dquantprint(f"Mean validation R²: {np.mean(all_val_r2):.4f} +/- {np.std(all_val_r2):.4f}")
|
|
502
|
+
self.dquantprint(f"Maximum validation error: {np.max(all_val_errors):.6f}")
|
|
503
|
+
self.dquantprint(f"Minimum validation error: {np.min(all_val_errors):.6f}")
|
|
541
504
|
if show_results:
|
|
542
505
|
self.V.forward_validation_errors(all_val_errors, all_val_r2)
|
|
543
506
|
return
|
|
@@ -571,7 +534,6 @@ class FichEn:
|
|
|
571
534
|
else:
|
|
572
535
|
window_targets = target_func(y[i])
|
|
573
536
|
|
|
574
|
-
#self.dquantprint(len(window_features))
|
|
575
537
|
XX.append(window_features)
|
|
576
538
|
YY.append(window_targets)
|
|
577
539
|
|
|
@@ -580,11 +542,11 @@ class FichEn:
|
|
|
580
542
|
bar = '█' * filled_chars + '░' * (50 - filled_chars)
|
|
581
543
|
time_per = time.time() - startt
|
|
582
544
|
if percent < 10:
|
|
583
|
-
self.dquantprint(f'\
|
|
545
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
584
546
|
elif percent >= 10 and percent < 100:
|
|
585
|
-
self.dquantprint(f'\
|
|
547
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
586
548
|
else:
|
|
587
|
-
self.dquantprint(f'\
|
|
549
|
+
self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
|
|
588
550
|
|
|
589
551
|
self.dquantprint()
|
|
590
552
|
self.dquantprint("time spended: ", time.time() - start_)
|
|
@@ -601,12 +563,15 @@ class FichEn:
|
|
|
601
563
|
|
|
602
564
|
self.train_errors = []
|
|
603
565
|
self.val_errors = []
|
|
566
|
+
self.train_mae = []
|
|
567
|
+
self.val_mae = []
|
|
604
568
|
self.train_qlike = []
|
|
605
569
|
self.val_qlike = []
|
|
606
570
|
self.train_r2 = []
|
|
607
571
|
self.val_r2 = []
|
|
608
572
|
|
|
609
573
|
self.best_val_error = float('inf')
|
|
574
|
+
self.best_val_mae = float('inf')
|
|
610
575
|
self.best_val_qlike = float('inf')
|
|
611
576
|
self.best_r2 = -float('inf')
|
|
612
577
|
self.patience_counter = 0
|
|
@@ -619,6 +584,8 @@ class FichEn:
|
|
|
619
584
|
self.dquantprint(f'{i} trees')
|
|
620
585
|
t_error = 0
|
|
621
586
|
v_error = 0
|
|
587
|
+
t_mae = 0
|
|
588
|
+
v_mae = 0
|
|
622
589
|
t_qlike = 0
|
|
623
590
|
v_qlike = 0
|
|
624
591
|
t_r2 = 0
|
|
@@ -627,11 +594,10 @@ class FichEn:
|
|
|
627
594
|
horizon_list = list(range(horizon))
|
|
628
595
|
else:
|
|
629
596
|
horizon_list = horizon
|
|
630
|
-
|
|
631
|
-
if len(Y_scaled.shape) == 2 and Y_scaled.shape[1] > 1:
|
|
597
|
+
if len(Y_scaled.shape) == 2 and Y_scaled.shape[1] > 0:
|
|
632
598
|
for h_idx, h in enumerate(horizon_list):
|
|
633
599
|
if h_idx >= Y_scaled.shape[1]:
|
|
634
|
-
self.dquantprint(f"
|
|
600
|
+
self.dquantprint(f"Warning: horizon {h} extends beyond y, skipping")
|
|
635
601
|
continue
|
|
636
602
|
|
|
637
603
|
y_h = Y_scaled.iloc[:, h_idx] if hasattr(Y_scaled, 'iloc') else Y_scaled[:, h_idx]
|
|
@@ -657,6 +623,8 @@ class FichEn:
|
|
|
657
623
|
if i != 1:
|
|
658
624
|
t_error += mean_squared_error(y_h_clean, self.models[h_idx].predict(X_h))
|
|
659
625
|
v_error += mean_squared_error(y_h_v_clean, self.models[h_idx].predict(X_h_v))
|
|
626
|
+
t_mae += mean_absolute_error(y_h_clean, self.models[h_idx].predict(X_h))
|
|
627
|
+
v_mae += mean_absolute_error(y_h_v_clean, self.models[h_idx].predict(X_h_v))
|
|
660
628
|
t_qlike += qlike_score(y_h_clean, self.models[h_idx].predict(X_h))
|
|
661
629
|
v_qlike += qlike_score(y_h_v_clean, self.models[h_idx].predict(X_h_v))
|
|
662
630
|
t_r2 += r2_score(y_h_clean, self.models[h_idx].predict(X_h))
|
|
@@ -664,6 +632,8 @@ class FichEn:
|
|
|
664
632
|
else:
|
|
665
633
|
t_error += mean_squared_error(y_h_clean, model.predict(X_h))
|
|
666
634
|
v_error += mean_squared_error(y_h_v_clean, model.predict(X_h_v))
|
|
635
|
+
t_mae += mean_absolute_error(y_h_clean, model.predict(X_h))
|
|
636
|
+
v_mae += mean_absolute_error(y_h_v_clean, model.predict(X_h_v))
|
|
667
637
|
t_qlike += qlike_score(y_h_clean, model.predict(X_h))
|
|
668
638
|
v_qlike += qlike_score(y_h_v_clean, model.predict(X_h_v))
|
|
669
639
|
t_r2 += r2_score(y_h_clean, model.predict(X_h))
|
|
@@ -672,6 +642,8 @@ class FichEn:
|
|
|
672
642
|
|
|
673
643
|
var_test_error = float(t_error)/horizon
|
|
674
644
|
var_val_error = float(v_error)/horizon
|
|
645
|
+
var_test_mae = float(t_mae) / horizon
|
|
646
|
+
var_val_mae = float(v_mae) / horizon
|
|
675
647
|
var_test_qlike = float(t_qlike) / horizon
|
|
676
648
|
var_val_qlike = float(v_qlike) / horizon
|
|
677
649
|
var_test_r2 = float(t_r2)/horizon
|
|
@@ -679,10 +651,20 @@ class FichEn:
|
|
|
679
651
|
|
|
680
652
|
if self.early_stopping:
|
|
681
653
|
if len(self.val_errors) > 0:
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
654
|
+
if self.loss == "MAE":
|
|
655
|
+
current_min = min(self.val_mae)
|
|
656
|
+
best_so_far = min(self.best_val_mae, current_min)
|
|
657
|
+
no_improvement_count = len(self.val_mae) - self.val_mae.index(best_so_far) - 1
|
|
658
|
+
elif self.loss == "MSE":
|
|
659
|
+
current_min = min(self.val_errors)
|
|
660
|
+
best_so_far = min(self.best_val_error, current_min)
|
|
661
|
+
no_improvement_count = len(self.val_errors) - self.val_errors.index(best_so_far) - 1
|
|
662
|
+
elif self.loss == "QLIKE":
|
|
663
|
+
current_min = min(self.val_qlike)
|
|
664
|
+
best_so_far = min(self.best_val_qlike, current_min)
|
|
665
|
+
no_improvement_count = len(self.val_qlike) - self.val_qlike.index(best_so_far) - 1
|
|
666
|
+
else:
|
|
667
|
+
raise "Unavailable loss function"
|
|
686
668
|
|
|
687
669
|
if no_improvement_count >= self.patience:
|
|
688
670
|
self.dquantprint(f'Early stopping at {i} trees (no improvement for {self.patience} steps)')
|
|
@@ -694,6 +676,8 @@ class FichEn:
|
|
|
694
676
|
|
|
695
677
|
self.train_errors.append(var_test_error)
|
|
696
678
|
self.val_errors.append(var_val_error)
|
|
679
|
+
self.train_mae.append(var_test_mae)
|
|
680
|
+
self.val_mae.append(var_val_mae)
|
|
697
681
|
self.train_qlike.append(var_test_qlike)
|
|
698
682
|
self.val_qlike.append(var_val_qlike)
|
|
699
683
|
self.train_r2.append(var_test_r2)
|
|
@@ -702,12 +686,14 @@ class FichEn:
|
|
|
702
686
|
self.dquantprint('Validation QLIKE: ', var_val_qlike)
|
|
703
687
|
self.dquantprint('Train MSE: ', var_test_error)
|
|
704
688
|
self.dquantprint('Validation MSE: ', var_val_error)
|
|
689
|
+
self.dquantprint('Train MAE: ', var_test_mae)
|
|
690
|
+
self.dquantprint('Validation MAE: ', var_val_mae)
|
|
705
691
|
self.dquantprint('Train r2: ', var_test_r2)
|
|
706
692
|
self.dquantprint('Validation r2: ', var_val_r2)
|
|
707
|
-
self.dquantprint(f"
|
|
693
|
+
self.dquantprint(f"{time.time() - start} seconds spent")
|
|
708
694
|
|
|
709
695
|
except KeyboardInterrupt:
|
|
710
|
-
self.dquantprint("\
|
|
696
|
+
self.dquantprint("\nTraining interrupted by Ctrl+C!")
|
|
711
697
|
|
|
712
698
|
if show_results:
|
|
713
699
|
self.V.show_errors(self.train_errors, self.val_errors, self.train_r2, self.val_r2)
|
|
@@ -724,7 +710,7 @@ class FichEn:
|
|
|
724
710
|
X = feature_func(latest_data)
|
|
725
711
|
|
|
726
712
|
if not self.is_fitted and not self.onnx_load:
|
|
727
|
-
raise ValueError("
|
|
713
|
+
raise ValueError("The model is not trained yet!")
|
|
728
714
|
|
|
729
715
|
if self.onnx_load:
|
|
730
716
|
predictions = []
|
|
@@ -743,20 +729,15 @@ class FichEn:
|
|
|
743
729
|
|
|
744
730
|
pred_array = np.array(predictions)
|
|
745
731
|
|
|
746
|
-
# ИСПРАВЛЕНИЕ ЗДЕСЬ:
|
|
747
732
|
if pred_array.ndim == 1:
|
|
748
|
-
# Для одного сэмпла с 30 таргетами: (30,) -> (1, 30)
|
|
749
733
|
pred_array = pred_array.reshape(1, -1)
|
|
750
734
|
elif pred_array.ndim == 2:
|
|
751
735
|
if pred_array.shape[0] == 1 and pred_array.shape[1] == 30:
|
|
752
|
-
# Уже правильно (1, 30) - ничего не делаем
|
|
753
736
|
pass
|
|
754
737
|
elif pred_array.shape[0] == 30 and pred_array.shape[1] == 1:
|
|
755
|
-
# Неправильная форма (30, 1) -> (1, 30)
|
|
756
738
|
pred_array = pred_array.T
|
|
757
739
|
elif pred_array.shape[0] > 1 and pred_array.shape[1] == 30:
|
|
758
|
-
|
|
759
|
-
pred_array = pred_array[0:1, :] # Берем первую модель
|
|
740
|
+
pred_array = pred_array[0:1, :]
|
|
760
741
|
predictions = self.scaler_y.inverse_transform(pred_array).flatten()
|
|
761
742
|
|
|
762
743
|
if show:
|
|
@@ -792,20 +773,15 @@ class FichEn:
|
|
|
792
773
|
|
|
793
774
|
pred_array = np.array(predictions)
|
|
794
775
|
|
|
795
|
-
# ИСПРАВЛЕНИЕ ЗДЕСЬ:
|
|
796
776
|
if pred_array.ndim == 1:
|
|
797
|
-
# Для одного сэмпла с 30 таргетами: (30,) -> (1, 30)
|
|
798
777
|
pred_array = pred_array.reshape(1, -1)
|
|
799
778
|
elif pred_array.ndim == 2:
|
|
800
779
|
if pred_array.shape[0] == 1 and pred_array.shape[1] == 30:
|
|
801
|
-
# Уже правильно (1, 30) - ничего не делаем
|
|
802
780
|
pass
|
|
803
781
|
elif pred_array.shape[0] == 30 and pred_array.shape[1] == 1:
|
|
804
|
-
# Неправильная форма (30, 1) -> (1, 30)
|
|
805
782
|
pred_array = pred_array.T
|
|
806
783
|
elif pred_array.shape[0] > 1 and pred_array.shape[1] == 30:
|
|
807
|
-
|
|
808
|
-
pred_array = pred_array[0:1, :] # Берем первую модель
|
|
784
|
+
pred_array = pred_array[0:1, :]
|
|
809
785
|
predictions = self.scaler_y.inverse_transform(pred_array).flatten()
|
|
810
786
|
|
|
811
787
|
if show:
|
|
@@ -835,7 +811,6 @@ class FichEn:
|
|
|
835
811
|
scaler_data = {
|
|
836
812
|
"mean": self.scaler.mean_.tolist() if self.scaler.mean_ is not None else [],
|
|
837
813
|
"std": self.scaler.scale_.tolist() if self.scaler.scale_ is not None else [],
|
|
838
|
-
# scale_ = стандартное отклонение
|
|
839
814
|
"var": self.scaler.var_.tolist() if self.scaler.var_ is not None else []
|
|
840
815
|
}
|
|
841
816
|
mean_str = ','.join(str(x) for x in scaler_data['mean'])
|
|
@@ -844,7 +819,6 @@ class FichEn:
|
|
|
844
819
|
scaler_data_y = {
|
|
845
820
|
"mean": self.scaler_y.mean_.tolist() if self.scaler_y.mean_ is not None else [],
|
|
846
821
|
"std": self.scaler_y.scale_.tolist() if self.scaler_y.scale_ is not None else [],
|
|
847
|
-
# scale_ = стандартное отклонение
|
|
848
822
|
"var": self.scaler_y.var_.tolist() if self.scaler_y.var_ is not None else []
|
|
849
823
|
}
|
|
850
824
|
mean_str_y = ','.join(str(x) for x in scaler_data_y['mean'])
|
|
@@ -852,14 +826,12 @@ class FichEn:
|
|
|
852
826
|
|
|
853
827
|
|
|
854
828
|
os.makedirs(name, exist_ok=True)
|
|
855
|
-
self.dquantprint(f"
|
|
829
|
+
self.dquantprint(f"Directory '{name}' has been created or already exists")
|
|
856
830
|
|
|
857
|
-
# 2. Создаём папку для ONNX файлов
|
|
858
831
|
onnx_dir = os.path.join(name, f"{name}_onnx")
|
|
859
832
|
os.makedirs(onnx_dir, exist_ok=True)
|
|
860
833
|
|
|
861
|
-
|
|
862
|
-
mq5_file_path = os.path.join(name, f"{name}.mq5") # Изменено с .mql5 на .mq5
|
|
834
|
+
mq5_file_path = os.path.join(name, f"{name}.mq5")
|
|
863
835
|
with open(mq5_file_path, "w", encoding="utf-8") as f:
|
|
864
836
|
f.write("//+------------------------------------------------------------------+\n")
|
|
865
837
|
f.write(f"//| {name}.mq5 |\n")
|
|
@@ -914,10 +886,9 @@ class FichEn:
|
|
|
914
886
|
f.write(f' model_handle{i} = OnnxCreateFromBuffer(ExtModelData{i}, ONNX_USE_CPU_ONLY);\n')
|
|
915
887
|
f.write(f' if (model_handle{i} == INVALID_HANDLE)\n')
|
|
916
888
|
f.write(' {\n')
|
|
917
|
-
f.write(f' Print("
|
|
889
|
+
f.write(f' Print("Error loading ONNX model {i}: ", GetLastError());\n')
|
|
918
890
|
f.write(' return INIT_FAILED;\n')
|
|
919
891
|
f.write(' }\n')
|
|
920
|
-
# f.write(f' Print("ONNX-модель {i} успешно загружена");\n\n')
|
|
921
892
|
|
|
922
893
|
f.write(' return(INIT_SUCCEEDED);\n')
|
|
923
894
|
f.write('}\n\n')
|
|
@@ -1419,7 +1390,6 @@ class FichEn:
|
|
|
1419
1390
|
f.write(' return true;\n')
|
|
1420
1391
|
f.write('}\n\n')
|
|
1421
1392
|
|
|
1422
|
-
# GetForecast function
|
|
1423
1393
|
f.write('//+------------------------------------------------------------------+\n')
|
|
1424
1394
|
f.write('//| Get forecast from ONNX model |\n')
|
|
1425
1395
|
f.write('//+------------------------------------------------------------------+\n')
|
|
@@ -1455,9 +1425,8 @@ class FichEn:
|
|
|
1455
1425
|
f.write(' }\n')
|
|
1456
1426
|
f.write('}\n\n')
|
|
1457
1427
|
|
|
1458
|
-
self.dquantprint(f"
|
|
1428
|
+
self.dquantprint(f"File {mq5_file_path} created successfully")
|
|
1459
1429
|
|
|
1460
|
-
# 4. Создаём файл проекта MQL5 (.mqproj)
|
|
1461
1430
|
proj_file_path = os.path.join(name, f"{name}.mqproj")
|
|
1462
1431
|
with open(proj_file_path, "w", encoding="utf-8-sig") as f:
|
|
1463
1432
|
f.write('{\n')
|
|
@@ -1490,12 +1459,13 @@ class FichEn:
|
|
|
1490
1459
|
f.write(' ]\n')
|
|
1491
1460
|
f.write('}\n')
|
|
1492
1461
|
|
|
1493
|
-
self.dquantprint(f"
|
|
1462
|
+
self.dquantprint(f"File {proj_file_path} created successfully")
|
|
1494
1463
|
|
|
1495
1464
|
|
|
1496
1465
|
|
|
1497
1466
|
class VolClustGB(FichEn):
|
|
1498
|
-
def __init__(self, sett, early_stopping=True, output=True):
|
|
1467
|
+
def __init__(self, sett, early_stopping=True, output=True, loss="MAE"):
|
|
1468
|
+
self.loss = loss
|
|
1499
1469
|
self.output = output
|
|
1500
1470
|
self.models = []
|
|
1501
1471
|
self.scaler = StandardScaler()
|
|
@@ -1518,7 +1488,8 @@ class VolClustGB(FichEn):
|
|
|
1518
1488
|
}
|
|
1519
1489
|
self.meta = {
|
|
1520
1490
|
"model_type": "gb",
|
|
1521
|
-
"model_settings": self.default_sett
|
|
1491
|
+
"model_settings": self.default_sett,
|
|
1492
|
+
"model_loss": loss
|
|
1522
1493
|
}
|
|
1523
1494
|
if sett == {}:
|
|
1524
1495
|
self.base_model = GradientBoostingRegressor(**self.default_sett)
|
|
@@ -1564,36 +1535,35 @@ class VolClustGB(FichEn):
|
|
|
1564
1535
|
self.save_mql5(name)
|
|
1565
1536
|
onnx_dir = os.path.join(name, f"{name}_onnx")
|
|
1566
1537
|
os.makedirs(onnx_dir, exist_ok=True)
|
|
1567
|
-
self.dquantprint(f"
|
|
1538
|
+
self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
|
|
1568
1539
|
|
|
1569
|
-
# 4. Сохраняем модели и scaler в поддиректорию
|
|
1570
1540
|
initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
|
|
1571
1541
|
|
|
1572
1542
|
if hasattr(self, 'scaler') and self.scaler is not None:
|
|
1573
1543
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
|
|
1574
1544
|
joblib.dump(self.scaler, scaler_path)
|
|
1575
|
-
self.dquantprint(f"Scaler
|
|
1545
|
+
self.dquantprint(f"Scaler is saved in {scaler_path}")
|
|
1576
1546
|
|
|
1577
1547
|
if hasattr(self, 'scaler_y') and self.scaler_y is not None:
|
|
1578
1548
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
|
|
1579
1549
|
joblib.dump(self.scaler_y, scaler_path)
|
|
1580
|
-
self.dquantprint(f"Scalery
|
|
1550
|
+
self.dquantprint(f"Scalery is saved in {scaler_path}")
|
|
1581
1551
|
|
|
1582
1552
|
for i in range(len(self.models)):
|
|
1583
1553
|
onx = convert_sklearn(self.models[i], initial_types=initial_type, target_opset=12)
|
|
1584
1554
|
file_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
|
|
1585
1555
|
with open(file_path, "wb") as f:
|
|
1586
1556
|
f.write(onx.SerializeToString())
|
|
1587
|
-
self.dquantprint(f"
|
|
1557
|
+
self.dquantprint(f"Model {i} is saved in {file_path}")
|
|
1588
1558
|
|
|
1589
|
-
self.dquantprint(f"
|
|
1559
|
+
self.dquantprint(f"All operations in directory '{name}' completed successfully!")
|
|
1590
1560
|
|
|
1591
1561
|
|
|
1592
1562
|
def load(self, name):
|
|
1593
1563
|
self.loaded_models = []
|
|
1594
1564
|
|
|
1595
1565
|
if not os.path.exists(name):
|
|
1596
|
-
raise FileNotFoundError(f"
|
|
1566
|
+
raise FileNotFoundError(f"Directory {name} not found")
|
|
1597
1567
|
|
|
1598
1568
|
try:
|
|
1599
1569
|
file_path = os.path.join(name, f"{name}_features.json")
|
|
@@ -1627,7 +1597,7 @@ class VolClustGB(FichEn):
|
|
|
1627
1597
|
model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
|
|
1628
1598
|
|
|
1629
1599
|
if not model_files:
|
|
1630
|
-
raise FileNotFoundError(f"
|
|
1600
|
+
raise FileNotFoundError(f"No .onnx files found in directory {name}")
|
|
1631
1601
|
|
|
1632
1602
|
model_files.sort()
|
|
1633
1603
|
ml = len(model_files)
|
|
@@ -1656,7 +1626,8 @@ class VolClustGB(FichEn):
|
|
|
1656
1626
|
|
|
1657
1627
|
|
|
1658
1628
|
class VolClustXGB(FichEn):
|
|
1659
|
-
def __init__(self, sett, early_stopping=True, output=True,
|
|
1629
|
+
def __init__(self, sett, early_stopping=True, output=True, loss="QLIKE"):
|
|
1630
|
+
self.loss = loss
|
|
1660
1631
|
self.output = output
|
|
1661
1632
|
self.models = []
|
|
1662
1633
|
self.scaler = StandardScaler()
|
|
@@ -1666,31 +1637,41 @@ class VolClustXGB(FichEn):
|
|
|
1666
1637
|
self.onnx_load = False
|
|
1667
1638
|
self.early_stopping = early_stopping
|
|
1668
1639
|
self.V = Visualization('dark')
|
|
1669
|
-
# qlike_obj
|
|
1670
1640
|
self.default_sett = {
|
|
1671
|
-
#'objective': 'reg:squarederror',
|
|
1672
1641
|
'learning_rate': 0.1,
|
|
1673
|
-
'
|
|
1674
|
-
'max_depth': 3,
|
|
1642
|
+
'max_depth': 6,
|
|
1675
1643
|
'min_child_weight': 5,
|
|
1644
|
+
'gamma': 0.1,
|
|
1676
1645
|
'subsample': 0.8,
|
|
1677
|
-
'
|
|
1646
|
+
'colsample_bytree': 0.8,
|
|
1647
|
+
'reg_alpha': 0.0,
|
|
1648
|
+
'reg_lambda': 1.0,
|
|
1649
|
+
'random_state': 42,
|
|
1650
|
+
'tree_method': 'hist',
|
|
1651
|
+
'device': 'cpu'
|
|
1678
1652
|
}
|
|
1679
|
-
|
|
1653
|
+
|
|
1654
|
+
if loss == "MSE":
|
|
1680
1655
|
self.default_sett['objective'] = 'reg:squarederror'
|
|
1656
|
+
elif loss == "MAE":
|
|
1657
|
+
self.default_sett['objective'] = 'reg:absoluteerror'
|
|
1681
1658
|
|
|
1682
1659
|
self.meta = {
|
|
1683
1660
|
"model_type": "xgb",
|
|
1684
|
-
"model_settings": self.default_sett
|
|
1661
|
+
"model_settings": self.default_sett,
|
|
1662
|
+
"model_loss": loss
|
|
1685
1663
|
}
|
|
1686
1664
|
if sett == {}:
|
|
1687
|
-
if
|
|
1665
|
+
if loss == "QLIKE":
|
|
1688
1666
|
self.base_model = xgboost.XGBRegressor(**self.default_sett, objective=self.qlike_obj)
|
|
1689
1667
|
else:
|
|
1690
1668
|
self.base_model = xgboost.XGBRegressor(**self.default_sett)
|
|
1691
1669
|
else:
|
|
1692
|
-
|
|
1693
|
-
|
|
1670
|
+
try:
|
|
1671
|
+
if sett['objective']: del sett['objective']
|
|
1672
|
+
except KeyError:
|
|
1673
|
+
pass
|
|
1674
|
+
if loss == "QLIKE":
|
|
1694
1675
|
self.base_model = xgboost.XGBRegressor(**sett, objective=self.qlike_obj)
|
|
1695
1676
|
else:
|
|
1696
1677
|
self.base_model = xgboost.XGBRegressor(**sett)
|
|
@@ -1733,28 +1714,27 @@ class VolClustXGB(FichEn):
|
|
|
1733
1714
|
self.save_mql5(name)
|
|
1734
1715
|
onnx_dir = os.path.join(name, f"{name}_onnx")
|
|
1735
1716
|
os.makedirs(onnx_dir, exist_ok=True)
|
|
1736
|
-
self.dquantprint(f"
|
|
1717
|
+
self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
|
|
1737
1718
|
|
|
1738
|
-
# 4. Сохраняем модели и scaler в поддиректорию
|
|
1739
1719
|
initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
|
|
1740
1720
|
|
|
1741
1721
|
if hasattr(self, 'scaler') and self.scaler is not None:
|
|
1742
1722
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
|
|
1743
1723
|
joblib.dump(self.scaler, scaler_path)
|
|
1744
|
-
self.dquantprint(f"Scaler
|
|
1724
|
+
self.dquantprint(f"Scaler is saved in {scaler_path}")
|
|
1745
1725
|
|
|
1746
1726
|
if hasattr(self, 'scaler_y') and self.scaler_y is not None:
|
|
1747
1727
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
|
|
1748
1728
|
joblib.dump(self.scaler_y, scaler_path)
|
|
1749
|
-
self.dquantprint(f"Scalery
|
|
1729
|
+
self.dquantprint(f"Scalery is saved in {scaler_path}")
|
|
1750
1730
|
|
|
1751
1731
|
for i in range(len(self.models)):
|
|
1752
1732
|
onx = onnxmltools.convert_xgboost(self.models[i], initial_types=initial_type, target_opset=9)
|
|
1753
1733
|
model_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
|
|
1754
1734
|
onnxmltools.utils.save_model(onx, model_path)
|
|
1755
|
-
self.dquantprint(f"
|
|
1735
|
+
self.dquantprint(f"Model {i} is saved in {model_path}")
|
|
1756
1736
|
|
|
1757
|
-
self.dquantprint(f"
|
|
1737
|
+
self.dquantprint(f"All operations in directory '{name}' completed successfully!")
|
|
1758
1738
|
|
|
1759
1739
|
|
|
1760
1740
|
|
|
@@ -1762,7 +1742,7 @@ class VolClustXGB(FichEn):
|
|
|
1762
1742
|
self.loaded_models = []
|
|
1763
1743
|
|
|
1764
1744
|
if not os.path.exists(name):
|
|
1765
|
-
raise FileNotFoundError(f"
|
|
1745
|
+
raise FileNotFoundError(f"Directory {name} not found")
|
|
1766
1746
|
|
|
1767
1747
|
try:
|
|
1768
1748
|
file_path = os.path.join(name, f"{name}_features.json")
|
|
@@ -1796,7 +1776,7 @@ class VolClustXGB(FichEn):
|
|
|
1796
1776
|
model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
|
|
1797
1777
|
|
|
1798
1778
|
if not model_files:
|
|
1799
|
-
raise FileNotFoundError(f"
|
|
1779
|
+
raise FileNotFoundError(f"No .onnx files found in directory {name}")
|
|
1800
1780
|
|
|
1801
1781
|
model_files.sort()
|
|
1802
1782
|
ml = len(model_files)
|
|
@@ -1823,7 +1803,8 @@ class VolClustXGB(FichEn):
|
|
|
1823
1803
|
|
|
1824
1804
|
|
|
1825
1805
|
class VolClustLightGBM(FichEn):
|
|
1826
|
-
def __init__(self, sett, early_stopping=True, output=True,
|
|
1806
|
+
def __init__(self, sett, early_stopping=True, output=True, loss="QLIKE"):
|
|
1807
|
+
self.loss = loss
|
|
1827
1808
|
self.output = output
|
|
1828
1809
|
self.models = []
|
|
1829
1810
|
self.scaler = StandardScaler()
|
|
@@ -1834,28 +1815,42 @@ class VolClustLightGBM(FichEn):
|
|
|
1834
1815
|
self.early_stopping = early_stopping
|
|
1835
1816
|
self.V = Visualization('dark')
|
|
1836
1817
|
self.default_sett = {
|
|
1837
|
-
'num_leaves': 7,
|
|
1838
|
-
'min_data_in_leaf': 3,
|
|
1839
|
-
'min_data_in_bin': 3,
|
|
1840
1818
|
'learning_rate': 0.1,
|
|
1819
|
+
'max_depth': 6,
|
|
1820
|
+
'num_leaves': 2**6 - 1,
|
|
1821
|
+
'min_child_samples': 5,
|
|
1822
|
+
'min_split_gain': 0.1,
|
|
1823
|
+
'bagging_fraction': 0.8,
|
|
1824
|
+
'bagging_freq': 1,
|
|
1825
|
+
'feature_fraction': 0.8,
|
|
1826
|
+
'reg_alpha': 0.0,
|
|
1827
|
+
'reg_lambda': 1.0,
|
|
1828
|
+
'random_state': 42,
|
|
1841
1829
|
'verbosity': -1,
|
|
1842
|
-
'
|
|
1830
|
+
'boosting_type': 'gbdt'
|
|
1843
1831
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1832
|
+
|
|
1833
|
+
if loss == "MSE":
|
|
1834
|
+
self.default_sett['objective'] = 'mse'
|
|
1835
|
+
elif loss == "MAE":
|
|
1836
|
+
self.default_sett['objective'] = 'mae'
|
|
1846
1837
|
|
|
1847
1838
|
self.meta = {
|
|
1848
1839
|
"model_type": "lgbm",
|
|
1849
|
-
"model_settings": self.default_sett
|
|
1840
|
+
"model_settings": self.default_sett,
|
|
1841
|
+
"models_loss": loss
|
|
1850
1842
|
}
|
|
1851
1843
|
if sett == {}:
|
|
1852
|
-
if
|
|
1844
|
+
if loss == "QLIKE":
|
|
1853
1845
|
self.base_model = lgb.LGBMRegressor(**self.default_sett, objective=self.qlike_obj)
|
|
1854
1846
|
else:
|
|
1855
1847
|
self.base_model = lgb.LGBMRegressor(**self.default_sett)
|
|
1856
1848
|
else:
|
|
1857
|
-
|
|
1858
|
-
|
|
1849
|
+
try:
|
|
1850
|
+
if sett['objective']: del sett['objective']
|
|
1851
|
+
except KeyError:
|
|
1852
|
+
pass
|
|
1853
|
+
if loss == "QLIKE":
|
|
1859
1854
|
self.base_model = lgb.LGBMRegressor(**sett, objective=self.qlike_obj)
|
|
1860
1855
|
else:
|
|
1861
1856
|
self.base_model = lgb.LGBMRegressor(**sett)
|
|
@@ -1898,36 +1893,35 @@ class VolClustLightGBM(FichEn):
|
|
|
1898
1893
|
self.save_mql5(name)
|
|
1899
1894
|
onnx_dir = os.path.join(name, f"{name}_onnx")
|
|
1900
1895
|
os.makedirs(onnx_dir, exist_ok=True)
|
|
1901
|
-
self.dquantprint(f"
|
|
1896
|
+
self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
|
|
1902
1897
|
|
|
1903
|
-
# 4. Сохраняем модели и scaler в поддиректорию
|
|
1904
1898
|
initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
|
|
1905
1899
|
|
|
1906
1900
|
if hasattr(self, 'scaler') and self.scaler is not None:
|
|
1907
1901
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
|
|
1908
1902
|
joblib.dump(self.scaler, scaler_path)
|
|
1909
|
-
self.dquantprint(f"Scaler
|
|
1903
|
+
self.dquantprint(f"Scaler is saved in {scaler_path}")
|
|
1910
1904
|
|
|
1911
1905
|
if hasattr(self, 'scaler_y') and self.scaler_y is not None:
|
|
1912
1906
|
scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
|
|
1913
1907
|
joblib.dump(self.scaler_y, scaler_path)
|
|
1914
|
-
self.dquantprint(f"Scalery
|
|
1908
|
+
self.dquantprint(f"Scalery is saved in {scaler_path}")
|
|
1915
1909
|
|
|
1916
1910
|
for i in range(len(self.models)):
|
|
1917
1911
|
onx = onnxmltools.convert_lightgbm(self.models[i], initial_types=initial_type, zipmap=False,
|
|
1918
1912
|
target_opset=12)
|
|
1919
1913
|
file_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
|
|
1920
1914
|
onnxmltools.utils.save_model(onx, file_path)
|
|
1921
|
-
self.dquantprint(f"
|
|
1915
|
+
self.dquantprint(f"Model {i} is saved in {file_path}")
|
|
1922
1916
|
|
|
1923
|
-
self.dquantprint(f"
|
|
1917
|
+
self.dquantprint(f"All operations in directory '{name}' completed successfully!")
|
|
1924
1918
|
|
|
1925
1919
|
|
|
1926
1920
|
def load(self, name):
|
|
1927
1921
|
self.loaded_models = []
|
|
1928
1922
|
|
|
1929
1923
|
if not os.path.exists(name):
|
|
1930
|
-
raise FileNotFoundError(f"
|
|
1924
|
+
raise FileNotFoundError(f"Directory {name} not found")
|
|
1931
1925
|
|
|
1932
1926
|
try:
|
|
1933
1927
|
file_path = os.path.join(name, f"{name}_features.json")
|
|
@@ -1961,7 +1955,7 @@ class VolClustLightGBM(FichEn):
|
|
|
1961
1955
|
model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
|
|
1962
1956
|
|
|
1963
1957
|
if not model_files:
|
|
1964
|
-
raise FileNotFoundError(f"
|
|
1958
|
+
raise FileNotFoundError(f"No .onnx files found in directory {name}")
|
|
1965
1959
|
|
|
1966
1960
|
model_files.sort()
|
|
1967
1961
|
ml = len(model_files)
|
|
@@ -1985,170 +1979,3 @@ class VolClustLightGBM(FichEn):
|
|
|
1985
1979
|
self.loaded_models.append(session)
|
|
1986
1980
|
|
|
1987
1981
|
self.onnx_load = True
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
"""
|
|
1991
|
-
time spended: 65.44393944740295
|
|
1992
|
-
[ 1.00901477e-02 6.06840734e-03 7.89991808e-03 2.40415813e-03
|
|
1993
|
-
1.30973943e-04 2.53802438e-03 7.55212328e-03 6.40525625e-01
|
|
1994
|
-
0.00000000e+00 2.81739978e-02 1.71405577e-02 7.20318643e-03
|
|
1995
|
-
2.66850655e-02 1.37758612e-05 2.63183893e-02 1.85560851e-03
|
|
1996
|
-
9.53905366e-01 0.00000000e+00 4.29736387e-02 2.55626153e-02
|
|
1997
|
-
2.36549673e-02 2.80319922e-02 -3.03892649e-04 2.81246929e-02
|
|
1998
|
-
1.48489457e-02 2.72801986e-01 0.00000000e+00 3.72218795e-02
|
|
1999
|
-
2.20329899e-02 1.21903154e-02 3.24872375e-02 1.21786687e-04
|
|
2000
|
-
3.31424959e-02 4.07938359e-03 1.05498777e-01 0.00000000e+00
|
|
2001
|
-
7.37316373e-02 4.32737643e-02 3.21723278e-02 5.74076879e-02
|
|
2002
|
-
-3.87169703e-04 5.87003299e-02 1.50313074e-02 1.78512223e-01
|
|
2003
|
-
0.00000000e+00 4.04910463e-02 2.44025016e-02 2.97286458e-02
|
|
2004
|
-
4.09296639e-03 5.20381594e-04 4.62173561e-03 3.58693107e-02
|
|
2005
|
-
5.82791094e-01 0.00000000e+00 4.58374744e-02 2.74720640e-02
|
|
2006
|
-
3.16518085e-02 1.28362178e-02 4.88255628e-04 1.34072113e-02
|
|
2007
|
-
3.24302631e-02 4.51602205e-01 0.00000000e+00 2.04805939e-02
|
|
2008
|
-
1.21755897e-02 1.55781241e-02 8.44683596e-03 -1.44448658e-04
|
|
2009
|
-
8.33816248e-03 1.21424314e-02 0.00000000e+00 0.00000000e+00
|
|
2010
|
-
2.98493845e-02 1.78514990e-02 2.09793890e-02 4.31824090e-03
|
|
2011
|
-
2.91972368e-05 4.35677518e-03 2.54926093e-02 3.56991113e-01
|
|
2012
|
-
0.00000000e+00 4.38209920e-02 2.67519393e-02 1.94066006e-02
|
|
2013
|
-
3.52507396e-02 9.13841081e-05 3.45452848e-02 9.27570718e-03
|
|
2014
|
-
8.67142706e-01 0.00000000e+00 2.23729157e-02 1.34131927e-02
|
|
2015
|
-
1.50097284e-02 9.27476481e-03 -4.87292988e-04 8.83061573e-03
|
|
2016
|
-
1.35423000e-02 4.21120863e-01 0.00000000e+00 1.49549846e-02
|
|
2017
|
-
8.95837170e-03 1.02428690e-02 3.70974367e-03 8.63321678e-05
|
|
2018
|
-
3.80296545e-03 1.11520191e-02 3.26991207e-01 0.00000000e+00
|
|
2019
|
-
4.26058712e-02 2.58258056e-02 1.75734110e-02 3.62848420e-02
|
|
2020
|
-
5.55038464e-04 3.50793990e-02 7.30531730e-03 8.35520105e-01
|
|
2021
|
-
0.00000000e+00 1.48660486e-02 8.95036835e-03 9.96263886e-03
|
|
2022
|
-
4.81100437e-03 -4.97779422e-05 4.84922797e-03 1.00168207e-02
|
|
2023
|
-
6.67079520e-01 0.00000000e+00 3.05811410e-02 1.81291235e-02
|
|
2024
|
-
1.35250294e-02 2.35798305e-02 -1.06096226e-04 2.37539365e-02
|
|
2025
|
-
6.82720443e-03 7.05013333e-02 0.00000000e+00 9.97877681e-02
|
|
2026
|
-
5.71429634e-02 9.93251430e-03 9.43035288e-02 -2.15592232e-04
|
|
2027
|
-
9.86776488e-02 1.11011933e-03 3.53888733e-03 0.00000000e+00
|
|
2028
|
-
6.15493679e-02 3.69277996e-02 4.30480571e-02 2.30142933e-02
|
|
2029
|
-
3.82434298e-04 2.36635998e-02 3.78857681e-02 4.78877653e-01
|
|
2030
|
-
0.00000000e+00 4.07323827e-02 2.42627809e-02 3.03729349e-02
|
|
2031
|
-
1.75768508e-03 -1.89331202e-04 1.56989951e-03 3.91624832e-02
|
|
2032
|
-
2.94759703e-01 0.00000000e+00 3.89312610e-02 2.37273964e-02
|
|
2033
|
-
3.48261445e-02 2.14988488e-04 4.55482200e-05 1.69417160e-04
|
|
2034
|
-
3.87618438e-02 8.72129781e-01 0.00000000e+00 6.17359291e-01
|
|
2035
|
-
2.93932853e-01 1.08930483e-01 4.64730175e-01 4.39776373e-04
|
|
2036
|
-
5.92024459e-01 2.53348322e-02 3.59865231e-02 0.00000000e+00
|
|
2037
|
-
3.11147546e-01 2.11229224e-01 2.60957183e-01 1.12686222e-01
|
|
2038
|
-
8.45532816e-03 9.81137169e-02 2.13033829e-01 8.41486709e-01
|
|
2039
|
-
0.00000000e+00 9.61773087e-02 5.59225605e-02 4.42007214e-02
|
|
2040
|
-
6.75355700e-02 1.80191261e-03 7.16702268e-02 2.45070819e-02
|
|
2041
|
-
1.50546410e-01 0.00000000e+00 1.23761654e-01 7.29214118e-02
|
|
2042
|
-
9.68913447e-02 3.62457326e-02 1.29941148e-04 3.54667798e-02
|
|
2043
|
-
8.82948742e-02 3.34199130e-01 0.00000000e+00 1.62919592e-01
|
|
2044
|
-
9.78764618e-02 1.22212154e-01 7.26450577e-02 -1.41299781e-03
|
|
2045
|
-
7.39357846e-02 8.75708093e-02 5.42211975e-01 0.00000000e+00
|
|
2046
|
-
7.45248895e-02 4.52017387e-02 4.64108595e-02 4.12455257e-02
|
|
2047
|
-
-2.27759272e-03 4.26840965e-02 3.18407930e-02 6.25823123e-01
|
|
2048
|
-
0.00000000e+00 5.01099799e-02 3.03195942e-02 3.68273961e-02
|
|
2049
|
-
2.44820439e-03 2.83362114e-04 2.16184786e-03 4.79481321e-02
|
|
2050
|
-
6.44204942e-01 0.00000000e+00 1.76503480e-01 1.13815750e-01
|
|
2051
|
-
6.65450214e-02 1.67104324e-01 1.12708932e-03 1.52761574e-01
|
|
2052
|
-
2.37419066e-02 8.73218209e-01 0.00000000e+00 1.57850455e-01
|
|
2053
|
-
9.26514801e-02 1.13630263e-01 1.22445001e-03 7.43594102e-05
|
|
2054
|
-
1.14934127e-03 1.56701114e-01 3.40320281e-01 0.00000000e+00
|
|
2055
|
-
7.19979354e-02 4.34659656e-02 5.21177072e-02 2.21448508e-03
|
|
2056
|
-
1.25191284e-03 3.46885170e-03 6.85290837e-02 5.66441411e-01
|
|
2057
|
-
0.00000000e+00 9.19313837e-02 5.28749679e-02 4.98083731e-02
|
|
2058
|
-
5.90770239e-02 8.43358015e-05 6.09412847e-02 3.09900990e-02
|
|
2059
|
-
1.22037653e-02 0.00000000e+00 1.02696046e-01 6.47826521e-02
|
|
2060
|
-
3.54393880e-02 9.57832377e-02 1.74497187e-04 9.11645446e-02
|
|
2061
|
-
1.15315016e-02 9.58084134e-01 0.00000000e+00 5.61199048e-02
|
|
2062
|
-
3.44009941e-02 2.49703201e-02 4.84447086e-02 3.01829683e-03
|
|
2063
|
-
4.42716886e-02 1.18482162e-02 8.56546369e-01 0.00000000e+00
|
|
2064
|
-
5.32228122e-02 3.18107827e-02 3.69621168e-02 8.01155994e-03
|
|
2065
|
-
5.85698106e-04 8.62943647e-03 4.45933758e-02 4.05350998e-01
|
|
2066
|
-
0.00000000e+00 2.15145177e-02 1.30245089e-02 1.62742830e-02
|
|
2067
|
-
5.28121136e-03 -8.77263769e-04 6.14455405e-03 1.53699637e-02
|
|
2068
|
-
8.68350803e-01 0.00000000e+00 5.05633636e-02 2.96374579e-02
|
|
2069
|
-
2.35973846e-02 3.74133767e-02 4.55768528e-04 3.85778362e-02
|
|
2070
|
-
1.19855274e-02 9.46606724e-03 0.00000000e+00 5.63840947e-02
|
|
2071
|
-
3.33798150e-02 3.34520599e-02 3.58132408e-02 -4.07618484e-04
|
|
2072
|
-
3.60546411e-02 1.99614159e-02 3.55645082e-01 0.00000000e+00
|
|
2073
|
-
5.57884077e-02 3.26136331e-02 7.71543102e-03 5.26502133e-02
|
|
2074
|
-
5.79304149e-04 5.46401883e-02 1.14821941e-03 5.92355248e-03
|
|
2075
|
-
0.00000000e+00 9.54862414e-02 5.94218027e-02 4.00815346e-02
|
|
2076
|
-
8.22684486e-02 5.43653418e-04 7.84316689e-02 1.70545725e-02
|
|
2077
|
-
8.57720697e-01 0.00000000e+00 2.02454145e-02 1.21577151e-02
|
|
2078
|
-
1.43197749e-02 1.36810741e-03 1.18759225e-04 1.24841275e-03
|
|
2079
|
-
1.89970017e-02 4.94675292e-01 0.00000000e+00 6.20877978e-02
|
|
2080
|
-
3.84604802e-02 4.87031762e-02 2.57778032e-02 -2.00581227e-04
|
|
2081
|
-
2.56489734e-02 3.64388244e-02 9.85866990e-01 0.00000000e+00
|
|
2082
|
-
7.24692836e-02 4.32326577e-02 5.50895288e-02 2.78887560e-02
|
|
2083
|
-
0.00000000e+00 2.75034548e-02 4.49658288e-02 4.01572960e-01
|
|
2084
|
-
0.00000000e+00 4.89923950e-02 2.89772392e-02 3.65664667e-02
|
|
2085
|
-
8.90628383e-03 5.60189477e-04 9.50625226e-03 3.94861427e-02
|
|
2086
|
-
1.82037110e-01 0.00000000e+00 2.65697886e-02 1.61453720e-02
|
|
2087
|
-
1.38432176e-02 1.97258038e-02 7.27424183e-04 1.88050990e-02
|
|
2088
|
-
7.76468969e-03 9.37379581e-01 0.00000000e+00 2.46622989e-02
|
|
2089
|
-
1.47933610e-02 1.67767982e-02 1.11868608e-02 -7.34744665e-04
|
|
2090
|
-
1.05149231e-02 1.41473759e-02 4.48996965e-01 0.00000000e+00
|
|
2091
|
-
6.72313405e-02 4.17978961e-02 7.27511817e-03 6.83840155e-02
|
|
2092
|
-
-4.23498691e-04 6.65217268e-02 7.09613790e-04 1.00000000e+00
|
|
2093
|
-
0.00000000e+00 4.05808633e-02 2.40200436e-02 2.87843914e-02
|
|
2094
|
-
1.32013831e-02 2.59571539e-04 1.35484777e-02 2.70323856e-02
|
|
2095
|
-
1.36321339e-01 0.00000000e+00 2.76677447e-02 1.67989744e-02
|
|
2096
|
-
1.27991081e-02 2.17346261e-02 3.91139046e-04 2.11089920e-02
|
|
2097
|
-
6.55875268e-03 8.90965792e-01 0.00000000e+00 2.22339109e-02
|
|
2098
|
-
1.34302943e-02 1.93488183e-02 4.37399798e-03 5.29667003e-04
|
|
2099
|
-
4.91324488e-03 1.73206660e-02 7.57573661e-01 0.00000000e+00
|
|
2100
|
-
7.30232075e-02 4.27061128e-02 2.56072816e-02 6.16526462e-02
|
|
2101
|
-
2.51412998e-04 6.38442505e-02 9.17895698e-03 1.25699176e-01
|
|
2102
|
-
0.00000000e+00 1.98494355e-02 1.19230831e-02 1.40594483e-02
|
|
2103
|
-
9.34113613e-04 2.83895912e-04 1.21844594e-03 1.86309896e-02
|
|
2104
|
-
5.07988653e-01 0.00000000e+00 4.43071401e-02 2.66348271e-02
|
|
2105
|
-
3.08453405e-02 1.61980943e-02 -1.45620908e-04 1.62132316e-02
|
|
2106
|
-
2.80939085e-02 5.18062994e-01 0.00000000e+00 4.42411056e-02
|
|
2107
|
-
2.62008186e-02 3.37862051e-02 1.82479034e-02 -7.99863781e-04
|
|
2108
|
-
1.76155499e-02 2.58256919e-02 5.94497091e-01 0.00000000e+00
|
|
2109
|
-
2.40756419e-02 1.43885928e-02 1.82440682e-02 3.81350856e-04
|
|
2110
|
-
-2.56613507e-04 1.24810073e-04 2.39508318e-02 2.95056894e-01
|
|
2111
|
-
0.00000000e+00 4.44530014e-02 2.61539413e-02 2.34725191e-02
|
|
2112
|
-
2.97129371e-02 4.71806267e-04 3.06305774e-02 1.38224240e-02
|
|
2113
|
-
2.94891979e-02 0.00000000e+00 8.13491945e-02 5.08256128e-02
|
|
2114
|
-
3.51490041e-02 6.90291127e-02 -2.32655230e-04 6.69331464e-02
|
|
2115
|
-
1.44160481e-02 9.69519652e-01 0.00000000e+00 1.64667468e-02
|
|
2116
|
-
9.87202072e-03 1.14533989e-02 2.90152110e-03 -3.54366267e-05
|
|
2117
|
-
2.87029796e-03 1.35964488e-02 3.92401519e-01 0.00000000e+00
|
|
2118
|
-
2.48991200e-02 1.51168312e-02 7.20748225e-03 2.25009020e-02
|
|
2119
|
-
-5.36407562e-04 2.27860523e-02 2.11306769e-03 9.31981961e-01
|
|
2120
|
-
0.00000000e+00 1.57825262e-02 9.43347831e-03 8.63093904e-03
|
|
2121
|
-
9.44698796e-03 4.53071603e-04 9.94482320e-03 5.83770297e-03
|
|
2122
|
-
1.97150369e-01 0.00000000e+00 5.88186630e-02 3.45510576e-02
|
|
2123
|
-
2.67466667e-02 4.37078926e-02 -3.70718529e-04 4.43064339e-02
|
|
2124
|
-
1.45122291e-02 1.14765291e-01 0.00000000e+00 1.45500976e-02
|
|
2125
|
-
8.73308037e-03 1.03194872e-02 2.37642848e-04 -3.16019514e-04
|
|
2126
|
-
7.83484265e-05 1.44717492e-02 4.58307320e-01 0.00000000e+00
|
|
2127
|
-
3.90720635e-02 2.38379593e-02 1.46013508e-02 3.38498125e-02
|
|
2128
|
-
-1.24039168e-04 3.34073566e-02 5.66470690e-03 8.96944072e-01
|
|
2129
|
-
0.00000000e+00 5.52093720e-02 3.38163892e-02 2.62722462e-02
|
|
2130
|
-
4.29733472e-02 5.51653396e-04 4.15114252e-02 1.36979468e-02
|
|
2131
|
-
8.48703084e-01 0.00000000e+00 1.91329742e-02 1.12056766e-02
|
|
2132
|
-
7.58118553e-03 1.61780845e-02 5.90264833e-04 1.54576573e-02
|
|
2133
|
-
3.08505200e-03 8.33624529e-01 0.00000000e+00 1.58114158e-02
|
|
2134
|
-
9.48141355e-03 1.16968974e-02 2.51773978e-03 -5.52143041e-05
|
|
2135
|
-
2.56978724e-03 1.32416286e-02 4.03234229e-01 0.00000000e+00
|
|
2136
|
-
1.81235587e-02 1.09543091e-02 7.99943802e-03 1.44176361e-02
|
|
2137
|
-
2.64490251e-05 1.42877506e-02 3.83580801e-03 8.51084356e-01
|
|
2138
|
-
0.00000000e+00 1.49035498e-02 9.01786107e-03 0.00000000e+00
|
|
2139
|
-
1.49573560e-02 -5.74993747e-05 1.49035498e-02 0.00000000e+00
|
|
2140
|
-
1.00000000e+00 0.00000000e+00 1.07237191e-02 6.46880826e-03
|
|
2141
|
-
9.26255244e-03 1.46866263e-03 1.75372147e-04 1.29221253e-03
|
|
2142
|
-
9.43150654e-03 9.10789689e-01 0.00000000e+00 1.23360969e-01
|
|
2143
|
-
7.83966160e-02 3.67183038e-02 1.19841406e-01 -3.93352924e-05
|
|
2144
|
-
1.12978228e-01 1.03827418e-02 9.34866426e-01 0.00000000e+00
|
|
2145
|
-
1.04797471e-01 6.06890467e-02 8.08996063e-02 1.63219782e-02
|
|
2146
|
-
-3.88998460e-04 1.60669109e-02 8.87305601e-02 1.38085306e-01
|
|
2147
|
-
0.00000000e+00 4.39345720e-02 2.57854018e-02 2.96597192e-02
|
|
2148
|
-
2.35369104e-02 1.60506376e-03 2.16570141e-02 2.12386179e-02
|
|
2149
|
-
5.18074610e-01 0.00000000e+00]
|
|
2150
|
-
[0.02178552 0.03785454 0.03499315 0.02283531 0.04798502 0.08585039
|
|
2151
|
-
0.023324 0.03473237 0.13709623 0.07662905 0.04318881 0.05538318
|
|
2152
|
-
0.05529575 0.05300378 0.03236753 0.04895759 0.0345107 0.03046795
|
|
2153
|
-
0.03755051 0.0754602 ]
|
|
2154
|
-
"""
|
|
@@ -269,7 +269,7 @@ class Visualization:
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
fig.savefig(filename, **save_kwargs)
|
|
272
|
-
print(f"
|
|
272
|
+
print(f"The graph saved as {filename}")
|
|
273
273
|
|
|
274
274
|
def show_vol(self, df, pred, save_path=None):
|
|
275
275
|
fig, ax = self.__create_figure(figsize=(15, 6))
|
|
@@ -299,9 +299,9 @@ class Visualization:
|
|
|
299
299
|
|
|
300
300
|
ax.set_xlim(-1, len(df))
|
|
301
301
|
ax.set_ylim(0, max_bar_height * 1.3)
|
|
302
|
-
ax.set_xlabel('
|
|
302
|
+
ax.set_xlabel('Time')
|
|
303
303
|
ax.set_ylabel('')
|
|
304
|
-
ax.set_title('
|
|
304
|
+
ax.set_title('Volumetric graph')
|
|
305
305
|
|
|
306
306
|
self.__style_axes(ax)
|
|
307
307
|
|
|
@@ -315,10 +315,8 @@ class Visualization:
|
|
|
315
315
|
plt.show()
|
|
316
316
|
|
|
317
317
|
def forward_validation_errors(self, mse_errors, r2_errors, save_path=None):
|
|
318
|
-
# Первый график - MSE Loss
|
|
319
318
|
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
|
320
319
|
|
|
321
|
-
# Первый график - MSE Loss
|
|
322
320
|
ax1.plot(list(mse_errors), label='Train Loss',
|
|
323
321
|
color=self.config['colors']['primary'])
|
|
324
322
|
ax1.set_xlabel('Trees')
|
|
@@ -329,7 +327,6 @@ class Visualization:
|
|
|
329
327
|
self.__style_axes(ax1)
|
|
330
328
|
self.__style_legend(ax1)
|
|
331
329
|
|
|
332
|
-
# Второй график - R² Score
|
|
333
330
|
ax2.plot(list(r2_errors), label='Train R²',
|
|
334
331
|
color=self.config['colors']['primary'])
|
|
335
332
|
|
|
@@ -350,10 +347,8 @@ class Visualization:
|
|
|
350
347
|
|
|
351
348
|
|
|
352
349
|
def show_errors(self, train_errors, val_errors, train_r2, val_r2, save_path=None):
|
|
353
|
-
# Первый график - MSE Loss
|
|
354
350
|
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
|
355
351
|
|
|
356
|
-
# Первый график - MSE Loss
|
|
357
352
|
ax1.plot(list(train_errors), label='Train Loss',
|
|
358
353
|
color=self.config['colors']['primary'])
|
|
359
354
|
ax1.plot(list(val_errors), label='Validation Loss',
|
|
@@ -366,7 +361,6 @@ class Visualization:
|
|
|
366
361
|
self.__style_axes(ax1)
|
|
367
362
|
self.__style_legend(ax1)
|
|
368
363
|
|
|
369
|
-
# Второй график - R² Score
|
|
370
364
|
ax2.plot(list(train_r2), label='Train R²',
|
|
371
365
|
color=self.config['colors']['primary'])
|
|
372
366
|
ax2.plot(list(val_r2), label='Validation R²',
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def qlike_score(y_true, y_pred):
|
|
5
|
-
y_true = np.asarray(y_true, dtype=np.float64)
|
|
6
|
-
y_pred = np.asarray(y_pred, dtype=np.float64)
|
|
7
|
-
eps = 1e-10
|
|
8
|
-
y_pred = np.clip(y_pred, eps, None)
|
|
9
|
-
loss = np.log(y_pred) + y_true / y_pred
|
|
10
|
-
return np.mean(loss)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|