项目文件夹

文件
wehub-resource-sync 593b94c120
pytest / Unit Tests (push) Has been cancelled
pytest / Integration (integration_tests_a) (push) Has been cancelled
pytest / Integration (integration_tests_b) (push) Has been cancelled
pytest / Integration (integration_tests_c) (push) Has been cancelled
pytest / Integration (integration_tests_d) (push) Has been cancelled
pytest / Integration (integration_tests_e) (push) Has been cancelled
pytest / Integration (integration_tests_f) (push) Has been cancelled
pytest / Integration (integration_tests_g) (push) Has been cancelled
pytest / Integration (integration_tests_h) (push) Has been cancelled
pytest / Integration (integration_tests_i) (push) Has been cancelled
pytest / Integration (integration_tests_j) (push) Has been cancelled
pytest / Distributed (distributed_a) (push) Has been cancelled
pytest / Distributed (distributed_b) (push) Has been cancelled
pytest / Distributed (distributed_c) (push) Has been cancelled
pytest / Distributed (distributed_d) (push) Has been cancelled
pytest / Distributed (distributed_e) (push) Has been cancelled
pytest / Distributed (distributed_f) (push) Has been cancelled
pytest / Minimal Install (push) Has been cancelled
pytest / Event File (push) Has been cancelled
pytest (slow) / py-slow (push) Has been cancelled
Publish JSON Schema / publish-schema (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:20 +08:00

123 行
5.4 KiB
Python

"""Utilities used for managing output feature dicts."""
import numpy as np
import torch
from ludwig.utils.torch_utils import sequence_length_3D, sequence_mask
def get_feature_concat_name(feature_name: str, tensor_name: str) -> str:
return feature_name + "::" + tensor_name
def get_tensor_name_from_concat_name(concat_name: str) -> str:
return concat_name.split("::")[-1]
def get_feature_name_from_concat_name(concat_name: str) -> str:
return "::".join(concat_name.split("::")[:-1])
def get_single_output_feature_tensors(
output_feature_dict: dict[str, torch.Tensor], feature_name: str
) -> dict[str, torch.Tensor]:
"""Returns a map of tensors related to the given feature_name."""
single_output_feature_tensors = {}
for concat_name, tensor in output_feature_dict.items():
if get_feature_name_from_concat_name(concat_name) == feature_name:
single_output_feature_tensors[get_tensor_name_from_concat_name(concat_name)] = tensor
return single_output_feature_tensors
def get_output_feature_tensor(
output_dict: dict[str, torch.Tensor], feature_name: str, tensor_name: str
) -> torch.Tensor:
"""Returns a tensor related for the given feature_name and tensor_name."""
concat_name = get_feature_concat_name(feature_name, tensor_name)
if concat_name not in output_dict:
raise ValueError(
f"Could not find {tensor_name} for {feature_name} in the output_dict with keys: {output_dict.keys()}"
)
return output_dict[get_feature_concat_name(feature_name, tensor_name)]
def set_output_feature_tensor(
output_dict: dict[str, torch.Tensor], feature_name: str, tensor_name: str, tensor: torch.Tensor
):
"""Adds tensor for the given feature_name and tensor_name to the tensor dict."""
output_dict[get_feature_concat_name(feature_name, tensor_name)] = tensor
def concat_dependencies(
feature_name: str,
dependencies: list[str],
dependency_reducers: torch.ModuleDict,
combiner_hidden_state: torch.Tensor,
other_output_feature_states: dict[str, torch.Tensor],
) -> torch.Tensor:
"""Concatenates combiner_hidden_state with other output feature hidden states based on listed dependencies."""
# No dependencies.
if not dependencies:
return combiner_hidden_state
dependency_hidden_states = []
for feature_name in dependencies:
# The dependent feature should be present since ECD does a topological sort over output features.
feature_hidden_state = other_output_feature_states[feature_name]
# This feature is sequential.
if len(combiner_hidden_state.shape) > 2:
if len(feature_hidden_state.shape) > 2:
# The dependent feature is also sequential.
# matrix matrix -> concat
if combiner_hidden_state.shape[1] != feature_hidden_state.shape[1]:
raise ValueError(
f"Sequence length mismatch between combiner output ({combiner_hidden_state.shape[1]}) "
f"and dependent feature '{feature_name}' ({feature_hidden_state.shape[1]}). "
f"Both sequential features must have the same sequence length."
)
dependency_hidden_states.append(feature_hidden_state)
else:
# The dependent feature is not sequential.
# matrix vector -> tile concat
sequence_max_length = combiner_hidden_state.shape[1]
multipliers = (1, sequence_max_length, 1)
tiled_representation = torch.tile(torch.unsqueeze(feature_hidden_state, 1), multipliers)
sequence_length = sequence_length_3D(combiner_hidden_state)
mask = sequence_mask(sequence_length, sequence_max_length)
tiled_representation = torch.mul(
tiled_representation,
mask[:, :, np.newaxis].type(torch.float32),
)
dependency_hidden_states.append(tiled_representation)
else:
# This feature is not sequential.
if len(feature_hidden_state.shape) > 2:
# The dependent feature is sequential.
# vector matrix -> reduce concat
reducer = dependency_reducers[feature_name]
dependency_hidden_states.append(reducer(feature_hidden_state))
else:
# The dependent feature is not sequential.
# vector vector -> concat
dependency_hidden_states.append(feature_hidden_state)
try:
hidden = torch.cat([combiner_hidden_state] + dependency_hidden_states, dim=-1)
except Exception as e:
raise ValueError(
f"Shape mismatch {e} while concatenating dependent features of {feature_name}: "
f"{dependencies}. Concatenating the feature activations tensor {combiner_hidden_state} "
f"with activation tensors of dependencies: {dependency_hidden_states}. The error is "
"likely due to a mismatch of the second dimension (sequence length) or a "
"difference in ranks. Likely solutions are setting the maximum_sequence_length "
"of all sequential features to be the same, or reduce the output of some "
"features, or disabling the bucketing setting bucketing_field to None / null, "
"as activating it will reduce the length of the field the bucketing is "
"performed on."
)
return hidden