示例代碼:
# Generate Keywords
import torch
import os
from tqdm import tqdm
import json
import nltk
import numpy as npfrom span_marker import SpanMarkerModelmodel = SpanMarkerModel.from_pretrained("tomaarsen/span-marker-mbert-base-multinerd")
model.cuda()
# pipe = pipeline("token-classification", model="jasminejwebb/KeywordIdentifier", aggregation_strategy="simple",device= 'cuda')# Function to write a dictionary to a JSON file
def wr_dict(filename, dic):data = []if os.path.isfile(filename):with open(filename, 'r') as f:data = json.load(f)data.append(dic)with open(filename, 'w') as f:json.dump(data, f)# Function to remove a file
def rm_file(file_path):if os.path.exists(file_path):os.remove(file_path)with open('datasource/news_filter_fact_out_same.json', 'r') as file:data = json.load(file)save_path = 'datasource/news_filter_entity.json'
rm_file(save_path)
save_list = []fact_count = sum(len(d['fact_list']) for d in data)
print(f'Before: {fact_count}')# Run inference
for item in tqdm(data):fact_list = item['fact_list']item['fact_key'] = []for sample in fact_list:facts = {}sample = sample.strip()if not sample.endswith('.'):continue facts['fact'] = sampletokens = nltk.word_tokenize(sample)length = len(tokens)if length<18:continueentity_list = []entities = model.predict(sample)for e in entities:entity_list.append(e['span'])if len(entity_list)==0:continue# stripped_text = []# for group in generated_text:# if group['entity_group'] == 'LABEL_1':# stripped_text.append(group['word'].strip())# generated_text = generated_text[0]['generated_text']# generated_text = generated_text.split(',')stripped_text = [text.strip() for text in entity_list]print(stripped_text)facts['keywords'] = stripped_text# RAKE# rake_nltk_var.extract_keywords_from_text(sample)# keywords = rake_nltk_var.get_ranked_phrases()# print(facts['keywords'])item['fact_key'].append(facts)# print(item['fact_key'])save_list.append(item)with open(save_path, "w") as json_file:json.dump(save_list, json_file)fact_count = sum(len(d['fact_key']) for d in data)
print(f'After: {fact_count}')
代碼的目的是:用實體識別模型提取每一條事實性句子的關鍵詞(實體),并保存到 JSON 文件中。
代碼的結構和運行流程:
🔧 一、模型加載
from span_marker import SpanMarkerModel
model = SpanMarkerModel.from_pretrained("tomaarsen/span-marker-mbert-base-multinerd")
model.cuda()
- 使用了
SpanMarker
這個庫,它是一種更先進的實體識別方法(NER),相比傳統的 BIO 標注性能更高。 tomaarsen/span-marker-mbert-base-multinerd
是一個已經訓練好的多語言實體識別模型。.cuda()
表示把模型加載到 GPU 上,加快推理速度。
📂 二、數據準備
with open('datasource/news_filter_fact_out_same.json', 'r') as file:data = json.load(file)
- 這一步讀取已經過濾并處理好的新聞數據,每一項
data[i]
是一條新聞,里面有多個事實性句子(fact)。
{"title": "...","fact_list": ["xxx.", "yyy.", ...]
}
🧹 三、清理舊文件 + 初始化變量
save_path = 'datasource/news_filter_entity.json'
rm_file(save_path)
save_list = []
rm_file
刪除舊的結果文件(如果存在)。save_list
用來保存新生成的數據。
📊 四、統計原始句子數量
fact_count = sum(len(d['fact_list']) for d in data)
print(f'Before: {fact_count}')
- 統計一共多少個“事實性句子”準備處理。
🔁 五、主循環(核心邏輯)
for item in tqdm(data):
對每一條新聞循環:
1. 拿出其中的事實性句子列表:
fact_list = item['fact_list']
item['fact_key'] = []
2. 對每個句子進行處理:
for sample in fact_list:sample = sample.strip()if not sample.endswith('.'):continue
- 只處理以英文句號結尾的句子(
.endswith('.')
)。
tokens = nltk.word_tokenize(sample)if len(tokens) < 18:continue
- 用
nltk
對句子進行分詞,句子太短(小于 18 個詞)就跳過,避免提取沒意義的實體。
3. 用模型預測實體:
entities = model.predict(sample)for e in entities:entity_list.append(e['span'])
- 用
span-marker
模型提取實體。 - 每個實體是一個
e['span']
字段(即:這段文本里的實體字符串)。 - 例如句子中可能識別出:
['United States', 'Donald Trump', 'White House']
4. 保存實體
facts = {'fact': sample, 'keywords': stripped_text}item['fact_key'].append(facts)
- 保存格式是:
{"fact": "原始句子","keywords": ["實體1", "實體2", ...]
}
💾 六、最終保存
save_list.append(item)
with open(save_path, "w") as json_file:json.dump(save_list, json_file)
- 把每一條新聞及其抽取出的實體(關鍵詞)保存到
news_filter_entity.json
文件中。
📈 七、統計處理后數據量
fact_count = sum(len(d['fact_key']) for d in data)
print(f'After: {fact_count}')
- 輸出提取成功的句子數量。
🔚 總結
步驟 | 作用 |
---|---|
加載模型 | 用 SpanMarker 加載多語言實體識別模型 |
讀取數據 | 加載事實性句子列表 |
循環處理 | 每條句子判斷格式、長度,使用模型提取實體 |
保存數據 | 每條句子提取到的實體寫入 JSON 文件 |
? 輸出格式(簡化):
{"title": "Some News","fact_list": [...],"fact_key": [{"fact": "Joe Biden visited China on Tuesday.","keywords": ["Joe Biden", "China", "Tuesday"]},...]
}