diff --git a/.gitignore b/.gitignore index e26da35..6642e14 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ models/ /datasets/ examples/datasets/.~lock* .vscode +output.txt # But don't ignore these paths: !models/sentencepiece/ diff --git a/__init__.py b/__init__.py index bab0007..0659283 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,6 @@ # This file is auto-generated. Do not edit manually. from typing import Dict, Type, TypeVar +from .modules.hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode from .modules.pytorch_wrapper.pt_abs import PtAbs from .modules.pytorch_wrapper.pt_acos import PtAcos from .modules.pytorch_wrapper.pt_add import PtAdd @@ -111,6 +112,7 @@ from .modules.pytorch_wrapper.pt_tokenizer import PtTokenizer from .modules.pytorch_wrapper.pt_train_classification_model import PtTrainClassificationModel from .modules.pytorch_wrapper.pt_train_classification_model_lr import PtTrainClassificationModelLr from .modules.pytorch_wrapper.pt_train_classification_transformer_model import PtTrainClassificationTransformerModel +from .modules.pytorch_wrapper.pt_train_fine_tune_classification_transformer_model import PtTrainFineTuneClassificationTransformerModel from .modules.pytorch_wrapper.pt_train_model import PtTrainModel from .modules.pytorch_wrapper.pt_train_regression_model import PtTrainRegressionModel from .modules.pytorch_wrapper.pt_train_rnn_model import PtTrainRNNModel @@ -163,6 +165,7 @@ from .modules.pytorch_wrapper.ptn_embedding_rnn_linear import PtnEmbeddingRNNLin from .modules.pytorch_wrapper.ptn_embedding_transformer_linear import PtnEmbeddingTransformerLinear from .modules.pytorch_wrapper.ptn_gru import PtnGRU from .modules.pytorch_wrapper.ptn_gru_linear import PtnGRULinear +from .modules.pytorch_wrapper.ptn_hf_fine_tuned_classification_model import PtnHfFineTunedClassificationModel from .modules.pytorch_wrapper.ptn_huber_loss import PtnHuberLoss from .modules.pytorch_wrapper.ptn_instance_norm2d import PtnInstanceNorm2d from .modules.pytorch_wrapper.ptn_kl_div_loss import PtnKLDivLoss @@ -209,6 +212,7 @@ NODE_CLASS_MAPPINGS (Dict[str, Type[T]]): """ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = { + "HfTokenizerEncode": HfTokenizerEncode, "PtAbs": PtAbs, "PtAcos": PtAcos, "PtAdd": PtAdd, @@ -320,6 +324,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = { "PtTrainClassificationModel": PtTrainClassificationModel, "PtTrainClassificationModelLr": PtTrainClassificationModelLr, "PtTrainClassificationTransformerModel": PtTrainClassificationTransformerModel, + "PtTrainFineTuneClassificationTransformerModel": PtTrainFineTuneClassificationTransformerModel, "PtTrainModel": PtTrainModel, "PtTrainRNNModel": PtTrainRNNModel, "PtTrainRegressionModel": PtTrainRegressionModel, @@ -372,6 +377,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = { "PtnEmbeddingTransformerLinear": PtnEmbeddingTransformerLinear, "PtnGRU": PtnGRU, "PtnGRULinear": PtnGRULinear, + "PtnHfFineTunedClassificationModel": PtnHfFineTunedClassificationModel, "PtnHuberLoss": PtnHuberLoss, "PtnInstanceNorm2d": PtnInstanceNorm2d, "PtnKLDivLoss": PtnKLDivLoss, @@ -418,6 +424,7 @@ NODE_DISPLAY_NAME_MAPPINGS (Dict[str, str]): """ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = { + "HfTokenizerEncode": "Hf Tokenizer Encode", "PtAbs": "Pt Abs", "PtAcos": "Pt Acos", "PtAdd": "Pt Add", @@ -529,6 +536,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = { "PtTrainClassificationModel": "Pt Train Classification Model", "PtTrainClassificationModelLr": "Pt Train Classification Model Lr", "PtTrainClassificationTransformerModel": "Pt Train Classification Transformer Model", + "PtTrainFineTuneClassificationTransformerModel": "Pt Train Fine Tune Classification Transformer Model", "PtTrainModel": "Pt Train Model", "PtTrainRNNModel": "Pt Train RNN Model", "PtTrainRegressionModel": "Pt Train Regression Model", @@ -581,6 +589,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = { "PtnEmbeddingTransformerLinear": "Ptn Embedding Transformer Linear", "PtnGRU": "Ptn GRU", "PtnGRULinear": "Ptn GRU Linear", + "PtnHfFineTunedClassificationModel": "Ptn Hf Fine Tuned Classification Model", "PtnHuberLoss": "Ptn Huber Loss", "PtnInstanceNorm2d": "Ptn Instance Norm 2d", "PtnKLDivLoss": "Ptn KL Div Loss", diff --git a/docs/reference/hf_tokenizer_encode.md b/docs/reference/hf_tokenizer_encode.md new file mode 100644 index 0000000..f1db16c --- /dev/null +++ b/docs/reference/hf_tokenizer_encode.md @@ -0,0 +1,35 @@ +# Hf Tokenizer Encode +Hugging Face tokenizer wrapper for encoding text into token ID tensors. + + Args: + model_name (str): Name of the model. + padding (bool): Whether to pad sequences to equal length. + padding_method (str): 'longest' or 'max_length'. + - 'longest': pad to the longest sequence length after truncation in this batch. + - 'max_length': pad all sequences to the fixed length `max_length`. + truncation (bool): Whether to truncate sequences to `max_length`. + max_length (int): The target length for truncation or padding. + If you specify 0, it uses model's maximum input length. + + Returns: + PTCALLABLE: A tuple containing a callable that accepts a sentence or list of + sentences and returns token ID tensor(s) and attention mask(s). + +## Input +| Name | Data type | +|---|---| +| model_name | String | +| padding | Boolean | +| padding_method | | +| truncation | Boolean | +| max_length | Int | + +## Output +| Data type | +|---| +| Ptcallable | + +
+Category: PyTorch wrapper - Training + +ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved. diff --git a/docs/reference/node_reference.md b/docs/reference/node_reference.md index 9cc949a..d1369d9 100644 --- a/docs/reference/node_reference.md +++ b/docs/reference/node_reference.md @@ -160,6 +160,7 @@ | [Ptn Embedding Transformer Linear](ptn_embedding_transformer_linear.md) | A Transformer encoder model with a linear head. | | [Ptn GRU](ptn_gru.md) | A gated recurrent unit (GRU) model consisting of one or more of a recurrent layer. | | [Ptn GRU Linear](ptn_gru_linear.md) | A recurrent neural network (GRU) model with a linear head. | +| [Ptn Hf Fine Tuned Classification Model](ptn_hf_fine_tuned_classification_model.md) | A binary classification model containing a Hugging Face pretrained Transformer model. | | [Ptn Instance Norm 2d](ptn_instance_norm2d.md) | A normalization model to normalize elements over spatial axes within each channel for each sample. | | [Ptn LSTM](ptn_lstm.md) | A long short-term memory (LSTM) model consisting of one or more of a recurrent layer. | | [Ptn LSTM Linear](ptn_lstm_linear.md) | A recurrent neural network (LSTM) model with a linear head. | @@ -225,6 +226,7 @@ ## PyTorch wrapper - Training | Node | Description | | --- | --- | +| [Hf Tokenizer Encode](hf_tokenizer_encode.md) | Hugging Face tokenizer wrapper for encoding text into token ID tensors. | | [Pt Apply Function](pt_apply_function.md) | Applies a function to the input tensor. | | [Pt Compute Loss](pt_compute_loss.md) | Computes loss for the input with the target using the specified loss function. | | [Pt Data Loader](pt_data_loader.md) | Loads data from a dataset node and creates a PyTorch DataLoader. | @@ -236,6 +238,7 @@ | [Pt Train Classification Model](pt_train_classification_model.md) | Trains a classification model using a given dataset, optimizer, and number of epochs. | | [Pt Train Classification Model Lr](pt_train_classification_model_lr.md) | Trains a classification model using a given dataset, optimizer, and number of epochs with learning rate decay. | | [Pt Train Classification Transformer Model](pt_train_classification_transformer_model.md) | Trains a classification Transformer model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. | +| [Pt Train Fine Tune Classification Transformer Model](pt_train_fine_tune_classification_transformer_model.md) | Fine-tunes a classification Transformer model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. | | [Pt Train Model](pt_train_model.md) | Trains a model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. | | [Pt Train RNN Model](pt_train_rnn_model.md) | Trains an RNN model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. | | [Pt Train Regression Model](pt_train_regression_model.md) | Trains a regression model using a given dataset, optimizer, and number of epochs. | diff --git a/docs/reference/pt_train_fine_tune_classification_transformer_model.md b/docs/reference/pt_train_fine_tune_classification_transformer_model.md new file mode 100644 index 0000000..c0f671c --- /dev/null +++ b/docs/reference/pt_train_fine_tune_classification_transformer_model.md @@ -0,0 +1,45 @@ +# Pt Train Fine Tune Classification Transformer Model +Fine-tunes a classification Transformer model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. + + Args: + model (PTMODEL): The PyTorch model to be trained. + train_loader (torch.utils.data.DataLoader): DataLoader containing the training dataset. + optimizer (PTOPTIMIZER): Optimizer used for training. Only Adam and AdamW are supported. + loss (PTLOSS): The loss class. + epochs (int): Number of training epochs. + freeze_pretrained_module_epochs (int) : Number of epochs to freeze pretrained module. + use_gpu (bool): Whether to use GPU for training. + early_stopping (bool): Whether to turn on early stopping + early_stopping_rounds (int): Specifies the number of rounds to monitor the evaluation loss when early_stopping is enabled and validation data is specified. If the loss does not decrease compared to the current best loss within this period, training will be stopped. + output_best_val_model (bool): Whether to outputs the model with the best val loss or the model from the last epoch. + classification_metrics (bool): If True and if val_loader is set, print out classification metrics. This is only valid for classification model training. + val_loader (PTDATALOADER): DataLoader for validation dataset (optional). + +## Input +| Name | Data type | +|---|---| +| model | Ptmodel | +| train_loader | Ptdataloader | +| optimizer | Ptoptimizer | +| loss_function | Ptloss | +| epochs | Int | +| freeze_pretrained_module_epochs | Int | +| use_gpu | Boolean | +| early_stopping | Boolean | +| early_stopping_rounds | Int | +| output_best_val_model | Boolean | +| classification_metrics | Boolean | +| scheduler | Ptlrscheduler | +| val_loader | Ptdataloader | + +## Output +| Data type | +|---| +| Ptmodel | +| Tensor | +| Tensor | + +
+Category: PyTorch wrapper - Training + +ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved. diff --git a/docs/reference/ptn_hf_fine_tuned_classification_model.md b/docs/reference/ptn_hf_fine_tuned_classification_model.md new file mode 100644 index 0000000..3946447 --- /dev/null +++ b/docs/reference/ptn_hf_fine_tuned_classification_model.md @@ -0,0 +1,26 @@ +# Ptn Hf Fine Tuned Classification Model +A binary classification model containing a Hugging Face pretrained Transformer model. + + Args: + model_name (str): Name or path of the pretrained Hugging Face model. + use_mean_pooling (bool): If True, average token embeddings using the attention mask. + Otherwise, use pooler output or CLS token embedding. + dropout (float): Dropout rate applied before the final linear layer. + Set to 0.0 to disable dropout. Must be ≥ 0. + +## Input +| Name | Data type | +|---|---| +| model_name | String | +| use_mean_pooling | Boolean | +| dropout | Float | + +## Output +| Data type | +|---| +| Ptmodel | + +
+Category: PyTorch wrapper - Model + +ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved. diff --git a/docs/reference/ptv_hf_dataset_with_token_encode.md b/docs/reference/ptv_hf_dataset_with_token_encode.md index a89b877..fbefd2c 100644 --- a/docs/reference/ptv_hf_dataset_with_token_encode.md +++ b/docs/reference/ptv_hf_dataset_with_token_encode.md @@ -8,6 +8,7 @@ A PyTorch Dataset class wrapper for a Hugging Face dataset that converts text to label_field_name (str): Field name for labels. encode (PTCALLABLE): The reference to a token encoder function. remove_html_tags (bool): Remove html tags in text if True. + encode_return_dict (bool): Encode function returns a Dict instead of a Tuple. ## Input | Name | Data type | @@ -18,6 +19,7 @@ A PyTorch Dataset class wrapper for a Hugging Face dataset that converts text to | label_field_name | String | | encode | Ptcallable | | remove_html_tags | Boolean | +| encode_return_dict | Boolean | ## Output | Data type | diff --git a/docs/training_rnn_for_classification.md b/docs/training_rnn_for_classification.md index ea26409..93e609e 100644 --- a/docs/training_rnn_for_classification.md +++ b/docs/training_rnn_for_classification.md @@ -46,7 +46,7 @@ You can also enable `classification_metrics` to print validation accuracy to the ## Expected Accuracy -Using this workflow, you should get around **83% validation accuracy** on the Hugging Face version of the IMDB dataset, which is a solid result for an RNN. +Using this workflow, you should get around **85% validation accuracy** on the Hugging Face version of the IMDB dataset, which is a solid result for an RNN. Both GRU & LSTM workflows achieve approximately **87% validation accuracy**. # RNN Workflow with Training Embedding from Scratch diff --git a/examples/workflows/distilbert_classification.json b/examples/workflows/distilbert_classification.json new file mode 100644 index 0000000..5312d87 --- /dev/null +++ b/examples/workflows/distilbert_classification.json @@ -0,0 +1 @@ +{"last_node_id":35,"last_link_id":49,"nodes":[{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":13,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/distilbert_classification.pt"]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[36],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":9,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":24}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[34],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,true,"{\"num_workers\":1}"]},{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":10,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":25}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[35],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,false,"{\"num_workers\":1}"]},{"id":21,"type":"PtvHfDatasetWithTokenEncode","pos":[1907.6329345703125,1746.281982421875],"size":[271.5191650390625,178],"flags":{},"order":6,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":45}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[24],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","train","text","label",true,true]},{"id":30,"type":"HfTokenizerEncode","pos":[1482.29150390625,1882.735595703125],"size":[315,154],"flags":{},"order":4,"mode":0,"inputs":[{"name":"model_name","type":"STRING","widget":{"name":"model_name"},"link":44}],"outputs":[{"name":"PTCALLABLE","localized_name":"PTCALLABLE","type":"PTCALLABLE","links":[45,46],"slot_index":0}],"properties":{"Node name for S&R":"HfTokenizerEncode"},"widgets_values":["",true,"max_length",true,0]},{"id":24,"type":"PtvHfDatasetWithTokenEncode","pos":[1911.3275146484375,2022.5567626953125],"size":[271.5191650390625,178],"flags":{},"order":7,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":46}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[25],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","test","text","label",true,true]},{"id":31,"type":"CDAStringCreate","pos":[1494.0750732421875,1681.3331298828125],"size":[315,58],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","links":[44,48],"slot_index":0}],"properties":{"Node name for S&R":"CDAStringCreate"},"widgets_values":["distilbert-base-uncased"]},{"id":32,"type":"PtnHfFineTunedClassificationModel","pos":[2212.781494140625,1116.2008056640625],"size":[319.20001220703125,109.10855102539062],"flags":{},"order":5,"mode":0,"inputs":[{"name":"model_name","type":"STRING","widget":{"name":"model_name"},"link":48}],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[47,49],"slot_index":0}],"properties":{"Node name for S&R":"PtnHfFineTunedClassificationModel"},"widgets_values":["",true,0]},{"id":29,"type":"PtoAdamW","pos":[2673.749267578125,1107.9647216796875],"size":[285.66900634765625,158.52035522460938],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":47}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[42],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.00005000000000000003,0.9,0.999,0.01,false]},{"id":27,"type":"PtTrainClassificationTransformerModel","pos":[3090.223876953125,1736.2188720703125],"size":[344.3999938964844,292.4398193359375],"flags":{},"order":11,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":49},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":34},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":42},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":36},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":null},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":35}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[38],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainClassificationTransformerModel"},"widgets_values":[2,true,false,10,false,true]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":12,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":38}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/distilbert_classification.pt"]},{"id":34,"type":"MarkdownNote","pos":[1492.9459228515625,2107.386474609375],"size":[286.51580810546875,101.67364501953125],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[],"properties":{},"widgets_values":["Set max_length to 0 to use model's max_length."],"color":"#432","bgcolor":"#653"},{"id":35,"type":"MarkdownNote","pos":[1910.301025390625,2253.2001953125],"size":[273.0867614746094,101.08975982666016],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[],"properties":{},"widgets_values":["Set encode_return_dict to True for Hugging Face's models."],"color":"#432","bgcolor":"#653"}],"links":[[20,17,0,19,0,"STRING"],[24,21,0,7,0,"PTVDATASET"],[25,24,0,12,0,"PTVDATASET"],[34,7,0,27,1,"PTDATALOADER"],[35,12,0,27,5,"PTDATALOADER"],[36,16,0,27,3,"PTLOSS"],[38,27,0,17,0,"PTMODEL"],[42,29,0,27,2,"PTOPTIMIZER"],[44,31,0,30,0,"STRING"],[45,30,0,21,0,"PTCALLABLE"],[46,30,0,24,0,"PTCALLABLE"],[47,32,0,29,0,"PTMODEL"],[48,31,0,32,0,"STRING"],[49,32,0,27,0,"PTMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6658267047011096,"offset":[-1486.1782051740129,-635.1085045237869]},"node_versions":{"data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d","pt-wrapper":"6fa1ce92c78ce067426ad02bc0d756f7e89bfd4c"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/examples/workflows/embedding_rnn_classification.json b/examples/workflows/embedding_rnn_classification.json index f558e48..f1b81f8 100644 --- a/examples/workflows/embedding_rnn_classification.json +++ b/examples/workflows/embedding_rnn_classification.json @@ -1 +1 @@ -{"last_node_id":25,"last_link_id":28,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":9,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":25}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":8,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":24}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":10,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":23},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":17},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,50,true,false,10,false,true,true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":9,"type":"PtoAdam","pos":[2668.492919921875,1191.617431640625],"size":[315,106],"flags":{},"order":3,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":22}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[15,17],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdam"},"widgets_values":[0.001,0.9,0.999]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":5,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":15}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":12,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/embedding_rnn_classification.pt"]},{"id":20,"type":"PtnEmbeddingRNNLinear","pos":[2671.97216796875,1393.1790771484375],"size":[315,298],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[22,23],"slot_index":0}],"properties":{"Node name for S&R":"PtnEmbeddingRNNLinear"},"widgets_values":[32000,300,128,2,"tanh",true,true,0.1,true,1,true]},{"id":21,"type":"PtvHfDatasetWithTokenEncode","pos":[1907.6329345703125,1746.281982421875],"size":[271.5191650390625,130.8897247314453],"flags":{},"order":6,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":27}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[24],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","train","text","label"]},{"id":22,"type":"SpEncode","pos":[1502.9549560546875,1913.823974609375],"size":[315,154],"flags":{},"order":4,"mode":0,"inputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","link":26}],"outputs":[{"name":"PTCALLABLE","localized_name":"PTCALLABLE","type":"PTCALLABLE","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"SpEncode"},"widgets_values":[true,"max_length",0,true,300]},{"id":25,"type":"SpLoadModel","pos":[1246.61181640625,1912.7467041015625],"size":[210,60.936126708984375],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","links":[26],"slot_index":0}],"properties":{"Node name for S&R":"SpLoadModel"},"widgets_values":["spiece.model"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":11,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/embedding_rnn_classification.pt"]},{"id":24,"type":"PtvHfDatasetWithTokenEncode","pos":[1911.3275146484375,2022.5567626953125],"size":[271.5191650390625,130.8897247314453],"flags":{},"order":7,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":28}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[25],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","test","text","label"]}],"links":[[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[15,9,0,15,0,"PTOPTIMIZER"],[16,15,0,14,4,"PTLRSCHEDULER"],[17,9,0,14,2,"PTOPTIMIZER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[22,20,0,9,0,"PTMODEL"],[23,20,0,14,0,"PTMODEL"],[24,21,0,7,0,"PTVDATASET"],[25,24,0,12,0,"PTVDATASET"],[26,25,0,22,0,"SPMODEL"],[27,22,0,21,0,"PTCALLABLE"],[28,22,0,24,0,"PTCALLABLE"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.9366078361504352,"offset":[-1728.9490496794083,-1464.6600418938542]},"node_versions":{"pt-wrapper":"dfcc202c5004f0fde0a527ec54c4e9724a73ec1e","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file +{"last_node_id":25,"last_link_id":28,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":9,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":25}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":8,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":24}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":9,"type":"PtoAdam","pos":[2668.492919921875,1191.617431640625],"size":[315,106],"flags":{},"order":3,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":22}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[15,17],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdam"},"widgets_values":[0.001,0.9,0.999]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":5,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":15}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":12,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/embedding_rnn_classification.pt"]},{"id":20,"type":"PtnEmbeddingRNNLinear","pos":[2671.97216796875,1393.1790771484375],"size":[315,298],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[22,23],"slot_index":0}],"properties":{"Node name for S&R":"PtnEmbeddingRNNLinear"},"widgets_values":[32000,300,128,2,"tanh",true,true,0.1,true,1,true]},{"id":21,"type":"PtvHfDatasetWithTokenEncode","pos":[1907.6329345703125,1746.281982421875],"size":[271.5191650390625,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":27}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[24],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","train","text","label",false]},{"id":22,"type":"SpEncode","pos":[1502.9549560546875,1913.823974609375],"size":[315,154],"flags":{},"order":4,"mode":0,"inputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","link":26}],"outputs":[{"name":"PTCALLABLE","localized_name":"PTCALLABLE","type":"PTCALLABLE","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"SpEncode"},"widgets_values":[true,"max_length",0,true,300]},{"id":25,"type":"SpLoadModel","pos":[1246.61181640625,1912.7467041015625],"size":[210,60.936126708984375],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","links":[26],"slot_index":0}],"properties":{"Node name for S&R":"SpLoadModel"},"widgets_values":["spiece.model"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":11,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/embedding_rnn_classification.pt"]},{"id":24,"type":"PtvHfDatasetWithTokenEncode","pos":[1911.3275146484375,2022.5567626953125],"size":[271.5191650390625,154],"flags":{},"order":7,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":28}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[25],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","test","text","label",false]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":10,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":23},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":17},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,10,true,false,10,false,true,true]}],"links":[[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[15,9,0,15,0,"PTOPTIMIZER"],[16,15,0,14,4,"PTLRSCHEDULER"],[17,9,0,14,2,"PTOPTIMIZER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[22,20,0,9,0,"PTMODEL"],[23,20,0,14,0,"PTMODEL"],[24,21,0,7,0,"PTVDATASET"],[25,24,0,12,0,"PTVDATASET"],[26,25,0,22,0,"SPMODEL"],[27,22,0,21,0,"PTCALLABLE"],[28,22,0,24,0,"PTCALLABLE"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.0139333231369811,"offset":[-2176.4930227302984,-1180.960541106078]},"node_versions":{"pt-wrapper":"acf0e1c9794a552dc18e9cc1aea2343137b94388","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/examples/workflows/embedding_transformer_classification.json b/examples/workflows/embedding_transformer_classification.json index b0161b2..d608c21 100644 --- a/examples/workflows/embedding_transformer_classification.json +++ b/examples/workflows/embedding_transformer_classification.json @@ -1 +1 @@ -{"last_node_id":29,"last_link_id":43,"nodes":[{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":12,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/embedding_transformer_classification.pt"]},{"id":25,"type":"SpLoadModel","pos":[1246.61181640625,1912.7467041015625],"size":[210,60.936126708984375],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","links":[26],"slot_index":0}],"properties":{"Node name for S&R":"SpLoadModel"},"widgets_values":["spiece.model"]},{"id":21,"type":"PtvHfDatasetWithTokenEncode","pos":[1907.6329345703125,1746.281982421875],"size":[271.5191650390625,154],"flags":{},"order":5,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":27}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[24],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","train","text","label",true]},{"id":24,"type":"PtvHfDatasetWithTokenEncode","pos":[1911.3275146484375,2022.5567626953125],"size":[271.5191650390625,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":28}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[25],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","test","text","label",true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[36],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":8,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":24}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[34],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,true,"{\"num_workers\":1}"]},{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":9,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":25}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[35],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,false,"{\"num_workers\":1}"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":11,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":38}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/embedding_transformer_classification.pt"]},{"id":28,"type":"PtoLrSchedulerCosineAnnealing","pos":[3098.5263671875,1348.582275390625],"size":[311.11163330078125,113.72386932373047],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":43}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[40],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerCosineAnnealing"},"widgets_values":[10,1.0000000000000005e-9]},{"id":29,"type":"PtoAdamW","pos":[2673.749267578125,1107.9647216796875],"size":[285.66900634765625,158.52035522460938],"flags":{},"order":4,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":41}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[42,43],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.0003000000000000002,0.9,0.999,0.01,false]},{"id":26,"type":"PtnEmbeddingTransformerLinear","pos":[2669.3544921875,1336.1724853515625],"size":[303.65289306640625,370],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[32,41],"slot_index":0}],"properties":{"Node name for S&R":"PtnEmbeddingTransformerLinear"},"widgets_values":[2,32000,256,8,512,0.5,"gelu",0.00001,true,false,true,512,1,true]},{"id":27,"type":"PtTrainClassificationTransformerModel","pos":[3090.223876953125,1736.2188720703125],"size":[344.3999938964844,292.4398193359375],"flags":{},"order":10,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":32},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":34},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":42},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":36},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":40},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":35}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[38],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainClassificationTransformerModel"},"widgets_values":[10,true,false,10,false,true]},{"id":22,"type":"SpEncode","pos":[1502.9549560546875,1913.823974609375],"size":[315,154],"flags":{},"order":3,"mode":0,"inputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","link":26}],"outputs":[{"name":"PTCALLABLE","localized_name":"PTCALLABLE","type":"PTCALLABLE","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"SpEncode"},"widgets_values":[true,"max_length",0,true,512]}],"links":[[20,17,0,19,0,"STRING"],[24,21,0,7,0,"PTVDATASET"],[25,24,0,12,0,"PTVDATASET"],[26,25,0,22,0,"SPMODEL"],[27,22,0,21,0,"PTCALLABLE"],[28,22,0,24,0,"PTCALLABLE"],[32,26,0,27,0,"PTMODEL"],[34,7,0,27,1,"PTDATALOADER"],[35,12,0,27,5,"PTDATALOADER"],[36,16,0,27,3,"PTLOSS"],[38,27,0,17,0,"PTMODEL"],[40,28,0,27,4,"PTLRSCHEDULER"],[41,26,0,29,0,"PTMODEL"],[42,29,0,27,2,"PTOPTIMIZER"],[43,29,0,28,0,"PTOPTIMIZER"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.115326655450681,"offset":[-1077.6725411509767,-1390.0549035093902]},"node_versions":{"data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d","pt-wrapper":"3ba2eb708ba62ffb55b9855d79346746b961c250"},"ue_links":[]},"version":0.4} \ No newline at end of file +{"last_node_id":29,"last_link_id":43,"nodes":[{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":12,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/embedding_transformer_classification.pt"]},{"id":25,"type":"SpLoadModel","pos":[1246.61181640625,1912.7467041015625],"size":[210,60.936126708984375],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","links":[26],"slot_index":0}],"properties":{"Node name for S&R":"SpLoadModel"},"widgets_values":["spiece.model"]},{"id":21,"type":"PtvHfDatasetWithTokenEncode","pos":[1907.6329345703125,1746.281982421875],"size":[271.5191650390625,154],"flags":{},"order":5,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":27}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[24],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","train","text","label",true]},{"id":24,"type":"PtvHfDatasetWithTokenEncode","pos":[1911.3275146484375,2022.5567626953125],"size":[271.5191650390625,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"encode","localized_name":"encode","type":"PTCALLABLE","link":28}],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[25],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfDatasetWithTokenEncode"},"widgets_values":["imdb","test","text","label",true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[36],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":8,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":24}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[34],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,true,"{\"num_workers\":1}"]},{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":9,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":25}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[35],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[32,false,"{\"num_workers\":1}"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":11,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":38}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/embedding_transformer_classification.pt"]},{"id":28,"type":"PtoLrSchedulerCosineAnnealing","pos":[3098.5263671875,1348.582275390625],"size":[311.11163330078125,113.72386932373047],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":43}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[40],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerCosineAnnealing"},"widgets_values":[10,1.0000000000000005e-9]},{"id":29,"type":"PtoAdamW","pos":[2673.749267578125,1107.9647216796875],"size":[285.66900634765625,158.52035522460938],"flags":{},"order":4,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":41}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[42,43],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.0003000000000000002,0.9,0.999,0.01,false]},{"id":26,"type":"PtnEmbeddingTransformerLinear","pos":[2669.3544921875,1336.1724853515625],"size":[303.65289306640625,370],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[32,41],"slot_index":0}],"properties":{"Node name for S&R":"PtnEmbeddingTransformerLinear"},"widgets_values":[2,32000,256,8,512,0.5,"gelu",0.00001,true,false,true,512,1,true]},{"id":22,"type":"SpEncode","pos":[1502.9549560546875,1913.823974609375],"size":[315,154],"flags":{},"order":3,"mode":0,"inputs":[{"name":"spmodel","localized_name":"spmodel","type":"SPMODEL","link":26}],"outputs":[{"name":"PTCALLABLE","localized_name":"PTCALLABLE","type":"PTCALLABLE","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"SpEncode"},"widgets_values":[true,"max_length",0,true,512]},{"id":27,"type":"PtTrainClassificationTransformerModel","pos":[3090.223876953125,1736.2188720703125],"size":[344.3999938964844,292.4398193359375],"flags":{},"order":10,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":32},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":34},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":42},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":36},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":40},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":35}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[38],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainClassificationTransformerModel"},"widgets_values":[5,true,false,10,false,true]}],"links":[[20,17,0,19,0,"STRING"],[24,21,0,7,0,"PTVDATASET"],[25,24,0,12,0,"PTVDATASET"],[26,25,0,22,0,"SPMODEL"],[27,22,0,21,0,"PTCALLABLE"],[28,22,0,24,0,"PTCALLABLE"],[32,26,0,27,0,"PTMODEL"],[34,7,0,27,1,"PTDATALOADER"],[35,12,0,27,5,"PTDATALOADER"],[36,16,0,27,3,"PTLOSS"],[38,27,0,17,0,"PTMODEL"],[40,28,0,27,4,"PTLRSCHEDULER"],[41,26,0,29,0,"PTMODEL"],[42,29,0,27,2,"PTOPTIMIZER"],[43,29,0,28,0,"PTOPTIMIZER"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.0139333231369811,"offset":[-2368.835983847664,-1201.8963368034495]},"node_versions":{"data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d","pt-wrapper":"acf0e1c9794a552dc18e9cc1aea2343137b94388"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/examples/workflows/gru_classification.json b/examples/workflows/gru_classification.json index 6531ffd..afffb89 100644 --- a/examples/workflows/gru_classification.json +++ b/examples/workflows/gru_classification.json @@ -1 +1 @@ -{"last_node_id":21,"last_link_id":26,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":23},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":26},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,50,true,false,10,false,true,true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/gru_classification.pt"]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":25}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[10,0.5000000000000002]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/gru_classification.pt"]},{"id":20,"type":"PtnGRULinear","pos":[2672.0244140625,1382.3995361328125],"size":[315,250],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[23,24],"slot_index":0}],"properties":{"Node name for S&R":"PtnGRULinear"},"widgets_values":[100,512,2,true,true,0.4,true,1,true]},{"id":21,"type":"PtoAdamW","pos":[2676.04931640625,1162.1456298828125],"size":[315,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":24}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[25,26],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.001,0.9,0.999,0.01,false]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[16,15,0,14,4,"PTLRSCHEDULER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[23,20,0,14,0,"PTMODEL"],[24,20,0,21,0,"PTMODEL"],[25,21,0,15,0,"PTOPTIMIZER"],[26,21,0,14,2,"PTOPTIMIZER"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.3972131526604054,"offset":[-634.2050513544009,-140.5171891315913]},"node_versions":{"pt-wrapper":"b4bd168592762ed6fdc7dc4261d1f5fdf0d91e30","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file +{"last_node_id":21,"last_link_id":26,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/gru_classification.pt"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/gru_classification.pt"]},{"id":20,"type":"PtnGRULinear","pos":[2672.0244140625,1382.3995361328125],"size":[315,250],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[23,24],"slot_index":0}],"properties":{"Node name for S&R":"PtnGRULinear"},"widgets_values":[100,512,2,true,true,0.4,true,1,true]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":25}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":21,"type":"PtoAdamW","pos":[2676.04931640625,1162.1456298828125],"size":[315,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":24}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[25,26],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.0003000000000000002,0.9,0.999,0.01,false]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":23},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":26},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,10,true,false,10,false,true,true]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[16,15,0,14,4,"PTLRSCHEDULER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[23,20,0,14,0,"PTMODEL"],[24,20,0,21,0,"PTMODEL"],[25,21,0,15,0,"PTOPTIMIZER"],[26,21,0,14,2,"PTOPTIMIZER"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7740560629342431,"offset":[-1688.800250191328,-1064.425742506968]},"node_versions":{"pt-wrapper":"acf0e1c9794a552dc18e9cc1aea2343137b94388","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/examples/workflows/lstm_classification.json b/examples/workflows/lstm_classification.json index 0b1de88..bef2f5a 100644 --- a/examples/workflows/lstm_classification.json +++ b/examples/workflows/lstm_classification.json @@ -1 +1 @@ -{"last_node_id":22,"last_link_id":28,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":28},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":26},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,50,true,false,10,false,true,true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/lstm_classification.pt"]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":25}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[10,0.5000000000000002]},{"id":21,"type":"PtoAdamW","pos":[2676.04931640625,1162.1456298828125],"size":[315,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":27}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[25,26],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.001,0.9,0.999,0.01,false]},{"id":22,"type":"PtnLSTMLinear","pos":[2680.248779296875,1391.870849609375],"size":[315,274],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"PtnLSTMLinear"},"widgets_values":[100,512,2,true,true,0.4,true,0,1,true]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/lstm_classification.pt"]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[16,15,0,14,4,"PTLRSCHEDULER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[25,21,0,15,0,"PTOPTIMIZER"],[26,21,0,14,2,"PTOPTIMIZER"],[27,22,0,21,0,"PTMODEL"],[28,22,0,14,0,"PTMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6397157544911096,"offset":[-1591.995279947916,-928.1316784347933]},"node_versions":{"pt-wrapper":"70586c134bf52d39b4a3b7275d8312964699e2be","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file +{"last_node_id":22,"last_link_id":28,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/lstm_classification.pt"]},{"id":22,"type":"PtnLSTMLinear","pos":[2680.248779296875,1391.870849609375],"size":[315,274],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[27,28],"slot_index":0}],"properties":{"Node name for S&R":"PtnLSTMLinear"},"widgets_values":[100,512,2,true,true,0.4,true,0,1,true]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/lstm_classification.pt"]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":25}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":21,"type":"PtoAdamW","pos":[2676.04931640625,1162.1456298828125],"size":[315,154],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":27}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[25,26],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdamW"},"widgets_values":[0.0003000000000000002,0.9,0.999,0.01,false]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":28},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":26},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,15,true,false,10,false,true,true]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[16,15,0,14,4,"PTLRSCHEDULER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[25,21,0,15,0,"PTOPTIMIZER"],[26,21,0,14,2,"PTOPTIMIZER"],[27,22,0,21,0,"PTMODEL"],[28,22,0,14,0,"PTMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.8514616692276674,"offset":[-1912.2817677147568,-1067.545807133622]},"node_versions":{"pt-wrapper":"acf0e1c9794a552dc18e9cc1aea2343137b94388","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/examples/workflows/rnn_classification.json b/examples/workflows/rnn_classification.json index 7133602..158b4e8 100644 --- a/examples/workflows/rnn_classification.json +++ b/examples/workflows/rnn_classification.json @@ -1 +1 @@ -{"last_node_id":19,"last_link_id":21,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,326],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":12},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":17},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,50,true,false,10,false,true,true]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":9,"type":"PtoAdam","pos":[2668.492919921875,1191.617431640625],"size":[315,106],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":21}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[15,17],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdam"},"widgets_values":[0.001,0.9,0.999]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":15}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,100],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/rnn_classification.pt"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/rnn_classification.pt"]},{"id":13,"type":"PtnRNNLinear","pos":[2668.492919921875,1374.7393798828125],"size":[315,274],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[12,21],"slot_index":0}],"properties":{"Node name for S&R":"PtnRNNLinear"},"widgets_values":[100,128,2,"tanh",true,true,0.1,true,1,true]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[12,13,0,14,0,"PTMODEL"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[15,9,0,15,0,"PTOPTIMIZER"],[16,15,0,14,4,"PTLRSCHEDULER"],[17,9,0,14,2,"PTOPTIMIZER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[21,13,0,9,0,"PTMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7036873299402207,"offset":[-1643.4385821927863,-998.2899215112109]},"node_versions":{"pt-wrapper":"b4b5dc48f3843c4c802d035fac042d0d79bea5a1","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file +{"last_node_id":19,"last_link_id":21,"nodes":[{"id":12,"type":"PtDataLoader","pos":[2290.658447265625,2016.2130126953125],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":10}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[14],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,false,"{\"num_workers\":1}"]},{"id":7,"type":"PtDataLoader","pos":[2293.7060546875,1735.56494140625],"size":[271.68658447265625,173.3039093017578],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataset","localized_name":"dataset","type":"PTVDATASET","link":11}],"outputs":[{"name":"PTDATALOADER","localized_name":"PTDATALOADER","type":"PTDATALOADER","links":[13],"slot_index":0}],"properties":{"Node name for S&R":"PtDataLoader"},"widgets_values":[128,true,"{\"num_workers\":1}"]},{"id":16,"type":"PtnBCEWithLogitsLoss","pos":[2668.492919921875,1800.2408447265625],"size":[315,58],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"PTLOSS","localized_name":"PTLOSS","type":"PTLOSS","links":[18],"slot_index":0}],"properties":{"Node name for S&R":"PtnBCEWithLogitsLoss"},"widgets_values":["mean"]},{"id":10,"type":"PtvHfGloveDataset","pos":[1927.5224609375,1735.56494140625],"size":[315,178],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[11],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","train",100,300,"text","label"]},{"id":11,"type":"PtvHfGloveDataset","pos":[1920.82177734375,2017.7349853515625],"size":[315,178],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[{"name":"PTVDATASET","localized_name":"PTVDATASET","type":"PTVDATASET","links":[10],"slot_index":0}],"properties":{"Node name for S&R":"PtvHfGloveDataset"},"widgets_values":["imdb","test",100,300,"text","label"]},{"id":9,"type":"PtoAdam","pos":[2668.492919921875,1191.617431640625],"size":[315,106],"flags":{},"order":6,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":21}],"outputs":[{"name":"PTOPTIMIZER","localized_name":"PTOPTIMIZER","type":"PTOPTIMIZER","links":[15,17],"slot_index":0}],"properties":{"Node name for S&R":"PtoAdam"},"widgets_values":[0.001,0.9,0.999]},{"id":15,"type":"PtoLrSchedulerReduceOnPlateau","pos":[3111.27294921875,1377.6142578125],"size":[314.1559143066406,82],"flags":{},"order":7,"mode":0,"inputs":[{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":15}],"outputs":[{"name":"PTLRSCHEDULER","localized_name":"PTLRSCHEDULER","type":"PTLRSCHEDULER","links":[16],"slot_index":0}],"properties":{"Node name for S&R":"PtoLrSchedulerReduceOnPlateau"},"widgets_values":[3,0.5000000000000002]},{"id":19,"type":"PandasShowText","pos":[3504.62841796875,1897.03662109375],"size":[302.7994079589844,112],"flags":{},"order":10,"mode":0,"inputs":[{"name":"text","type":"STRING","widget":{"name":"text"},"link":20}],"outputs":[{"name":"STRING","localized_name":"STRING","type":"STRING","shape":6,"links":null}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","/container/transfer/models/rnn_classification.pt"]},{"id":17,"type":"PtSaveModel","pos":[3495.453125,1735.56494140625],"size":[318.3275146484375,91.27499389648438],"flags":{},"order":9,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":19}],"outputs":[{"name":"model full path","localized_name":"model full path","type":"STRING","links":[20],"slot_index":0}],"properties":{"Node name for S&R":"PtSaveModel"},"widgets_values":["/container/transfer/models/rnn_classification.pt"]},{"id":13,"type":"PtnRNNLinear","pos":[2668.492919921875,1374.7393798828125],"size":[315,274],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"PTMODEL","localized_name":"PTMODEL","type":"PTMODEL","links":[12,21],"slot_index":0}],"properties":{"Node name for S&R":"PtnRNNLinear"},"widgets_values":[100,128,2,"tanh",true,true,0.1,true,1,true]},{"id":14,"type":"PtTrainRNNModel","pos":[3111.27294921875,1735.56494140625],"size":[315,346],"flags":{},"order":8,"mode":0,"inputs":[{"name":"model","localized_name":"model","type":"PTMODEL","link":12},{"name":"train_loader","localized_name":"train_loader","type":"PTDATALOADER","link":13},{"name":"optimizer","localized_name":"optimizer","type":"PTOPTIMIZER","link":17},{"name":"loss_function","localized_name":"loss_function","type":"PTLOSS","link":18},{"name":"scheduler","localized_name":"scheduler","type":"PTLRSCHEDULER","shape":7,"link":16},{"name":"val_loader","localized_name":"val_loader","type":"PTDATALOADER","shape":7,"link":14},{"name":"h_0","localized_name":"h_0","type":"TENSOR","shape":7,"link":null}],"outputs":[{"name":"Model","localized_name":"Model","type":"PTMODEL","links":[19],"slot_index":0},{"name":"train loss","localized_name":"train loss","type":"TENSOR","links":null},{"name":"val loss","localized_name":"val loss","type":"TENSOR","links":null}],"properties":{"Node name for S&R":"PtTrainRNNModel"},"widgets_values":[true,10,true,false,10,false,true,true]}],"links":[[10,11,0,12,0,"PTVDATASET"],[11,10,0,7,0,"PTVDATASET"],[12,13,0,14,0,"PTMODEL"],[13,7,0,14,1,"PTDATALOADER"],[14,12,0,14,5,"PTDATALOADER"],[15,9,0,15,0,"PTOPTIMIZER"],[16,15,0,14,4,"PTLRSCHEDULER"],[17,9,0,14,2,"PTOPTIMIZER"],[18,16,0,14,3,"PTLOSS"],[19,14,0,17,0,"PTMODEL"],[20,17,0,19,0,"STRING"],[21,13,0,9,0,"PTMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.8514616692276671,"offset":[-2392.064250349222,-1358.7790640114683]},"node_versions":{"pt-wrapper":"acf0e1c9794a552dc18e9cc1aea2343137b94388","data-analysis":"68dd090367adffa569c3b3993d56e422f4516d2d"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/modules/hugging_face_wrapper/hf_dataset_with_token_encode.py b/modules/hugging_face_wrapper/hf_dataset_with_token_encode.py new file mode 100644 index 0000000..c6953d7 --- /dev/null +++ b/modules/hugging_face_wrapper/hf_dataset_with_token_encode.py @@ -0,0 +1,89 @@ +from typing import Tuple, Callable, Optional +import re +from html import unescape +import torch +from torch.utils.data import Dataset +from datasets import load_dataset # Hugging Face (not PyTorch) + + +class HfDatasetWithTokenEncode(Dataset): + """ + Hugging Face Dataset wrapper with custom token encode function. + + pragma: skip_doc + """ + def __init__(self, + dataset_name: str, + split: str, + sample_field_name: str = "text", + label_field_name: str = "label", + encode: Optional[Callable]=None, + remove_html_tags:Optional[bool]=False, + encode_return_dict:Optional[bool]=False) -> None: + """ + Initializes the dataset by loading Hugging Face dataset. + + Args: + dataset_name (str): The name of the Hugging Face dataset. + split (str): The dataset split (e.g., 'train'). + sample_field_name (str): Field name for text samples. + label_field_name (str): Field name for labels. + encode (Optional[Callable]): Token encode function + remove_html_tags (Optional[bool]): Remove html tags in text if True. + encode_return_dict (Optional[bool]): Encode function returns a Dict instead of a Tuple. + """ + self.dataset = load_dataset(dataset_name, split=split) + self.sample_field_name = sample_field_name + self.label_field_name = label_field_name + self.encode = encode + self.remove_html_tags = remove_html_tags + self.encode_return_dict = encode_return_dict + + def __getitem__(self, idx: int) -> Tuple[torch.Tensor, torch.Tensor]: + """ + Retrieves the (tokens, label) pair at the given index. + + Args: + idx (int): Index of the item. + + Returns: + Tuple[Tuple[torch.Tensor, torch.Tensor], torch.Tensor]: Tuple of the following: + - Tokens tensor and masks tensor. + - Label tensor + """ + # Get a text sample from database and convert to a word embedding + sample = self.dataset[idx] + if self.remove_html_tags: + # Decode HTML entities like "&", "<", etc. to their actual characters + text = unescape(sample[self.sample_field_name]) + + # Remove HTML tags (like
,

