当前位置: 首页 > news >正文

传统机器学习与大模型 + Prompt 的对比示例

下面两段代码分别展示了传统机器学习和大模型 + Prompt 在文本分类任务上的实现方式,帮助你直观感受两者的差异。

传统机器学习方法(使用 BERT 微调)

traditional-ml-text-classification传统机器学习文本分类实现

import torch
from torch.utils.data import Dataset, DataLoader
from transformers import BertTokenizer, BertForSequenceClassification, AdamW
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd

# 1. 准备数据
data = {
    'text': [
        "我想预订明天的机票", "查询今天的天气", "帮我设置闹钟",
        "播放周杰伦的歌曲", "今天有什么新闻", "推荐几部科幻电影"
    ],
    'label': [0, 1, 2, 3, 4, 5]  # 0:订票, 1:天气, 2:闹钟, 3:音乐, 4:新闻, 5:电影
}
df = pd.DataFrame(data)

# 2. 数据集划分
train_df, val_df = train_test_split(df, test_size=0.2, random_state=42)

# 3. 创建数据集类
class TextClassificationDataset(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,
            add_special_tokens=True,
            max_length=self.max_len,
            return_token_type_ids=False,
            padding='max_length',
            truncation=True,
            return_attention_mask=True,
            return_tensors='pt'
        )
        
        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'label': torch.tensor(label, dtype=torch.long)
        }

# 4. 初始化tokenizer和模型
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertForSequenceClassification.from_pretrained(
    'bert-base-chinese',
    num_labels=6
)

# 5. 创建数据加载器
train_dataset = TextClassificationDataset(
    train_df['text'].values,
    train_df['label'].values,
    tokenizer
)
val_dataset = TextClassificationDataset(
    val_df['text'].values,
    val_df['label'].values,
    tokenizer
)

train_loader = DataLoader(train_dataset, batch_size=2, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=2)

# 6. 训练模型
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

optimizer = AdamW(model.parameters(), lr=2e-5)
epochs = 3

for epoch in range(epochs):
    model.train()
    train_loss = 0
    
    for batch in train_loader:
        input_ids = batch['input_ids'].to(device)
        attention_mask = batch['attention_mask'].to(device)
        labels = batch['label'].to(device)
        
        optimizer.zero_grad()
        outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
        loss = outputs.loss
        train_loss += loss.item()
        
        loss.backward()
        optimizer.step()
    
    avg_train_loss = train_loss / len(train_loader)
    print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_train_loss:.4f}")

# 7. 评估模型
model.eval()
predictions = []
true_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['label'].to(device)
        
        outputs = model(input_ids, attention_mask=attention_mask)
        preds = torch.argmax(outputs.logits, dim=1)
        
        predictions.extend(preds.cpu().numpy())
        true_labels.extend(labels.cpu().numpy())

accuracy = accuracy_score(true_labels, predictions)
print(f"Validation Accuracy: {accuracy:.4f}")

# 8. 保存模型
model.save_pretrained('./intent_classifier')
tokenizer.save_pretrained('./intent_classifier')
 

大模型 + Prompt 方法(使用 OpenAI API)

llm-prompt-text-classification大模型+Prompt文本分类实现

import openai
import json
from typing import List, Dict, Tuple

# 1. 设置API密钥(实际使用时需替换为你的密钥)
openai.api_key = "your-openai-api-key"

# 2. 定义意图分类器
class IntentClassifier:
    def __init__(self, intents: Dict[str, List[str]]):
        """
        初始化意图分类器
        
        Args:
            intents: 字典,键为意图名称,值为该意图的示例列表
        """
        self.intents = intents
        self.prompt_template = self._build_prompt_template()
    
    def _build_prompt_template(self) -> str:
        """构建分类Prompt模板"""
        intent_examples = []
        for intent_name, examples in self.intents.items():
            examples_str = "\n".join([f"- {ex}" for ex in examples])
            intent_examples.append(f"意图: {intent_name}\n示例:\n{examples_str}\n")
        
        intent_list = ", ".join(self.intents.keys())
        
        prompt = f"""
        你是一个文本意图分类器。请根据以下意图及其示例,对用户输入进行分类。
        
        可能的意图包括: {intent_list}
        
        各意图的示例:
        {"".join(intent_examples)}
        
        请对以下用户输入进行分类,只返回意图名称,不要有其他解释:
        """
        
        return prompt.strip()
    
    def classify(self, user_input: str) -> str:
        """
        使用大模型API对用户输入进行意图分类
        
        Args:
            user_input: 用户输入的文本
        
        Returns:
            预测的意图名称
        """
        full_prompt = f"{self.prompt_template}\n\n用户输入: {user_input}"
        
        try:
            response = openai.ChatCompletion.create(
                model="gpt-3.5-turbo",
                messages=[
                    {"role": "system", "content": "你是一个精确的意图分类器,只返回意图名称。"},
                    {"role": "user", "content": full_prompt}
                ],
                temperature=0.0,  # 降低随机性,提高分类准确性
                max_tokens=50
            )
            
            # 提取模型返回的意图
            predicted_intent = response.choices[0].message.content.strip()
            
            # 简单后处理:确保返回的是有效意图
            if predicted_intent in self.intents:
                return predicted_intent
            else:
                # 如果返回的不是有效意图,尝试映射或默认分类
                for intent_name in self.intents:
                    if intent_name.lower() in predicted_intent.lower():
                        return intent_name
                
                # 默认返回第一个意图(实际应用中应更智能地处理)
                return list(self.intents.keys())[0]
                
        except Exception as e:
            print(f"API调用错误: {e}")
            return list(self.intents.keys())[0]  # 出错时返回默认意图

