🔥博客主页:是dream
🚀系列专栏:深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发
💘每日语录:每一步都算数,即使你觉得前进得缓慢,你仍在超越那些停滞不前的人。
🎉感谢大家点赞👍收藏⭐指正✍️
目录
🚀🚀🚀感谢关注我的CSDN博客,更多自然语言处理技巧和应用,请持续关注!
一、句法分析
1. 句法分析简介
句法分析是自然语言处理的核心技术,它帮助我们解析句子的结构和词汇之间的关系。句法分析可以分为两种主要类型:句法结构分析和依存句法分析。
1.1 句法结构分析(也叫短语结构分析或成分句法分析)
句法结构分析的主要任务是识别句子中的短语结构和各个短语之间的层次句法关系。这种分析通常使用形式语法,如上下文无关文法(CFG)或树邻接文法(TAG)等。在这种分析中,句子被分解成一个个短语,例如名词短语(NP)或动词短语(VP),并建立它们之间的层次关系。虽然句法结构分析提供了一种详细的句子结构描述,但由于复杂性,其准确率可能不高。
1.2 依存句法分析
依存句法分析的任务是确定句子中词汇之间的依存关系,即词汇与其它词汇之间的句法依赖关系。在依存句法分析中,每个词汇都被标记为一个节点,这些节点之间通过依存关系连接起来,构成一个依存树。依存树的根节点通常是句子的核心动词,而其他词汇以不同方式依赖于核心动词。这种方法更为常用,因为它提供了相对简洁的句子结构表示,并且在实际应用中表现出更好的性能。
二、实例
题目:给定待抽取商品标签的热水器评论数据comment.csv(其中“评论”列保存了用户对该品牌热水器的评论),从数据集中随机选取2000篇文档,采用句法分析技术抽取各条评论数据的关键标签(如价格便宜、质量不错等),并进行统计,最后输出出现频率最高的20种标签。
2.1 分析
采用依存句法分析的步骤如下:
1、抽取文档:首先,从一个CSV文件中读取所有数据。将这一列的数据存储到一个列表中。然后,随机选择2000个文档,这可以通过生成2000个随机数来选择对应的文档索引。
2、句法分析:使用LTP(语言技术平台)或其他适合的工具对这2000个文档进行分词和依存句法分析。将分词结果和句法分析结果分别存储到两个不同的列表中。这将帮助你理解文档中词汇之间的依存关系。
3、合并关键词:在句法分析的结果中,你可以提取出主谓关系、状中关系、定中关系和动补关系等关键的依存关系。这些关系可以帮助你抽取出文档中的重要信息。将这些关键词和关系合并起来,以便后续的关系抽取或分析。
对抽取到的关系进行统计的实现流程分析如下:
据顾客的评论来了解商品的使用情况,并直观地判断商品的好坏,通常需要执行以下流程:
1、提取关键标签:首先,从顾客评论中提取关键标签或关键词汇,这些标签应当能够反映出商品的关键特征和用户体验。这可以通过自然语言处理技术如分词、词性标注、实体识别等来实现。提取后的关键标签将帮助你理解评论的内容。
2、统计关键标签的词频:创建一个空字典或计数器,用于统计每个关键标签的出现频率。遍历顾客评论,并将关键标签与它们的频次存储在字典中。这一步骤有助于了解哪些标签在评论中出现得最频繁。
3、排序标签:基于标签的词频,对关键标签进行排序,通常按照词频从高到低排序。这将使你能够识别出在评论中被提及最频繁的标签。
4、选择前20种标签:从排序后的标签列表中选择出现频率最高的前20种标签。这些标签可能代表了顾客对商品的最常见评价和关注点。
2.2 代码
2.2.1 抽取文档
def data_load(file_path):
data = pd.read_csv(file_path) # 读取文件中所有数据
# 按列分离数据
x = data[['评论']] # 读取某一列
data_list = x.values.tolist() # 将csv文件中的评论这一列存放到列表中
# 随机选取2000个数
list = [random.randint(0, len(x) - 1) for _ in range(2000)]
document = []
# 随机选取的2000个评论
for i in range(2000):
num = list[i]
document.append(data_list[num])
return document
基于pandas.read_csv读取csv文件中的所有数据,按列分离数据后,基于values.tolist函数将其放入data_list列表中。
2.2.2 句法分析
def ltp_analysis():
ltp = LTP(path="small") # 默认加载 Small 模型
# ltp = LTP(path="small")
# 其中 path 可接受的路径为下载下来的模型或者解压后的文件夹路径
final_dep = []
final_seg = []
for i in range(2000):
seg, hidden = ltp.seg(document[i]) # 分词
# print(hidden)
# pos = ltp.pos(hidden)
# ner = ltp.ner(hidden)
dep = ltp.dep(hidden) # 语义依存关系 句法分析
final_dep.append(dep)
final_seg.append(seg)
# print(dep)
# print(finally_seg)
# print(finally_dep)
final_sent = []
final_dep0 = []
for i in range(2000):
sent = final_seg[i][0]
dep0 = final_dep[i][0]
# print(sent)
# print(dep0)
final_sent.append(sent)
final_dep0.append(dep0)
return final_seg, final_dep, final_sent, final_dep0
使用LTP对2000个文档进行分词和句法分析,并将结果存储到两个不同的列表中。具体操作如下:对这2000个文档分别进行分词,使用LTP中的ltp.seg()函数进行分词操作。分词的结果将存储在一个名为seg的列表中。接着,对这2000个文档进行句法分析,使用LTP中的ltp.dep()函数进行句法分析操作。句法分析的结果将存储在一个名为dep的列表中。
2.2.3 合并关键词
def combine_keywords(final_seg, final_dep, final_dep0):
pos_dict = {'SBV': '主谓关系',
'ATT': '定中关系',
'VOB': '动宾关系',
'ADV': '状中关系',
'CMP': '动补关系',
'IOB': '间宾关系',
}
finally_word = []
for i in range(2000):
for w1, w2, r in final_dep0[i]:
sent = final_seg[i][0]
dep0 = final_dep[i][0]
if r == 'SBV':
# print(sent[w1-1],sent[w2-1],pos_dict[r])
if (w2 - 1, w2, 'ADV') in final_dep0[i]:
if (w1 - 1, w1, 'ATT') in final_dep0[i]:
str1 = sent[w1 - 1 - 1] + sent[w1 - 1] + sent[w2 - 1 - 1] + sent[w2 - 1]
# print(str1)
finally_word.append(str1)
# print(sent[w1-1-1] ,sent[w1-1],sent[w2-1-1],sent[w2-1] )
else:
str2 = sent[w1 - 1] + sent[w2 - 1 - 1] + sent[w2 - 1]
# print(str2)
finally_word.append(str2)
# print(sent[w1-1],sent[w2-1-1],sent[w2-1] )
if r == 'CMP':
str3 = sent[w2 - 1] + sent[w1 - 1]
# print(str3)
finally_word.append(str3)
# print(sent[w2-1],sent[w1-1])
return finally_word
将句子中的主谓、状中、定中、动补关系提取出来,并合并关键词。
2.2.4 词频统计
wordcount = {}
for word in final_word:
wordcount[word] = wordcount.get(word, 0) + 1
frequences = sorted(wordcount.items(), key=lambda x: x[1], reverse=True)[:20]
print(frequences)
对文本中单词出现频率的统计和排序操作。首先,通过遍历文本,统计每个单词的出现次数,并将结果存储在一个字典中。然后,使用排序函数对这个字典按照单词出现的频率进行排序,最后选择前20个频率最高的单词。
2.3 结果
2.4 优缺点分析
2.4.1 采用句法分析进行标签抽取的优缺点
优点:句法分析可以准确地找到句子中的关键成分,有助于提取准确的标签和关系,尤其适用于处理复杂的语言结构和模糊的语料。
缺点: 不一定连续,句法分析可能会导致标签不一定是连续的,这可能增加后续处理的复杂性。 句法分析的难度较高,其准确率有待提升,尤其对于某些语言或复杂句子,可能存在误差。
2.4.2 依存语法相对于短语结构语法的优点
简洁性:依存语法的表示形式相对简洁,易于理解和标注,不需要像短语结构语法那样定义大量的语法规则。
语义关系:依存语法可以轻松表示词语之间的语义关系,有助于语义分析、信息抽取等任务,使得处理语义信息更方便。
高效解码:依存语法通常具有更高效的解码算法,这在大规模文本处理中尤为重要。
灵活性:依存语法可以更灵活地表示一些语句,不受严格的短语结构规则限制,适用于各种类型的语言。
2.5 全部代码(结合新版本的ltp-已更)
# 读入文档
import pandas as pd
import numpy as np
import random
"""
函数:提取分词,语义依存关系分析
return: 处理后的句子和其对应的语义依存关系分析结果
"""
from ltp import LTP
def data_load(file_path):
data = pd.read_csv(file_path)
print(data.head())
x = data[['评论']]
data_list = x.values.tolist()
indices = random.sample(range(len(x)), 1000) # 随机选取1000条评论
document = [data_list[i] for i in indices]
return document
def ltp_analysis(document):
ltp = LTP() # 加载模型
final_dep = []
final_seg = []
for i in range(len(document)):
text = document[i][0] # 提取文本内容
result = ltp.pipeline([text], tasks=["cws", "dep"]) # 分词和依存句法分析
seg = result.cws # 分词结果
dep = result.dep # 依存句法分析结果
final_dep.append(dep)
final_seg.append(seg)
final_sent = []
final_dep0 = []
for i in range(len(final_seg)):
sent = final_seg[i]
dep0 = final_dep[i]
final_sent.append(sent)
final_dep0.append(dep0)
return final_seg, final_dep, final_sent, final_dep0
def combine_keywords(final_seg, final_dep, final_dep0):
pos_dict = {
'SBV': '主谓关系',
'ATT': '定中关系',
'VOB': '动宾关系',
'ADV': '状中关系',
'CMP': '动补关系',
'IOB': '间宾关系',
}
finally_word = []
for i in range(len(final_dep0)): # 遍历每条句子的依存信息
sent = final_seg[i][0] # 获取当前句子的分词
dep_info = final_dep0[i] # 当前句子的依存信息,应该是一个字典的列表
for j, item in enumerate(dep_info): # 遍历依存信息中的每一条关系
head = item.get('head', [])
label = item.get('label', [])
if not isinstance(head, list) or not isinstance(label, list) or len(head) != len(label):
print(f"Skipping malformed dependency: {item}")
continue
for idx, (h, l) in enumerate(zip(head, label)): # 遍历 head 和 label 的每一对
if l in pos_dict: # 如果当前关系在目标关系字典中
w1 = h - 1 # head 指向的单词索引
w2 = idx # 当前单词索引
if w1 >= 0 and w2 >= 0 and w1 < len(sent) and w2 < len(sent): # 确保索引有效
if l == 'SBV': # 主谓关系
str2 = sent[w1] + sent[w2]
finally_word.append(str2)
elif l == 'CMP': # 动补关系
str3 = sent[w2] + sent[w1]
finally_word.append(str3)
return finally_word
if __name__ == '__main__':
document = data_load(file_path=r'D:\MyUI\comment.csv')
finally_seg, finally_dep, finally_sent, finally_dep0 = ltp_analysis(document)
final_word = combine_keywords(finally_seg, finally_dep, finally_dep0)
print(final_word)
wordcount = {}
for word in final_word:
wordcount[word] = wordcount.get(word, 0) + 1
frequences = sorted(wordcount.items(), key=lambda x: x[1], reverse=True)[:20]
print(frequences)