, etc.) + # The regex "<.*?>" uses .*? (non-greedy match) to ensure it matches one tag at a time, + # instead of greedily removing everything between the first '<' and last '>' + text = re.sub(r"<.*?>", " ", text) + + # Replace consecutive white space to a single white space + text = re.sub(r" +", " ", text) + else: + text = sample[self.sample_field_name] + + if self.encode_return_dict: + output = self.encode(text) + tokens = output["input_ids"] + masks = output["attention_mask"] + else: + tokens, masks = self.encode(text) + + # Get a corresponding label + label = torch.tensor(sample[self.label_field_name], dtype=torch.long) + return (tokens.squeeze(0), masks.squeeze(0)), label.squeeze(0) + + + def __len__(self) -> int: + """ + Returns the number of samples in the dataset. + + Returns: + int: Dataset length. + """ + return len(self.dataset) diff --git a/modules/hugging_face_wrapper/hf_glove_dataset.py b/modules/hugging_face_wrapper/hf_glove_dataset.py new file mode 100644 index 0000000..48c4768 --- /dev/null +++ b/modules/hugging_face_wrapper/hf_glove_dataset.py @@ -0,0 +1,132 @@ +from typing import Tuple +import re +from html import unescape +import torch +from torch.utils.data import Dataset +from datasets import load_dataset # Hugging Face (not PyTorch) +import scipy +import numpy as np +# Monkey-patch gensim as it relies on scipy's deprecated triu method +# /gensim/matutils.py has this line which causes ImportError: +# from scipy.linalg import get_blas_funcs, triu +# TODO: Monitor gensim and fix this if upgrade is made +scipy.linalg.triu = np.triu +import gensim.downloader as api + +class HfGloveDataset(Dataset): + """ + Hugging Face Dataset wrapper with word embedding support. + + pragma: skip_doc + """ + def __init__(self, + dataset_name: str, + split: str, + glove_dim: int = 100, + max_seq_len: int = 256, + sample_field_name: str = "text", + label_field_name: str = "label") -> None: + """ + Initializes the dataset by loading Hugging Face dataset and GloVe vectors. + + Args: + dataset_name (str): The name of the Hugging Face dataset. + split (str): The dataset split (e.g., 'train'). + glove_dim (int): Dimensionality of GloVe embeddings. + max_seq_len (int): Maximum sequence length. + sample_field_name (str): Field name for text samples. + label_field_name (str): Field name for labels. + """ + self.dataset = load_dataset(dataset_name, split=split) + self.glove_dim = glove_dim + self.max_seq_len = max_seq_len + self.sample_field_name = sample_field_name + self.label_field_name = label_field_name + + # Load GloVe from gensim + glove_name = f"glove-wiki-gigaword-{glove_dim}" + self.glove = api.load(glove_name) + self.unk_vector = torch.zeros(glove_dim) + + def tokenize(self, text: str) -> list[str]: + """ + Tokenizes raw text into a list of lowercase word tokens. + It removes HTML tags, decodes HTML entities, strips punctuation + (while keeping letters and numbers), and splits on whitespace. + + Args: + text (str): Raw text input (may include HTML and punctuation). + + Returns: + list[str]: List of clean, lowercase word tokens. + """ + # Decode HTML entities like "&", "<", etc. to their actual characters + text = unescape(text) + + # Remove HTML tags (like
,

