Add batchnorm, dropout, and trainable nodes

This commit is contained in:
Tasha Upchurch
2025-06-22 00:40:22 -06:00
parent 713dc85127
commit a7c48b87a6
2 changed files with 107 additions and 0 deletions
+81
View File
@@ -1296,3 +1296,84 @@ class PlotSeriesString:
buf.close()
return (im,)
@ETK_pytorch_base
class AddBatchNormLayer:
"""Adds a BatchNorm layer to an ``nn.Sequential`` model."""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"model": ("TORCH_MODEL",),
"num_features": ("INT", {"min": 1}),
"one_d": ("BOOLEAN", {"default": True}),
}
}
RETURN_TYPES = ("TORCH_MODEL",)
FUNCTION = "add_batchnorm_layer"
CATEGORY = "model"
def add_batchnorm_layer(self, model, num_features, one_d=True):
layer = nn.BatchNorm1d(num_features) if one_d else nn.BatchNorm2d(num_features)
if isinstance(model, nn.Sequential):
model.insert(len(model), layer)
else:
raise TypeError("The provided model is not a nn.Sequential model.")
return (model,)
@ETK_pytorch_base
class AddDropoutLayer:
"""Adds a Dropout layer to an ``nn.Sequential`` model."""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"model": ("TORCH_MODEL",),
"p": ("FLOAT", {"min": 0.0, "max": 1.0, "default": 0.5}),
},
"optional": {
"inplace": (["True", "False"], {"default": "False"}),
},
}
RETURN_TYPES = ("TORCH_MODEL",)
FUNCTION = "add_dropout_layer"
CATEGORY = "model"
def add_dropout_layer(self, model, p=0.5, inplace="False"):
inplace = True if inplace in (True, "True") else False
layer = nn.Dropout(p=p, inplace=inplace)
if isinstance(model, nn.Sequential):
model.insert(len(model), layer)
else:
raise TypeError("The provided model is not a nn.Sequential model.")
return (model,)
@ETK_pytorch_base
class SetModelTrainable:
"""Sets ``requires_grad`` for all parameters of a model."""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"model": ("TORCH_MODEL",),
"requires_grad": (["True", "False"], {"default": "False"}),
}
}
RETURN_TYPES = ("TORCH_MODEL",)
FUNCTION = "set_trainable"
CATEGORY = "model"
def set_trainable(self, model, requires_grad="False"):
flag = True if requires_grad in (True, "True") else False
for param in model.parameters():
param.requires_grad = flag
return (model,)
+26
View File
@@ -36,6 +36,9 @@ from custom_nodes.EternalKernelLiteGraphNodes.pytorch_nodes import (
FuncModifyModel,
PlotSeriesString,
GridSearchTraining,
AddBatchNormLayer,
AddDropoutLayer,
SetModelTrainable,
)
@@ -318,3 +321,26 @@ def test_grid_search_training(monkeypatch):
best_model, best_params, metrics = node.grid_search_train(model, param_grid)
assert best_params["epochs"] == 1
assert len(metrics) == 2
def test_add_batchnorm_layer():
model = nn.Sequential(nn.Linear(4, 4))
node = AddBatchNormLayer()
out_model, = node.add_batchnorm_layer(model, 4, True)
assert isinstance(out_model[-1], nn.BatchNorm1d)
def test_add_dropout_layer():
model = nn.Sequential(nn.Linear(4, 4))
node = AddDropoutLayer()
out_model, = node.add_dropout_layer(model, 0.3)
assert isinstance(out_model[-1], nn.Dropout)
def test_set_model_trainable():
model = nn.Sequential(nn.Linear(1, 1))
node = SetModelTrainable()
frozen, = node.set_trainable(model, "False")
assert all(not p.requires_grad for p in frozen.parameters())
unfrozen, = node.set_trainable(frozen, "True")
assert all(p.requires_grad for p in unfrozen.parameters())