-
Notifications
You must be signed in to change notification settings - Fork 553
TextPredictor #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
TextPredictor #486
Changes from all commits
0a0a4c6
002683f
60a847c
60a9e27
bc7f38d
f9ca56b
fe0ecbb
4a52ac7
30cc834
14e6720
6b75a73
d10945e
06f64b2
c9ff3d4
e7b6f6d
2307b37
bf3203b
10c93b2
53b5f09
ee3cacb
8096a89
fed989b
c40af7d
d0b3b11
30e9f60
d15dd60
6c42839
301eb16
c59a3b2
f04b69e
2f07223
ea515d2
6cc2f9e
4cc2b4e
4fa136d
c5d9914
25c1baf
f9d3b22
c1568b4
1e4201d
9692d4e
1b2cb28
05941bc
984d000
74f27b5
c8848c7
7be2c5c
1c7f7ad
be60fa6
3a29c5b
543b660
4296129
ca30eab
5bd061f
2b150e7
505c894
cd98daf
98ee138
ff8c078
24a5333
2aeb563
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,7 @@ | |
| SUMMARIZATION, | ||
| NLG_TASKS, | ||
| MULTICHOICECLASSIFICATION, | ||
| MM_TASKS | ||
| ) | ||
|
|
||
| try: | ||
|
|
@@ -133,6 +134,13 @@ def estimator(self): | |
| def _preprocess(self, X): | ||
| return X | ||
|
|
||
| @staticmethod | ||
| def _join(X_train, y_train): | ||
| y_train = DataFrame(y_train, index=X_train.index) | ||
| y_train.columns = ["label"] | ||
| train_df = X_train.join(y_train) | ||
| return train_df | ||
|
|
||
| def _fit(self, X_train, y_train, **kwargs): | ||
|
|
||
| current_time = time.time() | ||
|
|
@@ -2127,6 +2135,115 @@ class XGBoostLimitDepth_TS(TS_SKLearn): | |
| base_class = XGBoostLimitDepthEstimator | ||
|
|
||
|
|
||
| class MultiModalEstimator(BaseEstimator): | ||
| """ | ||
| The class for tuning AutoGluon TextPredictor | ||
| """ | ||
| def __init__(self, task="binary", **config): | ||
| super().__init__(task, **config) | ||
| import uuid | ||
|
|
||
| self.trial_id = str(uuid.uuid1().hex)[:8] | ||
|
|
||
| @classmethod | ||
| def search_space(cls, **params): | ||
| """ | ||
| Add the possible search space configs here, e.g. 'optimization.lr' | ||
| reference: | ||
| https://auto.gluon.ai/stable/tutorials/text_prediction/customization.html#custom-hyperparameter-values | ||
| """ | ||
| search_space_dict = { | ||
| "model.fusion_mlp.hidden_sizes": { | ||
| "domain": tune.choice(list(range(32, 129))), | ||
| "init_value": 128, | ||
| }, | ||
| "optimization.learning_rate": { | ||
| "domain": tune.loguniform(lower=1E-5, upper=1E-4), | ||
| "init_value": 1E-4, | ||
| }, | ||
| "optimization.weight_decay": { | ||
| "domain": tune.choice([1E-4, 1E-3, 1E-2]), | ||
| "init_value": 1E-4, | ||
| }, | ||
| "optimization.warmup_steps": { | ||
| "domain": tune.choice([0.1, 0.2]), | ||
| "init_value": 0.1, | ||
| }, | ||
| } | ||
| return search_space_dict | ||
|
|
||
| def fit(self, X_train=None, y_train=None, budget=None, **kwargs): | ||
| from autogluon.text import TextPredictor | ||
| from .nlp.utils import AGArgs | ||
|
|
||
| self._kwargs = kwargs | ||
| self.ag_args = AGArgs(**kwargs["ag_args"]) | ||
| seed = self._kwargs.get("seed", 123) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why 123?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They used this value for their experiment. |
||
|
|
||
| # get & set the hyperparameters, update with self.params | ||
| hyperparameters = self.ag_args.hyperparameters | ||
| for key, value in self.params.items(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of a for loop, try implement using one line with dict.update()
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two problems here:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. both problems can be solved using python conditional value assignment https://stackoverflow.com/questions/6402311/python-conditional-assignment-operator |
||
| if key == "n_jobs": | ||
| continue | ||
| elif key == "model.fusion_mlp.hidden_sizes": | ||
| hyperparameters[key] = [value] | ||
| else: | ||
| hyperparameters[key] = value.item() if isinstance(value, np.float64) else value | ||
|
|
||
| start_time = time.time() | ||
| self.model_path = os.path.join(self.ag_args.output_dir, self.trial_id) | ||
| assert self._task in MM_TASKS, f"The task is not multimodal, but {self._task}. " | ||
| model = TextPredictor(path=self.model_path, | ||
| label="label", | ||
| problem_type=self._task[3:], | ||
| eval_metric=kwargs["metric"], | ||
| backend="pytorch", | ||
| verbosity=0) | ||
| train_data = BaseEstimator._join(X_train, y_train) | ||
| # use valid data for early stopping | ||
| X_val = kwargs.get("X_val") | ||
| y_val = kwargs.get("y_val") | ||
| if X_val is not None and y_val is not None: | ||
| tuning_data = BaseEstimator._join(X_val, y_val) | ||
| else: | ||
| tuning_data = None | ||
| # NOTE: if no tuning_data, model.fit() will holdout a fraction from train_data for early stopping | ||
| model.fit(train_data=train_data, | ||
| tuning_data=tuning_data, | ||
| hyperparameters=hyperparameters, | ||
| num_gpus=kwargs.get("gpu_per_trial", None), | ||
| time_limit=budget, | ||
| seed=seed) | ||
|
|
||
| training_time = time.time() - start_time | ||
| return training_time | ||
|
|
||
| def predict(self, X): | ||
| from autogluon.text import TextPredictor | ||
|
|
||
| model = TextPredictor.load(path=self.model_path, backend="pytorch") | ||
| output = model.predict(X, as_pandas=False) | ||
| return output | ||
|
|
||
| def predict_proba(self, X): | ||
| from autogluon.text import TextPredictor | ||
|
|
||
| # only works for classification tasks | ||
| assert ( | ||
| self._task in CLASSIFICATION | ||
| ), "predict_proba() only for classification tasks." | ||
| model = TextPredictor.load(path=self.model_path, backend="pytorch") | ||
| output = model.predict_proba(X, as_pandas=False) | ||
| return output | ||
|
|
||
| def score(self, X_val: DataFrame, y_val: Series, **kwargs): | ||
| from autogluon.text import TextPredictor | ||
|
|
||
| model = TextPredictor.load(path=self.model_path, backend="pytorch") | ||
| val_data = BaseEstimator._join(X_val, y_val) | ||
| return model.evaluate(val_data) | ||
|
|
||
|
|
||
| class suppress_stdout_stderr(object): | ||
| def __init__(self): | ||
| # Open a pair of null files | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There were only 4 hyperparameters and now there are 9. Which one was the search space used in your original experiment for autogluon?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original four are "model.network.agg_net.mid_units", "optimization.warmup_portion", "optimization.lr", "optimization.wd".