from collections import Counter import numpy as np import pandas as pd import torch import matplotlib.pyplot as plt from sklearn.metrics import accuracy_score, classification_report from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC from torch.utils.data import DataLoader, Dataset from tqdm import tqdm from transformers import AutoTokenizer, BertModel import joblib from sklearn.metrics import confusion_matrix import seaborn as sns # 1. ====================== 配置参数 ====================== MODEL_PATH = r'D:\pythonProject5\bert-base-chinese' BATCH_SIZE = 64 MAX_LENGTH = 128 SAVE_DIR = r'D:\pythonProject5\BSVMC_model' DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 2. ====================== 数据加载与划分 ====================== def load_data(file_path): """加载并预处理数据""" df = pd.read_csv(file_path).dropna(subset=['text', 'label']) texts = df['text'].astype(str).str.strip().tolist() labels = df['label'].astype(int).tolist() return texts, labels # 加载原始数据 texts, labels = load_data("train3.csv") # 第一次拆分:分出测试集(20%) train_val_texts, test_texts, train_val_labels, test_labels = train_test_split( texts, labels, test_size=0.2, stratify=labels, random_state=42 ) # 第二次拆分:分出训练集(70%)和验证集(30% of 80% = 24%) train_texts, val_texts, train_labels, val_labels = train_test_split( train_val_texts, train_val_labels, test_size=0.3, # 0.3 * 0.8 = 24% of original stratify=train_val_labels, random_state=42 ) # 3. ====================== 文本编码 ====================== tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH) def encode_texts(texts): return tokenizer( texts, truncation=True, padding="max_length", max_length=MAX_LENGTH, return_tensors="pt" ) # 编码所有数据集 train_encodings = encode_texts(train_texts) val_encodings = encode_texts(val_texts) test_encodings = encode_texts(test_texts) # 4. ====================== 数据集类 ====================== class TextDataset(Dataset): def __init__(self, encodings, labels): self.encodings = encodings self.labels = labels def __getitem__(self, idx): return { 'input_ids': self.encodings['input_ids'][idx], 'attention_mask': self.encodings['attention_mask'][idx], 'labels': torch.tensor(self.labels[idx]) } def __len__(self): return len(self.labels) # 创建所有数据集加载器 train_dataset = TextDataset(train_encodings, train_labels) val_dataset = TextDataset(val_encodings, val_labels) test_dataset = TextDataset(test_encodings, test_labels) train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle=False) test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False) # 5. ====================== 特征提取 ====================== def extract_features(bert_model, dataloader): """使用BERT提取CLS特征""" bert_model.eval() all_features = [] all_labels = [] with torch.no_grad(): for batch in tqdm(dataloader, desc="提取特征"): inputs = {k: v.to(DEVICE) for k, v in batch.items() if k != 'labels'} outputs = bert_model(**inputs) features = outputs.last_hidden_state[:, 0, :].cpu().numpy() all_features.append(features) all_labels.append(batch['labels'].numpy()) return np.vstack(all_features), np.concatenate(all_labels) # 加载并冻结BERT模型 bert_model = BertModel.from_pretrained(MODEL_PATH).to(DEVICE) for param in bert_model.parameters(): param.requires_grad = False # 提取所有特征 print("\n" + "=" * 30 + " 特征提取阶段 " + "=" * 30) train_features, train_labels = extract_features(bert_model, train_loader) val_features, val_labels = extract_features(bert_model, val_loader) test_features, test_labels = extract_features(bert_model, test_loader) # 6. ====================== 特征预处理 ====================== scaler = StandardScaler() train_features = scaler.fit_transform(train_features) # 只在训练集上fit val_features = scaler.transform(val_features) test_features = scaler.transform(test_features) # 7. ====================== 训练SVM ====================== print("\n" + "=" * 30 + " 训练SVM模型 " + "=" * 30) svm_model = SVC( kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42 ) svm_model.fit(train_features, train_labels) # 8. ====================== 评估模型 ====================== def evaluate(features, labels, model, dataset_name): preds = model.predict(features) acc = accuracy_score(labels, preds) print(f"\n[{dataset_name}] 评估结果:") print(f"准确率:{acc:.4f}") print(classification_report(labels, preds, digits=4)) return preds print("\n训练集评估:") _ = evaluate(train_features, train_labels, svm_model, "训练集") print("\n验证集评估:") val_preds = evaluate(val_features, val_labels, svm_model, "验证集") print("\n测试集评估:") test_preds = evaluate(test_features, test_labels, svm_model, "测试集") # 9. ====================== 保存模型 ====================== def save_pipeline(): """保存完整模型管道""" # 创建保存目录 import os os.makedirs(SAVE_DIR, exist_ok=True) # 保存BERT相关 bert_model.save_pretrained(SAVE_DIR) tokenizer.save_pretrained(SAVE_DIR) # 保存SVM和预处理 joblib.dump(svm_model, f"{SAVE_DIR}/svm_model.pkl") joblib.dump(scaler, f"{SAVE_DIR}/scaler.pkl") # 保存标签映射(假设标签为0: "中性", 1: "正面", 2: "负面") label_map = {0: "中性", 1: "正面", 2: "负面"} joblib.dump(label_map, f"{SAVE_DIR}/label_map.pkl") print(f"\n模型已保存至 {SAVE_DIR} 目录") save_pipeline() # 10. ===================== 可视化 ====================== plt.figure(figsize=(15, 5)) # 决策值分布 plt.subplot(1, 2, 1) plt.plot(svm_model.decision_function(train_features[:100]), 'o', alpha=0.5) plt.title("训练集前100样本决策值分布") plt.xlabel("样本索引") plt.ylabel("决策值") # 生成混淆矩阵 cm = confusion_matrix(y_true=test_labels, y_pred=test_preds) # 可视化 plt.figure(figsize=(10, 7)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['中性', '正面', '负面'], yticklabels=['中性', '正面', '负面']) plt.xlabel('Predicted label') plt.ylabel('True label') plt.title('confusion matrix') plt.show() # 准确率对比 plt.subplot(1, 2, 2) accuracies = [ accuracy_score(train_labels, svm_model.predict(train_features)), accuracy_score(val_labels, val_preds), accuracy_score(test_labels, test_preds) ] labels = ['train', 'Validation', 'test'] plt.bar(labels, accuracies, color=['blue', 'orange', 'green']) plt.ylim(0, 1) plt.title("Comparison of accuracy rates for each dataset") plt.ylabel("Accuracy rate") plt.tight_layout() plt.show()关于这个模型,直接画一下我的模型架构图
时间: 2025-06-05 20:47:12 浏览: 31
<think>嗯,用户想根据提供的代码绘制模型架构图,特别是包含BERT特征提取和SVM分类器的组合结构。首先,我需要确认用户的具体需求。他们可能已经有一个使用BERT提取特征然后用SVM进行分类的代码,但需要将整个流程可视化。用户之前的问题是关于如何获取现有的模型架构图,现在他们转向如何自己绘制架构图,特别是结合BERT和SVM的结构。需要回顾之前的回答,确保一致性。之前的回答提到了论文插图、开源代码库和工具如torchviz,但现在用户需要的是根据代码生成架构图,可能需要不同的方法。
接下来,我需要考虑如何将BERT和SVM的组合结构可视化。BERT作为特征提取器,输出CLS token的向量,然后SVM进行分类。架构图需要展示输入文本经过BERT处理,提取特征,再输入到SVM中。可能需要分步骤说明:数据流向、模型组件、连接方式。用户可能不熟悉绘图工具,所以需要推荐几种工具,比如draw.io、PowerPoint、Inkscape,或者代码生成工具如Netron、torchviz。同时,结合代码示例,说明如何用Python代码生成计算图,比如使用torchviz,但需要注意BERT和SVM的结合部分可能需要自定义。还需要考虑用户提供的代码是否完整。用户提到“根据提供的代码”,但实际提问中没有给出代码,所以可能需要假设一个示例代码,展示BERT提取特征后输入SVM的过程,并基于该代码生成架构图。例如,使用PyTorch或Hugging Face的BERT模型,提取CLS token,然后训练SVM。另外,用户可能对如何将两个不同框架的模型结合起来有疑问,比如BERT可能在PyTorch中,而SVM使用scikit-learn,这需要在图中标明不同的框架部分。同时,特征提取后的维度变化也是需要注意的细节,比如BERT输出768维向量,SVM输入该向量。还要注意用户提到的系统指令,比如数学公式的正确使用,引用文献的标注。例如,在解释BERT时,可能需要引用原始论文,但用户提供的引用[1]是关于fasttext和fine-tuning的模型,需要确认是否相关。不过用户提到引用仅供参考,应更多关注他们当前的问题,所以可能不需要过多依赖引用,除非直接相关。最后,生成相关问题时要围绕绘制架构图、模型组合结构、工具使用等,例如如何导出高清图,如何处理不同框架的模型,以及如何优化架构图的可读性。</think>### 基于代码的模型架构图绘制方法(BERT+SVM组合)
#### 一、代码与架构对应关系分析
假设已有以下典型代码结构:
```python
from transformers import BertModel
from sklearn.svm import SVC
# BERT特征提取
bert = BertModel.from_pretrained("bert-base-uncased")
inputs = tokenizer(text, return_tensors="pt")
outputs = bert(**inputs)
features = outputs.last_hidden_state[:, 0, :] # CLS token特征$ \in \mathbb{R}^{768} $[^1]
# SVM分类
svm = SVC(kernel="rbf")
svm.fit(features.detach().numpy(), labels)
```
#### 二、架构图关键组件绘制
1. **输入层**
- 文本输入序列(图示建议:文本框+箭头)
2. **BERT特征提取层**
- Token Embedding矩阵(形状:$ [seq\_len, 768] $)
- Transformer Encoder堆叠结构(标注层数:12层)
- CLS Token特征提取(红色高亮向量)
3. **SVM分类层**
- 高维空间映射(图示核函数$ K(x_i,x_j) = e^{-\gamma\|x_i-x_j\|^2} $)
- 决策边界(超平面分离示意图)
#### 三、可视化工具与代码
1. **手动绘制工具**
- draw.io(推荐架构模板:[AI Model Template](https://www.draw.io/?template=Neural_Network))
- PowerPoint(插入形状标注维度)
2. **代码生成工具**
```python
# 生成BERT部分计算图
from torchviz import make_dot
x = torch.randn(1, 512) # 模拟输入
dot = make_dot(bert(x).last_hidden_state, params=dict(bert.named_parameters()))
dot.render("bert_arch") # 生成graphviz文件
# SVM部分需手动添加标注
```
(包含维度转换标注)
#### 四、典型架构图要素
| 组件 | 标注要求 | 示例值 |
|----------------|-----------------------------|-----------------------|
| BERT输入 | 最大序列长度 | max_length=512 |
| 特征维度 | CLS向量维度 | hidden_size=768 |
| SVM核函数 | 数学表达式 | $ K(x,z) = e^{-\gamma\|x-z\|^2} $ |
| 数据流向 | 箭头方向+维度变化 | 512 tokens → 768D |
---
### 相关问题
1. 如何将PyTorch的BERT特征与scikit-learn的SVM结合时避免内存泄漏[^1]?
2. 在架构图中如何清晰展示不同框架(PyTorch/scikit-learn)的模块边界?
3. 使用CLS token以外的特征提取方式(如平均池化)是否需要修改架构图?
4. 如何导出高清矢量图用于论文发表?
5. 模型架构图中是否必须标注所有超参数(如BERT层数、SVM gamma值)?
---
如需具体工具配置说明或代码调试帮助,可提供实际代码片段进一步分析。
阅读全文
相关推荐



















