import paddle
2from paddlenlp.transformers import ErnieTokenizer, ErnieModel
3import numpy as np
4import json
5
6# 设置PaddlePaddle的全局随机种子
7paddle.seed(1234)
8
9# 初始化分词器
10tokenizer = ErnieTokenizer.from_pretrained('ernie-3.0-tiny-medium-v2-zh')
11
12# 初始化模型
13model = ErnieModel.from_pretrained('ernie-3.0-tiny-medium-v2-zh')
14
15# 确保模型处于评估模式
16model.eval()
17
18# 禁用模型的Dropout层(如果有的话)
19for layer in model.sublayers():
20 if isinstance(layer, paddle.nn.Dropout):
21 layer.train = False
22
23request_body = '{"data":[{"text": "想看销售的统计分析情况 智能销售"}]}'
24request_json = json.loads(request_body)
25texts = [item["text"] for item in request_json["data"]]
26
27# 存储所有句子的嵌入及其对应的原始文本
28sentence_embeddings = []
29sentences = []
30
31# 对每个句子进行循环处理
32for text in texts:
33 # 对句子进行编码
34 encoded_input = tokenizer(text, padding=True, truncation=True, return_tensors='paddle', max_seq_length=512)
35 input_ids = encoded_input['input_ids']
36
37 # 获取模型的隐藏状态输出
38 with paddle.no_grad(): # 不计算梯度,加快计算速度
39 outputs = model(input_ids)
40
41 # 假设我们取每个序列的最后一个隐藏状态作为句子的表示
42 sentence_embedding = outputs[0][0, -1, :]
43 sentence_embeddings.append(sentence_embedding.numpy())
44 sentences.append(text)
45
46# 将每个NumPy数组转换为Python列表
47sentence_embeddings_python_list = [embedding.tolist() for embedding in sentence_embeddings]
48
49# 打印包含所有句子嵌入及对应文本的Python字典
50data_dict = {
51 "sentences": sentences,
52 "vectors": sentence_embeddings_python_list
53}
54print(json.dumps(data_dict, ensure_ascii=False))
使用PaddlePaddle和Ernie模型来计算文本数据的向量表示。整体流程大致正确,但存在一些可以优化的地方。以下是对您的代码进行点评和提出优化建议:
-
模型配置:您已经设置了全局随机种子、禁用了Dropout层,并确保模型处于评估模式。这些都是正确的做法。
-
处理请求体:您通过
json.loads()
解析请求体并提取出所有待处理的文本。这部分代码没有问题。 -
编码文本:
- 您使用了
padding=True
和truncation=True
,这会自动对文本进行填充或截断以适应模型的最大长度限制(默认为512)。但是,对于Ernie模型,建议明确指定max_seq_length
参数(而不是max_length
),以保持与模型预期输入的一致性。 - 对于
return_tensors='pd'
,应改为return_tensors='paddle'
,以确保返回的张量类型与PaddlePaddle兼容。
- 您使用了
-
获取句子向量:
- 您选择每个序列的最后一个隐藏状态作为句子的表示。这是常见的做法之一,尤其是对于分类或问答任务。然而,对于语义相似度计算或聚类等任务,可能需要考虑其他方法,如取所有隐藏状态的均值或池化操作(如[CLS] token的隐藏状态)。
-
向量转换与输出:
- 将句子向量从NumPy数组转换为Python列表是合理的,以便将结果以JSON格式返回。
- 在构建最终输出的
data_dict
时,建议添加一个键(如sentences
)存储原始文本,以便用户能够对应地理解每个向量所代表的句子。
--------------------------------------------------------------------------------------------------------------
在深度学习编程中,`model.eval()` 是一个常见的方法调用,用于将神经网络模型切换到评估(evaluation)模式。这个操作通常是针对已经训练好的模型,在进行预测、验证或者测试阶段时进行的。以下是关于 `model.eval()` 的详细说明:
**作用**:
- **关闭 Dropout 和 Batch Normalization 的随机性**:在训练过程中,Dropout 层和 Batch Normalization 层通常引入随机性以增强模型的泛化能力。Dropout 在每次前向传播时随机丢弃一部分神经元输出,而 Batch Normalization 则依赖于当前 mini-batch 的均值和方差进行标准化。然而,在评估或预测时,我们希望结果是确定性的,不受随机因素影响。因此,切换到评估模式后,Dropout 层会保留所有神经元输出(相当于 dropout rate 设置为 0),Batch Norma