Added loss functions.

This commit is contained in:
HowToSD
2025-03-20 21:40:01 -07:00
parent 05196abbad
commit a6cefb1cf7
76 changed files with 1916 additions and 43 deletions
+30
View File
@@ -17,6 +17,7 @@ from .modules.pytorch_wrapper.pt_bitwise_right_shift import PtBitwiseRightShift
from .modules.pytorch_wrapper.pt_bitwise_xor import PtBitwiseXor
from .modules.pytorch_wrapper.pt_bmm import PtBmm
from .modules.pytorch_wrapper.pt_bool_create import PtBoolCreate
from .modules.pytorch_wrapper.pt_compute_loss import PtComputeLoss
from .modules.pytorch_wrapper.pt_concat import PtConcat
from .modules.pytorch_wrapper.pt_cos import PtCos
from .modules.pytorch_wrapper.pt_cosh import PtCosh
@@ -147,17 +148,26 @@ from .modules.pytorch_wrapper.ptf_softplus import PtfSoftplus
from .modules.pytorch_wrapper.ptf_tanh import PtfTanh
from .modules.pytorch_wrapper.ptn_avg_pool2d import PtnAvgPool2d
from .modules.pytorch_wrapper.ptn_batch_norm2d import PtnBatchNorm2d
from .modules.pytorch_wrapper.ptn_bce_loss import PtnBCELoss
from .modules.pytorch_wrapper.ptn_bce_with_logits_loss import PtnBCEWithLogitsLoss
from .modules.pytorch_wrapper.ptn_chained_model import PtnChainedModel
from .modules.pytorch_wrapper.ptn_conv2d import PtnConv2d
from .modules.pytorch_wrapper.ptn_conv_model import PtnConvModel
from .modules.pytorch_wrapper.ptn_cross_entropy_loss import PtnCrossEntropyLoss
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
from .modules.pytorch_wrapper.ptn_l1_loss import PtnL1Loss
from .modules.pytorch_wrapper.ptn_layer_norm import PtnLayerNorm
from .modules.pytorch_wrapper.ptn_linear import PtnLinear
from .modules.pytorch_wrapper.ptn_linear_model import PtnLinearModel
from .modules.pytorch_wrapper.ptn_max_pool2d import PtnMaxPool2d
from .modules.pytorch_wrapper.ptn_mse_loss import PtnMSELoss
from .modules.pytorch_wrapper.ptn_nll_loss import PtnNLLLoss
from .modules.pytorch_wrapper.ptn_pre_add_channel_axis import PtnPreAddChannelAxis
from .modules.pytorch_wrapper.ptn_pre_flatten import PtnPreFlatten
from .modules.pytorch_wrapper.ptn_resnet_model import PtnResnetModel
from .modules.pytorch_wrapper.ptn_smooth_l1_loss import PtnSmoothL1Loss
from .modules.pytorch_wrapper.pto_adam import PtoAdam
from .modules.pytorch_wrapper.pto_adamw import PtoAdamW
from .modules.pytorch_wrapper.pto_lr_scheduler_cosine_annealing import PtoLrSchedulerCosineAnnealing
@@ -198,6 +208,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PtBitwiseXor": PtBitwiseXor,
"PtBmm": PtBmm,
"PtBoolCreate": PtBoolCreate,
"PtComputeLoss": PtComputeLoss,
"PtConcat": PtConcat,
"PtCos": PtCos,
"PtCosh": PtCosh,
@@ -327,18 +338,27 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PtfSoftplus": PtfSoftplus,
"PtfTanh": PtfTanh,
"PtnAvgPool2d": PtnAvgPool2d,
"PtnBCELoss": PtnBCELoss,
"PtnBCEWithLogitsLoss": PtnBCEWithLogitsLoss,
"PtnBatchNorm2d": PtnBatchNorm2d,
"PtnChainedModel": PtnChainedModel,
"PtnConv2d": PtnConv2d,
"PtnConvModel": PtnConvModel,
"PtnCrossEntropyLoss": PtnCrossEntropyLoss,
"PtnHuberLoss": PtnHuberLoss,
"PtnInstanceNorm2d": PtnInstanceNorm2d,
"PtnKLDivLoss": PtnKLDivLoss,
"PtnL1Loss": PtnL1Loss,
"PtnLayerNorm": PtnLayerNorm,
"PtnLinear": PtnLinear,
"PtnLinearModel": PtnLinearModel,
"PtnMSELoss": PtnMSELoss,
"PtnMaxPool2d": PtnMaxPool2d,
"PtnNLLLoss": PtnNLLLoss,
"PtnPreAddChannelAxis": PtnPreAddChannelAxis,
"PtnPreFlatten": PtnPreFlatten,
"PtnResnetModel": PtnResnetModel,
"PtnSmoothL1Loss": PtnSmoothL1Loss,
"PtoAdam": PtoAdam,
"PtoAdamW": PtoAdamW,
"PtoLrSchedulerCosineAnnealing": PtoLrSchedulerCosineAnnealing,
@@ -379,6 +399,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PtBitwiseXor": "Pt Bitwise Xor",
"PtBmm": "Pt Bmm",
"PtBoolCreate": "Pt Bool Create",
"PtComputeLoss": "Pt Compute Loss",
"PtConcat": "Pt Concat",
"PtCos": "Pt Cos",
"PtCosh": "Pt Cosh",
@@ -508,18 +529,27 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PtfSoftplus": "Ptf Softplus",
"PtfTanh": "Ptf Tanh",
"PtnAvgPool2d": "Ptn Avg Pool 2d",
"PtnBCELoss": "Ptn BCE Loss",
"PtnBCEWithLogitsLoss": "Ptn BCE With Logits Loss",
"PtnBatchNorm2d": "Ptn Batch Norm 2d",
"PtnChainedModel": "Ptn Chained Model",
"PtnConv2d": "Ptn Conv 2d",
"PtnConvModel": "Ptn Conv Model",
"PtnCrossEntropyLoss": "Ptn Cross Entropy Loss",
"PtnHuberLoss": "Ptn Huber Loss",
"PtnInstanceNorm2d": "Ptn Instance Norm 2d",
"PtnKLDivLoss": "Ptn KL Div Loss",
"PtnL1Loss": "Ptn L1 Loss",
"PtnLayerNorm": "Ptn Layer Norm",
"PtnLinear": "Ptn Linear",
"PtnLinearModel": "Ptn Linear Model",
"PtnMSELoss": "Ptn MSE Loss",
"PtnMaxPool2d": "Ptn Max Pool 2d",
"PtnNLLLoss": "Ptn NLL Loss",
"PtnPreAddChannelAxis": "Ptn Pre Add Channel Axis",
"PtnPreFlatten": "Ptn Pre Flatten",
"PtnResnetModel": "Ptn Resnet Model",
"PtnSmoothL1Loss": "Ptn Smooth L1 Loss",
"PtoAdam": "Pto Adam",
"PtoAdamW": "Pto AdamW",
"PtoLrSchedulerCosineAnnealing": "Pto Lr Scheduler Cosine Annealing",
+4
View File
@@ -83,6 +83,10 @@ def format_display_name(class_name):
("Si L U", "SiLU"),
("G E L U", "GELU"),
("S G D", "SGD"),
("B C E", "BCE"),
("K L", "KL"),
("M S E", "MSE"),
("N L L", "NLL"),
("Data Frame", "DataFrame"),
("Multi Index", "MultiIndex"),
("MPL Bar", "MPL Bar Chart"),
+13
View File
@@ -111,6 +111,18 @@
| [Pt Logical Not](pt_logical_not.md) | Performs a logical NOT operation on a PyTorch tensor element-wise. |
| [Pt Logical Or](pt_logical_or.md) | Performs a logical OR operation on two PyTorch tensors element-wise. |
| [Pt Logical Xor](pt_logical_xor.md) | Performs a logical XOR operation on two PyTorch tensors element-wise. |
## PyTorch wrapper - Loss function
| Node | Description |
| --- | --- |
| [Ptn BCE Loss](ptn_bce_loss.md) | A class to compute the binary cross entropy loss. |
| [Ptn BCE With Logits Loss](ptn_bce_with_logits_loss.md) | A class to compute the sigmoid then binary cross entropy loss. |
| [Ptn Cross Entropy Loss](ptn_cross_entropy_loss.md) | A class to compute the cross entropy loss. |
| [Ptn Huber Loss](ptn_huber_loss.md) | |
| [Ptn KL Div Loss](ptn_kl_div_loss.md) | A class to compute the KL divergence loss. |
| [Ptn L1 Loss](ptn_l1_loss.md) | A class to compute the L1 loss. |
| [Ptn MSE Loss](ptn_mse_loss.md) | A class to compute the squared loss. |
| [Ptn NLL Loss](ptn_nll_loss.md) | A model to compute the negative log likelihood (NLL) loss. |
| [Ptn Smooth L1 Loss](ptn_smooth_l1_loss.md) | |
## PyTorch wrapper - Math operations
| Node | Description |
| --- | --- |
@@ -204,6 +216,7 @@
| Node | Description |
| --- | --- |
| [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. |
| [Pt Data Loader From Tensors](pt_data_loader_from_tensors.md) | Creates a Torchvision Dataloader from a pair of tensors. |
| [Pt Evaluate Classification Model](pt_evaluate_classification_model.md) | Performs inference on test data and computes evaluation metrics. |
+21
View File
@@ -0,0 +1,21 @@
# Pt Compute Loss
Computes loss for the input with the target using the specified loss function.
The user does not normally need to use this node. Instead the user should use training nodes that accept a loss object.
## Input
| Name | Data type |
|---|---|
| input_tens | Tensor |
| target_tens | Tensor |
| loss | Ptloss |
## Output
| Data type |
|---|
| Tensor |
<HR>
Category: PyTorch wrapper - Training
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+25
View File
@@ -0,0 +1,25 @@
# Ptn BCE Loss
A class to compute the binary cross entropy loss.
Unlike the Ptn BCE Loss With Logits node, which takes logits as input, this node expects probabilities. If the input consists of logits, apply a Sigmoid function first or use the Ptn BCE Loss With Logits node instead.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
@@ -0,0 +1,23 @@
# Ptn BCE With Logits Loss
A class to compute the sigmoid then binary cross entropy loss.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+25
View File
@@ -0,0 +1,25 @@
# Ptn Cross Entropy Loss
A class to compute the cross entropy loss.
Unlike Ptn NLL Loss node which takes log probabilities for input, input to this node needs to be logits. You can consider this node as a combination of log softmax and NLL.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+28
View File
@@ -0,0 +1,28 @@
# Ptn Huber Loss
A class to compute the Huber loss.
Please see [PyTorch documentation](https://pytorch.org/docs/stable/generated/torch.nn.HuberLoss.html) for details.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
delta (float): The threshold used to switch between adjusted MSE and L1 loss.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
| delta | Float |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+28
View File
@@ -0,0 +1,28 @@
# Ptn KL Div Loss
A class to compute the KL divergence loss.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`batchmean`: computes the sum then divides by the input size (recommended in the PyTorch document).
`mean`: computes the mean.
`sum`: computes the sum.
log_target (bool): Set to `True` if the target is in log probability instead of probability.
The input (y_hat) must always be in log-probability form, regardless of this flag.
## Input
| Name | Data type |
|---|---|
| reduction | None |
| log_target | Boolean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+23
View File
@@ -0,0 +1,23 @@
# Ptn L1 Loss
A class to compute the L1 loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+23
View File
@@ -0,0 +1,23 @@
# Ptn MSE Loss
A class to compute the squared loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+25
View File
@@ -0,0 +1,25 @@
# Ptn NLL Loss
A model to compute the negative log likelihood (NLL) loss.
Unlike Ptn Cross Entropy which takes input in logits, input to this nodes needs to be in log-probabilities.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+28
View File
@@ -0,0 +1,28 @@
# Ptn Smooth L1 Loss
A class to compute the Smooth L1 loss.
Please see [PyTorch documentation](https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html) for details and exact formulation.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
beta (float): The threshold used to switch between adjusted L2 and L1 loss.
## Input
| Name | Data type |
|---|---|
| reduction | Mean |
| beta | Float |
## Output
| Data type |
|---|
| Ptloss |
<HR>
Category: PyTorch wrapper - Loss function
ComfyUI Pt Wrapper Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+1 -1
View File
@@ -43,6 +43,6 @@ class PtApplyFunction:
closure (Callable): Differentiable function to apply to the tensor.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated model.
Tuple[nn.Module]: A tuple containing the tensor.
"""
return (closure(tens),)
@@ -0,0 +1,49 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtComputeLoss:
"""
Computes loss for the input with the target using the specified loss function.
The user does not normally need to use this node. Instead the user should use training nodes that accept a loss object.
category: PyTorch wrapper - Training
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the expected input types.
Returns:
Dict[str, Any]: A dictionary specifying required and optional input types.
"""
return {
"required": {
"input_tens": ("TENSOR", {}),
"target_tens": ("TENSOR", {}),
"loss": ("PTLOSS", {})
}
}
RETURN_TYPES: Tuple[str, ...] = ("TENSOR",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
def f(self,
input_tens: torch.Tensor,
target_tens: torch.Tensor,
loss: nn.Module) -> Tuple[torch.Tensor]:
"""
Computes loss for the input with the target using the specified loss function.
Args:
input_tens (torch.Tensor): Tensor containing the model output or y_hat.
target_tens (torch.Tensor): Tensor containing the ground truth or the label.
loss (nn.Module): Loss object instance.
Returns:
Tuple[nn.Module]: A tuple containing the computed loss.
"""
return (loss(input_tens, target_tens),)
+63
View File
@@ -0,0 +1,63 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnBCELoss:
"""
Ptn BCE Loss:
A class to compute the binary cross entropy loss.
Unlike the Ptn BCE Loss With Logits node, which takes logits as input, this node expects probabilities. If the input consists of logits, apply a Sigmoid function first or use the Ptn BCE Loss With Logits node instead.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A model to compute the cross entropy loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.BCELoss(reduction=reduction)
return (model,)
@@ -0,0 +1,61 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnBCEWithLogitsLoss:
"""
Ptn BCE With Logits Loss:
A class to compute the sigmoid then binary cross entropy loss.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A class to compute the sigmoid then binary cross entropy loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.BCEWithLogitsLoss(reduction=reduction)
return (model,)
@@ -0,0 +1,63 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnCrossEntropyLoss:
"""
Ptn Cross Entropy Loss:
A class to compute the cross entropy loss.
Unlike Ptn NLL Loss node which takes log probabilities for input, input to this node needs to be logits. You can consider this node as a combination of log softmax and NLL.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A model to compute the cross entropy loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.CrossEntropyLoss(reduction=reduction)
return (model,)
+68
View File
@@ -0,0 +1,68 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnHuberLoss:
"""
Ptn Huber Loss:
A class to compute the Huber loss.
Please see [PyTorch documentation](https://pytorch.org/docs/stable/generated/torch.nn.HuberLoss.html) for details.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
delta (float): The threshold used to switch between adjusted MSE and L1 loss.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),),
"delta": ("FLOAT", {"default":1.0, "min":0, "max":1e9, "step":0.0000000001}),
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str,
delta: float
) -> Tuple[nn.Module]:
"""
A model to compute the Huber loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
beta (float): The threshold used to switch between adjusted MSE and L1 loss.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.HuberLoss(reduction=reduction, delta=delta)
return (model,)
@@ -0,0 +1,71 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnKLDivLoss:
"""
Ptn KL Div Loss:
A class to compute the KL divergence loss.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`batchmean`: computes the sum then divides by the input size (recommended in the PyTorch document).
`mean`: computes the mean.
`sum`: computes the sum.
log_target (bool): Set to `True` if the target is in log probability instead of probability.
The input (y_hat) must always be in log-probability form, regardless of this flag.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("batchmean", "mean", "sum", "none"),),
"log_target": ("BOOLEAN", {"default": False})
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str,
log_target: bool
) -> Tuple[nn.Module]:
"""
A model to compute the cross entropy loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`batchmean`: computes the sum then divides by the input size (recommended in the PyTorch document).
`sum`: computes the sum.
`mean`: computes the mean.
log_target (bool): Set to `True` if the target is in log probability instead of probability.
The input (y_hat) must always be in log-probability form, regardless of this flag.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.KLDivLoss(
reduction=reduction,
log_target=log_target)
return (model,)
+62
View File
@@ -0,0 +1,62 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnL1Loss:
"""
Ptn L1 Loss:
A class to compute the L1 loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A model to compute the L1 loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.L1Loss(reduction=reduction)
return (model,)
+60
View File
@@ -0,0 +1,60 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnMSELoss:
"""
Ptn MSE Loss:
A class to compute the squared loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A model to compute the squared loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.MSELoss(reduction=reduction)
return (model,)
+63
View File
@@ -0,0 +1,63 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnNLLLoss:
"""
Ptn NLL Loss:
A model to compute the negative log likelihood (NLL) loss.
Unlike Ptn Cross Entropy which takes input in logits, input to this nodes needs to be in log-probabilities.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),)
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str
) -> Tuple[nn.Module]:
"""
A model to compute the NLL loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`sum`: computes the sum.
`mean`: computes the mean.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.NLLLoss(reduction=reduction)
return (model,)
@@ -0,0 +1,68 @@
from typing import Any, Dict, Tuple
import torch
import torch.nn as nn
class PtnSmoothL1Loss:
"""
Ptn Smooth L1 Loss:
A class to compute the Smooth L1 loss.
Please see [PyTorch documentation](https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html) for details and exact formulation.
Args:
reduction (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
beta (float): The threshold used to switch between adjusted L2 and L1 loss.
category: PyTorch wrapper - Loss function
"""
@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": {
"reduction": (("mean", "sum", "none"),),
"beta": ("FLOAT", {"default":1.0, "min":0, "max":1e9, "step":0.0000000001}),
}
}
RETURN_TYPES: Tuple[str] = ("PTLOSS",)
FUNCTION: str = "f"
CATEGORY: str = "Training"
@classmethod
def IS_CHANGED(cls, **kw):
return float("NaN")
def f(self,
reduction: str,
beta: float
) -> Tuple[nn.Module]:
"""
A model to compute the Smooth L1 loss.
Args:
reduction: (str): Reduction method.
`none`: no reduction will be applied done.
`mean`: computes the mean.
`sum`: computes the sum.
beta (float): The threshold used to switch between adjusted L2 and L1 loss.
Returns:
Tuple[nn.Module]: A tuple containing the instantiated PyTorch model.
"""
with torch.inference_mode(False):
model = nn.SmoothL1Loss(reduction=reduction, beta=beta)
return (model,)
+1 -1
View File
@@ -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.1.4"
version = "3.2.0"
license = {file = "LICENSE"}
[project.urls]
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_abs import PtAbs # Updated import to PtAbs
from pytorch_wrapper.pt_abs import PtAbs
class TestPtAbs(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_acos import PtAcos # Updated import to PtAcos
from pytorch_wrapper.pt_acos import PtAcos
class TestPtAcos(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_asin import PtAsin # Updated import to PtAsin
from pytorch_wrapper.pt_asin import PtAsin
class TestPtAsin(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_atan import PtAtan # Updated import to PtAtan
from pytorch_wrapper.pt_atan import PtAtan
class TestPtAtan(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_bitwise_and import PtBitwiseAnd # Updated import to PtBitwiseAnd
from pytorch_wrapper.pt_bitwise_and import PtBitwiseAnd
class TestPtBitwiseAnd(unittest.TestCase):
@@ -7,7 +7,7 @@ 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.pt_bitwise_left_shift import PtBitwiseLeftShift # Updated import to PtBitwiseLeftShift
from pytorch_wrapper.pt_bitwise_left_shift import PtBitwiseLeftShift
class TestPtBitwiseLeftShift(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_bitwise_not import PtBitwiseNot # Updated import to PtBitwiseNot
from pytorch_wrapper.pt_bitwise_not import PtBitwiseNot
class TestPtBitwiseNot(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_bitwise_or import PtBitwiseOr # Updated import to PtBitwiseOr
from pytorch_wrapper.pt_bitwise_or import PtBitwiseOr
class TestPtBitwiseOr(unittest.TestCase):
@@ -7,7 +7,7 @@ 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.pt_bitwise_right_shift import PtBitwiseRightShift # Updated import to PtBitwiseRightShift
from pytorch_wrapper.pt_bitwise_right_shift import PtBitwiseRightShift
class TestPtBitwiseRightShift(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_bitwise_xor import PtBitwiseXor # Updated import to PtBitwiseXor
from pytorch_wrapper.pt_bitwise_xor import PtBitwiseXor
class TestPtBitwiseXor(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_bmm import PtBmm # Updated import to PtBmm
from pytorch_wrapper.pt_bmm import PtBmm
class TestPtBmm(unittest.TestCase):
@@ -0,0 +1,86 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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.pt_compute_loss import PtComputeLoss
from pytorch_wrapper.ptn_l1_loss import PtnL1Loss
class TestComputeLoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.compute_node = PtComputeLoss()
self.loss_node = PtnL1Loss()
self.loss_fun_none = self.loss_node.f("none")[0]
self.loss_fun_mean = self.loss_node.f("mean")[0]
self.loss_fun_sum = self.loss_node.f("sum")[0]
# Test cases: (predicted values y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, -1.0, 10, -100, 1000], dtype=torch.float32),
torch.tensor([0.09, -1.1, 9, -101, 999], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor) -> Tensor:
"""
Compute the unreduced L1 loss.
Args:
y_hat (Tensor): Predicted values.
y (Tensor): Ground truth values.
Returns:
Tensor: Unreduced element-wise L1 loss.
"""
return torch.abs(y_hat - y)
def test_none(self) -> None:
"""
Test L1 loss with reduction='none'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
actual = self.compute_node.f(y_hat, y, self.loss_fun_none)[0]
expected = self.unreduced_loss(y_hat, y)
actual = self.loss_fun_none(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test L1 loss with reduction='mean'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.mean(dim=0)
actual = self.compute_node.f(y_hat, y, self.loss_fun_mean)[0]
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test L1 loss with reduction='sum'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.sum(dim=0)
actual = self.compute_node.f(y_hat, y, self.loss_fun_sum)[0]
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_cos import PtCos # Updated import to PtCos
from pytorch_wrapper.pt_cos import PtCos
class TestPtCos(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_cosh import PtCosh # Updated import to PtCosh
from pytorch_wrapper.pt_cosh import PtCosh
class TestPtCosh(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_div import PtDiv # Updated import to PtDiv
from pytorch_wrapper.pt_div import PtDiv
class TestPtDiv(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_einsum import PtEinsum # Updated import to PtEinsum
from pytorch_wrapper.pt_einsum import PtEinsum
class TestPtEinsum(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_eq import PtEq # Updated import to PtEq
from pytorch_wrapper.pt_eq import PtEq
class TestPtEq(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_exp import PtExp # Updated import to PtExp
from pytorch_wrapper.pt_exp import PtExp
class TestPtExp(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_ge import PtGe # Updated import to PtGe
from pytorch_wrapper.pt_ge import PtGe
class TestPtGe(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_gt import PtGt # Updated import to PtGt
from pytorch_wrapper.pt_gt import PtGt
class TestPtGt(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_le import PtLe # Updated import to PtLe
from pytorch_wrapper.pt_le import PtLe
class TestPtLe(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_log import PtLog # Updated import to PtLog
from pytorch_wrapper.pt_log import PtLog
class TestPtLog(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_logical_and import PtLogicalAnd # Updated import to PtLogicalAnd
from pytorch_wrapper.pt_logical_and import PtLogicalAnd
class TestPtLogicalAnd(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_logical_not import PtLogicalNot # Updated import to PtLogicalNot
from pytorch_wrapper.pt_logical_not import PtLogicalNot
class TestPtLogicalNot(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_logical_or import PtLogicalOr # Updated import to PtLogicalOr
from pytorch_wrapper.pt_logical_or import PtLogicalOr
class TestPtLogicalOr(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_logical_xor import PtLogicalXor # Updated import to PtLogicalXor
from pytorch_wrapper.pt_logical_xor import PtLogicalXor
class TestPtLogicalXor(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_lt import PtLt # Updated import to PtLt
from pytorch_wrapper.pt_lt import PtLt
class TestPtLt(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_matmul import PtMatMul # Updated import to PtMatMul
from pytorch_wrapper.pt_matmul import PtMatMul
class TestPtMatMul(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_mm import PtMm # Updated import to PtMm
from pytorch_wrapper.pt_mm import PtMm
class TestPtMm(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_mul import PtMul # Updated import to PtMul
from pytorch_wrapper.pt_mul import PtMul
class TestPtMul(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_ne import PtNe # Updated import to PtNe
from pytorch_wrapper.pt_ne import PtNe
class TestPtNe(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_neg import PtNeg # Updated import to PtNeg
from pytorch_wrapper.pt_neg import PtNeg
class TestPtNeg(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_neg import PtNeg # Updated import to PtNeg
from pytorch_wrapper.pt_neg import PtNeg
class TestPtNeg(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_sin import PtSin # Updated import to PtSin
from pytorch_wrapper.pt_sin import PtSin
class TestPtSin(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_sinh import PtSinh # Updated import to PtSinh
from pytorch_wrapper.pt_sinh import PtSinh
class TestPtSinh(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_sqrt import PtSqrt # Updated import to PtSqrt
from pytorch_wrapper.pt_sqrt import PtSqrt
class TestPtSqrt(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_tan import PtTan # Updated import to PtTan
from pytorch_wrapper.pt_tan import PtTan
class TestPtTan(unittest.TestCase):
+1 -1
View File
@@ -7,7 +7,7 @@ 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.pt_tanh import PtTanh # Updated import to PtTanh
from pytorch_wrapper.pt_tanh import PtTanh
class TestPtTanh(unittest.TestCase):
@@ -15,7 +15,7 @@ from pytorch_wrapper.ptv_transforms_to_tensor import PtvTransformsToTensor
from pytorch_wrapper.pt_data_loader import PtDataLoader
from pytorch_wrapper.pt_train_classification_model_lr import PtTrainClassificationModelLr
from pytorch_wrapper.pt_save_model import PtSaveModel
from pytorch_wrapper.pto_lr_scheduler_step import PtoLrSchedulerStep # Updated import
from pytorch_wrapper.pto_lr_scheduler_step import PtoLrSchedulerStep
class TestPtTrainClassificationConvModelLr(unittest.TestCase):
@@ -29,6 +29,7 @@ class TestPtnBatchNorm2d(unittest.TestCase):
mean_after = out.mean(dim=(0, 2, 3))
# Ensure std is not one before normalization
# Reference value: [2.2758, 2.4911, 2.2218]
self.assertFalse(
torch.allclose(
std_before,
@@ -36,12 +37,14 @@ class TestPtnBatchNorm2d(unittest.TestCase):
atol=1e-1))
# Ensure normalization happened (std should be 1 unless elements are very close)
# Reference value: [1.0190, 1.0190, 1.0190]
self.assertTrue(
torch.allclose(
std_after,
torch.ones_like(std_after),
atol=1e-1))
# Reference value: [0.0000e+00, 0.0000e+00, 2.2076e-09]
self.assertTrue(
torch.allclose(
mean_after,
@@ -0,0 +1,83 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_bce_loss import PtnBCELoss
class TestPtnBCELoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnBCELoss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
# Test cases: (predicted probabilities y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, 0.9], dtype=torch.float32),
torch.tensor([1, 0], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor) -> Tensor:
"""
Compute the unreduced binary cross-entropy loss.
Args:
y_hat (Tensor): Predicted probabilities.
y (Tensor): Ground truth binary labels.
Returns:
Tensor: Unreduced element-wise BCE loss.
"""
return -(y * torch.log(y_hat) + (1 - y) * torch.log(1 - y_hat))
def test_none(self) -> None:
"""
Test BCE loss with reduction='none'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
expected = self.unreduced_loss(y_hat, y)
actual = self.loss_fun_none(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test BCE loss with reduction='mean'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test BCE loss with reduction='sum'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,84 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_bce_with_logits_loss import PtnBCEWithLogitsLoss
class TestPtnBCEWithLogits(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnBCEWithLogitsLoss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
# Probabilities: 0.1, 0.8 → Logits: log(0.1/0.9), log(0.8/0.2)
logits = torch.log(torch.tensor([0.1, 0.8]) / torch.tensor([0.9, 0.2]))
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
logits.to(dtype=torch.float32),
torch.tensor([1, 0], dtype=torch.float32),
)
]
def unreduced_loss(self, logits: Tensor, y: Tensor) -> Tensor:
"""
Compute the unreduced BCEWithLogits loss.
Args:
logits (Tensor): Raw logits.
y (Tensor): Ground truth binary labels.
Returns:
Tensor: Unreduced element-wise BCEWithLogits loss.
"""
return torch.nn.functional.binary_cross_entropy_with_logits(logits, y, reduction='none')
def test_none(self) -> None:
"""
Test BCEWithLogits loss with reduction='none'.
"""
for logits, y in self.test_cases:
with self.subTest(logits=logits):
expected = self.unreduced_loss(logits, y)
actual = self.loss_fun_none(logits, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test BCEWithLogits loss with reduction='mean'.
"""
for logits, y in self.test_cases:
with self.subTest(logits=logits):
loss = self.unreduced_loss(logits, y)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(logits, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test BCEWithLogits loss with reduction='sum'.
"""
for logits, y in self.test_cases:
with self.subTest(logits=logits):
loss = self.unreduced_loss(logits, y)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(logits, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,85 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_cross_entropy_loss import PtnCrossEntropyLoss
class TestPtCrossEntropyLoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnCrossEntropyLoss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([
[-2.0, -1.0, 0.0, 1.0, 2.0],
[-40.0, -20.0, 0.0, 10.0, 20.0]
], dtype=torch.float32),
torch.tensor([0, 2], dtype=torch.int64)
)
]
def unreduced_loss(self, logits: Tensor, targets: Tensor) -> Tensor:
"""
Compute the unreduced cross entropy loss.
Args:
logits (Tensor): Raw, unnormalized class scores (logits).
targets (Tensor): Ground truth class indices.
Returns:
Tensor: Unreduced element-wise cross entropy loss.
"""
return torch.nn.functional.cross_entropy(logits, targets, reduction='none')
def test_none(self) -> None:
"""
Test cross entropy loss with reduction='none'.
"""
for logits, targets in self.test_cases:
with self.subTest(logits=logits):
expected = self.unreduced_loss(logits, targets)
actual = self.loss_fun_none(logits, targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test cross entropy loss with reduction='mean'.
"""
for logits, targets in self.test_cases:
with self.subTest(logits=logits):
loss = self.unreduced_loss(logits, targets)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(logits, targets)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test cross entropy loss with reduction='sum'.
"""
for logits, targets in self.test_cases:
with self.subTest(logits=logits):
loss = self.unreduced_loss(logits, targets)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(logits, targets)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
+107
View File
@@ -0,0 +1,107 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_huber_loss import PtnHuberLoss
class TestPtnHuberLoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnHuberLoss()
self.loss_fun_none_1 = self.node.f("none", 0.01)[0]
self.loss_fun_none_2 = self.node.f("none", 1)[0]
self.loss_fun_none_3 = self.node.f("none", 100)[0]
self.loss_fun_mean_1 = self.node.f("mean", 0.01)[0]
self.loss_fun_mean_2 = self.node.f("mean", 1)[0]
self.loss_fun_mean_3 = self.node.f("mean", 100)[0]
self.loss_fun_sum_1 = self.node.f("sum", 0.01)[0]
self.loss_fun_sum_2 = self.node.f("sum", 1)[0]
self.loss_fun_sum_3 = self.node.f("sum", 100)[0]
# Test cases: (predicted values y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, -1.0, 10, -100, 1000], dtype=torch.float32),
torch.tensor([0.09, -1.1, 9, -101, 999], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor, delta: float) -> Tensor:
return torch.nn.functional.huber_loss(y_hat, y, delta=delta, reduction="none")
def test_none_delta_001(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, delta=0.01)
actual = self.loss_fun_none_1(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_none_delta_1(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, delta=1)
actual = self.loss_fun_none_2(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_none_delta_100(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, delta=100)
actual = self.loss_fun_none_3(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_mean_delta_001(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=0.01)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_1(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
def test_mean_delta_1(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=1)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_2(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
def test_mean_delta_100(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=100)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_3(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
def test_sum_delta_001(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=0.01)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_1(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
def test_sum_delta_1(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=1)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_2(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
def test_sum_delta_100(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, delta=100)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_3(y_hat, y)
self.assertTrue(torch.equal(actual, expected))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,130 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_kl_div_loss import PtnKLDivLoss
class TestPtnKLDivLoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnKLDivLoss()
self.loss_fun_none = self.node.f("none", log_target=False)[0]
self.loss_fun_batchmean = self.node.f("batchmean", log_target=False)[0]
self.loss_fun_mean = self.node.f("mean", log_target=False)[0]
self.loss_fun_sum = self.node.f("sum", log_target=False)[0]
self.loss_fun_none_log = self.node.f("none", log_target=True)[0]
self.loss_fun_batchmean_log = self.node.f("batchmean", log_target=True)[0]
self.loss_fun_mean_log = self.node.f("mean", log_target=True)[0]
self.loss_fun_sum_log = self.node.f("sum", log_target=True)[0]
# log_probs: log_softmax of logits
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
# input (log-probabilities)
torch.log_softmax(
torch.tensor([
[-2.0, -1.0, 0.0, 1.0, 2.0],
[-40.0, -20.0, 0.0, 10.0, 20.0]
], dtype=torch.float32), dim=-1
),
# target (probabilities for log_target=False)
torch.tensor([
[0.04, 0.06, 0.2, 0.3, 0.4],
[0.4, 0.3, 0.2, 0.06, 0.04]
], dtype=torch.float32)
)
]
self.log_target_cases: List[Tuple[Tensor, Tensor]] = [
(
# input
torch.log_softmax(
torch.tensor([
[-2.0, -1.0, 0.0, 1.0, 2.0],
[-40.0, -20.0, 0.0, 10.0, 20.0]
], dtype=torch.float32), dim=-1
),
# target (log-probabilities)
torch.log_softmax(
torch.tensor([
[0.04, 0.06, 0.2, 0.3, 0.4],
[0.4, 0.3, 0.2, 0.06, 0.04]
], dtype=torch.float32), dim=-1
)
)
]
def unreduced_loss(self, log_probs: Tensor, probs: Tensor) -> Tensor:
return torch.nn.functional.kl_div(log_probs, probs, reduction='none', log_target=False)
def batchmean_loss(self, log_probs: Tensor, probs: Tensor) -> Tensor:
return torch.nn.functional.kl_div(log_probs, probs, reduction='batchmean', log_target=False)
def unreduced_loss_log_target(self, log_probs: Tensor, log_targets: Tensor) -> Tensor:
return torch.nn.functional.kl_div(log_probs, log_targets, reduction='none', log_target=True)
def batchmean_loss_log_target(self, log_probs: Tensor, log_targets: Tensor) -> Tensor:
return torch.nn.functional.kl_div(log_probs, log_targets, reduction='batchmean', log_target=True)
def test_none(self) -> None:
for log_probs, probs in self.test_cases:
expected = self.unreduced_loss(log_probs, probs)
actual = self.loss_fun_none(log_probs, probs)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4))
def test_mean(self) -> None:
for log_probs, probs in self.test_cases:
expected = self.unreduced_loss(log_probs, probs).mean()
actual = self.loss_fun_mean(log_probs, probs)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_batchmean(self) -> None:
for log_probs, probs in self.test_cases:
expected = self.batchmean_loss(log_probs, probs)
actual = self.loss_fun_batchmean(log_probs, probs)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_sum(self) -> None:
for log_probs, probs in self.test_cases:
expected = self.unreduced_loss(log_probs, probs).sum()
actual = self.loss_fun_sum(log_probs, probs)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_none_log_target(self) -> None:
for log_probs, log_targets in self.log_target_cases:
expected = self.unreduced_loss_log_target(log_probs, log_targets)
actual = self.loss_fun_none_log(log_probs, log_targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4))
def test_mean_log_target(self) -> None:
for log_probs, log_targets in self.log_target_cases:
expected = self.unreduced_loss_log_target(log_probs, log_targets).mean()
actual = self.loss_fun_mean_log(log_probs, log_targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_batchmean_log_target(self) -> None:
for log_probs, log_targets in self.log_target_cases:
expected = self.batchmean_loss_log_target(log_probs, log_targets)
actual = self.loss_fun_batchmean_log(log_probs, log_targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
def test_sum_log_target(self) -> None:
for log_probs, log_targets in self.log_target_cases:
expected = self.unreduced_loss_log_target(log_probs, log_targets).sum()
actual = self.loss_fun_sum_log(log_probs, log_targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6))
if __name__ == "__main__":
unittest.main()
+83
View File
@@ -0,0 +1,83 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_l1_loss import PtnL1Loss
class TestPtnL1Loss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnL1Loss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
# Test cases: (predicted values y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, -1.0, 10, -100, 1000], dtype=torch.float32),
torch.tensor([0.09, -1.1, 9, -101, 999], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor) -> Tensor:
"""
Compute the unreduced L1 loss.
Args:
y_hat (Tensor): Predicted values.
y (Tensor): Ground truth values.
Returns:
Tensor: Unreduced element-wise L1 loss.
"""
return torch.abs(y_hat - y)
def test_none(self) -> None:
"""
Test L1 loss with reduction='none'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
expected = self.unreduced_loss(y_hat, y)
actual = self.loss_fun_none(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test L1 loss with reduction='mean'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test L1 loss with reduction='sum'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,83 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_mse_loss import PtnMSELoss
class TestPtnMSELoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnMSELoss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
# Test cases: (predicted values y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, -1.0, 10, -100, 1000], dtype=torch.float32),
torch.tensor([0.09, -1.1, 9, -101, 999], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor) -> Tensor:
"""
Compute the unreduced mean squared error loss.
Args:
y_hat (Tensor): Predicted values.
y (Tensor): Ground truth values.
Returns:
Tensor: Unreduced element-wise MSE loss.
"""
return (y_hat - y) ** 2
def test_none(self) -> None:
"""
Test MSE loss with reduction='none'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
expected = self.unreduced_loss(y_hat, y)
actual = self.loss_fun_none(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test MSE loss with reduction='mean'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test MSE loss with reduction='sum'.
"""
for y_hat, y in self.test_cases:
with self.subTest(y_hat=y_hat):
loss = self.unreduced_loss(y_hat, y)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,89 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_nll_loss import PtnNLLLoss
class TestPtnNLLLoss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnNLLLoss()
self.loss_fun_none = self.node.f("none")[0]
self.loss_fun_mean = self.node.f("mean")[0]
self.loss_fun_sum = self.node.f("sum")[0]
logits = torch.tensor([
[-2.0, -1.0, 0.0, 1.0, 2.0],
[-40.0, -20.0, 0.0, 10.0, 20.0]
], dtype=torch.float32)
log_probs = torch.nn.functional.log_softmax(logits, dim=1)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
log_probs,
torch.tensor([0, 2], dtype=torch.int64)
)
]
def unreduced_loss(self, log_probs: Tensor, targets: Tensor) -> Tensor:
"""
Compute the unreduced negative log-likelihood loss.
Args:
log_probs (Tensor): Log-probabilities from log_softmax.
targets (Tensor): Ground truth class indices.
Returns:
Tensor: Unreduced element-wise NLL loss.
"""
return torch.nn.functional.nll_loss(log_probs, targets, reduction='none')
def test_none(self) -> None:
"""
Test NLL loss with reduction='none'.
"""
for log_probs, targets in self.test_cases:
with self.subTest(log_probs=log_probs):
expected = self.unreduced_loss(log_probs, targets)
actual = self.loss_fun_none(log_probs, targets)
self.assertTrue(torch.allclose(actual, expected, atol=1e-4),
f"Expected {expected}, got {actual}")
def test_mean(self) -> None:
"""
Test NLL loss with reduction='mean'.
"""
for log_probs, targets in self.test_cases:
with self.subTest(log_probs=log_probs):
loss = self.unreduced_loss(log_probs, targets)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean(log_probs, targets)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum(self) -> None:
"""
Test NLL loss with reduction='sum'.
"""
for log_probs, targets in self.test_cases:
with self.subTest(log_probs=log_probs):
loss = self.unreduced_loss(log_probs, targets)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum(log_probs, targets)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,116 @@
import os
import sys
import unittest
import torch
from torch import Tensor
from typing import List, Tuple
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_smooth_l1_loss import PtnSmoothL1Loss
class TestPtnSmoothL1Loss(unittest.TestCase):
def setUp(self) -> None:
"""
Set up the test instance by initializing the loss functions and test cases.
"""
self.node = PtnSmoothL1Loss()
self.loss_fun_none_1 = self.node.f("none", 0.01)[0]
self.loss_fun_none_2 = self.node.f("none", 1)[0]
self.loss_fun_none_3 = self.node.f("none", 100)[0]
self.loss_fun_mean_1 = self.node.f("mean", 0.01)[0]
self.loss_fun_mean_2 = self.node.f("mean", 1)[0]
self.loss_fun_mean_3 = self.node.f("mean", 100)[0]
self.loss_fun_sum_1 = self.node.f("sum", 0.01)[0]
self.loss_fun_sum_2 = self.node.f("sum", 1)[0]
self.loss_fun_sum_3 = self.node.f("sum", 100)[0]
# Test cases: (predicted values y_hat, ground truth y)
self.test_cases: List[Tuple[Tensor, Tensor]] = [
(
torch.tensor([0.1, -1.0, 10, -100, 1000], dtype=torch.float32),
torch.tensor([0.09, -1.1, 9, -101, 999], dtype=torch.float32),
)
]
def unreduced_loss(self, y_hat: Tensor, y: Tensor, beta: float) -> Tensor:
return torch.nn.functional.smooth_l1_loss(y_hat, y, beta=beta, reduction="none")
def test_none_beta_001(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, beta=0.01)
actual = self.loss_fun_none_1(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_none_beta_1(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, beta=1)
actual = self.loss_fun_none_2(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_none_beta_100(self) -> None:
for y_hat, y in self.test_cases:
expected = self.unreduced_loss(y_hat, y, beta=100)
actual = self.loss_fun_none_3(y_hat, y)
self.assertTrue(torch.allclose(actual, expected, atol=1e-6),
f"Expected {expected}, got {actual}")
def test_mean_beta_001(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=0.01)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_1(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_mean_beta_1(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=1)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_2(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_mean_beta_100(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=100)
expected = loss.mean(dim=0)
actual = self.loss_fun_mean_3(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum_beta_001(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=0.01)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_1(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum_beta_1(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=1)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_2(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
def test_sum_beta_100(self) -> None:
for y_hat, y in self.test_cases:
loss = self.unreduced_loss(y_hat, y, beta=100)
expected = loss.sum(dim=0)
actual = self.loss_fun_sum_3(y_hat, y)
self.assertTrue(torch.equal(actual, expected),
f"Expected {expected}, got {actual}")
if __name__ == "__main__":
unittest.main()
@@ -8,7 +8,7 @@ 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.pto_lr_scheduler_reduce_on_plateau import PtoLrSchedulerReduceOnPlateau # Updated import
from pytorch_wrapper.pto_lr_scheduler_reduce_on_plateau import PtoLrSchedulerReduceOnPlateau
class TestPtoLrSchedulerReduceOnPlateau(unittest.TestCase):
@@ -8,7 +8,7 @@ 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.pto_lr_scheduler_step import PtoLrSchedulerStep # Updated import
from pytorch_wrapper.pto_lr_scheduler_step import PtoLrSchedulerStep
class TestPtoLrSchedulerStep(unittest.TestCase):