# 3. 示例:使用Few-Shot方式定义意图
intents = {
    "订票": ["我想预订明天的机票", "查询从北京到上海的航班", "帮我订一张后天的火车票"],
    "天气": ["今天天气怎么样", "明天会下雨吗", "查询北京的气温"],
    "闹钟": ["设置早上7点的闹钟", "提醒我下午3点开会", "创建一个10分钟后的提醒"],
    "音乐": ["播放周杰伦的歌曲", "我想听流行音乐", "搜索陈奕迅的歌"],
    "新闻": ["今天有什么新闻", "最新的科技资讯", "查看国际新闻"],
    "电影": ["推荐几部科幻电影", "我想看动作片", "最近有什么新上映的电影"]
}

# 4. 创建分类器实例
classifier = IntentClassifier(intents)

# 5. 测试分类效果
test_inputs = [
    "我要预订后天去广州的飞机票",
    "今天上海的天气如何?",
    "帮我设置一个半小时后的提醒",
    "播放一首林俊杰的歌",
    "给我讲讲最近的体育新闻",
    "有哪些好看的悬疑电影推荐?"
]

for input_text in test_inputs:
    predicted_intent = classifier.classify(input_text)
    print(f"输入: {input_text}")
    print(f"预测意图: {predicted_intent}")
    print("-" * 30)

# 6. 处理新意图的方式(Zero-Shot)
def add_new_intent(classifier, intent_name, examples=None):
    """
    添加新意图(支持Zero-Shot或Few-Shot)
    
    Args:
        classifier: 分类器实例
        intent_name: 新意图名称
        examples: 新意图的示例列表(如果为None,则使用Zero-Shot)
    """
    if examples:
        # Few-Shot:添加示例并重建Prompt
        classifier.intents[intent_name] = examples
        classifier.prompt_template = classifier._build_prompt_template()
    else:
        # Zero-Shot:只需在使用时指定新意图
        pass
    
    return classifier

# 示例:添加一个新意图(Zero-Shot方式)
classifier = add_new_intent(classifier, "翻译", examples=["帮我把这句话翻译成英文", "中译英:我爱你", "翻译:Hello world"])

# 测试新意图
new_test = "将'人工智能很强大'翻译成英文"
print(f"输入: {new_test}")
print(f"预测意图: {classifier.classify(new_test)}")
 

对比分析

传统机器学习方法特点
  1. 数据依赖性强:需要准备标注好的训练集和验证集,示例中每个意图至少需要多个样本。
  2. 模型训练复杂
    • 需要定义数据集类、数据加载器
    • 涉及多轮训练、优化器设置、损失计算
    • 需要 GPU 加速以提高训练效率
  3. 模型适配成本高:新增意图需要重新训练整个模型。
  4. 优势:一旦训练完成,部署和推理成本较低,适合大规模生产环境。
大模型 + Prompt 方法特点
  1. 数据依赖性低:通过 Few-Shot 示例或 Zero-Shot 直接分类,无需大量标注数据。
  2. 实现简单
    • 只需构建结构化 Prompt
    • 调用 API 即可完成分类
    • 无需模型训练过程
  3. 灵活性高
    • 新增意图只需修改 Prompt,无需重新训练
    • 支持 Zero-Shot 学习,可快速适配新场景
  4. 成本与性能
    • 单次 API 调用成本较高
    • 响应速度受网络和 API 服务器影响
    • 适合小规模、快速迭代的应用场景

这两种方法各有优劣,实际应用中需要根据数据规模、实时性要求、成本限制等因素选择合适的方案。

http://www.xdnf.cn/news/975403.html

相关文章:

  • eureka如何绕过 LVS 的虚拟 IP(VIP),直接注册服务实例的本机真实 IP
  • SpringMVC异步处理Servlet
  • Wyn 商业智能与 3D 大屏的深度融合应用
  • 在ARM 架构的 Mac 上 更新Navicat到17后连接Oracle时报错:未加载 Oracle 库。
  • 高频面试之6Hive
  • 机器学习算法——集成学习
  • 电路图识图基础知识-变频器控制电动机系统解析(二十四)
  • 渗透测试PortSwigger Labs:遭遇html编码和转义符的反射型XSS
  • uniapp 云打包 iOS 应用上传到 app store 商店的过程
  • ZZU-ARM汇编语言实验 34
  • 【Rust UDP编程】rust udp编程方法解析与应用实战
  • uni-app bitmap.load() 返回 code=-100
  • XSP30是一款2~3节串联锂电池/锂离子电池升降压充电管理IC
  • Snipaste:轻量级截图,高效编辑
  • Spring中@Value注解:原理、加载顺序与实战指南
  • Springboot项目的目录结构
  • 西门子 SINAMICS S200伺服,重塑汽车焊接工艺新标准
  • 技术革新,EtherCAT转CAN网关,新能源汽车电池产线再升级
  • 汽车租赁小程序开发指南
  • Spark提交流程
  • SQL 注入:iBatis与修复
  • Charles里怎么进行断点调试
  • TripGenie:畅游济南旅行规划助手:团队工作纪实(十四)
  • 附加模块--Qt SQL模块功能及架构解析
  • SpringCloud系列 - Nacos 配置中心(二)
  • Hadoop 2.7.7 单机伪分布式安装与配置教程(JDK 8)
  • 如何设计三高架构
  • 小米玄戒O1架构深度解析(二):多核任务调度策略详解
  • 【系统设计【1】】系统设计面试方法论:从0到百万用户的需求到架构的推演
  • RPG24.设置武器伤害(二):将效果应用于目标