hankcs/HanLP · error · ValueError
DataParallel not supported when CRF is used
Error message
DataParallel not supported when CRF is used
What it means
When a tagger is configured with crf=True, build_criterion returns the model's CRF module as the loss (CRF computes its own log-likelihood). A raw CRF has shared parameters, so wrapping the model in nn.DataParallel (which replicates the module and scatters/gathers batch dimensions) breaks CRF's sequence-level computation; HanLP therefore refuses the combination.
Source
Thrown at hanlp/components/taggers/tagger.py:37
from hanlp.utils.time_util import CountdownTimer
from hanlp_common.util import reorder
from hanlp_trie import DictInterface, TrieDict
from hanlp_trie.dictionary import TupleTrieDict
class Tagger(DistillableComponent, ABC):
def build_optimizer(self, optimizer, lr, **kwargs):
if optimizer == 'adam':
return optim.Adam(params=self.model.parameters(), lr=lr)
elif optimizer == 'sgd':
return torch.optim.SGD(self.model.parameters(), lr=lr)
def build_criterion(self, model=None, reduction='mean', decoder=None, **kwargs):
if self.config.get('crf', False):
if not model:
model = decoder or self.model
if isinstance(model, nn.DataParallel):
raise ValueError('DataParallel not supported when CRF is used')
return self.model_from_config.module.crf
return model.crf
else:
return nn.CrossEntropyLoss(reduction=reduction)
def build_metric(self, **kwargs):
return CategoricalAccuracy()
@abstractmethod
def feed_batch(self, batch):
pass
def compute_loss(self, criterion, out, y, mask):
if self.config.get('crf', False):
criterion: CRF = criterion
loss = -criterion.forward(out, y, mask)
else:
loss = criterion(out[mask], y[mask])View on GitHub (pinned to ddb1299bdd)
Solutions
- Train on a single GPU: set devices to one GPU id (e.g. devices=0 or devices=-1 depending on config) so DataParallel is not used
- Disable CRF (crf=False) if multi-GPU training is required — you lose sequence-level loss but can parallelize
- Use DistributedDataParallel-style training outside HanLP's loop only if you understand CRF gather implications
Example fix
# before (hanlp.json / training config)
{"crf": true, "devices": [0, 1]}
# after
{"crf": true, "devices": [0]} Defensive patterns
Strategy: validation
Validate before calling
import torch.nn as nn
assert not (config.get('crf', False) and isinstance(model, nn.DataParallel)), 'CRF + DataParallel unsupported; use a single device' Prevention
- Limit devices to one GPU when crf=True in config
- Document single-GPU constraint for CRF-based taggers in team training docs
When it happens
Trigger: Training a tagger (e.g. RNN/CRF tagger) with config crf=True while running on multiple GPUs so HanLP wraps the model in nn.DataParallel, then execute_training_loop calls build_criterion and hits the check. Note: the code after the raise (return self.model_from_config.module.crf) is unreachable dead code.
Common situations: Scaling single-GPU CRF training to a multi-GPU machine with devices in config; enabling CRF for better sequence tagging accuracy then hitting multi-GPU training.
Related errors
- invalid number of tags: {num_tags}
- invalid reduction: {reduction}
- emissions must have dimension of 3, got {emissions.dim()}
- expected last dimension of emissions is {self.num_tags}, got
- Got average f{average}, expected one of None, 'token', or 'b
AI-assisted analysis of hankcs/HanLP@ddb1299bdd (2026-08-27).
Data as JSON: /api/errors/228db24696aaf48f.
Report an issue: GitHub.