赞
踩
对于一段话,具有表征它描述内容的,可以称之为主题词。
这些都可以成为关键词,也就是说一句话可以有多个关键词,例如:
这样一句话,我们认为,王小二、山顶、求婚可以称之为主题词。
作为用来进行计算机进行数据挖掘的材料,比较显然的是,通过一段描述性的话,是很难进行的。而用主题词来表征一句话的含义,可以很好的实现相关信息的查找。
主题词的提取,在这里我们基于TF-IDF算法来实现。
核心思想:词的重要性,可以被量化,通过分值的高低,实现主题词的提取。
算法实现的也就是词的重要性打分,而TF-IDF算法,也可以看作TF*IDF
也就是TF分
(比较好理解,一个词在语句中出现的次数很多,那么它可能比较重要)
和IDF分
(它的意思是,在多个语句中都出现词,像的、地、得这样的助词,没有实在的含义,基本不会成为主题词)
那么将TF值与IDF值相乘,所得到的TF*IDF则可以作为这个词在该句中的一个评分量化,进而根据设置阈值,大于这个阈值的词成为该句的主题词(所以一个句子,可以有多个主题词,也可以没有)
使用python语言的实现过程
使用的是csv文件
结构如下:
Description就是我们要处理的语句内容,在每一行的第7列(后面用6进行索引,列表计数从0开始),下面写个代码,读取一下
import csv # 读取数据 with open('attacks.csv', 'r', encoding='UTF-8') as csv文件: 文件内容 = csv.reader(csv文件) 文件内容列表 = list(文件内容) # print(文件内容列表) pass # 列表存储词条 大词条库 = [] def 删除字符函数(输入0): """ :param 输入0: 待处理的字符串 :return: 删除无用字符后的字符串 """ 删除字符 = "()[],.'&-…/1234567890:" 处理 = 输入0 for i in 删除字符: 处理 = 处理.replace(i, ' ') # 由于 " 无法和 "" 同时出现,这里再进行一次删除后返回 return 处理.replace('"', ' ') for 序号0, 记录 in enumerate(文件内容列表): """ 记录[6]:即Description下的语句字符串 删除字符函数(记录[6]):返回删除了无关字符的字符串 删除字符函数(记录[6]).split(' '):以 " " 空格进行字符串划分, 返回一个分割成字符的列表 然后添加进大词条库 """ 大词条库.append( 删除字符函数(记录[6]).split(' ')) """ 当取出语句字符串后,将它删除,以便之后存入选好的主题词列表 判断语句表示表头Description不做改动 """ if 序号0 != 0: 文件内容列表[序号0].remove(记录[6])
效果
至此,我们得到了待处理的语句词条大列表了,其中每一个小列表,都是一条语句的词汇内容。
这里完成了对词在语句中个数、以及词出现过的句子的数目的统计
class 我的tf_idf类: def __init__(self, 待处理大词条库, TFIDF阈值=0.3, 频繁模式阈值=0.2): """ :param 待处理大词条库: 2维列表形式,第一维列表保存有一个段字库 """ self.初始大词条库 = 待处理大词条库 self.语句总数 = len(待处理大词条库) self.总词条词频库 = [] self.总词条单词评分库 = [] self.词在句出现总频库 = {} self.TFIDF阈值 = TFIDF阈值 self.总词条主题词库 = [] self.频繁模式阈值 = 频繁模式阈值 self.频繁模式表 = [] def 语句词库(self, 词条分词库): """ :param 词条分词库: 输入的是一条语句的词汇列表 :return: 返回该词汇列表各个词汇的词频统计字典 以及self.词在句出现总频库 这个是统计词汇在各个语句中出现的情况 """ """ 词条词频库:使用字典进行词频统计,字典使用字符串(称为键)进行索引,得到键值, 键值反复被键(也就是某个词汇)索引累加,完成词频统计 重复记录:在完成语句词频的统计时,也完成了对这个词在语句中出现的次数, 由于一句只统计一次,所以需要在此记录一下,是否这个词在该列表被统计过了 """ 词条词频库 = {} 重复记录 = [] for 单词 in 词条分词库: """ 这里出现的try/except都是为了做一件事, try:给字典里面的字符串键值加1, except:这个键不在字典里,则添加进去,初始化键值为1 """ try: 词条词频库[单词] += 1 """ 若单词在重复记录出现了,则跳过 若没有,则记录入重复记录列表 同时在self.词在句出现总频库中给这个词汇的键值加1 """ if 单词 in 重复记录: pass else: 重复记录.append(单词) try: self.词在句出现总频库[单词] += 1 except: self.词在句出现总频库.update({单词: 1}) pass except: 词条词频库.update({单词: 1}) """ 若单词在重复记录出现了,则跳过 若没有,则记录入重复记录列表 同时在self.词在句出现总频库中给这个词汇的键值加1 """ if 单词 in 重复记录: pass else: 重复记录.append(单词) try: self.词在句出现总频库[单词] += 1 except: self.词在句出现总频库.update({单词: 1}) pass return 词条词频库 pass def 文本词库(self): """ :return: None """ """ 对每条语句词库重复调用 在self.总词条词频库记录所有的语句以及其词频 """ for 词条 in self.初始大词条库: self.总词条词频库.append(self.语句词库(词条)) pass
完成了词汇数目的统计,下面的算法就很容易了
def tf_idf函数(self, 单词条频库): """ :param 单词条频库: 输入单词条评分 :return: 无 """ """ 这里还使用了self.词在句出现总频库, 也就是查找词在某些句子中出现的语句数 """ 单词评分库 = {} 词总数 = sum(list(单词条频库.values())) for 单词 in 单词条频库: 单词TF分数 = 单词条频库[单词] / 词总数 单词IDF分数 = log(self.语句总数 / (self.词在句出现总频库[单词] + 1)) 单词评分库.update({单词: 单词TF分数 * 单词IDF分数}) return 单词评分库 def tf_idf加速函数(self): self.总词条单词评分库 = list(map(self.tf_idf函数, self.总词条词频库)) pass def tf_idf阈值划分(self, 单词条评分): """ :param 单词条评分: 输入单词条评分库 :return: """ 主题词 = {} for 词汇 in 单词条评分: if 单词条评分[词汇] >= self.TFIDF阈值: 主题词.update({词汇: 单词条评分[词汇]}) pass pass return 主题词 def tf_idf阈值划分加速函数(self): """ 对 tf_idf阈值划分调用 :return: 无 """ self.总词条主题词库 = list(map(self.tf_idf阈值划分, self.总词条单词评分库)) pass
至此,需要的处理结果就提取到了
这里包括了TF-IDF的算法结果,还有基于不同语义下的等价类划分,直观的讲,就是将一些列抽出来,组成集合,再在集合内去除重复元素
import csv from math import log from tqdm import tqdm # 读取数据 with open('attacks.csv', 'r', encoding='UTF-8') as csv文件: 文件内容 = csv.reader(csv文件) 文件内容列表 = list(文件内容) # print(文件内容列表) pass # 列表存储词条 大词条库 = [] 大词条库 = [] 时间国家库 = [] 时间城市库 = [] 情报词库 = [] def 删除字符函数(输入0): """ :param 输入0: 待处理的字符串 :return: 删除无用字符后的字符串 """ 删除字符 = "()[],.'&-…/1234567890:" 处理 = 输入0 for i in 删除字符: 处理 = 处理.replace(i, ' ') # 由于 " 无法和 "" 同时出现,这里再进行一次删除后返回 return 处理.replace('"', ' ') for 序号0, 记录 in enumerate(文件内容列表): """ 记录[6]:即Description下的语句字符串 删除字符函数(记录[6]):返回删除了无关字符的字符串 删除字符函数(记录[6]).split(' '):以 " " 空格进行字符串划分, 返回一个分割成字符的列表 然后添加进大词条库 """ 大词条库.append( 删除字符函数(记录[6]).split(' ')) """ 当取出语句字符串后,将它删除,以便之后存入选好的主题词列表 判断语句表示表头Description不做改动 """ if 序号0 != 0: 文件内容列表[序号0].remove(记录[6]) class 我的tf_idf类: def __init__(self, 待处理大词条库, TFIDF阈值=0.3, 频繁模式阈值=0.2): """ :param 待处理大词条库: 2维列表形式,第一维列表保存有一个段字库 """ self.初始大词条库 = 待处理大词条库 self.语句总数 = len(待处理大词条库) self.总词条词频库 = [] self.总词条单词评分库 = [] self.词在句出现总频库 = {} self.TFIDF阈值 = TFIDF阈值 self.总词条主题词库 = [] self.频繁模式阈值 = 频繁模式阈值 self.频繁模式表 = [] def 语句词库(self, 词条分词库): """ :param 词条分词库: 输入的是一条语句的词汇列表 :return: 返回该词汇列表各个词汇的词频统计字典 以及self.词在句出现总频库 这个是统计词汇在各个语句中出现的情况 """ """ 词条词频库:使用字典进行词频统计,字典使用字符串(称为键)进行索引,得到键值, 键值反复被键(也就是某个词汇)索引累加,完成词频统计 重复记录:在完成语句词频的统计时,也完成了对这个词在语句中出现的次数, 由于一句只统计一次,所以需要在此记录一下,是否这个词在该列表被统计过了 """ 词条词频库 = {} 重复记录 = [] for 单词 in 词条分词库: """ 这里出现的try/except都是为了做一件事, try:给字典里面的字符串键值加1, except:这个键不在字典里,则添加进去,初始化键值为1 """ try: 词条词频库[单词] += 1 """ 若单词在重复记录出现了,则跳过 若没有,则记录入重复记录列表 同时在self.词在句出现总频库中给这个词汇的键值加1 """ if 单词 in 重复记录: pass else: 重复记录.append(单词) try: self.词在句出现总频库[单词] += 1 except: self.词在句出现总频库.update({单词: 1}) pass except: 词条词频库.update({单词: 1}) """ 若单词在重复记录出现了,则跳过 若没有,则记录入重复记录列表 同时在self.词在句出现总频库中给这个词汇的键值加1 """ if 单词 in 重复记录: pass else: 重复记录.append(单词) try: self.词在句出现总频库[单词] += 1 except: self.词在句出现总频库.update({单词: 1}) pass return 词条词频库 pass def 文本词库(self): """ :return: None """ """ 对每条语句词库重复调用 在self.总词条词频库记录所有的语句以及其词频 """ for 词条 in self.初始大词条库: self.总词条词频库.append(self.语句词库(词条)) pass def tf_idf函数(self, 单词条频库): """ :param 单词条频库: 输入单词条评分 :return: 无 """ """ 这里还使用了self.词在句出现总频库, 也就是查找词在某些句子中出现的语句条数 """ 单词评分库 = {} 词总数 = sum(list(单词条频库.values())) for 单词 in 单词条频库: 单词TF分数 = 单词条频库[单词] / 词总数 单词IDF分数 = log(self.语句总数 / (self.词在句出现总频库[单词] + 1)) 单词评分库.update({单词: 单词TF分数 * 单词IDF分数}) return 单词评分库 def tf_idf加速函数(self): self.总词条单词评分库 = list(map(self.tf_idf函数, self.总词条词频库)) pass def tf_idf阈值划分(self, 单词条评分): """ :param 单词条评分: 输入单词条评分库 :return: """ 主题词 = {} for 词汇 in 单词条评分: if 单词条评分[词汇] >= self.TFIDF阈值: 主题词.update({词汇: 单词条评分[词汇]}) pass pass return 主题词 def tf_idf阈值划分加速函数(self): """ 对 tf_idf阈值划分调用 :return: 无 """ self.总词条主题词库 = list(map(self.tf_idf阈值划分, self.总词条单词评分库)) pass def TFIDF(self): """ 启动函数 :return: 无 """ self.文本词库() self.tf_idf加速函数() self.tf_idf阈值划分加速函数() #################################################################################################################### # 词的TF_IDF的评分计算 #################################################################################################################### 工作啦 = 我的tf_idf类(大词条库, TFIDF阈值=0.35) 工作啦.TFIDF() print(工作啦.总词条主题词库) def 结果表格形式(): """ 这个函数是为了把原来删掉了Description的文件内容列表 填充进主题词列表,方便后面的主题词处理 同时把待选的时间国家库/时间城市库提取做好 :return: """ import pandas as pd for 序号1, 主题词 in enumerate(工作啦.总词条主题词库): if 序号1 != 0: 文件内容列表[序号1].append([]) if 主题词: for 主题词0 in 主题词: 文件内容列表[序号1][-1].append(主题词0) else: 文件内容列表[序号1][-1].append([]) 主题词提取 = pd.DataFrame(文件内容列表[1:], columns=文件内容列表[0]).drop(['index'], axis=1) print(主题词提取) for 序号3, 记录1 in enumerate(文件内容列表): # print(记录) if 记录1[6]: 时间国家库.append([记录1[1], 记录1[2]]) 时间城市库.append([记录1[1], 记录1[3]]) # print(主题词提取) 结果表格形式() #################################################################################################################### # 等价语义划分 #################################################################################################################### def 查询函数(输入列表, 新元素, 查询参数): """ 函数功能是解决一个问题,在将一个元素(可以是一个字符串,也可以是一个列表) 添加入新的列表时,先查询在这个列表是否存在了这个元素 :param 输入列表: 待被添加进新元素的原列表 :param 新元素: 待添加元素 :param 查询参数: 新元素的数据长度 :return: 布尔值: True: 未存在(即可以添加的意思) False: 已存在(就不添加了) """ index = 0 for 子元素 in 输入列表: 查询元素个数 = 0 for 查询元素个数 in range(查询参数): try: if 子元素[查询元素个数] == 新元素[查询元素个数]: 查询元素个数 += 1 except: pass if 查询元素个数 == 查询参数 and 查询元素个数 != 0: index += 1 break if index: return False else: return True #################################################################################################################### # 基于情报语义 def 情报语义事务(): """ 在从工作啦.总词条主题词库提取主题词至情报词库的过程中 同时,进行该词库是否在情报词库进行判断 :return: 无 """ """ tqdm库是可以显示处理进度的函数包 """ for 词条主题词 in tqdm(工作啦.总词条主题词库): if 词条主题词: if 查询函数(情报词库, list(词条主题词.keys()), len(词条主题词)): # good = list(词条主题词.keys()) 情报词库.append(list(词条主题词.keys())) 情报语义事务() print(情报词库) ######################################### # 基于时间国家语义 def 时间国家事务(): """ 在从时间国家库提取关键字组合(即时间和国家的组合) 至时间国家事务库0的过程中, 同时,进行该是否在时间国家事务库0进行判断 :return: 基于时间国家语义的时间国家事务库0 """ 时间国家事务库0 = [] for 序号2, 时间国家 in enumerate(时间国家库): if 序号2: if 查询函数(时间国家事务库0, 时间国家, 2): 时间国家事务库0.append(时间国家) return 时间国家事务库0 时间国家事务库 = 时间国家事务() print(时间国家事务库) ######################################### # 基于时间城市语义 def 时间城市事务(): """ 在从时间城市库提取关键字组合(即时间和城市的组合) 至时间城市事务库0的过程中, 同时,进行该是否在时间城市事务库0进行判断 :return: 基于时间城市语义的时间城市事务0 """ 时间城市事务库0 = [] for 序号3, 时间城市 in tqdm(enumerate(时间城市库)): if 序号3: if 查询函数(时间城市事务库0, 时间城市, 2): 时间城市事务库0.append(时间城市) return 时间城市事务库0 时间城市事务库 = 时间城市事务() print(时间城市事务库)
工作啦.总词条主题词库所打印的,就是最后的主题词提取结果
下接
数据挖掘(二) Apriori算法的python实现
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。