upgini 1.1.223__py3-none-any.whl → 1.1.224__py3-none-any.whl
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.
Potentially problematic release.
This version of upgini might be problematic. Click here for more details.
- upgini/dataset.py +5 -1
- upgini/features_enricher.py +315 -214
- upgini/resource_bundle/strings.properties +3 -2
- upgini/utils/display_utils.py +10 -3
- {upgini-1.1.223.dist-info → upgini-1.1.224.dist-info}/METADATA +18 -16
- {upgini-1.1.223.dist-info → upgini-1.1.224.dist-info}/RECORD +9 -10
- {upgini-1.1.223.dist-info → upgini-1.1.224.dist-info}/WHEEL +1 -1
- upgini/fingerprint.js +0 -8
- {upgini-1.1.223.dist-info → upgini-1.1.224.dist-info}/LICENSE +0 -0
- {upgini-1.1.223.dist-info → upgini-1.1.224.dist-info}/top_level.txt +0 -0
upgini/dataset.py
CHANGED
|
@@ -349,7 +349,11 @@ class Dataset: # (pd.DataFrame):
|
|
|
349
349
|
self.columns_renaming[ipv4] = original_ip
|
|
350
350
|
|
|
351
351
|
ipv6 = ip + "_v6"
|
|
352
|
-
self.data[ipv6] =
|
|
352
|
+
self.data[ipv6] = (
|
|
353
|
+
self.data[ip].apply(self._to_ipv6)
|
|
354
|
+
.apply(self.__ip_to_int)
|
|
355
|
+
.astype("string").str.replace(".0", "", regex=False)
|
|
356
|
+
)
|
|
353
357
|
self.data = self.data.drop(columns=ip)
|
|
354
358
|
self.meaning_types[ipv6] = FileColumnMeaningType.IPV6_ADDRESS
|
|
355
359
|
self.etalon_def[FileColumnMeaningType.IPV6_ADDRESS.value] = ipv6
|
upgini/features_enricher.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from functools import reduce
|
|
2
1
|
import gc
|
|
3
2
|
import hashlib
|
|
4
3
|
import itertools
|
|
@@ -11,6 +10,8 @@ import sys
|
|
|
11
10
|
import tempfile
|
|
12
11
|
import time
|
|
13
12
|
import uuid
|
|
13
|
+
from collections import namedtuple
|
|
14
|
+
from functools import reduce
|
|
14
15
|
from threading import Thread
|
|
15
16
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
|
16
17
|
|
|
@@ -294,6 +295,18 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
294
295
|
|
|
295
296
|
api_key = property(_get_api_key, _set_api_key)
|
|
296
297
|
|
|
298
|
+
@staticmethod
|
|
299
|
+
def _check_eval_set(eval_set, X):
|
|
300
|
+
checked_eval_set = []
|
|
301
|
+
if eval_set is not None and not isinstance(eval_set, list):
|
|
302
|
+
raise ValidationError(bundle.get("unsupported_type_eval_set").format(type(eval_set)))
|
|
303
|
+
for eval_pair in eval_set or []:
|
|
304
|
+
if not isinstance(eval_pair, tuple) or len(eval_pair) != 2:
|
|
305
|
+
raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
|
|
306
|
+
if not is_frames_equal(X, eval_pair[0]):
|
|
307
|
+
checked_eval_set.append(eval_pair)
|
|
308
|
+
return checked_eval_set
|
|
309
|
+
|
|
297
310
|
def fit(
|
|
298
311
|
self,
|
|
299
312
|
X: Union[pd.DataFrame, pd.Series, np.ndarray],
|
|
@@ -370,19 +383,13 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
370
383
|
try:
|
|
371
384
|
self.X = X
|
|
372
385
|
self.y = y
|
|
373
|
-
|
|
374
|
-
for eval_pair in eval_set or []:
|
|
375
|
-
if len(eval_pair) != 2:
|
|
376
|
-
raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
|
|
377
|
-
if not is_frames_equal(X, eval_pair[0]):
|
|
378
|
-
checked_eval_set.append(eval_pair)
|
|
379
|
-
self.eval_set = checked_eval_set
|
|
386
|
+
self.eval_set = self._check_eval_set(eval_set, X)
|
|
380
387
|
self.dump_input(trace_id, X, y, eval_set)
|
|
381
388
|
self.__inner_fit(
|
|
382
389
|
trace_id,
|
|
383
390
|
X,
|
|
384
391
|
y,
|
|
385
|
-
|
|
392
|
+
self.eval_set,
|
|
386
393
|
progress_bar,
|
|
387
394
|
start_time=start_time,
|
|
388
395
|
exclude_features_sources=exclude_features_sources,
|
|
@@ -512,13 +519,7 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
512
519
|
try:
|
|
513
520
|
self.X = X
|
|
514
521
|
self.y = y
|
|
515
|
-
|
|
516
|
-
for eval_pair in eval_set or []:
|
|
517
|
-
if len(eval_pair) != 2:
|
|
518
|
-
raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
|
|
519
|
-
if not is_frames_equal(X, eval_pair[0]):
|
|
520
|
-
checked_eval_set.append(eval_pair)
|
|
521
|
-
self.eval_set = checked_eval_set
|
|
522
|
+
self.eval_set = self._check_eval_set(eval_set, X)
|
|
522
523
|
self.dump_input(trace_id, X, y, eval_set)
|
|
523
524
|
|
|
524
525
|
if _num_samples(drop_duplicates(X)) > Dataset.MAX_ROWS:
|
|
@@ -528,7 +529,7 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
528
529
|
trace_id,
|
|
529
530
|
X,
|
|
530
531
|
y,
|
|
531
|
-
|
|
532
|
+
self.eval_set,
|
|
532
533
|
progress_bar,
|
|
533
534
|
start_time=start_time,
|
|
534
535
|
exclude_features_sources=exclude_features_sources,
|
|
@@ -1189,12 +1190,7 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
1189
1190
|
if X is None:
|
|
1190
1191
|
return True, self.X, self.y, self.eval_set
|
|
1191
1192
|
|
|
1192
|
-
checked_eval_set =
|
|
1193
|
-
for eval_pair in eval_set or []:
|
|
1194
|
-
if len(eval_pair) != 2:
|
|
1195
|
-
raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
|
|
1196
|
-
if not is_frames_equal(X, eval_pair[0]):
|
|
1197
|
-
checked_eval_set.append(eval_pair)
|
|
1193
|
+
checked_eval_set = self._check_eval_set(eval_set, X)
|
|
1198
1194
|
|
|
1199
1195
|
if (
|
|
1200
1196
|
X is self.X
|
|
@@ -1231,181 +1227,28 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
1231
1227
|
progress_bar: Optional[ProgressBar] = None,
|
|
1232
1228
|
progress_callback: Optional[Callable[[SearchProgress], Any]] = None,
|
|
1233
1229
|
):
|
|
1234
|
-
is_demo_dataset = hash_input(X, y, eval_set) in DEMO_DATASET_HASHES
|
|
1235
1230
|
is_input_same_as_fit, X, y, eval_set = self._is_input_same_as_fit(X, y, eval_set)
|
|
1231
|
+
is_demo_dataset = hash_input(X, y, eval_set) in DEMO_DATASET_HASHES
|
|
1236
1232
|
validated_X = self._validate_X(X)
|
|
1237
1233
|
validated_y = self._validate_y(validated_X, y)
|
|
1234
|
+
validated_eval_set = (
|
|
1235
|
+
[self._validate_eval_set_pair(validated_X, eval_set_pair) for eval_set_pair in eval_set]
|
|
1236
|
+
if eval_set
|
|
1237
|
+
else None
|
|
1238
|
+
)
|
|
1238
1239
|
|
|
1239
|
-
eval_set_sampled_dict =
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
if eval_set is not None:
|
|
1252
|
-
for idx in range(len(eval_set)):
|
|
1253
|
-
eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
|
|
1254
|
-
eval_y_sampled = eval_set[idx][1]
|
|
1255
|
-
enriched_eval_X = eval_X_sampled
|
|
1256
|
-
eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
|
|
1257
|
-
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1258
|
-
elif not self.imbalanced and not exclude_features_sources and is_input_same_as_fit:
|
|
1259
|
-
self.logger.info("Dataset is not imbalanced, so use enriched_X from fit")
|
|
1260
|
-
search_keys = self.fit_search_keys
|
|
1261
|
-
|
|
1262
|
-
rows_to_drop = None
|
|
1263
|
-
task_type = self.model_task_type or define_task(validated_y, self.logger, silent=True)
|
|
1264
|
-
if task_type == ModelTaskType.REGRESSION:
|
|
1265
|
-
target_outliers_df = self._search_task.get_target_outliers(trace_id)
|
|
1266
|
-
if target_outliers_df is not None and len(target_outliers_df) > 0:
|
|
1267
|
-
outliers = pd.merge(
|
|
1268
|
-
self.df_with_original_index,
|
|
1269
|
-
target_outliers_df,
|
|
1270
|
-
left_on=SYSTEM_RECORD_ID,
|
|
1271
|
-
right_on=SYSTEM_RECORD_ID,
|
|
1272
|
-
how="inner",
|
|
1273
|
-
)
|
|
1274
|
-
top_outliers = outliers.sort_values(by=TARGET, ascending=False)[TARGET].head(3)
|
|
1275
|
-
if remove_outliers_calc_metrics is None or remove_outliers_calc_metrics is True:
|
|
1276
|
-
rows_to_drop = outliers
|
|
1277
|
-
not_msg = ""
|
|
1278
|
-
else:
|
|
1279
|
-
not_msg = "not "
|
|
1280
|
-
msg = bundle.get("target_outliers_warning").format(len(target_outliers_df), top_outliers, not_msg)
|
|
1281
|
-
print(msg)
|
|
1282
|
-
self.logger.warning(msg)
|
|
1283
|
-
|
|
1284
|
-
enriched_Xy, enriched_eval_sets = self.__enrich(
|
|
1285
|
-
self.df_with_original_index,
|
|
1286
|
-
self._search_task.get_all_initial_raw_features(trace_id, metrics_calculation=True),
|
|
1287
|
-
rows_to_drop=rows_to_drop,
|
|
1288
|
-
)
|
|
1289
|
-
|
|
1290
|
-
enriched_X = drop_existing_columns(enriched_Xy, TARGET)
|
|
1291
|
-
x_columns = [
|
|
1292
|
-
c for c in validated_X.columns.to_list() + self.fit_generated_features if c in enriched_X.columns
|
|
1293
|
-
]
|
|
1294
|
-
X_sampled = enriched_Xy[x_columns].copy()
|
|
1295
|
-
y_sampled = enriched_Xy[TARGET].copy()
|
|
1296
|
-
|
|
1297
|
-
self.logger.info(f"Shape of enriched_X: {enriched_X.shape}")
|
|
1298
|
-
self.logger.info(f"Shape of X after sampling: {X_sampled.shape}")
|
|
1299
|
-
self.logger.info(f"Shape of y after sampling: {len(y_sampled)}")
|
|
1300
|
-
|
|
1301
|
-
if eval_set is not None:
|
|
1302
|
-
if len(enriched_eval_sets) != len(eval_set):
|
|
1303
|
-
raise ValidationError(
|
|
1304
|
-
bundle.get("metrics_eval_set_count_diff").format(len(enriched_eval_sets), len(eval_set))
|
|
1305
|
-
)
|
|
1306
|
-
|
|
1307
|
-
for idx in range(len(eval_set)):
|
|
1308
|
-
enriched_eval_X = drop_existing_columns(enriched_eval_sets[idx + 1], TARGET)
|
|
1309
|
-
eval_X_sampled = enriched_eval_sets[idx + 1][x_columns].copy()
|
|
1310
|
-
eval_y_sampled = enriched_eval_sets[idx + 1][TARGET].copy()
|
|
1311
|
-
eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
|
|
1312
|
-
|
|
1313
|
-
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1314
|
-
else:
|
|
1315
|
-
self.logger.info("Dataset is imbalanced or exclude_features_sources or X was passed. Run transform")
|
|
1316
|
-
print(bundle.get("prepare_data_for_metrics"))
|
|
1317
|
-
if eval_set is not None:
|
|
1318
|
-
self.logger.info("Transform with eval_set")
|
|
1319
|
-
# concatenate X and eval_set with eval_set_index
|
|
1320
|
-
df_with_eval_set_index = validated_X.copy()
|
|
1321
|
-
df_with_eval_set_index[TARGET] = validated_y
|
|
1322
|
-
df_with_eval_set_index[EVAL_SET_INDEX] = 0
|
|
1323
|
-
for idx, eval_pair in enumerate(eval_set):
|
|
1324
|
-
eval_x, eval_y = self._validate_eval_set_pair(validated_X, eval_pair)
|
|
1325
|
-
eval_df_with_index = eval_x.copy()
|
|
1326
|
-
eval_df_with_index[TARGET] = eval_y
|
|
1327
|
-
eval_df_with_index[EVAL_SET_INDEX] = idx + 1
|
|
1328
|
-
df_with_eval_set_index = pd.concat([df_with_eval_set_index, eval_df_with_index])
|
|
1329
|
-
|
|
1330
|
-
# downsample if need to eval_set threshold
|
|
1331
|
-
num_samples = _num_samples(df_with_eval_set_index)
|
|
1332
|
-
if num_samples > Dataset.FIT_SAMPLE_WITH_EVAL_SET_THRESHOLD:
|
|
1333
|
-
self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS}")
|
|
1334
|
-
df_with_eval_set_index = df_with_eval_set_index.sample(
|
|
1335
|
-
n=Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS, random_state=self.random_state
|
|
1336
|
-
)
|
|
1337
|
-
|
|
1338
|
-
X_sampled = (
|
|
1339
|
-
df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0]
|
|
1340
|
-
.copy()
|
|
1341
|
-
.drop(columns=[EVAL_SET_INDEX, TARGET])
|
|
1342
|
-
)
|
|
1343
|
-
X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
|
|
1344
|
-
y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0].copy()[TARGET]
|
|
1345
|
-
eval_set_sampled_dict = dict()
|
|
1346
|
-
for idx in range(len(eval_set)):
|
|
1347
|
-
eval_x_sampled = (
|
|
1348
|
-
df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)]
|
|
1349
|
-
.copy()
|
|
1350
|
-
.drop(columns=[EVAL_SET_INDEX, TARGET])
|
|
1351
|
-
)
|
|
1352
|
-
eval_x_sampled, _ = self._extend_x(eval_x_sampled, is_demo_dataset)
|
|
1353
|
-
eval_y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)].copy()[
|
|
1354
|
-
TARGET
|
|
1355
|
-
]
|
|
1356
|
-
eval_set_sampled_dict[idx] = (eval_x_sampled, eval_y_sampled)
|
|
1357
|
-
|
|
1358
|
-
df_with_eval_set_index.drop(columns=TARGET, inplace=True)
|
|
1359
|
-
|
|
1360
|
-
enriched = self.transform(
|
|
1361
|
-
df_with_eval_set_index,
|
|
1362
|
-
exclude_features_sources=exclude_features_sources,
|
|
1363
|
-
silent_mode=True,
|
|
1364
|
-
trace_id=trace_id,
|
|
1365
|
-
metrics_calculation=True,
|
|
1366
|
-
progress_bar=progress_bar,
|
|
1367
|
-
progress_callback=progress_callback,
|
|
1368
|
-
)
|
|
1369
|
-
if enriched is None:
|
|
1370
|
-
return None
|
|
1371
|
-
|
|
1372
|
-
enriched_X = enriched[enriched[EVAL_SET_INDEX] == 0].copy()
|
|
1373
|
-
enriched_X.drop(columns=EVAL_SET_INDEX, inplace=True)
|
|
1374
|
-
|
|
1375
|
-
for idx in range(len(eval_set)):
|
|
1376
|
-
enriched_eval_x = enriched[enriched[EVAL_SET_INDEX] == (idx + 1)].copy()
|
|
1377
|
-
enriched_eval_x.drop(columns=EVAL_SET_INDEX, inplace=True)
|
|
1378
|
-
eval_x_sampled, eval_y_sampled = eval_set_sampled_dict[idx]
|
|
1379
|
-
eval_set_sampled_dict[idx] = (eval_x_sampled, enriched_eval_x, eval_y_sampled)
|
|
1380
|
-
else:
|
|
1381
|
-
self.logger.info("Transform without eval_set")
|
|
1382
|
-
df = self.X.copy()
|
|
1383
|
-
|
|
1384
|
-
df[TARGET] = validated_y
|
|
1385
|
-
num_samples = _num_samples(df)
|
|
1386
|
-
if num_samples > Dataset.FIT_SAMPLE_THRESHOLD:
|
|
1387
|
-
self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_ROWS}")
|
|
1388
|
-
df = df.sample(n=Dataset.FIT_SAMPLE_ROWS, random_state=self.random_state)
|
|
1389
|
-
|
|
1390
|
-
X_sampled = df.copy().drop(columns=TARGET)
|
|
1391
|
-
X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
|
|
1392
|
-
y_sampled = df.copy()[TARGET]
|
|
1393
|
-
|
|
1394
|
-
df.drop(columns=TARGET, inplace=True)
|
|
1395
|
-
|
|
1396
|
-
enriched_X = self.transform(
|
|
1397
|
-
df,
|
|
1398
|
-
exclude_features_sources=exclude_features_sources,
|
|
1399
|
-
silent_mode=True,
|
|
1400
|
-
trace_id=trace_id,
|
|
1401
|
-
metrics_calculation=True,
|
|
1402
|
-
progress_bar=progress_bar,
|
|
1403
|
-
progress_callback=progress_callback,
|
|
1404
|
-
)
|
|
1405
|
-
if enriched_X is None:
|
|
1406
|
-
return None
|
|
1407
|
-
|
|
1408
|
-
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1240
|
+
X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys = self._sample_data_for_metrics(
|
|
1241
|
+
trace_id,
|
|
1242
|
+
validated_X,
|
|
1243
|
+
validated_y,
|
|
1244
|
+
validated_eval_set,
|
|
1245
|
+
exclude_features_sources,
|
|
1246
|
+
is_input_same_as_fit,
|
|
1247
|
+
is_demo_dataset,
|
|
1248
|
+
remove_outliers_calc_metrics,
|
|
1249
|
+
progress_bar,
|
|
1250
|
+
progress_callback,
|
|
1251
|
+
)
|
|
1409
1252
|
|
|
1410
1253
|
excluding_search_keys = list(search_keys.keys())
|
|
1411
1254
|
if search_keys_for_metrics is not None and len(search_keys_for_metrics) > 0:
|
|
@@ -1425,12 +1268,12 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
1425
1268
|
X_sorted, y_sorted = self._sort_by_keys(X_sampled, y_sampled, search_keys, self.cv)
|
|
1426
1269
|
enriched_X_sorted, enriched_y_sorted = self._sort_by_keys(enriched_X, y_sampled, search_keys, self.cv)
|
|
1427
1270
|
|
|
1428
|
-
group_columns = self._get_group_columns(search_keys)
|
|
1271
|
+
group_columns = sorted(self._get_group_columns(search_keys))
|
|
1429
1272
|
groups = (
|
|
1430
1273
|
None
|
|
1431
|
-
if not group_columns
|
|
1274
|
+
if not group_columns or self.cv != CVType.group_k_fold
|
|
1432
1275
|
else reduce(
|
|
1433
|
-
lambda left, right: left + "_" + right, [
|
|
1276
|
+
lambda left, right: left + "_" + right, [enriched_X_sorted[c].astype(str) for c in group_columns]
|
|
1434
1277
|
).factorize()[0]
|
|
1435
1278
|
)
|
|
1436
1279
|
|
|
@@ -1478,6 +1321,258 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
1478
1321
|
groups,
|
|
1479
1322
|
)
|
|
1480
1323
|
|
|
1324
|
+
_SampledDataForMetrics = namedtuple(
|
|
1325
|
+
"_SampledDataForMetrics", "X_sampled y_sampled enriched_X eval_set_sampled_dict search_keys"
|
|
1326
|
+
)
|
|
1327
|
+
|
|
1328
|
+
def _sample_data_for_metrics(
|
|
1329
|
+
self,
|
|
1330
|
+
trace_id: str,
|
|
1331
|
+
validated_X: Union[pd.DataFrame, pd.Series, np.ndarray, None],
|
|
1332
|
+
validated_y: Union[pd.DataFrame, pd.Series, np.ndarray, List, None],
|
|
1333
|
+
eval_set: Optional[List[tuple]],
|
|
1334
|
+
exclude_features_sources: Optional[List[str]],
|
|
1335
|
+
is_input_same_as_fit: bool,
|
|
1336
|
+
is_demo_dataset: bool,
|
|
1337
|
+
remove_outliers_calc_metrics: Optional[bool],
|
|
1338
|
+
progress_bar: Optional[ProgressBar],
|
|
1339
|
+
progress_callback: Optional[Callable[[SearchProgress], Any]],
|
|
1340
|
+
) -> _SampledDataForMetrics:
|
|
1341
|
+
if self.__cached_sampled_datasets is not None and is_input_same_as_fit and remove_outliers_calc_metrics is None:
|
|
1342
|
+
self.logger.info("Cached enriched dataset found - use it")
|
|
1343
|
+
return self.__get_sampled_cached_enriched(exclude_features_sources)
|
|
1344
|
+
elif len(self.feature_importances_) == 0:
|
|
1345
|
+
self.logger.info("No external features selected. So use only input datasets for metrics calculation")
|
|
1346
|
+
return self.__sample_only_input(validated_X, validated_y, eval_set, is_demo_dataset)
|
|
1347
|
+
elif not self.imbalanced and not exclude_features_sources and is_input_same_as_fit:
|
|
1348
|
+
self.logger.info("Dataset is not imbalanced, so use enriched_X from fit")
|
|
1349
|
+
return self.__sample_balanced(
|
|
1350
|
+
validated_X, validated_y, eval_set, trace_id, remove_outliers_calc_metrics, is_demo_dataset
|
|
1351
|
+
)
|
|
1352
|
+
else:
|
|
1353
|
+
self.logger.info("Dataset is imbalanced or exclude_features_sources or X was passed. Run transform")
|
|
1354
|
+
print(bundle.get("prepare_data_for_metrics"))
|
|
1355
|
+
return self.__sample_imbalanced(
|
|
1356
|
+
validated_X,
|
|
1357
|
+
validated_y,
|
|
1358
|
+
eval_set,
|
|
1359
|
+
is_demo_dataset,
|
|
1360
|
+
exclude_features_sources,
|
|
1361
|
+
trace_id,
|
|
1362
|
+
progress_bar,
|
|
1363
|
+
progress_callback,
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
def __get_sampled_cached_enriched(self, exclude_features_sources: Optional[List[str]]) -> _SampledDataForMetrics:
|
|
1367
|
+
X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys = self.__cached_sampled_datasets
|
|
1368
|
+
if exclude_features_sources:
|
|
1369
|
+
enriched_X = drop_existing_columns(enriched_X, exclude_features_sources)
|
|
1370
|
+
|
|
1371
|
+
return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1372
|
+
|
|
1373
|
+
def __sample_only_input(
|
|
1374
|
+
self, validated_X: pd.DataFrame, validated_y: pd.Series, eval_set: Optional[List[tuple]], is_demo_dataset: bool
|
|
1375
|
+
) -> _SampledDataForMetrics:
|
|
1376
|
+
eval_set_sampled_dict = dict()
|
|
1377
|
+
X_sampled, search_keys = self._extend_x(validated_X, is_demo_dataset)
|
|
1378
|
+
y_sampled = validated_y
|
|
1379
|
+
enriched_X = X_sampled
|
|
1380
|
+
if eval_set is not None:
|
|
1381
|
+
for idx in range(len(eval_set)):
|
|
1382
|
+
eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
|
|
1383
|
+
eval_y_sampled = eval_set[idx][1]
|
|
1384
|
+
enriched_eval_X = eval_X_sampled
|
|
1385
|
+
eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
|
|
1386
|
+
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1387
|
+
|
|
1388
|
+
return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1389
|
+
|
|
1390
|
+
def __sample_balanced(
|
|
1391
|
+
self,
|
|
1392
|
+
validated_X: pd.DataFrame,
|
|
1393
|
+
validated_y: pd.Series,
|
|
1394
|
+
eval_set: Optional[List[tuple]],
|
|
1395
|
+
trace_id: str,
|
|
1396
|
+
remove_outliers_calc_metrics: Optional[bool],
|
|
1397
|
+
is_demo_dataset: bool,
|
|
1398
|
+
) -> _SampledDataForMetrics:
|
|
1399
|
+
eval_set_sampled_dict = dict()
|
|
1400
|
+
search_keys = self.fit_search_keys
|
|
1401
|
+
|
|
1402
|
+
rows_to_drop = None
|
|
1403
|
+
task_type = self.model_task_type or define_task(validated_y, self.logger, silent=True)
|
|
1404
|
+
if task_type == ModelTaskType.REGRESSION:
|
|
1405
|
+
target_outliers_df = self._search_task.get_target_outliers(trace_id)
|
|
1406
|
+
if target_outliers_df is not None and len(target_outliers_df) > 0:
|
|
1407
|
+
outliers = pd.merge(
|
|
1408
|
+
self.df_with_original_index,
|
|
1409
|
+
target_outliers_df,
|
|
1410
|
+
left_on=SYSTEM_RECORD_ID,
|
|
1411
|
+
right_on=SYSTEM_RECORD_ID,
|
|
1412
|
+
how="inner",
|
|
1413
|
+
)
|
|
1414
|
+
top_outliers = outliers.sort_values(by=TARGET, ascending=False)[TARGET].head(3)
|
|
1415
|
+
if remove_outliers_calc_metrics is None or remove_outliers_calc_metrics is True:
|
|
1416
|
+
rows_to_drop = outliers
|
|
1417
|
+
not_msg = ""
|
|
1418
|
+
else:
|
|
1419
|
+
not_msg = "not "
|
|
1420
|
+
msg = bundle.get("target_outliers_warning").format(len(target_outliers_df), top_outliers, not_msg)
|
|
1421
|
+
print(msg)
|
|
1422
|
+
self.logger.warning(msg)
|
|
1423
|
+
|
|
1424
|
+
# index in each dataset (X, eval set) may be reordered and non unique, but index in validated datasets
|
|
1425
|
+
# can differs from it
|
|
1426
|
+
enriched_Xy, enriched_eval_sets = self.__enrich(
|
|
1427
|
+
self.df_with_original_index,
|
|
1428
|
+
self._search_task.get_all_initial_raw_features(trace_id, metrics_calculation=True),
|
|
1429
|
+
rows_to_drop=rows_to_drop,
|
|
1430
|
+
)
|
|
1431
|
+
|
|
1432
|
+
enriched_X = drop_existing_columns(enriched_Xy, TARGET)
|
|
1433
|
+
X_sampled, search_keys = self._extend_x(validated_X, is_demo_dataset)
|
|
1434
|
+
y_sampled = enriched_Xy[TARGET].copy()
|
|
1435
|
+
|
|
1436
|
+
self.logger.info(f"Shape of enriched_X: {enriched_X.shape}")
|
|
1437
|
+
self.logger.info(f"Shape of X after sampling: {X_sampled.shape}")
|
|
1438
|
+
self.logger.info(f"Shape of y after sampling: {len(y_sampled)}")
|
|
1439
|
+
|
|
1440
|
+
if eval_set is not None:
|
|
1441
|
+
if len(enriched_eval_sets) != len(eval_set):
|
|
1442
|
+
raise ValidationError(
|
|
1443
|
+
bundle.get("metrics_eval_set_count_diff").format(len(enriched_eval_sets), len(eval_set))
|
|
1444
|
+
)
|
|
1445
|
+
|
|
1446
|
+
for idx in range(len(eval_set)):
|
|
1447
|
+
enriched_eval_X = drop_existing_columns(enriched_eval_sets[idx + 1], TARGET)
|
|
1448
|
+
eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
|
|
1449
|
+
eval_y_sampled = eval_set[idx][1].copy()
|
|
1450
|
+
eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
|
|
1451
|
+
|
|
1452
|
+
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1453
|
+
|
|
1454
|
+
return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1455
|
+
|
|
1456
|
+
def __sample_imbalanced(
|
|
1457
|
+
self,
|
|
1458
|
+
validated_X: pd.DataFrame,
|
|
1459
|
+
validated_y: pd.Series,
|
|
1460
|
+
eval_set: Optional[List[tuple]],
|
|
1461
|
+
is_demo_dataset: bool,
|
|
1462
|
+
exclude_features_sources: Optional[List[str]],
|
|
1463
|
+
trace_id: str,
|
|
1464
|
+
progress_bar: Optional[ProgressBar],
|
|
1465
|
+
progress_callback: Optional[Callable[[SearchProgress], Any]],
|
|
1466
|
+
) -> _SampledDataForMetrics:
|
|
1467
|
+
eval_set_sampled_dict = dict()
|
|
1468
|
+
if eval_set is not None:
|
|
1469
|
+
self.logger.info("Transform with eval_set")
|
|
1470
|
+
# concatenate X and eval_set with eval_set_index
|
|
1471
|
+
df_with_eval_set_index = validated_X.copy()
|
|
1472
|
+
df_with_eval_set_index[TARGET] = validated_y
|
|
1473
|
+
df_with_eval_set_index[EVAL_SET_INDEX] = 0
|
|
1474
|
+
for idx, eval_pair in enumerate(eval_set):
|
|
1475
|
+
eval_x, eval_y = self._validate_eval_set_pair(validated_X, eval_pair)
|
|
1476
|
+
eval_df_with_index = eval_x.copy()
|
|
1477
|
+
eval_df_with_index[TARGET] = eval_y
|
|
1478
|
+
eval_df_with_index[EVAL_SET_INDEX] = idx + 1
|
|
1479
|
+
df_with_eval_set_index = pd.concat([df_with_eval_set_index, eval_df_with_index])
|
|
1480
|
+
|
|
1481
|
+
# downsample if need to eval_set threshold
|
|
1482
|
+
num_samples = _num_samples(df_with_eval_set_index)
|
|
1483
|
+
if num_samples > Dataset.FIT_SAMPLE_WITH_EVAL_SET_THRESHOLD:
|
|
1484
|
+
self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS}")
|
|
1485
|
+
df_with_eval_set_index = df_with_eval_set_index.sample(
|
|
1486
|
+
n=Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS, random_state=self.random_state
|
|
1487
|
+
)
|
|
1488
|
+
|
|
1489
|
+
X_sampled = (
|
|
1490
|
+
df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0]
|
|
1491
|
+
.copy()
|
|
1492
|
+
.drop(columns=[EVAL_SET_INDEX, TARGET])
|
|
1493
|
+
)
|
|
1494
|
+
X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
|
|
1495
|
+
y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0].copy()[TARGET]
|
|
1496
|
+
eval_set_sampled_dict = dict()
|
|
1497
|
+
for idx in range(len(eval_set)):
|
|
1498
|
+
eval_x_sampled = (
|
|
1499
|
+
df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)]
|
|
1500
|
+
.copy()
|
|
1501
|
+
.drop(columns=[EVAL_SET_INDEX, TARGET])
|
|
1502
|
+
)
|
|
1503
|
+
eval_x_sampled, _ = self._extend_x(eval_x_sampled, is_demo_dataset)
|
|
1504
|
+
eval_y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)].copy()[
|
|
1505
|
+
TARGET
|
|
1506
|
+
]
|
|
1507
|
+
eval_set_sampled_dict[idx] = (eval_x_sampled, eval_y_sampled)
|
|
1508
|
+
|
|
1509
|
+
df_with_eval_set_index.drop(columns=TARGET, inplace=True)
|
|
1510
|
+
|
|
1511
|
+
enriched = self.transform(
|
|
1512
|
+
df_with_eval_set_index,
|
|
1513
|
+
exclude_features_sources=exclude_features_sources,
|
|
1514
|
+
silent_mode=True,
|
|
1515
|
+
trace_id=trace_id,
|
|
1516
|
+
metrics_calculation=True,
|
|
1517
|
+
progress_bar=progress_bar,
|
|
1518
|
+
progress_callback=progress_callback,
|
|
1519
|
+
)
|
|
1520
|
+
if enriched is None:
|
|
1521
|
+
return None
|
|
1522
|
+
|
|
1523
|
+
enriched_X = enriched[enriched[EVAL_SET_INDEX] == 0].copy()
|
|
1524
|
+
enriched_X.drop(columns=EVAL_SET_INDEX, inplace=True)
|
|
1525
|
+
|
|
1526
|
+
for idx in range(len(eval_set)):
|
|
1527
|
+
enriched_eval_x = enriched[enriched[EVAL_SET_INDEX] == (idx + 1)].copy()
|
|
1528
|
+
enriched_eval_x.drop(columns=EVAL_SET_INDEX, inplace=True)
|
|
1529
|
+
eval_x_sampled, eval_y_sampled = eval_set_sampled_dict[idx]
|
|
1530
|
+
eval_set_sampled_dict[idx] = (eval_x_sampled, enriched_eval_x, eval_y_sampled)
|
|
1531
|
+
else:
|
|
1532
|
+
self.logger.info("Transform without eval_set")
|
|
1533
|
+
df = self.X.copy()
|
|
1534
|
+
|
|
1535
|
+
df[TARGET] = validated_y
|
|
1536
|
+
num_samples = _num_samples(df)
|
|
1537
|
+
if num_samples > Dataset.FIT_SAMPLE_THRESHOLD:
|
|
1538
|
+
self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_ROWS}")
|
|
1539
|
+
df = df.sample(n=Dataset.FIT_SAMPLE_ROWS, random_state=self.random_state)
|
|
1540
|
+
|
|
1541
|
+
X_sampled = df.copy().drop(columns=TARGET)
|
|
1542
|
+
X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
|
|
1543
|
+
y_sampled = df.copy()[TARGET]
|
|
1544
|
+
|
|
1545
|
+
df.drop(columns=TARGET, inplace=True)
|
|
1546
|
+
|
|
1547
|
+
enriched_X = self.transform(
|
|
1548
|
+
df,
|
|
1549
|
+
exclude_features_sources=exclude_features_sources,
|
|
1550
|
+
silent_mode=True,
|
|
1551
|
+
trace_id=trace_id,
|
|
1552
|
+
metrics_calculation=True,
|
|
1553
|
+
progress_bar=progress_bar,
|
|
1554
|
+
progress_callback=progress_callback,
|
|
1555
|
+
)
|
|
1556
|
+
if enriched_X is None:
|
|
1557
|
+
return None
|
|
1558
|
+
|
|
1559
|
+
self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1560
|
+
|
|
1561
|
+
return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
|
|
1562
|
+
|
|
1563
|
+
def __mk_sampled_data_tuple(
|
|
1564
|
+
self,
|
|
1565
|
+
X_sampled: pd.DataFrame,
|
|
1566
|
+
y_sampled: pd.Series,
|
|
1567
|
+
enriched_X: pd.DataFrame,
|
|
1568
|
+
eval_set_sampled_dict: Dict,
|
|
1569
|
+
search_keys: Dict,
|
|
1570
|
+
):
|
|
1571
|
+
search_keys = {k: v for k, v in search_keys.items() if k in X_sampled.columns.to_list()}
|
|
1572
|
+
return FeaturesEnricher._SampledDataForMetrics(
|
|
1573
|
+
X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys
|
|
1574
|
+
)
|
|
1575
|
+
|
|
1481
1576
|
def get_search_id(self) -> Optional[str]:
|
|
1482
1577
|
"""Returns search_id of the fitted enricher. Not available before a successful fit."""
|
|
1483
1578
|
return self._search_task.search_task_id if self._search_task else None
|
|
@@ -2065,9 +2160,6 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2065
2160
|
if autofe_description is not None:
|
|
2066
2161
|
display_html_dataframe(autofe_description, autofe_description, "*Description of AutoFE feature names")
|
|
2067
2162
|
|
|
2068
|
-
if not self.warning_counter.has_warnings():
|
|
2069
|
-
self.__display_support_link(bundle.get("all_ok_community_invite"))
|
|
2070
|
-
|
|
2071
2163
|
if self._has_paid_features(exclude_features_sources):
|
|
2072
2164
|
if calculate_metrics is not None and calculate_metrics:
|
|
2073
2165
|
msg = bundle.get("metrics_with_paid_features")
|
|
@@ -2108,6 +2200,9 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2108
2200
|
|
|
2109
2201
|
self.__show_report_button()
|
|
2110
2202
|
|
|
2203
|
+
if not self.warning_counter.has_warnings():
|
|
2204
|
+
self.__display_support_link(bundle.get("all_ok_community_invite"))
|
|
2205
|
+
|
|
2111
2206
|
def __adjust_cv(self, df: pd.DataFrame, date_column: pd.Series, model_task_type: ModelTaskType):
|
|
2112
2207
|
# Check Multivariate time series
|
|
2113
2208
|
if (
|
|
@@ -2118,17 +2213,18 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2118
2213
|
and is_blocked_time_series(df, date_column, list(self.fit_search_keys.keys()) + [TARGET])
|
|
2119
2214
|
):
|
|
2120
2215
|
msg = bundle.get("multivariate_timeseries_detected")
|
|
2121
|
-
self.__override_cv(CVType.blocked_time_series, msg)
|
|
2216
|
+
self.__override_cv(CVType.blocked_time_series, msg, print_warning=False)
|
|
2122
2217
|
elif (
|
|
2123
|
-
self.cv is None
|
|
2218
|
+
(self.cv is None or self.cv == CVType.k_fold)
|
|
2124
2219
|
and model_task_type != ModelTaskType.REGRESSION
|
|
2125
2220
|
and self._get_group_columns(self.fit_search_keys)
|
|
2126
2221
|
):
|
|
2127
2222
|
msg = bundle.get("group_k_fold_in_classification")
|
|
2128
|
-
self.__override_cv(CVType.group_k_fold, msg)
|
|
2223
|
+
self.__override_cv(CVType.group_k_fold, msg, print_warning=self.cv is not None)
|
|
2129
2224
|
|
|
2130
|
-
def __override_cv(self, cv: CVType, msg: str):
|
|
2131
|
-
|
|
2225
|
+
def __override_cv(self, cv: CVType, msg: str, print_warning: bool = True):
|
|
2226
|
+
if print_warning:
|
|
2227
|
+
print(msg)
|
|
2132
2228
|
self.logger.warning(msg)
|
|
2133
2229
|
self.cv = cv
|
|
2134
2230
|
self.runtime_parameters.properties["cv_type"] = self.cv.name
|
|
@@ -2448,8 +2544,10 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2448
2544
|
self, df: pd.DataFrame, meaning_types: Dict[str, FileColumnMeaningType], search_keys: Dict[str, SearchKey]
|
|
2449
2545
|
) -> pd.DataFrame:
|
|
2450
2546
|
# save original order or rows
|
|
2451
|
-
|
|
2452
|
-
|
|
2547
|
+
original_index_name = df.index.name
|
|
2548
|
+
index_name = df.index.name or DEFAULT_INDEX
|
|
2549
|
+
df = df.reset_index().reset_index(drop=True)
|
|
2550
|
+
df = df.rename(columns={index_name: ORIGINAL_INDEX})
|
|
2453
2551
|
|
|
2454
2552
|
# order by date and idempotent order by other keys
|
|
2455
2553
|
if self.cv not in [CVType.time_series, CVType.blocked_time_series]:
|
|
@@ -2480,7 +2578,8 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2480
2578
|
|
|
2481
2579
|
# return original order
|
|
2482
2580
|
df = df.set_index(ORIGINAL_INDEX)
|
|
2483
|
-
df =
|
|
2581
|
+
df.index.name = original_index_name
|
|
2582
|
+
# df = df.sort_index()
|
|
2484
2583
|
|
|
2485
2584
|
meaning_types[SYSTEM_RECORD_ID] = FileColumnMeaningType.SYSTEM_RECORD_ID
|
|
2486
2585
|
return df
|
|
@@ -2541,6 +2640,9 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2541
2640
|
self.logger.warning(f"X contain columns with same name as returned from backend: {dup_features}")
|
|
2542
2641
|
raise ValidationError(bundle.get("returned_features_same_as_passed").format(dup_features))
|
|
2543
2642
|
|
|
2643
|
+
# index overrites from result_features
|
|
2644
|
+
original_index_name = df_with_original_index.index.name
|
|
2645
|
+
df_with_original_index = df_with_original_index.reset_index()
|
|
2544
2646
|
result_features = pd.merge(
|
|
2545
2647
|
df_with_original_index,
|
|
2546
2648
|
result_features,
|
|
@@ -2548,6 +2650,8 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2548
2650
|
right_on=SYSTEM_RECORD_ID,
|
|
2549
2651
|
how="left" if is_transform else "inner",
|
|
2550
2652
|
)
|
|
2653
|
+
result_features = result_features.set_index(original_index_name or DEFAULT_INDEX)
|
|
2654
|
+
result_features.index.name = original_index_name
|
|
2551
2655
|
|
|
2552
2656
|
if rows_to_drop is not None:
|
|
2553
2657
|
print(f"Before dropping target outliers size: {len(result_features)}")
|
|
@@ -2986,6 +3090,7 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
2986
3090
|
autofe_descriptions_df=self.get_autofe_features_description(),
|
|
2987
3091
|
search_id=self._search_task.search_task_id,
|
|
2988
3092
|
email=get_rest_client(self.endpoint, self.api_key).get_current_email(),
|
|
3093
|
+
search_keys=[str(sk) for sk in self.search_keys.values()],
|
|
2989
3094
|
)
|
|
2990
3095
|
except Exception:
|
|
2991
3096
|
pass
|
|
@@ -3109,19 +3214,15 @@ class FeaturesEnricher(TransformerMixin):
|
|
|
3109
3214
|
def __display_support_link(self, link_text: Optional[str] = None):
|
|
3110
3215
|
support_link = bundle.get("support_link")
|
|
3111
3216
|
link_text = link_text or bundle.get("support_text")
|
|
3112
|
-
# badge = bundle.get("slack_community_bage")
|
|
3113
|
-
# alt = bundle.get("slack_community_alt")
|
|
3114
3217
|
try:
|
|
3115
3218
|
from IPython.display import HTML, display
|
|
3116
3219
|
|
|
3117
3220
|
_ = get_ipython() # type: ignore
|
|
3118
3221
|
self.logger.warning(link_text)
|
|
3119
|
-
print(link_text)
|
|
3120
3222
|
display(
|
|
3121
3223
|
HTML(
|
|
3122
|
-
f"""<a href='{support_link}' target='_blank' rel='noopener noreferrer'>
|
|
3123
|
-
|
|
3124
|
-
# <img alt='{alt}' src='{badge}'></a>
|
|
3224
|
+
f"""{link_text} <a href='{support_link}' target='_blank' rel='noopener noreferrer'>
|
|
3225
|
+
here</a>"""
|
|
3125
3226
|
)
|
|
3126
3227
|
)
|
|
3127
3228
|
except (ImportError, NameError):
|
|
@@ -17,7 +17,7 @@ transform_usage_warning=You are trying to launch enrichment for {} rows, which w
|
|
|
17
17
|
support_link=https://upgini.com/support
|
|
18
18
|
# slack_community_link=https://4mlg.short.gy/join-upgini-community
|
|
19
19
|
# slack_community_text=\nWARNING: Looks like you've run into an error. For help request write us in the Upgini community
|
|
20
|
-
support_text=\nWARNING: Looks like you've run into an error. For help request write us in support
|
|
20
|
+
support_text=\nWARNING: Looks like you've run into an error. For help request write us in support
|
|
21
21
|
slack_community_bage=https://img.shields.io/badge/slack-@upgini-orange.svg?logo=slack
|
|
22
22
|
slack_community_alt=Upgini Slack community
|
|
23
23
|
version_warning=\nWARNING: Unsupported library version detected {},\nplease update with “%pip install -U upgini” to the latest {} and restart Jupyter kernel
|
|
@@ -110,6 +110,7 @@ y_is_empty=y is empty
|
|
|
110
110
|
x_contains_reserved_column_name=Column name {} is reserved. Please rename column and try again
|
|
111
111
|
missing_generate_feature=\nWARNING: Feature {} specified in `generate_features` is not present in input columns: {}
|
|
112
112
|
# eval set validation
|
|
113
|
+
unsupported_type_eval_set=Unsupported type of eval_set: {}. It should be tuple of two elements: X and y
|
|
113
114
|
eval_set_invalid_tuple_size=eval_set contains a tuple of size {}. It should contain only pairs of X and y
|
|
114
115
|
unsupported_x_type_eval_set=Unsupported type of X in eval_set: {}. Use pandas.DataFrame, pandas.Series or numpy.ndarray or list.
|
|
115
116
|
eval_x_and_x_diff_shape=The column set in eval_set are differ from the column set in X
|
|
@@ -193,7 +194,7 @@ phone_detected=Phone numbers detected in column `{}`. It can be used only with a
|
|
|
193
194
|
phone_detected_not_registered=\nWARNING: Phone numbers detected in column `{}`. It can be used only with api_key from profile.upgini.com\nSee docs to turn off the automatic detection: https://github.com/upgini/upgini/blob/main/README.md#turn-off-autodetection-for-search-key-columns
|
|
194
195
|
target_type_detected=Detected task type: {}\n
|
|
195
196
|
# all_ok_community_invite=Chat with us in Slack community:
|
|
196
|
-
all_ok_community_invite=
|
|
197
|
+
all_ok_community_invite=Support request
|
|
197
198
|
too_small_for_metrics=Your train dataset contains less than 500 rows. For such dataset Upgini will not calculate accuracy metrics. Please increase the number of rows in the training dataset to calculate accuracy metrics
|
|
198
199
|
imbalance_multiclass=Class {0} is on 25% quantile of classes distribution ({1} records in train dataset). \nDownsample classes with records more than {1}.
|
|
199
200
|
loss_selection_info=Using loss `{}` for feature selection
|
upgini/utils/display_utils.py
CHANGED
|
@@ -5,7 +5,7 @@ import urllib.parse
|
|
|
5
5
|
import uuid
|
|
6
6
|
from datetime import datetime, timezone
|
|
7
7
|
from io import BytesIO
|
|
8
|
-
from typing import Callable, Optional
|
|
8
|
+
from typing import Callable, List, Optional
|
|
9
9
|
|
|
10
10
|
import pandas as pd
|
|
11
11
|
from xhtml2pdf import pisa
|
|
@@ -133,6 +133,7 @@ def make_html_report(
|
|
|
133
133
|
autofe_descriptions_df: Optional[pd.DataFrame],
|
|
134
134
|
search_id: str,
|
|
135
135
|
email: Optional[str] = None,
|
|
136
|
+
search_keys: Optional[List[str]] = None,
|
|
136
137
|
):
|
|
137
138
|
# relevant_features_df = relevant_features_df.copy()
|
|
138
139
|
# relevant_features_df["Feature name"] = relevant_features_df["Feature name"].apply(
|
|
@@ -236,6 +237,11 @@ def make_html_report(
|
|
|
236
237
|
<p>This report was generated automatically by Upgini.</p>
|
|
237
238
|
<p>The report shows a listing of relevant features for your
|
|
238
239
|
ML task and accuracy metrics after enrichment.</p>
|
|
240
|
+
{
|
|
241
|
+
f"The following primary keys was used for data search: {search_keys}"
|
|
242
|
+
if search_keys is not None
|
|
243
|
+
else ""
|
|
244
|
+
}
|
|
239
245
|
{"<h3>All relevant features. Accuracy after enrichment</h3>" + make_table(metrics_df)
|
|
240
246
|
if metrics_df is not None
|
|
241
247
|
else ""
|
|
@@ -244,7 +250,7 @@ def make_html_report(
|
|
|
244
250
|
{make_table(relevant_datasources_df)}
|
|
245
251
|
<h3>All relevant features. Listing</h3>
|
|
246
252
|
{make_table(relevant_features_df, wrap_long_string=25)}
|
|
247
|
-
{"<h3>Description of AutoFE feature names</h3>" + make_table(autofe_descriptions_df)
|
|
253
|
+
{"<h3>Description of AutoFE feature names</h3>" + make_table(autofe_descriptions_df, wrap_long_string=25)
|
|
248
254
|
if autofe_descriptions_df is not None
|
|
249
255
|
else ""
|
|
250
256
|
}
|
|
@@ -261,12 +267,13 @@ def prepare_and_show_report(
|
|
|
261
267
|
autofe_descriptions_df: Optional[pd.DataFrame],
|
|
262
268
|
search_id: str,
|
|
263
269
|
email: Optional[str],
|
|
270
|
+
search_keys: Optional[List[str]] = None,
|
|
264
271
|
):
|
|
265
272
|
if not ipython_available():
|
|
266
273
|
return
|
|
267
274
|
|
|
268
275
|
report = make_html_report(
|
|
269
|
-
relevant_features_df, relevant_datasources_df, metrics_df, autofe_descriptions_df, search_id, email
|
|
276
|
+
relevant_features_df, relevant_datasources_df, metrics_df, autofe_descriptions_df, search_id, email, search_keys
|
|
270
277
|
)
|
|
271
278
|
|
|
272
279
|
if len(relevant_features_df) > 0:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: upgini
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.224
|
|
4
4
|
Summary: Intelligent data search & enrichment for Machine Learning
|
|
5
5
|
Home-page: https://upgini.com/
|
|
6
6
|
Author: Upgini Developers
|
|
@@ -9,6 +9,7 @@ License: BSD 3-Clause License
|
|
|
9
9
|
Project-URL: Bug Reports, https://github.com/upgini/upgini/issues
|
|
10
10
|
Project-URL: Source, https://github.com/upgini/upgini
|
|
11
11
|
Keywords: data science,machine learning,data mining,automl,data search
|
|
12
|
+
Platform: UNKNOWN
|
|
12
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
13
14
|
Classifier: Intended Audience :: Customer Service
|
|
14
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -26,20 +27,19 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
26
27
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
27
28
|
Requires-Python: >=3.7,<3.11
|
|
28
29
|
Description-Content-Type: text/markdown
|
|
29
|
-
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist: ipywidgets (>=8.1.0)
|
|
30
|
+
Requires-Dist: python-dateutil >=2.8.0
|
|
31
|
+
Requires-Dist: requests >=2.8.0
|
|
32
|
+
Requires-Dist: pandas <2.0.0,>=1.1.0
|
|
33
|
+
Requires-Dist: numpy >=1.19.0
|
|
34
|
+
Requires-Dist: scikit-learn >=1.0.1
|
|
35
|
+
Requires-Dist: pydantic <2.0.0,>=1.8.2
|
|
36
|
+
Requires-Dist: fastparquet >=0.8.1
|
|
37
|
+
Requires-Dist: python-json-logger >=2.0.2
|
|
38
|
+
Requires-Dist: catboost >=1.0.3
|
|
39
|
+
Requires-Dist: lightgbm >=3.3.2
|
|
40
|
+
Requires-Dist: pyjwt >=2.8.0
|
|
41
|
+
Requires-Dist: xhtml2pdf ==0.2.11
|
|
42
|
+
Requires-Dist: ipywidgets >=8.1.0
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
<!-- <h2 align="center"> <a href="https://upgini.com/">Upgini</a> : low-code feature search and enrichment library for machine learning </h2> -->
|
|
@@ -151,7 +151,7 @@ Requires-Dist: ipywidgets (>=8.1.0)
|
|
|
151
151
|
* The goal is to predict salary for data science job postning based on information about employer and job description.
|
|
152
152
|
* Following this guide, you'll learn how to **search & auto generate new relevant features with Upgini library**
|
|
153
153
|
* The evaluation metric is [Mean Absolute Error (MAE)](https://en.wikipedia.org/wiki/Mean_absolute_error).
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
Run [Feature search & generation notebook](https://github.com/upgini/upgini/blob/main/notebooks/Upgini_Features_search%26generation.ipynb) inside your browser:
|
|
156
156
|
|
|
157
157
|
[](https://colab.research.google.com/github/upgini/upgini/blob/main/notebooks/Upgini_Features_search%26generation.ipynb)
|
|
@@ -842,3 +842,5 @@ Some convenient ways to start contributing are:
|
|
|
842
842
|
|
|
843
843
|
<sup>😔 Found mistype or a bug in code snippet? Our bad! <a href="https://github.com/upgini/upgini/issues/new?assignees=&title=readme%2Fbug">
|
|
844
844
|
Please report it here.</a></sup>
|
|
845
|
+
|
|
846
|
+
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
upgini/__init__.py,sha256=asENHgEVHQBIkV-e_0IhE_ZWqkCG6398U3ZLrNzAH6k,407
|
|
2
2
|
upgini/ads.py,sha256=mre6xn44wcC_fg63iLT_kTh4mViZqR9AKRJZAtpQz8Y,2592
|
|
3
|
-
upgini/dataset.py,sha256=
|
|
3
|
+
upgini/dataset.py,sha256=7z9zbVvd1_MiufmoZlCwEHwQ25Q2DX_0g9PFcSMlqMY,49764
|
|
4
4
|
upgini/errors.py,sha256=BqpvfhW2jJW5fa5KXj0alhXatGl-WK4xTl309-QNLp8,959
|
|
5
|
-
upgini/features_enricher.py,sha256=
|
|
6
|
-
upgini/fingerprint.js,sha256=VygVIQlN1v4NGZfjHqtRogOw8zjTnnMNJg_f7M5iGQU,33442
|
|
5
|
+
upgini/features_enricher.py,sha256=a78eCA6uS1kPtSLQQB3wQFBIiAPn4b0i3AjvlUyBm38,155965
|
|
7
6
|
upgini/http.py,sha256=KIAwmBwo9dQxTVEEHKE-BOGcOcJ6o5Q5f6R2kvX-aAc,40808
|
|
8
7
|
upgini/metadata.py,sha256=LUvOc3SGkvXwBPpGkCnacywpR6lAmZ2mGJqcD7LAsXI,7235
|
|
9
8
|
upgini/metrics.py,sha256=YeYHJtEIs8OG-EzidG-nbSYB919pjZ4MMbdcZ_jfV2s,23639
|
|
@@ -20,7 +19,7 @@ upgini/normalizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
20
19
|
upgini/normalizer/phone_normalizer.py,sha256=VIgLXuDuzzjPEXiy_LyDVLZKGaS7-le6Fh6T4D-TQDU,9930
|
|
21
20
|
upgini/resource_bundle/__init__.py,sha256=M7GtS7KPQw9pinz8P2aQWXpSkD2YFwUPVGk1w92Pn84,7888
|
|
22
21
|
upgini/resource_bundle/exceptions.py,sha256=KT-OnqA2J4OTfLjhbEl3KFZM2ci7EOPjqJuY_rXp3vs,622
|
|
23
|
-
upgini/resource_bundle/strings.properties,sha256=
|
|
22
|
+
upgini/resource_bundle/strings.properties,sha256=NPEfvUleQm09klmPo8sQMF_B_brs3nY2mt8GENsLICw,24355
|
|
24
23
|
upgini/sampler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
24
|
upgini/sampler/base.py,sha256=X2PVsfZ3Rl7twpFDh5UWyxqY2K_jcMGxZ2NcHLwFRj4,6489
|
|
26
25
|
upgini/sampler/random_under_sampler.py,sha256=whX_f_TtalHH8Seyn_7n3sX_TSiDHeYfALmme9saqDg,4082
|
|
@@ -32,7 +31,7 @@ upgini/utils/country_utils.py,sha256=9BXSXoGm3nVoOZE_bRENY-KMkwMUFvAF3Au0zxUNA1o
|
|
|
32
31
|
upgini/utils/custom_loss_utils.py,sha256=DBslpjWGPt7xTeypt78baR59012SYphbPsO_YLKdilo,3972
|
|
33
32
|
upgini/utils/cv_utils.py,sha256=NTVd7itVWiyrEiM2LPXHGXIzMCncdGR4SRxrOu57Euc,2492
|
|
34
33
|
upgini/utils/datetime_utils.py,sha256=P56e7gcgAogJYfs2Blzk1uypxb9yrFzNaeJpMCRm6Zc,7716
|
|
35
|
-
upgini/utils/display_utils.py,sha256=
|
|
34
|
+
upgini/utils/display_utils.py,sha256=mGqs2XzD_4bmeRgmrGXWjxt_ZQigc2leaXBcRge9DkY,10676
|
|
36
35
|
upgini/utils/email_utils.py,sha256=MhCLUAWqbp81xRyKizauNhVx6t_MFeJQRQ8pFM7EpFo,3480
|
|
37
36
|
upgini/utils/fallback_progress_bar.py,sha256=f-VzVbiO6oU9WoKzEgoegYotixdiKanGlvdQCOGC-NY,1128
|
|
38
37
|
upgini/utils/features_validator.py,sha256=iP8muF3PUf_aP9m7O3i3LPMuJPTNbw8rCAWqgvDt_h8,2369
|
|
@@ -45,8 +44,8 @@ upgini/utils/sklearn_ext.py,sha256=IMx2La70AXAggApVpT7sMEjWqVWon5AMZt4MARDsIMQ,4
|
|
|
45
44
|
upgini/utils/target_utils.py,sha256=cu52icjhDIPpEStHYMXrD2hIl9gzvfnxZr0Ra5osV0k,1616
|
|
46
45
|
upgini/utils/track_info.py,sha256=DVNVZmXUb4f25DSPEuUNEFx49hNEBfmuY9iSW5jkMnI,5708
|
|
47
46
|
upgini/utils/warning_counter.py,sha256=vnmdFo5-7GBkU2bK9h_uC0K0Y_wtfcYstxOdeRfacO0,228
|
|
48
|
-
upgini-1.1.
|
|
49
|
-
upgini-1.1.
|
|
50
|
-
upgini-1.1.
|
|
51
|
-
upgini-1.1.
|
|
52
|
-
upgini-1.1.
|
|
47
|
+
upgini-1.1.224.dist-info/LICENSE,sha256=5RRzgvdJUu3BUDfv4bzVU6FqKgwHlIay63pPCSmSgzw,1514
|
|
48
|
+
upgini-1.1.224.dist-info/METADATA,sha256=FB0guMPa2N-aDRYBvSTaXjpFii-1n_z6he1jNX6AeYE,48277
|
|
49
|
+
upgini-1.1.224.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
50
|
+
upgini-1.1.224.dist-info/top_level.txt,sha256=OFhTGiDIWKl5gFI49qvWq1R9IKflPaE2PekcbDXDtx4,7
|
|
51
|
+
upgini-1.1.224.dist-info/RECORD,,
|
upgini/fingerprint.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FingerprintJS v3.4.2 - Copyright (c) FingerprintJS, Inc, 2023 (https://fingerprint.com)
|
|
3
|
-
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
|
|
4
|
-
*
|
|
5
|
-
* This software contains code from open-source projects:
|
|
6
|
-
* MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
|
|
7
|
-
*/
|
|
8
|
-
var e=function(){return e=Object.assign||function(e){for(var n,t=1,r=arguments.length;t<r;t++)for(var o in n=arguments[t])Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o]);return e},e.apply(this,arguments)};function n(e,n,t,r){return new(t||(t=Promise))((function(o,a){function i(e){try{u(r.next(e))}catch(n){a(n)}}function c(e){try{u(r.throw(e))}catch(n){a(n)}}function u(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(i,c)}u((r=r.apply(e,n||[])).next())}))}function t(e,n){var t,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function c(c){return function(u){return function(c){if(t)throw new TypeError("Generator is already executing.");for(;a&&(a=0,c[0]&&(i=0)),i;)try{if(t=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return i.label++,{value:c[1],done:!1};case 5:i.label++,r=c[1],c=[0];continue;case 7:c=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){i=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){i.label=c[1];break}if(6===c[0]&&i.label<o[1]){i.label=o[1],o=c;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(c);break}o[2]&&i.ops.pop(),i.trys.pop();continue}c=n.call(e,i)}catch(u){c=[6,u],r=0}finally{t=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}}function r(e,n,t){if(t||2===arguments.length)for(var r,o=0,a=n.length;o<a;o++)!r&&o in n||(r||(r=Array.prototype.slice.call(n,0,o)),r[o]=n[o]);return e.concat(r||Array.prototype.slice.call(n))}function o(e,n){return new Promise((function(t){return setTimeout(t,e,n)}))}function a(e){return!!e&&"function"==typeof e.then}function i(e,n){try{var t=e();a(t)?t.then((function(e){return n(!0,e)}),(function(e){return n(!1,e)})):n(!0,t)}catch(r){n(!1,r)}}function c(e,r,a){return void 0===a&&(a=16),n(this,void 0,void 0,(function(){var n,i,c,u;return t(this,(function(t){switch(t.label){case 0:n=Array(e.length),i=Date.now(),c=0,t.label=1;case 1:return c<e.length?(n[c]=r(e[c],c),(u=Date.now())>=i+a?(i=u,[4,o(0)]):[3,3]):[3,4];case 2:t.sent(),t.label=3;case 3:return++c,[3,1];case 4:return[2,n]}}))}))}function u(e){e.then(void 0,(function(){}))}function l(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]+n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]+n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]+n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]+n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function s(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]*n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]*n[3],t[1]+=t[2]>>>16,t[2]&=65535,t[2]+=e[3]*n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]*n[3],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[2]*n[2],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[3]*n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]*n[3]+e[1]*n[2]+e[2]*n[1]+e[3]*n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function d(e,n){return 32===(n%=64)?[e[1],e[0]]:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n|e[0]>>>32-n]:(n-=32,[e[1]<<n|e[0]>>>32-n,e[0]<<n|e[1]>>>32-n])}function m(e,n){return 0===(n%=64)?e:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n]:[e[1]<<n-32,0]}function f(e,n){return[e[0]^n[0],e[1]^n[1]]}function v(e){return e=f(e,[0,e[0]>>>1]),e=f(e=s(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=f(e=s(e,[3301882366,444984403]),[0,e[0]>>>1])}function h(e,n){n=n||0;var t,r=(e=e||"").length%16,o=e.length-r,a=[0,n],i=[0,n],c=[0,0],u=[0,0],h=[2277735313,289559509],p=[1291169091,658871167];for(t=0;t<o;t+=16)c=[255&e.charCodeAt(t+4)|(255&e.charCodeAt(t+5))<<8|(255&e.charCodeAt(t+6))<<16|(255&e.charCodeAt(t+7))<<24,255&e.charCodeAt(t)|(255&e.charCodeAt(t+1))<<8|(255&e.charCodeAt(t+2))<<16|(255&e.charCodeAt(t+3))<<24],u=[255&e.charCodeAt(t+12)|(255&e.charCodeAt(t+13))<<8|(255&e.charCodeAt(t+14))<<16|(255&e.charCodeAt(t+15))<<24,255&e.charCodeAt(t+8)|(255&e.charCodeAt(t+9))<<8|(255&e.charCodeAt(t+10))<<16|(255&e.charCodeAt(t+11))<<24],c=d(c=s(c,h),31),a=l(a=d(a=f(a,c=s(c,p)),27),i),a=l(s(a,[0,5]),[0,1390208809]),u=d(u=s(u,p),33),i=l(i=d(i=f(i,u=s(u,h)),31),a),i=l(s(i,[0,5]),[0,944331445]);switch(c=[0,0],u=[0,0],r){case 15:u=f(u,m([0,e.charCodeAt(t+14)],48));case 14:u=f(u,m([0,e.charCodeAt(t+13)],40));case 13:u=f(u,m([0,e.charCodeAt(t+12)],32));case 12:u=f(u,m([0,e.charCodeAt(t+11)],24));case 11:u=f(u,m([0,e.charCodeAt(t+10)],16));case 10:u=f(u,m([0,e.charCodeAt(t+9)],8));case 9:u=s(u=f(u,[0,e.charCodeAt(t+8)]),p),i=f(i,u=s(u=d(u,33),h));case 8:c=f(c,m([0,e.charCodeAt(t+7)],56));case 7:c=f(c,m([0,e.charCodeAt(t+6)],48));case 6:c=f(c,m([0,e.charCodeAt(t+5)],40));case 5:c=f(c,m([0,e.charCodeAt(t+4)],32));case 4:c=f(c,m([0,e.charCodeAt(t+3)],24));case 3:c=f(c,m([0,e.charCodeAt(t+2)],16));case 2:c=f(c,m([0,e.charCodeAt(t+1)],8));case 1:c=s(c=f(c,[0,e.charCodeAt(t)]),h),a=f(a,c=s(c=d(c,31),p))}return a=l(a=f(a,[0,e.length]),i=f(i,[0,e.length])),i=l(i,a),a=l(a=v(a),i=v(i)),i=l(i,a),("00000000"+(a[0]>>>0).toString(16)).slice(-8)+("00000000"+(a[1]>>>0).toString(16)).slice(-8)+("00000000"+(i[0]>>>0).toString(16)).slice(-8)+("00000000"+(i[1]>>>0).toString(16)).slice(-8)}function p(e){return parseInt(e)}function b(e){return parseFloat(e)}function y(e,n){return"number"==typeof e&&isNaN(e)?n:e}function g(e){return e.reduce((function(e,n){return e+(n?1:0)}),0)}function w(e,n){if(void 0===n&&(n=1),Math.abs(n)>=1)return Math.round(e/n)*n;var t=1/n;return Math.round(e*t)/t}function L(e){return e&&"object"==typeof e&&"message"in e?e:{message:e}}function k(e){return"function"!=typeof e}function V(e,r,o){var a=Object.keys(e).filter((function(e){return!function(e,n){for(var t=0,r=e.length;t<r;++t)if(e[t]===n)return!0;return!1}(o,e)})),l=c(a,(function(n){return function(e,n){var t=new Promise((function(t){var r=Date.now();i(e.bind(null,n),(function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];var o=Date.now()-r;if(!e[0])return t((function(){return{error:L(e[1]),duration:o}}));var a=e[1];if(k(a))return t((function(){return{value:a,duration:o}}));t((function(){return new Promise((function(e){var n=Date.now();i(a,(function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var a=o+Date.now()-n;if(!t[0])return e({error:L(t[1]),duration:a});e({value:t[1],duration:a})}))}))}))}))}));return u(t),function(){return t.then((function(e){return e()}))}}(e[n],r)}));return u(l),function(){return n(this,void 0,void 0,(function(){var e,n,r,o;return t(this,(function(t){switch(t.label){case 0:return[4,l];case 1:return[4,c(t.sent(),(function(e){var n=e();return u(n),n}))];case 2:return e=t.sent(),[4,Promise.all(e)];case 3:for(n=t.sent(),r={},o=0;o<a.length;++o)r[a[o]]=n[o];return[2,r]}}))}))}}function Z(e,n){var t=function(e){return k(e)?n(e):function(){var t=e();return a(t)?t.then(n):n(t)}};return function(n){var r=e(n);return a(r)?r.then(t):t(r)}}function W(){var e=window,n=navigator;return g(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in n,"msPointerEnabled"in n])>=4}function C(){var e=window,n=navigator;return g(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in n,"msSaveBlob"in n])>=3&&!W()}function S(){var e=window,n=navigator;return g(["webkitPersistentStorage"in n,"webkitTemporaryStorage"in n,0===n.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function x(){var e=window,n=navigator;return g(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===n.vendor.indexOf("Apple"),"getStorageUpdates"in n,"WebKitMediaKeys"in e])>=4}function F(){var e=window;return g(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function Y(){var e,n,t=window;return g(["buildID"in navigator,"MozAppearance"in(null!==(n=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==n?n:{}),"onmozfullscreenchange"in t,"mozInnerScreenX"in t,"CSSMozDocumentRule"in t,"CanvasCaptureMediaStream"in t])>=4}function M(){var e=document;return e.fullscreenElement||e.msFullscreenElement||e.mozFullScreenElement||e.webkitFullscreenElement||null}function G(){var e=S(),n=Y();if(!e&&!n)return!1;var t=window;return g(["onorientationchange"in t,"orientation"in t,e&&!("SharedWorker"in t),n&&/android/i.test(navigator.appVersion)])>=2}function R(e){var n=new Error(e);return n.name=e,n}function X(e,r,a){var i,c,u;return void 0===a&&(a=50),n(this,void 0,void 0,(function(){var n,l;return t(this,(function(t){switch(t.label){case 0:n=document,t.label=1;case 1:return n.body?[3,3]:[4,o(a)];case 2:return t.sent(),[3,1];case 3:l=n.createElement("iframe"),t.label=4;case 4:return t.trys.push([4,,10,11]),[4,new Promise((function(e,t){var o=!1,a=function(){o=!0,e()};l.onload=a,l.onerror=function(e){o=!0,t(e)};var i=l.style;i.setProperty("display","block","important"),i.position="absolute",i.top="0",i.left="0",i.visibility="hidden",r&&"srcdoc"in l?l.srcdoc=r:l.src="about:blank",n.body.appendChild(l);var c=function(){var e,n;o||("complete"===(null===(n=null===(e=l.contentWindow)||void 0===e?void 0:e.document)||void 0===n?void 0:n.readyState)?a():setTimeout(c,10))};c()}))];case 5:t.sent(),t.label=6;case 6:return(null===(c=null===(i=l.contentWindow)||void 0===i?void 0:i.document)||void 0===c?void 0:c.body)?[3,8]:[4,o(a)];case 7:return t.sent(),[3,6];case 8:return[4,e(l,l.contentWindow)];case 9:return[2,t.sent()];case 10:return null===(u=l.parentNode)||void 0===u||u.removeChild(l),[7];case 11:return[2]}}))}))}function A(e){for(var n=function(e){for(var n,t,r="Unexpected syntax '".concat(e,"'"),o=/^\s*([a-z-]*)(.*)$/i.exec(e),a=o[1]||void 0,i={},c=/([.:#][\w-]+|\[.+?\])/gi,u=function(e,n){i[e]=i[e]||[],i[e].push(n)};;){var l=c.exec(o[2]);if(!l)break;var s=l[0];switch(s[0]){case".":u("class",s.slice(1));break;case"#":u("id",s.slice(1));break;case"[":var d=/^\[([\w-]+)([~|^$*]?=("(.*?)"|([\w-]+)))?(\s+[is])?\]$/.exec(s);if(!d)throw new Error(r);u(d[1],null!==(t=null!==(n=d[4])&&void 0!==n?n:d[5])&&void 0!==t?t:"");break;default:throw new Error(r)}}return[a,i]}(e),t=n[0],r=n[1],o=document.createElement(null!=t?t:"div"),a=0,i=Object.keys(r);a<i.length;a++){var c=i[a],u=r[c].join(" ");"style"===c?j(o.style,u):o.setAttribute(c,u)}return o}function j(e,n){for(var t=0,r=n.split(";");t<r.length;t++){var o=r[t],a=/^\s*([\w-]+)\s*:\s*(.+?)(\s*!([\w-]+))?\s*$/.exec(o);if(a){var i=a[1],c=a[2],u=a[4];e.setProperty(i,c,u||"")}}}var I=["monospace","sans-serif","serif"],J=["sans-serif-thin","ARNO PRO","Agency FB","Arabic Typesetting","Arial Unicode MS","AvantGarde Bk BT","BankGothic Md BT","Batang","Bitstream Vera Sans Mono","Calibri","Century","Century Gothic","Clarendon","EUROSTILE","Franklin Gothic","Futura Bk BT","Futura Md BT","GOTHAM","Gill Sans","HELV","Haettenschweiler","Helvetica Neue","Humanst521 BT","Leelawadee","Letter Gothic","Levenim MT","Lucida Bright","Lucida Sans","Menlo","MS Mincho","MS Outlook","MS Reference Specialty","MS UI Gothic","MT Extra","MYRIAD PRO","Marlett","Meiryo UI","Microsoft Uighur","Minion Pro","Monotype Corsiva","PMingLiU","Pristina","SCRIPTINA","Segoe UI Light","Serifa","SimHei","Small Fonts","Staccato222 BT","TRAJAN PRO","Univers CE 55 Medium","Vrinda","ZWAdobeF"];function H(e){return e.toDataURL()}var P,N;function z(){var e=this;return function(){if(void 0===N){var e=function(){var n=D();E(n)?N=setTimeout(e,2500):(P=n,N=void 0)};e()}}(),function(){return n(e,void 0,void 0,(function(){var e;return t(this,(function(n){switch(n.label){case 0:return E(e=D())?P?[2,r([],P,!0)]:M()?[4,(t=document,(t.exitFullscreen||t.msExitFullscreen||t.mozCancelFullScreen||t.webkitExitFullscreen).call(t))]:[3,2]:[3,2];case 1:n.sent(),e=D(),n.label=2;case 2:return E(e)||(P=e),[2,e]}var t}))}))}}function D(){var e=screen;return[y(b(e.availTop),null),y(b(e.width)-b(e.availWidth)-y(b(e.availLeft),0),null),y(b(e.height)-b(e.availHeight)-y(b(e.availTop),0),null),y(b(e.availLeft),null)]}function E(e){for(var n=0;n<4;++n)if(e[n])return!1;return!0}function T(e){var r;return n(this,void 0,void 0,(function(){var n,a,i,c,u,l,s;return t(this,(function(t){switch(t.label){case 0:for(n=document,a=n.createElement("div"),i=new Array(e.length),c={},B(a),s=0;s<e.length;++s)"DIALOG"===(u=A(e[s])).tagName&&u.show(),B(l=n.createElement("div")),l.appendChild(u),a.appendChild(l),i[s]=u;t.label=1;case 1:return n.body?[3,3]:[4,o(50)];case 2:return t.sent(),[3,1];case 3:n.body.appendChild(a);try{for(s=0;s<e.length;++s)i[s].offsetParent||(c[e[s]]=!0)}finally{null===(r=a.parentNode)||void 0===r||r.removeChild(a)}return[2,c]}}))}))}function B(e){e.style.setProperty("display","block","important")}function _(e){return matchMedia("(inverted-colors: ".concat(e,")")).matches}function O(e){return matchMedia("(forced-colors: ".concat(e,")")).matches}function U(e){return matchMedia("(prefers-contrast: ".concat(e,")")).matches}function Q(e){return matchMedia("(prefers-reduced-motion: ".concat(e,")")).matches}function K(e){return matchMedia("(dynamic-range: ".concat(e,")")).matches}var q=Math,$=function(){return 0};var ee={default:[],apple:[{font:"-apple-system-body"}],serif:[{fontFamily:"serif"}],sans:[{fontFamily:"sans-serif"}],mono:[{fontFamily:"monospace"}],min:[{fontSize:"1px"}],system:[{fontFamily:"system-ui"}]};var ne={fonts:function(){return X((function(e,n){var t=n.document,r=t.body;r.style.fontSize="48px";var o=t.createElement("div"),a={},i={},c=function(e){var n=t.createElement("span"),r=n.style;return r.position="absolute",r.top="0",r.left="0",r.fontFamily=e,n.textContent="mmMwWLliI0O&1",o.appendChild(n),n},u=I.map(c),l=function(){for(var e={},n=function(n){e[n]=I.map((function(e){return function(e,n){return c("'".concat(e,"',").concat(n))}(n,e)}))},t=0,r=J;t<r.length;t++){n(r[t])}return e}();r.appendChild(o);for(var s=0;s<I.length;s++)a[I[s]]=u[s].offsetWidth,i[I[s]]=u[s].offsetHeight;return J.filter((function(e){return n=l[e],I.some((function(e,t){return n[t].offsetWidth!==a[e]||n[t].offsetHeight!==i[e]}));var n}))}))},domBlockers:function(e){var r=(void 0===e?{}:e).debug;return n(this,void 0,void 0,(function(){var e,n,o,a,i;return t(this,(function(t){switch(t.label){case 0:return x()||G()?(c=atob,e={abpIndo:["#Iklan-Melayang","#Kolom-Iklan-728","#SidebarIklan-wrapper",'[title="ALIENBOLA" i]',c("I0JveC1CYW5uZXItYWRz")],abpvn:[".quangcao","#mobileCatfish",c("LmNsb3NlLWFkcw=="),'[id^="bn_bottom_fixed_"]',"#pmadv"],adBlockFinland:[".mainostila",c("LnNwb25zb3JpdA=="),".ylamainos",c("YVtocmVmKj0iL2NsaWNrdGhyZ2guYXNwPyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hcHAucmVhZHBlYWsuY29tL2FkcyJd")],adBlockPersian:["#navbar_notice_50",".kadr",'TABLE[width="140px"]',"#divAgahi",c("YVtocmVmXj0iaHR0cDovL2cxLnYuZndtcm0ubmV0L2FkLyJd")],adBlockWarningRemoval:["#adblock-honeypot",".adblocker-root",".wp_adblock_detect",c("LmhlYWRlci1ibG9ja2VkLWFk"),c("I2FkX2Jsb2NrZXI=")],adGuardAnnoyances:[".hs-sosyal","#cookieconsentdiv",'div[class^="app_gdpr"]',".as-oil",'[data-cypress="soft-push-notification-modal"]'],adGuardBase:[".BetterJsPopOverlay",c("I2FkXzMwMFgyNTA="),c("I2Jhbm5lcmZsb2F0MjI="),c("I2NhbXBhaWduLWJhbm5lcg=="),c("I0FkLUNvbnRlbnQ=")],adGuardChinese:[c("LlppX2FkX2FfSA=="),c("YVtocmVmKj0iLmh0aGJldDM0LmNvbSJd"),"#widget-quan",c("YVtocmVmKj0iLzg0OTkyMDIwLnh5eiJd"),c("YVtocmVmKj0iLjE5NTZobC5jb20vIl0=")],adGuardFrench:["#pavePub",c("LmFkLWRlc2t0b3AtcmVjdGFuZ2xl"),".mobile_adhesion",".widgetadv",c("LmFkc19iYW4=")],adGuardGerman:['aside[data-portal-id="leaderboard"]'],adGuardJapanese:["#kauli_yad_1",c("YVtocmVmXj0iaHR0cDovL2FkMi50cmFmZmljZ2F0ZS5uZXQvIl0="),c("Ll9wb3BJbl9pbmZpbml0ZV9hZA=="),c("LmFkZ29vZ2xl"),c("Ll9faXNib29zdFJldHVybkFk")],adGuardMobile:[c("YW1wLWF1dG8tYWRz"),c("LmFtcF9hZA=="),'amp-embed[type="24smi"]',"#mgid_iframe1",c("I2FkX2ludmlld19hcmVh")],adGuardRussian:[c("YVtocmVmXj0iaHR0cHM6Ly9hZC5sZXRtZWFkcy5jb20vIl0="),c("LnJlY2xhbWE="),'div[id^="smi2adblock"]',c("ZGl2W2lkXj0iQWRGb3hfYmFubmVyXyJd"),"#psyduckpockeball"],adGuardSocial:[c("YVtocmVmXj0iLy93d3cuc3R1bWJsZXVwb24uY29tL3N1Ym1pdD91cmw9Il0="),c("YVtocmVmXj0iLy90ZWxlZ3JhbS5tZS9zaGFyZS91cmw/Il0="),".etsy-tweet","#inlineShare",".popup-social"],adGuardSpanishPortuguese:["#barraPublicidade","#Publicidade","#publiEspecial","#queTooltip",".cnt-publi"],adGuardTrackingProtection:["#qoo-counter",c("YVtocmVmXj0iaHR0cDovL2NsaWNrLmhvdGxvZy5ydS8iXQ=="),c("YVtocmVmXj0iaHR0cDovL2hpdGNvdW50ZXIucnUvdG9wL3N0YXQucGhwIl0="),c("YVtocmVmXj0iaHR0cDovL3RvcC5tYWlsLnJ1L2p1bXAiXQ=="),"#top100counter"],adGuardTurkish:["#backkapat",c("I3Jla2xhbWk="),c("YVtocmVmXj0iaHR0cDovL2Fkc2Vydi5vbnRlay5jb20udHIvIl0="),c("YVtocmVmXj0iaHR0cDovL2l6bGVuemkuY29tL2NhbXBhaWduLyJd"),c("YVtocmVmXj0iaHR0cDovL3d3dy5pbnN0YWxsYWRzLm5ldC8iXQ==")],bulgarian:[c("dGQjZnJlZW5ldF90YWJsZV9hZHM="),"#ea_intext_div",".lapni-pop-over","#xenium_hot_offers"],easyList:[".yb-floorad",c("LndpZGdldF9wb19hZHNfd2lkZ2V0"),c("LnRyYWZmaWNqdW5reS1hZA=="),".textad_headline",c("LnNwb25zb3JlZC10ZXh0LWxpbmtz")],easyListChina:[c("LmFwcGd1aWRlLXdyYXBbb25jbGljayo9ImJjZWJvcy5jb20iXQ=="),c("LmZyb250cGFnZUFkdk0="),"#taotaole","#aafoot.top_box",".cfa_popup"],easyListCookie:[".ezmob-footer",".cc-CookieWarning","[data-cookie-number]",c("LmF3LWNvb2tpZS1iYW5uZXI="),".sygnal24-gdpr-modal-wrap"],easyListCzechSlovak:["#onlajny-stickers",c("I3Jla2xhbW5pLWJveA=="),c("LnJla2xhbWEtbWVnYWJvYXJk"),".sklik",c("W2lkXj0ic2tsaWtSZWtsYW1hIl0=")],easyListDutch:[c("I2FkdmVydGVudGll"),c("I3ZpcEFkbWFya3RCYW5uZXJCbG9jaw=="),".adstekst",c("YVtocmVmXj0iaHR0cHM6Ly94bHR1YmUubmwvY2xpY2svIl0="),"#semilo-lrectangle"],easyListGermany:["#SSpotIMPopSlider",c("LnNwb25zb3JsaW5rZ3J1ZW4="),c("I3dlcmJ1bmdza3k="),c("I3Jla2xhbWUtcmVjaHRzLW1pdHRl"),c("YVtocmVmXj0iaHR0cHM6Ly9iZDc0Mi5jb20vIl0=")],easyListItaly:[c("LmJveF9hZHZfYW5udW5jaQ=="),".sb-box-pubbliredazionale",c("YVtocmVmXj0iaHR0cDovL2FmZmlsaWF6aW9uaWFkcy5zbmFpLml0LyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hZHNlcnZlci5odG1sLml0LyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hZmZpbGlhemlvbmlhZHMuc25haS5pdC8iXQ==")],easyListLithuania:[c("LnJla2xhbW9zX3RhcnBhcw=="),c("LnJla2xhbW9zX251b3JvZG9z"),c("aW1nW2FsdD0iUmVrbGFtaW5pcyBza3lkZWxpcyJd"),c("aW1nW2FsdD0iRGVkaWt1b3RpLmx0IHNlcnZlcmlhaSJd"),c("aW1nW2FsdD0iSG9zdGluZ2FzIFNlcnZlcmlhaS5sdCJd")],estonian:[c("QVtocmVmKj0iaHR0cDovL3BheTRyZXN1bHRzMjQuZXUiXQ==")],fanboyAnnoyances:["#ac-lre-player",".navigate-to-top","#subscribe_popup",".newsletter_holder","#back-top"],fanboyAntiFacebook:[".util-bar-module-firefly-visible"],fanboyEnhancedTrackers:[".open.pushModal","#issuem-leaky-paywall-articles-zero-remaining-nag","#sovrn_container",'div[class$="-hide"][zoompage-fontsize][style="display: block;"]',".BlockNag__Card"],fanboySocial:["#FollowUs","#meteored_share","#social_follow",".article-sharer",".community__social-desc"],frellwitSwedish:[c("YVtocmVmKj0iY2FzaW5vcHJvLnNlIl1bdGFyZ2V0PSJfYmxhbmsiXQ=="),c("YVtocmVmKj0iZG9rdG9yLXNlLm9uZWxpbmsubWUiXQ=="),"article.category-samarbete",c("ZGl2LmhvbGlkQWRz"),"ul.adsmodern"],greekAdBlock:[c("QVtocmVmKj0iYWRtYW4ub3RlbmV0LmdyL2NsaWNrPyJd"),c("QVtocmVmKj0iaHR0cDovL2F4aWFiYW5uZXJzLmV4b2R1cy5nci8iXQ=="),c("QVtocmVmKj0iaHR0cDovL2ludGVyYWN0aXZlLmZvcnRobmV0LmdyL2NsaWNrPyJd"),"DIV.agores300","TABLE.advright"],hungarian:["#cemp_doboz",".optimonk-iframe-container",c("LmFkX19tYWlu"),c("W2NsYXNzKj0iR29vZ2xlQWRzIl0="),"#hirdetesek_box"],iDontCareAboutCookies:['.alert-info[data-block-track*="CookieNotice"]',".ModuleTemplateCookieIndicator",".o--cookies--container","#cookies-policy-sticky","#stickyCookieBar"],icelandicAbp:[c("QVtocmVmXj0iL2ZyYW1ld29yay9yZXNvdXJjZXMvZm9ybXMvYWRzLmFzcHgiXQ==")],latvian:[c("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiAxMjBweDsgaGVpZ2h0OiA0MHB4OyBvdmVyZmxvdzogaGlkZGVuOyBwb3NpdGlvbjogcmVsYXRpdmU7Il0="),c("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiA4OHB4OyBoZWlnaHQ6IDMxcHg7IG92ZXJmbG93OiBoaWRkZW47IHBvc2l0aW9uOiByZWxhdGl2ZTsiXQ==")],listKr:[c("YVtocmVmKj0iLy9hZC5wbGFuYnBsdXMuY28ua3IvIl0="),c("I2xpdmVyZUFkV3JhcHBlcg=="),c("YVtocmVmKj0iLy9hZHYuaW1hZHJlcC5jby5rci8iXQ=="),c("aW5zLmZhc3R2aWV3LWFk"),".revenue_unit_item.dable"],listeAr:[c("LmdlbWluaUxCMUFk"),".right-and-left-sponsers",c("YVtocmVmKj0iLmFmbGFtLmluZm8iXQ=="),c("YVtocmVmKj0iYm9vcmFxLm9yZyJd"),c("YVtocmVmKj0iZHViaXp6bGUuY29tL2FyLz91dG1fc291cmNlPSJd")],listeFr:[c("YVtocmVmXj0iaHR0cDovL3Byb21vLnZhZG9yLmNvbS8iXQ=="),c("I2FkY29udGFpbmVyX3JlY2hlcmNoZQ=="),c("YVtocmVmKj0id2Vib3JhbWEuZnIvZmNnaS1iaW4vIl0="),".site-pub-interstitiel",'div[id^="crt-"][data-criteo-id]'],officialPolish:["#ceneo-placeholder-ceneo-12",c("W2hyZWZePSJodHRwczovL2FmZi5zZW5kaHViLnBsLyJd"),c("YVtocmVmXj0iaHR0cDovL2Fkdm1hbmFnZXIudGVjaGZ1bi5wbC9yZWRpcmVjdC8iXQ=="),c("YVtocmVmXj0iaHR0cDovL3d3dy50cml6ZXIucGwvP3V0bV9zb3VyY2UiXQ=="),c("ZGl2I3NrYXBpZWNfYWQ=")],ro:[c("YVtocmVmXj0iLy9hZmZ0cmsuYWx0ZXgucm8vQ291bnRlci9DbGljayJd"),c("YVtocmVmXj0iaHR0cHM6Ly9ibGFja2ZyaWRheXNhbGVzLnJvL3Ryay9zaG9wLyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9ldmVudC4ycGVyZm9ybWFudC5jb20vZXZlbnRzL2NsaWNrIl0="),c("YVtocmVmXj0iaHR0cHM6Ly9sLnByb2ZpdHNoYXJlLnJvLyJd"),'a[href^="/url/"]'],ruAd:[c("YVtocmVmKj0iLy9mZWJyYXJlLnJ1LyJd"),c("YVtocmVmKj0iLy91dGltZy5ydS8iXQ=="),c("YVtocmVmKj0iOi8vY2hpa2lkaWtpLnJ1Il0="),"#pgeldiz",".yandex-rtb-block"],thaiAds:["a[href*=macau-uta-popup]",c("I2Fkcy1nb29nbGUtbWlkZGxlX3JlY3RhbmdsZS1ncm91cA=="),c("LmFkczMwMHM="),".bumq",".img-kosana"],webAnnoyancesUltralist:["#mod-social-share-2","#social-tools",c("LmN0cGwtZnVsbGJhbm5lcg=="),".zergnet-recommend",".yt.btn-link.btn-md.btn"]},n=Object.keys(e),[4,T((i=[]).concat.apply(i,n.map((function(n){return e[n]}))))]):[2,void 0];case 1:return o=t.sent(),r&&function(e,n){for(var t="DOM blockers debug:\n```",r=0,o=Object.keys(e);r<o.length;r++){var a=o[r];t+="\n".concat(a,":");for(var i=0,c=e[a];i<c.length;i++){var u=c[i];t+="\n ".concat(n[u]?"🚫":"➡️"," ").concat(u)}}console.log("".concat(t,"\n```"))}(e,o),(a=n.filter((function(n){var t=e[n];return g(t.map((function(e){return o[e]})))>.6*t.length}))).sort(),[2,a]}var c}))}))},fontPreferences:function(){return function(e,n){void 0===n&&(n=4e3);return X((function(t,o){var a=o.document,i=a.body,c=i.style;c.width="".concat(n,"px"),c.webkitTextSizeAdjust=c.textSizeAdjust="none",S()?i.style.zoom="".concat(1/o.devicePixelRatio):x()&&(i.style.zoom="reset");var u=a.createElement("div");return u.textContent=r([],Array(n/20<<0),!0).map((function(){return"word"})).join(" "),i.appendChild(u),e(a,i)}),'<!doctype html><html><head><meta name="viewport" content="width=device-width, initial-scale=1">')}((function(e,n){for(var t={},r={},o=0,a=Object.keys(ee);o<a.length;o++){var i=a[o],c=ee[i],u=c[0],l=void 0===u?{}:u,s=c[1],d=void 0===s?"mmMwWLliI0fiflO&1":s,m=e.createElement("span");m.textContent=d,m.style.whiteSpace="nowrap";for(var f=0,v=Object.keys(l);f<v.length;f++){var h=v[f],p=l[h];void 0!==p&&(m.style[h]=p)}t[i]=m,n.appendChild(e.createElement("br")),n.appendChild(m)}for(var b=0,y=Object.keys(ee);b<y.length;b++){r[i=y[b]]=t[i].getBoundingClientRect().width}return r}))},audio:function(){var e=window,n=e.OfflineAudioContext||e.webkitOfflineAudioContext;if(!n)return-2;if(x()&&!F()&&!function(){var e=window;return g(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return-1;var t=new n(1,5e3,44100),r=t.createOscillator();r.type="triangle",r.frequency.value=1e4;var o=t.createDynamicsCompressor();o.threshold.value=-50,o.knee.value=40,o.ratio.value=12,o.attack.value=0,o.release.value=.25,r.connect(o),o.connect(t.destination),r.start(0);var i=function(e){var n=3,t=500,r=500,o=5e3,i=function(){};return[new Promise((function(c,l){var s=!1,d=0,m=0;e.oncomplete=function(e){return c(e.renderedBuffer)};var f=function(){setTimeout((function(){return l(R("timeout"))}),Math.min(r,m+o-Date.now()))},v=function(){try{var r=e.startRendering();switch(a(r)&&u(r),e.state){case"running":m=Date.now(),s&&f();break;case"suspended":document.hidden||d++,s&&d>=n?l(R("suspended")):setTimeout(v,t)}}catch(o){l(o)}};v(),i=function(){s||(s=!0,m>0&&f())}})),i]}(t),c=i[0],l=i[1],s=c.then((function(e){return function(e){for(var n=0,t=0;t<e.length;++t)n+=Math.abs(e[t]);return n}(e.getChannelData(0).subarray(4500))}),(function(e){if("timeout"===e.name||"suspended"===e.name)return-3;throw e}));return u(s),function(){return l(),s}},screenFrame:function(){var e=this,r=z();return function(){return n(e,void 0,void 0,(function(){var e,n;return t(this,(function(t){switch(t.label){case 0:return[4,r()];case 1:return e=t.sent(),[2,[(n=function(e){return null===e?null:w(e,10)})(e[0]),n(e[1]),n(e[2]),n(e[3])]]}}))}))}},osCpu:function(){return navigator.oscpu},languages:function(){var e,n=navigator,t=[],r=n.language||n.userLanguage||n.browserLanguage||n.systemLanguage;if(void 0!==r&&t.push([r]),Array.isArray(n.languages))S()&&g([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||t.push(n.languages);else if("string"==typeof n.languages){var o=n.languages;o&&t.push(o.split(","))}return t},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return y(b(navigator.deviceMemory),void 0)},screenResolution:function(){var e=screen,n=function(e){return y(p(e),null)},t=[n(e.width),n(e.height)];return t.sort().reverse(),t},hardwareConcurrency:function(){return y(p(navigator.hardwareConcurrency),void 0)},timezone:function(){var e,n=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(n){var t=(new n).resolvedOptions().timeZone;if(t)return t}var r,o=(r=(new Date).getFullYear(),-Math.max(b(new Date(r,0,1).getTimezoneOffset()),b(new Date(r,6,1).getTimezoneOffset())));return"UTC".concat(o>=0?"+":"").concat(Math.abs(o))},sessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},localStorage:function(){try{return!!window.localStorage}catch(e){return!0}},indexedDB:function(){if(!W()&&!C())try{return!!window.indexedDB}catch(e){return!0}},openDatabase:function(){return!!window.openDatabase},cpuClass:function(){return navigator.cpuClass},platform:function(){var e=navigator.platform;return"MacIntel"===e&&x()&&!F()?function(){if("iPad"===navigator.platform)return!0;var e=screen,n=e.width/e.height;return g(["MediaSource"in window,!!Element.prototype.webkitRequestFullscreen,n>.65&&n<1.53])>=2}()?"iPad":"iPhone":e},plugins:function(){var e=navigator.plugins;if(e){for(var n=[],t=0;t<e.length;++t){var r=e[t];if(r){for(var o=[],a=0;a<r.length;++a){var i=r[a];o.push({type:i.type,suffixes:i.suffixes})}n.push({name:r.name,description:r.description,mimeTypes:o})}}return n}},canvas:function(){var e,n,t=!1,r=function(){var e=document.createElement("canvas");return e.width=1,e.height=1,[e,e.getContext("2d")]}(),o=r[0],a=r[1];if(function(e,n){return!(!n||!e.toDataURL)}(o,a)){t=function(e){return e.rect(0,0,10,10),e.rect(2,2,6,6),!e.isPointInPath(5,5,"evenodd")}(a),function(e,n){e.width=240,e.height=60,n.textBaseline="alphabetic",n.fillStyle="#f60",n.fillRect(100,1,62,20),n.fillStyle="#069",n.font='11pt "Times New Roman"';var t="Cwm fjordbank gly ".concat(String.fromCharCode(55357,56835));n.fillText(t,2,15),n.fillStyle="rgba(102, 204, 0, 0.2)",n.font="18pt Arial",n.fillText(t,4,45)}(o,a);var i=H(o);i!==H(o)?e=n="unstable":(n=i,function(e,n){e.width=122,e.height=110,n.globalCompositeOperation="multiply";for(var t=0,r=[["#f2f",40,40],["#2ff",80,40],["#ff2",60,80]];t<r.length;t++){var o=r[t],a=o[0],i=o[1],c=o[2];n.fillStyle=a,n.beginPath(),n.arc(i,c,40,0,2*Math.PI,!0),n.closePath(),n.fill()}n.fillStyle="#f9c",n.arc(60,60,60,0,2*Math.PI,!0),n.arc(60,60,20,0,2*Math.PI,!0),n.fill("evenodd")}(o,a),e=H(o))}else e=n="";return{winding:t,geometry:e,text:n}},touchSupport:function(){var e,n=navigator,t=0;void 0!==n.maxTouchPoints?t=p(n.maxTouchPoints):void 0!==n.msMaxTouchPoints&&(t=n.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in window}},vendor:function(){return navigator.vendor||""},vendorFlavors:function(){for(var e=[],n=0,t=["chrome","safari","__crWeb","__gCrWeb","yandex","__yb","__ybro","__firefox__","__edgeTrackingPreventionStatistics","webkit","oprt","samsungAr","ucweb","UCShellJava","puffinDevice"];n<t.length;n++){var r=t[n],o=window[r];o&&"object"==typeof o&&e.push(r)}return e.sort()},cookiesEnabled:function(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var n=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",n}catch(t){return!1}},colorGamut:function(){for(var e=0,n=["rec2020","p3","srgb"];e<n.length;e++){var t=n[e];if(matchMedia("(color-gamut: ".concat(t,")")).matches)return t}},invertedColors:function(){return!!_("inverted")||!_("none")&&void 0},forcedColors:function(){return!!O("active")||!O("none")&&void 0},monochrome:function(){if(matchMedia("(min-monochrome: 0)").matches){for(var e=0;e<=100;++e)if(matchMedia("(max-monochrome: ".concat(e,")")).matches)return e;throw new Error("Too high value")}},contrast:function(){return U("no-preference")?0:U("high")||U("more")?1:U("low")||U("less")?-1:U("forced")?10:void 0},reducedMotion:function(){return!!Q("reduce")||!Q("no-preference")&&void 0},hdr:function(){return!!K("high")||!K("standard")&&void 0},math:function(){var e,n=q.acos||$,t=q.acosh||$,r=q.asin||$,o=q.asinh||$,a=q.atanh||$,i=q.atan||$,c=q.sin||$,u=q.sinh||$,l=q.cos||$,s=q.cosh||$,d=q.tan||$,m=q.tanh||$,f=q.exp||$,v=q.expm1||$,h=q.log1p||$;return{acos:n(.12312423423423424),acosh:t(1e308),acoshPf:(e=1e154,q.log(e+q.sqrt(e*e-1))),asin:r(.12312423423423424),asinh:o(1),asinhPf:function(e){return q.log(e+q.sqrt(e*e+1))}(1),atanh:a(.5),atanhPf:function(e){return q.log((1+e)/(1-e))/2}(.5),atan:i(.5),sin:c(-1e300),sinh:u(1),sinhPf:function(e){return q.exp(e)-1/q.exp(e)/2}(1),cos:l(10.000000000123),cosh:s(1),coshPf:function(e){return(q.exp(e)+1/q.exp(e))/2}(1),tan:d(-1e300),tanh:m(1),tanhPf:function(e){return(q.exp(2*e)-1)/(q.exp(2*e)+1)}(1),exp:f(1),expm1:v(1),expm1Pf:function(e){return q.exp(e)-1}(1),log1p:h(10),log1pPf:function(e){return q.log(1+e)}(10),powPI:function(e){return q.pow(q.PI,e)}(-100)}},videoCard:function(){var e,n=document.createElement("canvas"),t=null!==(e=n.getContext("webgl"))&&void 0!==e?e:n.getContext("experimental-webgl");if(t&&"getExtension"in t){var r=t.getExtension("WEBGL_debug_renderer_info");if(r)return{vendor:(t.getParameter(r.UNMASKED_VENDOR_WEBGL)||"").toString(),renderer:(t.getParameter(r.UNMASKED_RENDERER_WEBGL)||"").toString()}}},pdfViewerEnabled:function(){return navigator.pdfViewerEnabled},architecture:function(){var e=new Float32Array(1),n=new Uint8Array(e.buffer);return e[0]=1/0,e[0]=e[0]-e[0],n[3]}};function te(e){var n=function(e){if(G())return.4;if(x())return F()?.5:.3;var n=e.platform.value||"";if(/^Win/.test(n))return.6;if(/^Mac/.test(n))return.5;return.7}(e),t=function(e){return w(.99+.01*e,1e-4)}(n);return{score:n,comment:"$ if upgrade to Pro: https://fpjs.dev/pro".replace(/\$/g,"".concat(t))}}function re(n){return JSON.stringify(n,(function(n,t){return t instanceof Error?e({name:(r=t).name,message:r.message,stack:null===(o=r.stack)||void 0===o?void 0:o.split("\n")},r):t;var r,o}),2)}function oe(e){return h(function(e){for(var n="",t=0,r=Object.keys(e).sort();t<r.length;t++){var o=r[t],a=e[o],i=a.error?"error":JSON.stringify(a.value);n+="".concat(n?"|":"").concat(o.replace(/([:|\\])/g,"\\$1"),":").concat(i)}return n}(e))}function ae(e){return void 0===e&&(e=50),function(e,n){void 0===n&&(n=1/0);var t=window.requestIdleCallback;return t?new Promise((function(e){return t.call(window,(function(){return e()}),{timeout:n})})):o(Math.min(e,n))}(e,2*e)}function ie(e,r){var o=Date.now();return{get:function(a){return n(this,void 0,void 0,(function(){var n,i,c;return t(this,(function(t){switch(t.label){case 0:return n=Date.now(),[4,e()];case 1:return i=t.sent(),c=function(e){var n;return{get visitorId(){return void 0===n&&(n=oe(this.components)),n},set visitorId(e){n=e},confidence:te(e),components:e,version:"3.4.2"}}(i),(r||(null==a?void 0:a.debug))&&console.log("Copy the text below to get the debug data:\n\n```\nversion: ".concat(c.version,"\nuserAgent: ").concat(navigator.userAgent,"\ntimeBetweenLoadAndGet: ").concat(n-o,"\nvisitorId: ").concat(c.visitorId,"\ncomponents: ").concat(re(i),"\n```")),[2,c]}}))}))}}}function ce(e){var r=void 0===e?{}:e,o=r.delayFallback,a=r.debug;return r.monitoring,n(this,void 0,void 0,(function(){return t(this,(function(e){switch(e.label){case 0:return[4,ae(o)];case 1:return e.sent(),[2,ie(V(ne,{debug:a},[]),a)]}}))}))}var ue={load:ce,hashComponents:oe,componentsToDebugString:re},le=h;export{re as componentsToDebugString,ue as default,M as getFullscreenElement,z as getScreenFrame,oe as hashComponents,G as isAndroid,S as isChromium,F as isDesktopSafari,C as isEdgeHTML,Y as isGecko,W as isTrident,x as isWebKit,ce as load,V as loadSources,le as murmurX64Hash128,ae as prepareForSources,ne as sources,Z as transformSource,X as withIframe};
|
|
File without changes
|
|
File without changes
|