You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python+PyTorch的多概念商品评论匹配监督式NLP方案咨询

商品评论-概念多标签分类解决方案

这是典型的多标签文本分类任务,目标是为每条评论预测是否提及K个预设概念(输出N×K的布尔数组)。针对你有数百条标注数据、零样本模型效果不佳的情况,以下是基于Python和PyTorch的落地方案:

一、数据预处理

首先将标注数据整理成结构化格式,每条数据包含:评论文本、对应K个概念的0/1标签列表。

1. 定义数据集类

用PyTorch的Dataset封装数据,方便后续加载:

import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader
from transformers import AutoTokenizer

class CommentConceptDataset(Dataset):
    def __init__(self, texts, labels, tokenizer, max_len=128):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_len = max_len

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        text = str(self.texts[idx])
        label = self.labels[idx]

        encoding = self.tokenizer(
            text,
            truncation=True,
            padding='max_length',
            max_length=self.max_len,
            return_tensors='pt'
        )

        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'labels': torch.tensor(label, dtype=torch.float)
        }

2. 数据划分

将标注数据按8:1:1划分为训练集、验证集、测试集,确保各集合的概念分布均匀。

二、模型选择与定义

选择轻量且适合小样本微调的预训练模型,推荐DistilBERT(参数量仅为BERT的1/3,性能接近)或RoBERTa-base。模型结构为:预训练模型提取文本特征,接全连接层输出K个logits(对应K个概念的二分类预测)。

from transformers import AutoModel

class ConceptClassifier(torch.nn.Module):
    def __init__(self, model_name, num_labels):
        super().__init__()
        self.bert = AutoModel.from_pretrained(model_name)
        self.dropout = torch.nn.Dropout(p=0.3)
        self.classifier = torch.nn.Linear(self.bert.config.hidden_size, num_labels)

    def forward(self, input_ids, attention_mask):
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
        cls_output = outputs.last_hidden_state[:, 0, :]  # 取<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>token的输出作为文本表征
        cls_output = self.dropout(cls_output)
        logits = self.classifier(cls_output)
        return logits

三、训练与评估

1. 训练配置

# 初始化组件
model_name = 'distilbert-base-uncased'
tokenizer = AutoTokenizer.from_pretrained(model_name)
num_labels = 100  # 实际场景的概念数量
model = ConceptClassifier(model_name, num_labels)

# 损失函数、优化器(多标签分类用BCEWithLogitsLoss更合适)
loss_fn = torch.nn.BCEWithLogitsLoss()
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)

# 数据加载器(替换为你的真实数据)
train_texts = ["Great color and sound quality...", "The build feels very durable...", ...]
train_labels = [[1,1,0,0,...], [0,0,0,1,...], ...]  # 对应100个概念的0/1列表
train_dataset = CommentConceptDataset(train_texts, train_labels, tokenizer)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)

2. 训练循环

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

num_epochs = 5
for epoch in range(num_epochs):
    model.train()
    total_loss = 0

    for batch in train_loader:
        input_ids = batch['input_ids'].to(device)
        attention_mask = batch['attention_mask'].to(device)
        labels = batch['labels'].to(device)

        optimizer.zero_grad()
        logits = model(input_ids, attention_mask)
        loss = loss_fn(logits, labels)
        
        loss.backward()
        optimizer.step()
        total_loss += loss.item()

    avg_loss = total_loss / len(train_loader)
    print(f"Epoch {epoch+1}/{num_epochs}, Average Loss: {avg_loss:.4f}")

    # 验证环节(可选,用验证集监控模型泛化能力)
    model.eval()
    # 验证集逻辑与训练集类似,计算F1-score等指标

3. 评估指标

多标签分类常用Micro-F1和Macro-F1评估,用sklearn实现:

from sklearn.metrics import f1_score

def evaluate(model, val_loader, device):
    model.eval()
    all_preds = []
    all_labels = []

    with torch.no_grad():
        for batch in val_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)

            logits = model(input_ids, attention_mask)
            preds = torch.sigmoid(logits).cpu().numpy() >= 0.5  # 阈值可根据验证集调整
            
            all_preds.extend(preds)
            all_labels.extend(labels.cpu().numpy())

    micro_f1 = f1_score(all_labels, all_preds, average='micro')
    macro_f1 = f1_score(all_labels, all_preds, average='macro')
    print(f"Micro-F1: {micro_f1:.4f}, Macro-F1: {macro_f1:.4f}")
    return micro_f1, macro_f1

四、结果输出

训练完成后,用模型预测所有评论,生成N×K的布尔numpy数组:

def predict_all_comments(model, texts, tokenizer, device, max_len=128):
    model.eval()
    predictions = []

    with torch.no_grad():
        for text in texts:
            encoding = tokenizer(
                text,
                truncation=True,
                padding='max_length',
                max_length=max_len,
                return_tensors='pt'
            )
            input_ids = encoding['input_ids'].to(device)
            attention_mask = encoding['attention_mask'].to(device)

            logits = model(input_ids, attention_mask)
            pred = torch.sigmoid(logits).cpu().numpy()[0] >= 0.5
            predictions.append(pred)

    return np.array(predictions, dtype=bool)

# 示例调用
all_comments = ["Comment 1...", "Comment 2...", ...]
result_array = predict_all_comments(model, all_comments, tokenizer, device)
# result_array即为N×K的布尔numpy数组

五、优化建议

  • 数据增强:对标注评论做同义词替换、随机裁剪、回译等,扩充训练数据,提升模型泛化能力。
  • 阈值调整:根据验证集效果调整预测阈值(不一定是0.5),平衡精准率和召回率。
  • 分层学习率:预训练模型部分用较小的学习率(如1e-5),全连接层用较大的学习率(如1e-4),避免预训练特征被破坏。
  • 模型轻量化:如果部署资源有限,可使用transformers提供的动态量化方法压缩模型体积。

内容的提问来源于stack exchange,提问作者Shrayani Mondal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:57:43