上述代码,构建隐私词库都不需要用到余弦相似度计算吗,就是输出微博文本数据中与种子词相似的词汇
时间: 2024-02-23 07:57:32 浏览: 21
是的,上述代码并没有使用余弦相似度计算来构建隐私词库。它使用了一种简单的基于规则的方法,通过匹配微博文本数据中的词汇和种子词库中的词汇进行匹配,并将匹配成功的词汇添加到隐私词库中。这种方法虽然简单,但是在一些场景下可能效果不太好,因为它无法发现那些与种子词汇语义相似但是表达方式不同的词汇。余弦相似度计算可以帮助我们发现这些语义相似的词汇,因此在一些场景下可能更为有效。
相关问题
实现一个代码:采用python、bert、transformers,基于隐私相关种子词和大量微博用户博文文本数据,计算余弦相似度,构建隐私词库。微调bert来训练自己的微博用户文本数据后获得词向量来计算相似度结果是不是更准确?是的话请帮我实现带有微调功能的代码
好的,下面是基于BERT微调的代码实现:
```python
import torch
import random
import numpy as np
import pandas as pd
import jieba
from transformers import BertTokenizer, BertForSequenceClassification, AdamW
from sklearn.metrics.pairwise import cosine_similarity
# 设置随机数种子
random.seed(42)
np.random.seed(42)
torch.manual_seed(42)
# 加载微博文本数据
text_data = []
with open("output/weibo2.txt", "r", encoding="utf-8") as f:
for line in f:
text_data.append(line.strip())
# 加载种子词
seed_words = ['教育经历']
# 加载BERT模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertForSequenceClassification.from_pretrained('bert-base-chinese', num_labels=1)
# 对微博文本进行分词和编码
def encode_text(text):
words = jieba.lcut(text.strip())
tokens = ["[CLS]"] + words + ["[SEP]"]
token_ids = tokenizer.convert_tokens_to_ids(tokens)
segment_ids = [0] * len(token_ids)
return token_ids, segment_ids
# 构建数据集
data = []
for text in text_data:
token_ids, segment_ids = encode_text(text)
data.append((token_ids, segment_ids))
# 定义微调函数
def fine_tune(model, data, epochs=5, batch_size=32, lr=2e-5):
optimizer = AdamW(model.parameters(), lr=lr)
model.train()
for epoch in range(epochs):
np.random.shuffle(data)
for i in range(0, len(data), batch_size):
batch = data[i:i+batch_size]
batch_token_ids = torch.tensor([x[0] for x in batch])
batch_segment_ids = torch.tensor([x[1] for x in batch])
batch_labels = torch.zeros(len(batch))
optimizer.zero_grad()
loss, _ = model(batch_token_ids, batch_segment_ids, labels=batch_labels)
loss.backward()
optimizer.step()
# 微调模型
fine_tune(model, data)
# 获取微调后的词向量
def get_word_embeddings(model, token_ids, segment_ids):
model.eval()
with torch.no_grad():
outputs = model(token_ids.unsqueeze(0), segment_ids.unsqueeze(0))
embeddings = outputs[0][0]
return embeddings
# 构建隐私词库
privacy_words = set()
seed_embeddings = get_word_embeddings(model, *encode_text(" ".join(seed_words)))
for text in text_data:
token_ids, segment_ids = encode_text(text)
for i in range(1, len(token_ids) - 1):
word = tokenizer.convert_ids_to_tokens([token_ids[i]])[0]
if word in seed_words:
continue
embeddings = get_word_embeddings(model, token_ids[i], segment_ids[i])
sim = cosine_similarity(embeddings.reshape(1, -1), seed_embeddings.reshape(1, -1))[0][0]
if sim > 0.8 and len(word) > 1:
privacy_words.add(word)
print(privacy_words)
```
这个代码首先对微博文本数据进行分词和编码,并使用BERT微调模型来训练这些数据,以获得微博文本数据的词向量。随后,使用这些词向量来计算每个词与种子词的相似度,并构建隐私词库。
首先,通过人工手动选取部分隐私相关词作为种子词,得到种子词列表;其次,利用BERT模型训练大量的微博用户文本语料和种子词列表中的一个种子词,获取词向量;然后,计算微博文本语料中每个中文词汇与已有种子词的余弦相似度,两个向量之间的余弦相似度越大说明它们关联度越高。最后,设置关联度阈值为0.85,语料中大于等于阈值0.85的词汇并且实际语义也是相近的才能被认为是相关隐私风险词,并与种子词一起纳入隐私词库中,词库达到一定规模后,过滤去重,形成最终的隐私词库。注意:我需要Tokenizer模型分词分的是中文,并不是分成单个字。帮我实现上述描述的代码,并且运行之后不要报错
以下是基于Python和Hugging Face Transformers库的代码实现:
```
from transformers import BertTokenizer, BertModel
import numpy as np
import pandas as pd
import jieba
# 加载BERT模型和tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertModel.from_pretrained('bert-base-chinese', output_hidden_states=True)
# 加载种子词列表
seed_words = ["身份证", "手机号码", "地址", "信用卡", "密码", "账号", "银行卡", "个人信息"]
# 加载微博用户文本语料
data = pd.read_csv('weibo_data.csv')
# 预处理微博用户文本语料
data['text'] = data['text'].apply(lambda x: jieba.lcut(x))
data['text'] = data['text'].apply(lambda x: ' '.join(x))
# 计算微博文本语料中每个中文词汇与已有种子词的余弦相似度,得到相关性矩阵
embeddings = []
for text in data['text']:
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
with torch.no_grad():
outputs = model(**inputs)
hidden_states = outputs[2]
token_vecs = hidden_states[-2][0]
embeddings.append(token_vecs.numpy())
embeddings = np.concatenate(embeddings, axis=0)
seed_embeddings = []
for word in seed_words:
inputs = tokenizer(word, return_tensors='pt')
with torch.no_grad():
outputs = model(**inputs)
hidden_states = outputs[2]
token_vecs = hidden_states[-2][0]
seed_embeddings.append(token_vecs.numpy())
seed_embeddings = np.concatenate(seed_embeddings, axis=0)
cosine_sim = np.dot(embeddings, seed_embeddings.T) / (np.linalg.norm(embeddings, axis=1)[:, None] * np.linalg.norm(seed_embeddings, axis=1))
# 确定关联度阈值
threshold = 0.85
# 确定相关隐私风险词
related_words = []
for i, text in enumerate(data['text']):
related_indices = np.argwhere(cosine_sim[i] >= threshold).flatten()
related_words += [tokenizer.convert_ids_to_tokens(inputs['input_ids'][0, j].item()) for j in related_indices]
# 过滤去重,形成最终的隐私词库
privacy_words = list(set([word for word in related_words if len(word) > 1]))
print(privacy_words)
```
上述代码中,我们首先加载了BERT模型和tokenizer,然后加载了种子词列表和微博用户文本语料。接着,我们对微博用户文本语料进行了预处理,使用tokenizer将文本转化为BERT模型所需的输入格式,并使用模型计算了微博文本语料中每个中文词汇与已有种子词的余弦相似度,得到相关性矩阵。然后,我们确定了关联度阈值,并根据阈值筛选出相关隐私风险词。最后,我们进行了去重处理,得到最终的隐私词库。
需要注意的是,上述代码中使用了jieba分词器对微博用户文本语料进行了分词处理,同时我们也在tokenizer中设置了`padding`和`truncation`参数,以确保输入的文本长度一致。如果你的微博用户文本语料已经分好词,则可以直接跳过分词处理步骤,将分好的词汇列表传递给tokenizer即可。