, etc.) + # The regex "<.*?>" uses .*? (non-greedy match) to ensure it matches one tag at a time, + # instead of greedily removing everything between the first '<' and last '>' + text = re.sub(r"<.*?>", " ", text) + + # Remove all characters except letters, digits, and whitespace + # This strips punctuation like "!", ".", "(", but keeps words and numbers + text = re.sub(r"[^a-zA-Z0-9\s]", " ", text) + + # Replace consecutive white space to a single white space + text = re.sub(r" +", " ", text) + + # Convert to lowercase and split by whitespace to get token list + return text.lower().split() + + + def vectorize(self, tokens: list[str]) -> torch.Tensor: + """ + Converts tokens to a fixed-length tensor of word vectors. + + Args: + tokens (list[str]): A list of word tokens. + + Returns: + torch.Tensor: A tensor of shape (max_seq_len, glove_dim). + """ + vectors = [] + for token in tokens[:self.max_seq_len]: + if token in self.glove: + vec = torch.tensor(self.glove[token], dtype=torch.float32) + else: + vec = self.unk_vector + vectors.append(vec) + + if len(vectors) < self.max_seq_len: + pad = [torch.zeros(self.glove_dim) for _ in range(self.max_seq_len - len(vectors))] + vectors.extend(pad) + + return torch.stack(vectors) + + def __getitem__(self, idx: int) -> Tuple[torch.Tensor, torch.Tensor]: + """ + Retrieves the (embedded sequence, label) pair at the given index. + + Args: + idx (int): Index of the item. + + Returns: + Tuple[torch.Tensor, torch.Tensor]: Embedding tensor and label tensor. + """ + # Get a text sample from database and convert to a word embedding + sample = self.dataset[idx] + tokens = self.tokenize(sample[self.sample_field_name]) + emb_tensor = self.vectorize(tokens) + + # Get a corresponding label + label = torch.tensor(sample[self.label_field_name], dtype=torch.long) + return emb_tensor, label + + def __len__(self) -> int: + """ + Returns the number of samples in the dataset. + + Returns: + int: Dataset length. + """ + return len(self.dataset) diff --git a/modules/hugging_face_wrapper/hf_tokenizer_encode.py b/modules/hugging_face_wrapper/hf_tokenizer_encode.py new file mode 100644 index 0000000..5aa1b17 --- /dev/null +++ b/modules/hugging_face_wrapper/hf_tokenizer_encode.py @@ -0,0 +1,134 @@ +from typing import Any, Dict, Union, List, Tuple, Callable +import torch +from transformers import AutoTokenizer + + +class HfTokenizerEncode: + """ + Hugging Face tokenizer wrapper for encoding text into token ID tensors. + + Args: + model_name (str): Name of the model. + padding (bool): Whether to pad sequences to equal length. + padding_method (str): 'longest' or 'max_length'. + - 'longest': pad to the longest sequence length after truncation in this batch. + - 'max_length': pad all sequences to the fixed length `max_length`. + truncation (bool): Whether to truncate sequences to `max_length`. + max_length (int): The target length for truncation or padding. + If you specify 0, it uses model's maximum input length. + + Returns: + PTCALLABLE: A tuple containing a callable that accepts a sentence or list of + sentences and returns token ID tensor(s) and attention mask(s). + + category: PyTorch wrapper - Training + """ + + @classmethod + def INPUT_TYPES(cls) -> Dict[str, Any]: + """ + Defines the input types for the function. + + Returns: + Dict[str, Any]: A dictionary specifying required input types. + """ + return { + "required": { + "model_name": ("STRING", {"default":"", "multiline":False}), + "padding": ("BOOLEAN", {"default": True}), + "padding_method": (("max_length", "longest"),), + "truncation": ("BOOLEAN", {"default": True}), + "max_length": ("INT", {"default": 512, "min": 0, "max": 1_000_000}), + } + } + + RETURN_TYPES: Tuple[str] = ("PTCALLABLE",) + FUNCTION: str = "f" + CATEGORY: str = "Data Analysis" + + def encode( + self, + sentence: Union[str, List[str]], + ) -> Dict[str, torch.Tensor]: + + """ + Encodes a string or list of strings into token ID tensors. + + Args: + sentence (Union[str, List[str]]): Input sentence(s). + + Returns: + Dict: + input_ids: token IDs + attention_mask: Masks. 1 is non-padding, 0 is padding. + """ + if self.padding: + if self.max_length == 0: + retval = self.tokenizer( + sentence, + padding=self.padding_method, + truncation=self.truncation, + return_tensors="pt" + ) + else: + retval = self.tokenizer( + sentence, + padding=self.padding_method, + truncation=self.truncation, + max_length=self.max_length, + return_tensors="pt" + ) + else: # no padding + if self.max_length == 0: + retval = self.tokenizer( + sentence, + padding=False, + truncation=self.truncation, + return_tensors="pt" + ) + else: + retval = self.tokenizer( + sentence, + padding=False, + truncation=self.truncation, + return_tensors="pt" + ) + return retval + + def f( + self, + model_name: str, + padding: bool, + padding_method: str, + truncation: bool, + max_length: int + ) -> Tuple[Callable[[Union[str, List[str]]], Tuple[Union[torch.Tensor, List[torch.Tensor]], Union[torch.Tensor, List[torch.Tensor]]]]]: + """ + Instantiates a Hugging Face tokenizer, binds configuration and returns a callable encoder function. + - Supports includes: + - BertTokenizer + - RobertaTokenizer + - DistilBertTokenizer + - AlbertTokenizer + - ElectraTokenizer + + Args: + model_name (str): Name of the model. + padding (bool): Whether to pad sequences to equal length. + padding_method (str): 'longest' or 'max_length'. + - 'longest': pad to the longest sequence length after truncation in this batch. + - 'max_length': pad all sequences to the fixed length `max_length`. + truncation (bool): Whether to truncate sequences to `max_length`. + max_length (int): The target length for truncation or padding. + If you specify 0, it uses model's maximum input length. + + Returns: + Tuple[Callable]: A tuple containing a callable for the tokenizer function. + """ + + self.tokenizer = AutoTokenizer.from_pretrained(model_name) + self.padding = padding + self.padding_method = padding_method + self.truncation = truncation + self.max_length = max_length + return (self.encode,) diff --git a/modules/pytorch_wrapper/pt_train_classification_transformer_model.py b/modules/pytorch_wrapper/pt_train_classification_transformer_model.py index a9374c1..f867ad5 100644 --- a/modules/pytorch_wrapper/pt_train_classification_transformer_model.py +++ b/modules/pytorch_wrapper/pt_train_classification_transformer_model.py @@ -114,9 +114,6 @@ class PtTrainClassificationTransformerModel: best_val_loss = None rounds_since_best_val_loss = 0 - all_preds = [] - all_labels = [] - with torch.inference_mode(False): train_loss = [] val_loss = [] @@ -157,6 +154,8 @@ class PtTrainClassificationTransformerModel: if val_loader: with torch.no_grad(): + all_preds = [] + all_labels = [] model.train(False) # TODO: Change to model.*e*v*a*l() once Comfy's security checker is fixed. total_loss = 0 total_samples = len(val_loader.dataset) @@ -180,7 +179,7 @@ class PtTrainClassificationTransformerModel: if classification_metrics and y.squeeze().dim() == 1 : # Accuracy collection for binary classification - preds = (y_hat > 0.5).int().detach().cpu().numpy() + preds = (F.sigmoid(y_hat) > 0.5).int().detach().cpu().numpy() labels = y.int().detach().cpu().numpy() all_preds.extend(preds) all_labels.extend(labels) diff --git a/modules/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model.py b/modules/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model.py new file mode 100644 index 0000000..8db1907 --- /dev/null +++ b/modules/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model.py @@ -0,0 +1,253 @@ +import os +import sys +from typing import Any, Dict, Optional, Tuple, Union +import torch +import torch.nn as nn +import torch.nn.functional as F +from sklearn.metrics import accuracy_score +from .utils import set_requires_grad + +class PtTrainFineTuneClassificationTransformerModel: + """ + Fine-tunes a classification Transformer model using a given dataset, loss function, optimizer, and number of epochs with learning rate decay. + + Args: + model (PTMODEL): The PyTorch model to be trained. + train_loader (torch.utils.data.DataLoader): DataLoader containing the training dataset. + optimizer (PTOPTIMIZER): Optimizer used for training. Only Adam and AdamW are supported. + loss (PTLOSS): The loss class. + epochs (int): Number of training epochs. + freeze_pretrained_module_epochs (int) : Number of epochs to freeze pretrained module. + use_gpu (bool): Whether to use GPU for training. + early_stopping (bool): Whether to turn on early stopping + early_stopping_rounds (int): Specifies the number of rounds to monitor the evaluation loss when early_stopping is enabled and validation data is specified. If the loss does not decrease compared to the current best loss within this period, training will be stopped. + output_best_val_model (bool): Whether to outputs the model with the best val loss or the model from the last epoch. + classification_metrics (bool): If True and if val_loader is set, print out classification metrics. This is only valid for classification model training. + val_loader (PTDATALOADER): DataLoader for validation dataset (optional). + + category: PyTorch wrapper - Training + """ + + @classmethod + def INPUT_TYPES(cls) -> Dict[str, Any]: + """ + Defines the input types required for training the model. + + Returns: + Dict[str, Any]: A dictionary specifying required and optional input types. + """ + return { + "required": { + "model": ("PTMODEL", {}), + "train_loader": ("PTDATALOADER", {}), + "optimizer": ("PTOPTIMIZER", {}), + "loss_function": ("PTLOSS", {}), + "epochs": ("INT", {"default":2, "min":1, "max":1e6}), + "freeze_pretrained_module_epochs": ("INT", {"default":1, "min":1, "max":1e6}), + "use_gpu": ("BOOLEAN", {"default":False}), + "early_stopping": ("BOOLEAN", {"default":False}), + "early_stopping_rounds": ("INT", {"default":10, "min":1, "max":1000}), + "output_best_val_model": ("BOOLEAN", {"default":True}), + "classification_metrics": ("BOOLEAN", {"default":True}) + }, + "optional": { + "scheduler": ("PTLRSCHEDULER", {}), + "val_loader": ("PTDATALOADER", {}) + } + } + + RETURN_NAMES: tuple = ("Model", "train loss", "val loss") + RETURN_TYPES: tuple = ("PTMODEL","TENSOR","TENSOR") + FUNCTION: str = "f" + CATEGORY: str = "Training" + + @classmethod + def IS_CHANGED(cls, **kw): + return float("NaN") + + def f(self, + model: nn.Module, + train_loader: torch.utils.data.DataLoader, + optimizer: torch.optim.Optimizer, + loss_function: nn.Module, + epochs: int, + freeze_pretrained_module_epochs, + use_gpu: bool, + early_stopping: bool, + early_stopping_rounds: int, + output_best_val_model:bool, + classification_metrics:bool, + val_loader: Optional[torch.utils.data.DataLoader] = None, + ) -> Tuple[nn.Module, torch.Tensor, torch.Tensor]: + """ + Trains an Transformer model. + + Args: + model (torch.nn.Module): The PyTorch model to be trained. + train_loader (torch.utils.data.DataLoader): DataLoader containing the training dataset. + optimizer (PTOPTIMIZER): Optimizer used for training. Only Adam and AdamW are supported. + loss (torch.nn.Module): The loss class. + epochs (int): Number of training epochs. + freeze_pretrained_module_epochs (int) : Number of epochs to freeze pretrained module. + use_gpu (bool): Whether to use GPU for training. + early_stopping (bool): Whether to turn on early stopping + early_stopping_rounds (int): Specifies the number of rounds to monitor the evaluation loss when early_stopping is enabled and validation data is specified. If the loss does not decrease compared to the current best loss within this period, training will be stopped. + output_best_val_model (bool): Whether to outputs the model with the best val loss or the model from the last epoch. + classification_metrics (bool): If True and if val_loader is set, print out classification metrics. This is only valid for classification model training. + val_loader (Optional[torch.utils.data.DataLoader]): DataLoader for validation dataset (optional). + + Returns: + Tuple[torch.nn.Module, torch.Tensor, torch.Tensor]: A tuple containing the trained model, + training loss history, and validation loss history. + """ + checkpoint_dir = os.path.realpath( + os.path.join(os.path.dirname(__file__), "..", "..", "models", "tmp")) + print(f"Checkpoint tmp directory is set to {checkpoint_dir}") + if os.path.exists(checkpoint_dir) is False: + os.makedirs(checkpoint_dir) + print(f"Created {checkpoint_dir}") + best_checkpoint_path = os.path.join(checkpoint_dir, "best_model.pt") + + best_val_loss = None + rounds_since_best_val_loss = 0 + + with torch.inference_mode(False): + train_loss = [] + val_loss = [] + if use_gpu: + model.to("cuda") + + # Train the model + for epoch in range(epochs): + model.train() + total_loss = 0 + total_samples = len(train_loader.dataset) + + if epoch < freeze_pretrained_module_epochs: + set_requires_grad(model.llm_model, False) # freeze encoder + elif epoch == freeze_pretrained_module_epochs: + set_requires_grad(model.llm_model, True) # unfreeze encoder + + # Rebuild optimizer with separate LR for pretrained encoder and classifier head + if isinstance(optimizer, torch.optim.Adam): + lr = optimizer.defaults.get("lr", 1e-3) + betas = optimizer.defaults.get("betas", (0.9, 0.999)) + eps = optimizer.defaults.get("eps", 1e-8) + weight_decay = optimizer.defaults.get("weight_decay", 0) + + optimizer = torch.optim.Adam([ + {"params": model.llm_model.parameters(), "lr": lr * 0.2}, + {"params": model.linear.parameters(), "lr": lr} + ], lr=lr, betas=betas, eps=eps, weight_decay=weight_decay) + + elif isinstance(optimizer, torch.optim.AdamW): + lr = optimizer.defaults.get("lr", 1e-3) + betas = optimizer.defaults.get("betas", (0.9, 0.999)) + eps = optimizer.defaults.get("eps", 1e-8) + weight_decay = optimizer.defaults.get("weight_decay", 0) + + optimizer = torch.optim.AdamW([ + {"params": model.llm_model.parameters(), "lr": lr * 0.2}, + {"params": model.linear.parameters(), "lr": lr} + ], lr=lr, betas=betas, eps=eps, weight_decay=weight_decay) + + else: + raise ValueError("Only Adam and AdamW are supported for optimizer re-instantiation.") + + for x, y in train_loader: + if use_gpu: + if isinstance(x, list): + x = [e.to("cuda") for e in x] + else: + x = x.to("cuda") + y = y.to("cuda") + optimizer.zero_grad() + + y_hat = model(x) + if y.dim() == 1: + y = torch.unsqueeze(y, dim=-1) + y = y.to(torch.float32) + + loss = loss_function(y_hat, y) + loss.backward() + optimizer.step() + + batch_size = y.size(0) + batch_loss = loss.item() * batch_size + total_loss += batch_loss + + epoch_loss = total_loss / total_samples + print(f"Epoch (train) {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}") + train_loss.append(epoch_loss) + + if val_loader: + with torch.no_grad(): + all_preds = [] + all_labels = [] + + model.train(False) # TODO: Change to model.*e*v*a*l() once Comfy's security checker is fixed. + total_loss = 0 + total_samples = len(val_loader.dataset) + for x, y in val_loader: + if use_gpu: + if isinstance(x, list): + x = [e.to("cuda") for e in x] + else: + x = x.to("cuda") + y = y.to("cuda") + + y_hat = model(x) + if y.dim() == 1: + y = torch.unsqueeze(y, dim=-1) + y = y.to(torch.float32) + + loss = loss_function(y_hat, y) + batch_size = y.size(0) + batch_loss = loss.item() * batch_size + total_loss += batch_loss + + if classification_metrics and y.squeeze().dim() == 1 : + # Accuracy collection for binary classification + preds = (F.sigmoid(y_hat) > 0.5).int().detach().cpu().numpy() + labels = y.int().detach().cpu().numpy() + all_preds.extend(preds) + all_labels.extend(labels) + + epoch_loss = total_loss / total_samples + print(f"Epoch (val) {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}") + val_loss.append(epoch_loss) + + if classification_metrics: + if len(all_labels): + # Compute accuracy + acc = accuracy_score(all_labels, all_preds) + print(f"Validation Accuracy: {acc:.4f}") + else: + print("Accuracy was not computed as the label is not scalar.") + + if best_val_loss is None or epoch_loss < best_val_loss: + best_val_loss = epoch_loss + rounds_since_best_val_loss = 0 + torch.save(model.state_dict(), best_checkpoint_path) + print(f"Updated best val loss. Saved the model as {best_checkpoint_path}") + else: + rounds_since_best_val_loss += 1 + if early_stopping: + if rounds_since_best_val_loss >= early_stopping_rounds: + print(f"Val loss did not improve in {early_stopping_rounds} rounds. Stopping training.") + break + + if use_gpu: + model.to("cpu") + + if val_loader: + if epoch_loss > best_val_loss and output_best_val_model: + sd = torch.load(best_checkpoint_path, weights_only=True) + model.load_state_dict(sd) + print("Loaded the best model for output") + else: + print("Using the final epoch model for output.") + + return (model, + torch.tensor(train_loss, dtype=torch.float32), + torch.tensor(val_loss, dtype=torch.float32)) \ No newline at end of file diff --git a/modules/pytorch_wrapper/pt_train_rnn_model.py b/modules/pytorch_wrapper/pt_train_rnn_model.py index aca43e9..ea8dce7 100644 --- a/modules/pytorch_wrapper/pt_train_rnn_model.py +++ b/modules/pytorch_wrapper/pt_train_rnn_model.py @@ -127,9 +127,6 @@ class PtTrainRNNModel: best_val_loss = None rounds_since_best_val_loss = 0 - all_preds = [] - all_labels = [] - with torch.inference_mode(False): train_loss = [] val_loss = [] @@ -190,6 +187,8 @@ class PtTrainRNNModel: if val_loader: with torch.no_grad(): + all_preds = [] + all_labels = [] model.train(False) # TODO: Change to model.*e*v*a*l() once Comfy's security checker is fixed. total_loss = 0 total_samples = len(val_loader.dataset) @@ -228,7 +227,7 @@ class PtTrainRNNModel: if classification_metrics and y.squeeze().dim() == 1 : # Accuracy collection for binary classification - preds = (y_hat > 0.5).int().detach().cpu().numpy() + preds = (F.sigmoid(y_hat) > 0.5).int().detach().cpu().numpy() labels = y.int().detach().cpu().numpy() all_preds.extend(preds) all_labels.extend(labels) diff --git a/modules/pytorch_wrapper/ptn_gru.py b/modules/pytorch_wrapper/ptn_gru.py index 437ce8f..ed71bc7 100644 --- a/modules/pytorch_wrapper/ptn_gru.py +++ b/modules/pytorch_wrapper/ptn_gru.py @@ -35,7 +35,7 @@ class PtnGRU: "num_layers": ("INT", {"default": 1, "min": 1, "max": 1e3}), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), } } diff --git a/modules/pytorch_wrapper/ptn_gru_linear.py b/modules/pytorch_wrapper/ptn_gru_linear.py index 69dd86a..cdbde08 100644 --- a/modules/pytorch_wrapper/ptn_gru_linear.py +++ b/modules/pytorch_wrapper/ptn_gru_linear.py @@ -105,7 +105,7 @@ class PtnGRULinear: "num_layers": ("INT", {"default": 1, "min": 1, "max": 1e3}), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), "linear_output_size": ("INT", {"default": 1, "min": 1, "max": 1e6}), "linear_bias": ("BOOLEAN", {"default": True}), diff --git a/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model.py b/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model.py new file mode 100644 index 0000000..7adf927 --- /dev/null +++ b/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model.py @@ -0,0 +1,70 @@ +from typing import Any, Dict, Tuple +import torch +import torch.nn as nn + +from .ptn_hf_fine_tuned_classification_model_def import HfFineTunedClassificationModel + +class PtnHfFineTunedClassificationModel: + """ + A binary classification model containing a Hugging Face pretrained Transformer model. + + Args: + model_name (str): Name or path of the pretrained Hugging Face model. + use_mean_pooling (bool): If True, average token embeddings using the attention mask. + Otherwise, use pooler output or CLS token embedding. + dropout (float): Dropout rate applied before the final linear layer. + Set to 0.0 to disable dropout. Must be ≥ 0. + + category: PyTorch wrapper - Model + """ + + @classmethod + def INPUT_TYPES(cls) -> Dict[str, Any]: + """ + Defines the input types for the function. + + Returns: + Dict[str, Any]: A dictionary specifying required input types. + """ + return { + "required": { + "model_name": ("STRING", {"default": "", "multiline": False}), + "use_mean_pooling": ("BOOLEAN", {"default": True}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}) + } + } + + RETURN_TYPES: Tuple[str] = ("PTMODEL",) + FUNCTION: str = "f" + CATEGORY: str = "Training" + + @classmethod + def IS_CHANGED(cls, **kw): + return float("NaN") + + def f(self, + model_name: str, + use_mean_pooling: bool, + dropout: float + ) -> Tuple[nn.Module]: + """ + Instantiates a binary classification model containing a Hugging Face pretrained Transformer model. + + Args: + model_name (str): Name or path of the pretrained Hugging Face model. + use_mean_pooling (bool): If True, average token embeddings using the attention mask. + Otherwise, use pooler output or CLS token embedding. + dropout (float): Dropout rate applied before the final linear layer. + Set to 0.0 to disable dropout. Must be ≥ 0. + + Returns: + Tuple[nn.Module]: A tuple containing the instantiated PyTorch model. + """ + with torch.inference_mode(False): + model = HfFineTunedClassificationModel( + model_name=model_name, + use_mean_pooling=use_mean_pooling, + dropout=dropout + ) + + return (model,) diff --git a/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def.py b/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def.py new file mode 100644 index 0000000..6552675 --- /dev/null +++ b/modules/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def.py @@ -0,0 +1,92 @@ +from typing import List, Dict, Any, Tuple, Type +import torch +import torch.nn as nn +from transformers import AutoConfig, PreTrainedModel + +class HfFineTunedClassificationModel(nn.Module): + """Generic transformer-based binary classification model. + + Args: + model_name (str): Name or path of the pretrained Hugging Face model. + use_mean_pooling (bool): If True, average token embeddings using the attention mask. + Otherwise, use pooler output or CLS token embedding. + dropout (float): Dropout rate applied before the final linear layer. + Set to 0.0 to disable dropout. Must be ≥ 0. + + pragma: skip_doc + """ + + MODEL_CLASS_PREFIXES: List[Tuple[str, str]] = [ + ("bert-base-uncased", "BertModel"), + ("roberta-base", "RobertaModel"), + ("distilbert-base-uncased", "DistilBertModel"), + ("albert-base-v2", "AlbertModel"), + ("google/electra-base-discriminator", "ElectraModel"), + ] + + def __init__(self, + model_name: str, + use_mean_pooling: bool = False, + dropout: float = 0.1): + super().__init__() + if dropout < 0.0: + raise ValueError(f"Dropout must be non-negative, got {dropout}") + + self.config = AutoConfig.from_pretrained(model_name) + model_class = self._resolve_model_class(model_name) + self.llm_model: PreTrainedModel = model_class.from_pretrained(model_name, config=self.config) + + self.hidden_size = self.config.hidden_size + self.use_mean_pooling = use_mean_pooling + self.linear = nn.Linear(self.hidden_size, 1) + + self.use_dropout = dropout > 0.0 + if self.use_dropout: + self.dropout = nn.Dropout(dropout) + + # Initialize linear weight + nn.init.xavier_uniform_(self.linear.weight) + if self.linear.bias is not None: + nn.init.zeros_(self.linear.bias) + + def _resolve_model_class(self, model_name: str) -> Type[PreTrainedModel]: + for prefix, class_name in self.MODEL_CLASS_PREFIXES: + if model_name.startswith(prefix): + module = __import__("transformers", fromlist=[class_name]) + return getattr(module, class_name) + raise ValueError(f"Model '{model_name}' is not supported.") + + def forward(self, inputs:Tuple[torch.Tensor]) -> torch.Tensor: + """ + Runs a forward pass through the transformer model followed by optional dropout and a classification head. + + Args: + inputs (Tuple[torch.Tensor]): Tuple of below tensors: + input_ids (torch.Tensor): Token IDs of shape (batch_size, seq_len). + attention_mask (torch.Tensor): Attention mask of shape (batch_size, seq_len). + + Returns: + torch.Tensor: Raw classification logits of shape (batch_size, 1). + """ + input_ids, attention_mask = inputs + outputs = self.llm_model(input_ids=input_ids, attention_mask=attention_mask) + + if self.use_mean_pooling: + last_hidden = outputs.last_hidden_state + # Expand the mask across the hidden dimension + # e.g. if hidden size is 768, the (seq_len,) mask becomes (seq_len, 768) per sample. + input_mask_expanded = attention_mask.unsqueeze(-1).expand(last_hidden.size()) + sum_embeddings = torch.sum(last_hidden * input_mask_expanded, dim=1) + mask_adjusted_count = torch.clamp(input_mask_expanded.sum(1), min=1e-9) + x = sum_embeddings / mask_adjusted_count + elif hasattr(outputs, "pooler_output") and outputs.pooler_output is not None: + x = outputs.pooler_output + else: # Grab the first feature in the sequence + x = outputs.last_hidden_state[:, 0, :] + + assert x.dim() == 2 + + if self.use_dropout: + x = self.dropout(x) + x = self.linear(x) + return x diff --git a/modules/pytorch_wrapper/ptn_lstm.py b/modules/pytorch_wrapper/ptn_lstm.py index 589b1ac..b99596a 100644 --- a/modules/pytorch_wrapper/ptn_lstm.py +++ b/modules/pytorch_wrapper/ptn_lstm.py @@ -36,7 +36,7 @@ class PtnLSTM: "num_layers": ("INT", {"default": 1, "min": 1, "max": 1e3}), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), "proj_size": ("INT", {"default": 0, "min": 0, "max": 1e6}), } diff --git a/modules/pytorch_wrapper/ptn_lstm_linear.py b/modules/pytorch_wrapper/ptn_lstm_linear.py index fa109bd..4b62f63 100644 --- a/modules/pytorch_wrapper/ptn_lstm_linear.py +++ b/modules/pytorch_wrapper/ptn_lstm_linear.py @@ -108,7 +108,7 @@ class PtnLSTMLinear: "num_layers": ("INT", {"default": 1, "min": 1, "max": 1e3}), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), "proj_size": ("INT", {"default": 0, "min": 0, "max": 1e6}), "linear_output_size": ("INT", {"default": 1, "min": 1, "max": 1e6}), diff --git a/modules/pytorch_wrapper/ptn_rnn.py b/modules/pytorch_wrapper/ptn_rnn.py index 332e47e..2306a22 100644 --- a/modules/pytorch_wrapper/ptn_rnn.py +++ b/modules/pytorch_wrapper/ptn_rnn.py @@ -37,7 +37,7 @@ class PtnRNN: "nonlinearity": (("tanh", "relu"),), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), } } diff --git a/modules/pytorch_wrapper/ptn_rnn_linear.py b/modules/pytorch_wrapper/ptn_rnn_linear.py index a1fb977..76e0f3a 100644 --- a/modules/pytorch_wrapper/ptn_rnn_linear.py +++ b/modules/pytorch_wrapper/ptn_rnn_linear.py @@ -123,7 +123,7 @@ class PtnRNNLinear: "nonlinearity": (("tanh", "relu"),), "bias": ("BOOLEAN", {"default": True}), "batch_first": ("BOOLEAN", {"default": True}), - "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1}), + "dropout": ("FLOAT", {"default": 0, "min": 0, "max": 1, "step": 0.001}), "bidirectional": ("BOOLEAN", {"default": False}), "linear_output_size": ("INT", {"default": 1, "min": 1, "max": 1e6}), "linear_bias": ("BOOLEAN", {"default": True}), diff --git a/modules/pytorch_wrapper/ptv_hf_dataset_with_token_encode.py b/modules/pytorch_wrapper/ptv_hf_dataset_with_token_encode.py index d75b9f1..046241e 100644 --- a/modules/pytorch_wrapper/ptv_hf_dataset_with_token_encode.py +++ b/modules/pytorch_wrapper/ptv_hf_dataset_with_token_encode.py @@ -1,6 +1,12 @@ +import os +import sys from typing import Any, Dict, Tuple, Callable import torch +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode class PtvHfDatasetWithTokenEncode: """ @@ -13,6 +19,7 @@ class PtvHfDatasetWithTokenEncode: label_field_name (str): Field name for labels. encode (PTCALLABLE): The reference to a token encoder function. remove_html_tags (bool): Remove html tags in text if True. + encode_return_dict (bool): Encode function returns a Dict instead of a Tuple. category: PyTorch wrapper - Training """ @@ -33,6 +40,7 @@ class PtvHfDatasetWithTokenEncode: "label_field_name": ("STRING", {"default": "label","multiline": False}), "encode": ("PTCALLABLE", {}), "remove_html_tags": ("BOOLEAN", {"default": False}), + "encode_return_dict": ("BOOLEAN", {"default": False}), } } @@ -50,7 +58,8 @@ class PtvHfDatasetWithTokenEncode: sample_field_name: str, label_field_name: str, encode: Callable, - remove_html_tags:bool) -> Tuple: + remove_html_tags:bool, + encode_return_dict:bool) -> Tuple: """ Loads a dataset from Hugging Face with specified parameters. @@ -61,14 +70,11 @@ class PtvHfDatasetWithTokenEncode: label_field_name (str): Field name for labels. encode (Callable): The reference to a token encoder function. remove_html_tags (bool): Remove html tags in text if True. + encode_return_dict (bool): Encode function returns a Dict instead of a Tuple. Returns: Tuple: A tuple containing the dataset instance. """ - # Keep import within this method so that relevant packages are imported - # only when they are actually needed. - from .hf_dataset_with_token_encode import HfDatasetWithTokenEncode - with torch.inference_mode(False): dc = HfDatasetWithTokenEncode( dataset_name=name, @@ -76,5 +82,6 @@ class PtvHfDatasetWithTokenEncode: sample_field_name=sample_field_name, label_field_name=label_field_name, encode=encode, - remove_html_tags=remove_html_tags) + remove_html_tags=remove_html_tags, + encode_return_dict=encode_return_dict) return (dc,) diff --git a/modules/pytorch_wrapper/ptv_hf_glove_dataset.py b/modules/pytorch_wrapper/ptv_hf_glove_dataset.py index 6cd5660..f720e4d 100644 --- a/modules/pytorch_wrapper/ptv_hf_glove_dataset.py +++ b/modules/pytorch_wrapper/ptv_hf_glove_dataset.py @@ -1,6 +1,12 @@ +import os +import sys from typing import Any, Dict, Tuple import torch +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) +from hugging_face_wrapper.hf_glove_dataset import HfGloveDataset class PtvHfGloveDataset: """ @@ -65,9 +71,6 @@ class PtvHfGloveDataset: Returns: Tuple: A tuple containing the dataset instance. """ - # Keep import within this method so that relevant packages are imported - # only when they are actually needed. - from .hf_glove_dataset import HfGloveDataset with torch.inference_mode(False): dc = HfGloveDataset( diff --git a/modules/pytorch_wrapper/utils.py b/modules/pytorch_wrapper/utils.py index 333823a..4814e9b 100644 --- a/modules/pytorch_wrapper/utils.py +++ b/modules/pytorch_wrapper/utils.py @@ -4,7 +4,7 @@ from typing import Optional, Tuple, Union, List import random import numpy as np import torch - +import torch.nn as nn DTYPE_MAPPING = { "float32": torch.float32, @@ -237,3 +237,16 @@ def pad_truncate_sequence( return torch.stack(token_list), torch.stack(mask_list) else: return token_list, mask_list + + +def set_requires_grad(module: nn.Module, requires_grad: bool) -> None: + """ + Enables or disables gradient computation for all parameters in a given module. + + Args: + module (nn.Module): The PyTorch module whose parameters should be modified. + requires_grad (bool): If False, freezes the module (no gradients computed). + If True, unfreezes the module (gradients computed). + """ + for param in module.parameters(): + param.requires_grad = requires_grad diff --git a/pyproject.toml b/pyproject.toml index 7fc217a..a447533 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "pt-wrapper" description = "PyTorch extension for ComfyUI featuring extensive PyTorch wrapper nodes for seamless tensor operations and PyTorch model training." -version = "3.4.0" +version = "3.5.0" license = {file = "LICENSE"} [project.urls] diff --git a/requirements.txt b/requirements.txt index c05d0da..a7203c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,5 +4,6 @@ seaborn>=0.13.2 scipy>=1.14.1 scikit-learn>=1.6.1 datasets>=3.4.1 +transformers>=4.47.1 gensim==4.3.2 sentencepiece>=0.2.0 diff --git a/tests/hugging_face_wrapper/hf_dataset_with_tokenize_test.py b/tests/hugging_face_wrapper/hf_dataset_with_tokenize_test.py new file mode 100644 index 0000000..0cfeab8 --- /dev/null +++ b/tests/hugging_face_wrapper/hf_dataset_with_tokenize_test.py @@ -0,0 +1,89 @@ +import os +import sys +import unittest +import torch + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from sentencepiece_wrapper.sp_load_model import SpLoadModel +from sentencepiece_wrapper.sp_encode import SpEncode + + +class TestHfDatasetWithTokenEncode(unittest.TestCase): + """ + Tests Hugging Face Dataset wrapper with custom token_encode function. + """ + + def setUp(self): + """Set up test instance.""" + self.load_node = SpLoadModel() + self.sp = self.load_node.f("spiece.model")[0] + self.encode_node = SpEncode() + self.max_length=15 + encode = self.encode_node.f( + spmodel=self.sp, + padding=False, + padding_method="longest", + padding_value=0, + truncation=True, + max_length=self.max_length + )[0] + + self.ds = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "train", #split + encode=encode, + ) + + self.ds_remove_html = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "train", #split + encode=encode, + remove_html_tags=True + ) + + def test_loading(self): + it = iter(self.ds) + (sample, mask), label = next(it) + + # Compare text + actual = sample.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare mask + actual = mask.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare label + actual = label + expected = torch.tensor(0, dtype=torch.int64) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + + def test_loading_remove_html(self): + it = iter(self.ds_remove_html) + (sample, mask), label = next(it) + + # Compare text + actual = sample.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare mask + actual = mask.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare label + actual = label + expected = torch.tensor(0, dtype=torch.int64) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/hugging_face_wrapper/hf_dataset_with_tokenize_with_hf_tokenize_encode_test.py b/tests/hugging_face_wrapper/hf_dataset_with_tokenize_with_hf_tokenize_encode_test.py new file mode 100644 index 0000000..264d3c5 --- /dev/null +++ b/tests/hugging_face_wrapper/hf_dataset_with_tokenize_with_hf_tokenize_encode_test.py @@ -0,0 +1,86 @@ +import os +import sys +import unittest +import torch + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode + + +class TestHfDatasetWithTokenEncode(unittest.TestCase): + """ + Tests Hugging Face Dataset wrapper with custom token_encode function. + """ + + def setUp(self): + """Set up test instance.""" + self.max_length=15 + encode = HfTokenizerEncode().f( + model_name="distilbert-base-uncased", + padding=True, + padding_method="longest", + truncation=True, + max_length=self.max_length + )[0] + + self.ds = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "train", #split + encode=encode, + encode_return_dict=True + ) + + self.ds_remove_html = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "train", #split + encode=encode, + remove_html_tags=True, + encode_return_dict=True + ) + + def test_loading(self): + it = iter(self.ds) + (sample, mask), label = next(it) + + # Compare text + actual = sample.size() + expected = torch.Size((self.max_length,)) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare mask + actual = mask.size() + expected = torch.Size((self.max_length,)) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare label + actual = label + expected = torch.tensor(0, dtype=torch.int64) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + + def test_loading_remove_html(self): + it = iter(self.ds_remove_html) + (sample, mask), label = next(it) + + # Compare text + actual = sample.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare mask + actual = mask.size() + expected = torch.Size((self.max_length, )) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare label + actual = label + expected = torch.tensor(0, dtype=torch.int64) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/hugging_face_wrapper/hf_glove_dataset_test.py b/tests/hugging_face_wrapper/hf_glove_dataset_test.py new file mode 100644 index 0000000..fdee69d --- /dev/null +++ b/tests/hugging_face_wrapper/hf_glove_dataset_test.py @@ -0,0 +1,64 @@ +import os +import sys +import unittest +import torch + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from pytorch_wrapper.hf_glove_dataset import HfGloveDataset + + +class TestHfGloveDataset(unittest.TestCase): + """ + Tests Hugging Face Dataset wrapper with word embedding support. + """ + + def setUp(self): + """Set up test instance.""" + self.embedding_dim = 100 + self.max_seq_len = 256 + self.ds = HfGloveDataset( + "imdb", # dataset_name + "train", #split + self.embedding_dim, + self.max_seq_len + ) + + def test_vocabulary_size(self): + self.assertEqual(400000, len(self.ds.glove)) + + def test_tokenize(self): + """Test tokenization""" + s = "Maddie is a cute puppy." + actual = self.ds.tokenize(s) + expected = ['maddie', 'is', 'a', 'cute', 'puppy'] + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + def test_vectorize(self): + """Test embedding generation""" + s = "Maddie is a cute puppy." + tokens = self.ds.tokenize(s) + embeddings = self.ds.vectorize(tokens) + actual = embeddings.size() + expected = torch.Size((self.max_seq_len, self.embedding_dim)) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + def test_loading(self): + it = iter(self.ds) + sample = next(it) + + # Compare text + actual = sample[0].size() + expected = torch.Size((self.max_seq_len, self.embedding_dim)) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + # Compare label + actual = sample[1] + expected = torch.tensor(0, dtype=torch.int64) + self.assertEqual(expected, actual, f"expected {expected} and actual {actual} do not match.") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/hugging_face_wrapper/hf_tokenizer_encode_test.py b/tests/hugging_face_wrapper/hf_tokenizer_encode_test.py new file mode 100644 index 0000000..1363eb4 --- /dev/null +++ b/tests/hugging_face_wrapper/hf_tokenizer_encode_test.py @@ -0,0 +1,97 @@ +import os +import sys +import unittest +import torch +from itertools import product + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode + + +class TestHfTokenizerEncode(unittest.TestCase): + def setUp(self): + self.node = HfTokenizerEncode() + self.test_sentence_1d = "Hello, world" + self.test_sentence_2d = [ + "a b c d e f g h i j k l m n o p q r s t u v w x y z", + "a b c d e f g h i j k l"] + self.models = { + "bert-base-uncased": "BertTokenizer", + "roberta-base": "RobertaTokenizer", + "distilbert-base-uncased": "DistilBertTokenizer", + "albert-base-v2": "AlbertTokenizer", + "google/electra-small-discriminator": "ElectraTokenizer", + } + + def test_tokenizer_variants(self): + for model_name, tokenizer_name in self.models.items(): + for is_1d, padding, truncation, pad_method in product( + [True, False], [True, False], [True, False], ["longest", "max_length"] + ): + + if not is_1d and not padding: + continue # Cannot batch ragged output into tensors + + with self.subTest( + tokenizer_name=tokenizer_name, + is_1d=is_1d, + padding=padding, + truncation=truncation, + pad_method=pad_method + ): + sentence = self.test_sentence_1d if is_1d else self.test_sentence_2d + + if truncation: + max_length = 10 + else: + max_length = 256 + + encoder = self.node.f( + model_name=model_name, + padding=padding, + padding_method=pad_method, + truncation=truncation, + max_length=max_length + )[0] + output = encoder(sentence=sentence) + + input_ids = output["input_ids"] + mask = output["attention_mask"] + + # shape agreement + self.assertEqual(input_ids.shape, mask.shape) + + # correct batch size + self.assertEqual(input_ids.shape[0], 1 if is_1d else len(sentence)) + + # correct max length behavior + if not is_1d: + if truncation: + self.assertEqual(input_ids.shape[1], 10) + elif padding and pad_method == "longest": + self.assertEqual(input_ids[0].size(0), input_ids[1].size(0)) + elif padding and pad_method == "max_length": + self.assertGreaterEqual(input_ids.shape[1], 256) + + + def test_padding_false_1d(self): + for model_name in self.models: + with self.subTest(model=model_name): + encoder = self.node.f( + model_name=model_name, + padding=False, + padding_method="longest", + truncation=False, + max_length=256 + )[0] + output = encoder(sentence=self.test_sentence_1d) + input_ids = output["input_ids"] + self.assertEqual(input_ids.shape[0], 1) + self.assertGreater(torch.count_nonzero(input_ids), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pytorch_wrapper/pt_train_embedding_rnn_linear_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_embedding_rnn_linear_text_classification_model_test.py index 184dba8..e9c2441 100644 --- a/tests/pytorch_wrapper/pt_train_embedding_rnn_linear_text_classification_model_test.py +++ b/tests/pytorch_wrapper/pt_train_embedding_rnn_linear_text_classification_model_test.py @@ -14,7 +14,7 @@ MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") sys.path.append(MODULE_ROOT) from pytorch_wrapper.ptn_embedding_rnn_linear import PtnEmbeddingRNNLinear -from pytorch_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode from sentencepiece_wrapper.sp_load_model import SpLoadModel from sentencepiece_wrapper.sp_encode import SpEncode from pytorch_wrapper.pto_adam import PtoAdam diff --git a/tests/pytorch_wrapper/pt_train_embedding_transformer_linear_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_embedding_transformer_linear_text_classification_model_test.py index 610f0bc..c0aa8a1 100644 --- a/tests/pytorch_wrapper/pt_train_embedding_transformer_linear_text_classification_model_test.py +++ b/tests/pytorch_wrapper/pt_train_embedding_transformer_linear_text_classification_model_test.py @@ -14,7 +14,7 @@ MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") sys.path.append(MODULE_ROOT) from pytorch_wrapper.ptn_embedding_transformer_linear import PtnEmbeddingTransformerLinear -from pytorch_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode from sentencepiece_wrapper.sp_load_model import SpLoadModel from sentencepiece_wrapper.sp_encode import SpEncode from pytorch_wrapper.pto_adamw import PtoAdamW @@ -105,7 +105,7 @@ class TestPtTrainEmbeddingTransformerLinearTextClassificationModel(unittest.Test )[0] self.minimum_lr = 1e-9 - self.epochs = 10 + self.epochs = 5 self.scheduler = PtoLrSchedulerCosineAnnealing().f(self.optimizer, self.epochs, self.minimum_lr)[0] diff --git a/tests/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model_text_test.py b/tests/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model_text_test.py new file mode 100644 index 0000000..d400f24 --- /dev/null +++ b/tests/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model_text_test.py @@ -0,0 +1,139 @@ +""" +Dataset URL:https://huggingface.co/datasets/stanfordnlp/imdb + +This unit test covers a test case where pretrained module is not frozen. +For a case where pretrained module is frozen, see: +tests/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model_text_test.py + +For DistilBERT, this script should produce validation accuracy around 0.9242 for the first epoch and around 0.9216 for the secod epoch. +""" +import os +import sys +import unittest +import torch +import torch.nn as nn +import random +import numpy as np + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from pytorch_wrapper.ptn_hf_fine_tuned_classification_model import PtnHfFineTunedClassificationModel +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode +from pytorch_wrapper.pto_adamw import PtoAdamW +from pytorch_wrapper.pt_data_loader import PtDataLoader +from pytorch_wrapper.pt_train_classification_transformer_model import PtTrainClassificationTransformerModel +from pytorch_wrapper.pt_save_model import PtSaveModel +from pytorch_wrapper.pto_lr_scheduler_cosine_annealing import PtoLrSchedulerCosineAnnealing +from pytorch_wrapper.ptn_bce_with_logits_loss import PtnBCEWithLogitsLoss +from pytorch_wrapper.utils import set_seed + + +class TestPtnHfFineTunedTextClassificationModel(unittest.TestCase): + + @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") + def setUp(self): + set_seed(42) + + self.loss_fun = PtnBCEWithLogitsLoss().f(reduction="mean")[0] + self.batch_size = 32 + self.epochs = 2 + self.minimum_lr = 1e-9 + self.models = { + "bert-base-uncased": "BertTokenizer", + "distilbert-base-uncased": "DistilBertTokenizer", + "albert-base-v2": "AlbertTokenizer", + "roberta-base": "RobertaTokenizer", + # "google/electra-small-discriminator": "ElectraTokenizer", + } + self.model_path = "hf_fine_tuned_text_classification_model_test.pt" + self.linear_head = True + + @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") + def test_all_models(self): + for model_name in self.models: + print(f"\n=== Testing model: {model_name} ===") + + encode = HfTokenizerEncode().f( + model_name=model_name, + padding=True, + padding_method="max_length", + truncation=True, + max_length=0 # Use model's max length + )[0] + + train_dataset = HfDatasetWithTokenEncode( + "imdb", "train", encode=encode, + remove_html_tags=True, + encode_return_dict=True + ) + + test_dataset = HfDatasetWithTokenEncode( + "imdb", "test", encode=encode, + remove_html_tags=True, + encode_return_dict=True + ) + + train_loader = PtDataLoader().f( + dataset=train_dataset, + batch_size=self.batch_size, + shuffle=True, + parameters='{"num_workers":1}' + )[0] + + test_loader = PtDataLoader().f( + dataset=test_dataset, + batch_size=self.batch_size, + shuffle=False, + parameters='{"num_workers":1}' + )[0] + + model = PtnHfFineTunedClassificationModel().f( + model_name, + use_mean_pooling=True, + dropout=0.1 + )[0] + + optimizer = PtoAdamW().f( + model, 1e-5, 0.9, 0.999, + 0.01, # weight decay + False # amsgrad + )[0] + + scheduler = PtoLrSchedulerCosineAnnealing().f( + optimizer, + self.epochs, + self.minimum_lr + )[0] + + trainer = PtTrainClassificationTransformerModel() + + trained_model = trainer.f( + model, + train_loader, + optimizer, + self.loss_fun, + self.epochs, + use_gpu=True, + early_stopping=False, + early_stopping_rounds=1, + scheduler=scheduler, + output_best_val_model=False, + classification_metrics=True, + val_loader=test_loader + )[0] + + PtSaveModel().f(trained_model, self.model_path) + + # Clean up to free memory and VRAM + del model, trained_model, optimizer, scheduler, trainer + del train_loader, test_loader, train_dataset, test_dataset, encode + torch.cuda.empty_cache() + import gc + gc.collect() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pytorch_wrapper/pt_train_gru_linear_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_gru_linear_text_classification_model_test.py index dfc3402..82292c7 100644 --- a/tests/pytorch_wrapper/pt_train_gru_linear_text_classification_model_test.py +++ b/tests/pytorch_wrapper/pt_train_gru_linear_text_classification_model_test.py @@ -84,13 +84,13 @@ class TestPtTrainGRULinearTextClassificationModel(unittest.TestCase): )[0] self.optimizer = PtoAdamW().f(self.model, - 0.001, + 0.0003, 0.9, 0.999, weight_decay=0.01, amsgrad=False)[0] self.scheduler = PtoLrSchedulerReduceOnPlateau().f(self.optimizer, - grace_period=10, + grace_period=5, gamma=0.5 )[0] @@ -98,7 +98,7 @@ class TestPtTrainGRULinearTextClassificationModel(unittest.TestCase): self.save_model = PtSaveModel() self.load_model = PtLoadModel() self.linear_head = True - self.epochs = 50 + self.epochs = 20 @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") def test_1(self): diff --git a/tests/pytorch_wrapper/pt_train_hf_fine_tuned_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_hf_fine_tuned_text_classification_model_test.py new file mode 100644 index 0000000..e0b9f3c --- /dev/null +++ b/tests/pytorch_wrapper/pt_train_hf_fine_tuned_text_classification_model_test.py @@ -0,0 +1,131 @@ +""" +Dataset URL:https://huggingface.co/datasets/stanfordnlp/imdb + +This unit test covers a rare test case where pretrained module is not frozen. +For a case where pretrained module is frozen, see: +tests/pytorch_wrapper/pt_train_fine_tune_classification_transformer_model_text_test.py + +This script should produce validation accuracy around 0.9242 for the first epoch and around 0.9216 for the secod epoch. +""" +import os +import sys +import unittest +import torch +import torch.nn as nn +import random +import numpy as np + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from pytorch_wrapper.ptn_hf_fine_tuned_classification_model import PtnHfFineTunedClassificationModel +from hugging_face_wrapper.hf_dataset_with_token_encode import HfDatasetWithTokenEncode +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode +from pytorch_wrapper.pto_adamw import PtoAdamW +from pytorch_wrapper.pt_data_loader import PtDataLoader +from pytorch_wrapper.pt_train_classification_transformer_model import PtTrainClassificationTransformerModel +from pytorch_wrapper.pt_save_model import PtSaveModel +from pytorch_wrapper.pt_load_model import PtLoadModel +from pytorch_wrapper.pto_lr_scheduler_cosine_annealing import PtoLrSchedulerCosineAnnealing +from pytorch_wrapper.ptn_bce_with_logits_loss import PtnBCEWithLogitsLoss +from pytorch_wrapper.utils import set_seed + + +class TestPtnHfFineTunedTextClassificationModel(unittest.TestCase): + + @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") + def setUp(self): + set_seed(42) + + self.loss_fun =PtnBCEWithLogitsLoss().f(reduction="mean")[0] + + self.max_length=512 + self.model_name = "distilbert-base-uncased" + encode = HfTokenizerEncode().f( + model_name=self.model_name, + padding=True, + padding_method="max_length", + truncation=True, + max_length=0 # Use model's max length + )[0] + + train_dataset = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "train", #split + encode=encode, + remove_html_tags=True, + encode_return_dict=True + ) + + test_dataset = HfDatasetWithTokenEncode( + "imdb", # dataset_name + "test", #split + encode=encode, + remove_html_tags=True, + encode_return_dict=True + ) + + train_data_loader_node = PtDataLoader() + test_data_loader_node = PtDataLoader() + + self.train_loader = train_data_loader_node.f( + dataset=train_dataset, + batch_size=32, + shuffle=True, + parameters='{"num_workers":1}' + )[0] + + self.test_loader = test_data_loader_node.f( + dataset=test_dataset, + batch_size=32, + shuffle=False, + parameters='{"num_workers":1}' + )[0] + + self.model_path = "hf_fine_tuned_text_classification_model_test.pt" + + self.model = PtnHfFineTunedClassificationModel().f( + self.model_name, + use_mean_pooling=True, + dropout=0.1 + )[0] + + self.optimizer = PtoAdamW().f(self.model, 1e-5, 0.9, 0.999, + 0.01, # weight decay + False # amsgrad + )[0] + + self.minimum_lr = 1e-9 + self.epochs = 2 + self.scheduler = PtoLrSchedulerCosineAnnealing().f(self.optimizer, + self.epochs, + self.minimum_lr)[0] + + self.trainer = PtTrainClassificationTransformerModel() + self.save_model = PtSaveModel() + self.load_model = PtLoadModel() + self.linear_head = True + + + @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") + def test_1(self): + + trained_model = self.trainer.f( + self.model, + self.train_loader, + self.optimizer, + self.loss_fun, + self.epochs, # epochs + use_gpu=True, + early_stopping=False, + early_stopping_rounds=1, + scheduler=self.scheduler, + output_best_val_model=False, + classification_metrics=True, + val_loader=self.test_loader)[0] + self.save_model.f(trained_model, self.model_path) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pytorch_wrapper/pt_train_lstm_linear_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_lstm_linear_text_classification_model_test.py index ccefc89..fcac5e1 100644 --- a/tests/pytorch_wrapper/pt_train_lstm_linear_text_classification_model_test.py +++ b/tests/pytorch_wrapper/pt_train_lstm_linear_text_classification_model_test.py @@ -85,13 +85,13 @@ class TestPtTrainLSTMLinearTextClassificationModel(unittest.TestCase): )[0] self.optimizer = PtoAdamW().f(self.model, - 0.001, + 0.0003, 0.9, 0.999, weight_decay=0.01, amsgrad=False)[0] self.scheduler = PtoLrSchedulerReduceOnPlateau().f(self.optimizer, - grace_period=10, + grace_period=5, gamma=0.5 )[0] @@ -99,7 +99,7 @@ class TestPtTrainLSTMLinearTextClassificationModel(unittest.TestCase): self.save_model = PtSaveModel() self.load_model = PtLoadModel() self.linear_head = True - self.epochs = 50 + self.epochs = 15 @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") def test_1(self): diff --git a/tests/pytorch_wrapper/pt_train_rnn_linear_text_classification_model_test.py b/tests/pytorch_wrapper/pt_train_rnn_linear_text_classification_model_test.py index 61e2c27..85477b3 100644 --- a/tests/pytorch_wrapper/pt_train_rnn_linear_text_classification_model_test.py +++ b/tests/pytorch_wrapper/pt_train_rnn_linear_text_classification_model_test.py @@ -95,7 +95,7 @@ class TestPtTrainRNNLinearTextClassificationModel(unittest.TestCase): self.save_model = PtSaveModel() self.load_model = PtLoadModel() self.linear_head = True - self.epochs = 50 + self.epochs = 10 @unittest.skipIf(os.getenv("RUN_SKIPPED_TESTS") != "1", "Skipping unless explicitly enabled") def test_1(self): diff --git a/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def_test.py b/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def_test.py new file mode 100644 index 0000000..2316c9c --- /dev/null +++ b/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_def_test.py @@ -0,0 +1,52 @@ +import os +import sys +import unittest +import torch + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) +from pytorch_wrapper.ptn_hf_fine_tuned_classification_model_def import HfFineTunedClassificationModel +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode + + +class TestHfFineTunedClassificationModel(unittest.TestCase): + def setUp(self): + """Setup shared test conditions.""" + self.text = [ + "I really liked the scenary.", + "I did not like the vision of the creator." + ] + self.model_names = [ + "distilbert-base-uncased", + "bert-base-uncased", + "roberta-base", + "albert-base-v2", + "google/electra-base-discriminator" + ] + + def test_all_models(self): + """Run output shape test across all supported models.""" + for model_name in self.model_names: + with self.subTest(model_name=model_name): + encode = HfTokenizerEncode().f( + model_name=model_name, + padding=True, + padding_method="max_length", + truncation=True, + max_length=0 # Use model's max length + )[0] + + model = HfFineTunedClassificationModel( + model_name, + use_mean_pooling=True, + dropout=0.1 + ) + + token_dict = encode(self.text) + out = model((token_dict["input_ids"], token_dict["attention_mask"])) + self.assertEqual(out.size(), torch.Size([2, 1])) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_test.py b/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_test.py new file mode 100644 index 0000000..fbcf146 --- /dev/null +++ b/tests/pytorch_wrapper/ptn_hf_fine_tuned_classification_model_test.py @@ -0,0 +1,52 @@ +import os +import sys +import unittest +import torch + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) +from pytorch_wrapper.ptn_hf_fine_tuned_classification_model import PtnHfFineTunedClassificationModel +from hugging_face_wrapper.hf_tokenizer_encode import HfTokenizerEncode + + +class TestPtfHfFineTunedClassificationModel(unittest.TestCase): + def setUp(self): + """Setup shared test conditions.""" + self.text = [ + "I really liked the scenary.", + "I did not like the vision of the creator." + ] + self.model_names = [ + "distilbert-base-uncased", + "bert-base-uncased", + "roberta-base", + "albert-base-v2", + "google/electra-base-discriminator" + ] + + def test_all_models(self): + """Run output shape test across all supported models.""" + for model_name in self.model_names: + with self.subTest(model_name=model_name): + encode = HfTokenizerEncode().f( + model_name=model_name, + padding=True, + padding_method="max_length", + truncation=True, + max_length=0 # Use model's max length + )[0] + + model = PtnHfFineTunedClassificationModel().f( + model_name, + use_mean_pooling=True, + dropout=0.1 + )[0] + + token_dict = encode(self.text) + out = model((token_dict["input_ids"], token_dict["attention_mask"])) + self.assertEqual(out.size(), torch.Size([2, 1])) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pytorch_wrapper/ptv_hf_dataset_with_token_encode_test.py b/tests/pytorch_wrapper/ptv_hf_dataset_with_token_encode_test.py index a01d43e..d8b2158 100644 --- a/tests/pytorch_wrapper/ptv_hf_dataset_with_token_encode_test.py +++ b/tests/pytorch_wrapper/ptv_hf_dataset_with_token_encode_test.py @@ -37,7 +37,8 @@ class TestPtvHfDatasetWithTokenEncode(unittest.TestCase): "text", "label", encode, - False # remove_html_tags + False, # remove_html_tags + False # encode_return_dict )[0] diff --git a/tests/pytorch_wrapper/utils_set_requires_grad_test.py b/tests/pytorch_wrapper/utils_set_requires_grad_test.py new file mode 100644 index 0000000..5f258e4 --- /dev/null +++ b/tests/pytorch_wrapper/utils_set_requires_grad_test.py @@ -0,0 +1,36 @@ +import os +import sys +import unittest +import torch.nn as nn + + +PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules") +sys.path.append(MODULE_ROOT) + +from pytorch_wrapper.utils import set_requires_grad + + +class TestSetRequiresGrad(unittest.TestCase): + def setUp(self): + self.model = nn.Linear(2, 3, bias=True) + + def test_1(self): + # Check that gradients are initially enabled + for param in self.model.parameters(): + self.assertTrue(param.requires_grad) + + # Turn off gradients + set_requires_grad(self.model, False) + for param in self.model.parameters(): + self.assertFalse(param.requires_grad) + + # Turn on gradients + set_requires_grad(self.model, True) + for param in self.model.parameters(): + self.assertTrue(param.requires_grad) + + +if __name__ == "__main__": + unittest.main() +