竞赛 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现

news2024/12/23 22:35:19

文章目录

  • 0 前言
  • 1 项目背景
  • 2 算法架构
  • 3 FP-Growth算法原理
    • 3.1 FP树
    • 3.2 算法过程
    • 3.3 算法实现
      • 3.3.1 构建FP树
    • 3.4 从FP树中挖掘频繁项集
  • 4 系统设计展示
  • 5 最后

0 前言

🔥 优质竞赛项目系列,今天要分享的是

基于FP-Growth的新闻挖掘算法系统的设计与实现

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

1 项目背景

如今新闻泛滥,令人眼花缭乱,即使同一话题下的新闻也多得数不胜数。人们可以根据自己的职业和爱好关注专业新闻网站的不同热点要闻。因此,通过对人们关注新闻的热点问题进行分析,可以得出民众对某个领域的关切程度和社会需要解决的问题,也有利于了解当前的舆论焦点,有助于政府了解民意,便于国家对舆论进行正确引导,使我们的社会更加安定和谐。本文以财经领域为例,通过爬虫技术抓取网络上的大量财经新闻,通过对新闻内容文本进行预处理及密度聚类分析来发现热点;从发现的热点中,再进行词汇聚类分析,得出热点所涉及的人或事物,以此分析出社会对经济领域关注的问题和需要解决的问题。

在这里插入图片描述

2 算法架构

该项目学长要通过文本挖掘技术进行新闻热点问题分析,把从网上抓取到的财经新闻,通过对新闻内容的聚类,得到新闻热点;再对热点进行分析,通过对某一热点相关词汇的聚类,得到热点问题所涉及的人物、行业或组织等。

在这里插入图片描述
1、利用新闻 API、爬虫算法、多线程并行技术,抓取三大专业财经新闻网站(新浪财经、搜狐财经、新华网财经)的大量财经新闻报道;

2、对新闻进行去重、时间段过滤,然后对新闻内容文本进行 jieba
分词并词性标注,过滤出名词、动词、简称等词性,分词前使用自定义的用户词词典增加分词的准确性,分词后使用停用词词典、消歧词典、保留单字词典过滤掉对话题无关并且影响聚类准确性的词,建立每篇新闻的词库,利用
TF-IDF 特征提取之后对新闻进行 DBSCAN 聚类,并对每个类的大小进行排序;

3、针对聚类后的每一类新闻,为了得到该处热点的话题信息,还需要提取它们的标题,利用 TextRank
算法,对标题的重要程度进行排序,用重要性最高的标题来描述该处热点的话题

4、对所有的新闻内容进行 jieba 分词,并训练出 word2vec 词嵌入模型,然后对聚类后的每一类新闻,提取它们的内容分词后的结果,运用
word2vec 模型得到每个词的词向量,再利用 FP-Growth类算法进行相关新闻挖掘。

3 FP-Growth算法原理

3.1 FP树

FP树是一种存储数据的树结构,如下图所示,每一路分支表示数据集的一个项集,数字表示该元素在某分支中出现的次数

在这里插入图片描述

3.2 算法过程

1 构建FP树

  • 遍历数据集获得每个元素项的出现次数,去掉不满足最小支持度的元素项
  • 构建FP树:读入每个项集并将其添加到一条已存在的路径中,若该路径不存在,则创建一条新路径(每条路径是一个无序集合)

2 从FP树中挖掘频繁项集

  • 从FP树中获得条件模式基
  • 利用条件模式基构建相应元素的条件FP树,迭代直到树包含一个元素项为止

算法过程写得比较简略,具体过程我们在下节的实操中进一步理解。

3.3 算法实现

3.3.1 构建FP树



    class treeNode:
        def __init__(self,nameValue,numOccur,parentNode):
            self.name=nameValue #节点名
            self.count=numOccur #节点元素出现次数
            self.nodeLink=None #存放节点链表中,与该节点相连的下一个元素
            self.parent=parentNode
            self.children={} #用于存放节点的子节点,value为子节点名
        
        def inc(self,numOccur):
            self.count+=numOccur
        
        def disp(self,ind=1):
            print("   "*ind,self.name,self.count) #输出一行节点名和节点元素数,缩进表示该行节点所处树的深度
            for child in self.children.values():
                child.disp(ind+1) #对于子节点,深度+1
    
    # 构造FP树
    # dataSet为字典类型,表示探索频繁项集的数据集,keys为各项集,values为各项集在数据集中出现的次数
    # minSup为最小支持度,构造FP树的第一步是计算数据集各元素的支持度,选择满足最小支持度的元素进入下一步
    def createTree(dataSet,minSup=1):
        headerTable={}
    
        #遍历各项集,统计数据集中各元素的出现次数
        for key in dataSet.keys():
            for item in key:
                headerTable[item]=headerTable.get(item,0)+dataSet[key] 
                
        #遍历各元素,删除不满足最小支持度的元素
        for key in list(headerTable.keys()):
            if headerTable[key]<minSup:
                del headerTable[key]
        freqItemSet=set(headerTable.keys())
        
        #若没有元素满足最小支持度要求,返回None,结束函数
        if len(freqItemSet)==0:
            return None,None
        for key in headerTable.keys():
            headerTable[key]=[headerTable[key],None] #[元素出现次数,**指向每种项集第一个元素项的指针**]
        retTree=treeNode("Null Set",1,None) #初始化FP树的顶端节点
        
        for tranSet,count in dataSet.items():
            localD={} #存放每次循环中的频繁元素及其出现次数,便于利用全局出现次数对各项集元素进行项集内排序
            for item in tranSet:
                if item in freqItemSet:
                    localD[item]=headerTable[item][0]
            if len(localD)>0:
                orderedItems=[v[0] for v in sorted(localD.items(),key=operator.itemgetter(1),reverse=True)] #根据元素全局出现次数对每个项集(tranSet)中的元素进行排序
                updateTree(orderedItems,retTree,headerTable,count) #使用排序后的项集对树进行填充
        return retTree,headerTable


    #树的更新函数
    #items为按出现次数排序后的项集,是待更新到树中的项集;count为items项集在数据集中的出现次数
    #inTree为待被更新的树;headTable为头指针表,存放满足最小支持度要求的所有元素
    def updateTree(items,inTree,headerTable,count):
        #若项集items当前最频繁的元素在已有树的子节点中,则直接增加树子节点的计数值,增加值为items[0]的出现次数
        if items[0] in inTree.children: 
            inTree.children[items[0]].inc(count)
        else:#若项集items当前最频繁的元素不在已有树的子节点中(即,树分支不存在),则通过treeNode类新增一个子节点
            inTree.children[items[0]]=treeNode(items[0],count,inTree)
            #若新增节点后表头表中没有此元素,则将该新增节点作为表头元素加入表头表
            if headerTable[items[0]][1]==None: 
                headerTable[items[0]][1]=inTree.children[items[0]]
            else:#若新增节点后表头表中有此元素,则更新该元素的链表,即,在该元素链表末尾增加该元素
                updateHeader(headerTable[items[0]][1],inTree.children[items[0]])
        #对于项集items元素个数多于1的情况,对剩下的元素迭代updateTree
        if len(items)>1:
            updateTree(items[1::],inTree.children[items[0]],headerTable,count)


    #元素链表更新函数
    #nodeToTest为待被更新的元素链表的头部
    #targetNode为待加入到元素链表的元素节点
    def updateHeader(nodeToTest,targetNode):
        #若待被更新的元素链表当前元素的下一个元素不为空,则一直迭代寻找该元素链表的末位元素
        while nodeToTest.nodeLink!=None: 
            nodeToTest=nodeToTest.nodeLink #类似撸绳子,从首位一个一个逐渐撸到末位
        #找到该元素链表的末尾元素后,在此元素后追加targetNode为该元素链表的新末尾元素
        nodeToTest.nodeLink=targetNode



测试

#加载简单数据集
def loadSimpDat():
    simpDat = [['r', 'z', 'h', 'j', 'p'],
               ['z', 'y', 'x', 'w', 'v', 'u', 't', 's'],
               ['z'],
               ['r', 'x', 'n', 'o', 's'],
               ['y', 'r', 'x', 'z', 'q', 't', 'p'],
               ['y', 'z', 'x', 'e', 'q', 's', 't', 'm']]
    return simpDat

#将列表格式的数据集转化为字典格式
def createInitSet(dataSet):
    retDict={}
    for trans in dataSet:
        retDict[frozenset(trans)]=1
    return retDict

simpDat=loadSimpDat()
dataSet=createInitSet(simpDat)
myFPtree1,myHeaderTab1=createTree(dataSet,minSup=3)
myFPtree1.disp(),myHeaderTab1

输入数据:

在这里插入图片描述
由此数据集构建的FP树长这样,看看是不是满足上一节介绍的FP树结构

在这里插入图片描述

3.4 从FP树中挖掘频繁项集

具体过程如下:

1 从FP树中获得条件模式基

  • 条件模式基:以所查找元素项为结尾的路径集合,每条路径都是一条前缀路径,路径集合包括前缀路径和路径计数值。
  • 例如,元素"r"的条件模式基为 {x,s}2,{z,x,y}1,{z}1
  • 前缀路径:介于所查找元素和树根节点之间的所有内容
  • 路径计数值:等于该条前缀路径的起始元素项(即所查找的元素)的计数值

2 利用条件模式基构建相应元素的条件FP树

  • 对每个频繁项,都要创建一棵条件FP树。
  • 例如对元素t创建条件FP树:使用获得的t元素的条件模式基作为输入,利用构建FP树相同的逻辑构建元素t的条件FP树

3 迭代步骤(1)(2),直到树包含一个元素项为止

  • 接下来继续构建{t,x}{t,y}{t,z}对应的条件FP树(tx,ty,tz为t条件FP树的频繁项集),直到条件FP树中没有元素为止

  • 至此可以得到与元素t相关的频繁项集,包括2元素项集、3元素项集。。。

    #由叶节点回溯该叶节点所在的整条路径
    #leafNode为叶节点,treeNode格式;prefixPath为该叶节点的前缀路径集合,列表格式,在调用该函数前注意prefixPath的已有内容
    def ascendTree(leafNode,prefixPath):
        if leafNode.parent!=None:
            prefixPath.append(leafNode.name)
            ascendTree(leafNode.parent,prefixPath)
            
    #获得指定元素的条件模式基
    #basePat为指定元素;treeNode为指定元素链表的第一个元素节点,如指定"r"元素,则treeNode为r元素链表的第一个r节点
    def findPrefixPath(basePat,treeNode):
        condPats={} #存放指定元素的条件模式基
        while treeNode!=None: #当元素链表指向的节点不为空时(即,尚未遍历完指定元素的链表时)
            prefixPath=[]
            ascendTree(treeNode,prefixPath) #回溯该元素当前节点的前缀路径
            if len(prefixPath)>1:
                condPats[frozenset(prefixPath[1:])]=treeNode.count #构造该元素当前节点的条件模式基
            treeNode=treeNode.nodeLink #指向该元素链表的下一个元素
        return condPats
    
    #有FP树挖掘频繁项集
    #inTree: 构建好的整个数据集的FP树
    #headerTable: FP树的头指针表
    #minSup: 最小支持度,用于构建条件FP树
    #preFix: 新增频繁项集的缓存表,set([])格式
    #freqItemList: 频繁项集集合,list格式
    
    def mineTree(inTree,headerTable,minSup,preFix,freqItemList):
        #按头指针表中元素出现次数升序排序,即,从头指针表底端开始寻找频繁项集
        bigL=[v[0] for v in sorted(headerTable.items(),key=lambda p:p[1][0])] 
        for basePat in bigL:
            #将当前深度的频繁项追加到已有频繁项集中,然后将此频繁项集追加到频繁项集列表中
            newFreqSet=preFix.copy()
            newFreqSet.add(basePat)
            print("freqItemList add newFreqSet",newFreqSet)
            freqItemList.append(newFreqSet)
            #获取当前频繁项的条件模式基
            condPatBases=findPrefixPath(basePat,headerTable[basePat][1])
            #利用当前频繁项的条件模式基构建条件FP树
            myCondTree,myHead=createTree(condPatBases,minSup)
            #迭代,直到当前频繁项的条件FP树为空
            if myHead!=None:
                mineTree(myCondTree,myHead,minSup,newFreqSet,freqItemList)
    

接着刚才构建的FP树,测试一下,

freqItems=[]
mineTree(myFPtree1,myHeaderTab1,3,set([]),freqItems)
freqItems

我们从FP树中挖掘到的频繁项集如下,这里设置的最小支持度为3:

在这里插入图片描述
上图表示数据集中,支持度大于3(出现3次以上)的元素项集,即,频繁项集。

4 系统设计展示

为了方便操作及理解,学长使用 Python 的 tkinter 模块设计了一个系统操作界面

在这里插入图片描述

分析可视化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(未完待续。。。。)

5 最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1203224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

短剧软件APP开发方案

一、项目概述 短剧软件APP是一款集创作、拍摄、观看短剧于一体的移动应用。用户可以随时随地创作自己的短剧&#xff0c;也可以观看其他用户创作的短剧。本方案将详细介绍短剧软件APP的开发流程。 二、需求分析 在开发短剧软件APP之前&#xff0c;需要进行详细的需求分析。通…

MS321V/358V/324V低压、轨到轨输入输出运放

MS321V/MS358V/MS324V 是单个、两个和四个低压轨到轨输 入输出运放&#xff0c;可工作在幅度为 2.7V 到 5V 的单电源或者双电源条件 下。在低电源、空间节省和低成本应用方面是最有效的解决方案。 这些放大器专门设计为低压工作&#xff08; 2.7V 到 5V &#xff09;…

采集标准Docker容器日志:部署阿里云Logtail容器以及创建Logtail配置,用于采集标准Docker容器日志

文章目录 引言I 预备知识1.1 LogtailII 查询语法2.1 具体查询语法2.2 查询示例2.3 设置token时间(登录过期时间)see also引言 I 预备知识 1.1 Logtail Logtail是日志服务提供的日志采集Agent,用于采集阿里云ECS、自建IDC、其他云厂商等服务器上的日志。本文介绍Logtail的功…

飞天使-django概念之urls

urls 容易搞混的概念&#xff0c;域名&#xff0c;主机名&#xff0c;路由 网站模块多主机应用 不同模块解析不同的服务器ip地址 网页模块多路径应用 urlpatterns [ path(‘admin/’, admin.site.urls), path(‘’, app01views.index), path(‘movie/’, app01views.movi…

记一次线上问题引发的对 Mysql 锁机制分析

背景 最近双十一开门红期间组内出现了一次因 Mysql 死锁导致的线上问题&#xff0c;当时从监控可以看到数据库活跃连接数飙升&#xff0c;导致应用层数据库连接池被打满&#xff0c;后续所有请求都因获取不到连接而失败 整体业务代码精简逻辑如下&#xff1a; Transaction p…

探索向量数据库 | 重新定义数据存储与分析

随着大模型带来的应用需求提升&#xff0c;最近以来多家海外知名向量数据库创业企业传出融资喜讯。 随着AI时代的到来&#xff0c;向量数据库市场空间巨大&#xff0c;目前处于从0-1阶段&#xff0c;预测到2030年&#xff0c;全球向量数据库市场规模有望达到500亿美元&#xff…

软文推广中媒体矩阵的优势在哪儿

咱们日常生活中是不是经常听到一句俗语&#xff0c;不要把鸡蛋放在同一个篮子里&#xff0c;其实在广告界这句话也同样适用&#xff0c;媒介矩阵是指企业在策划广告活动时&#xff0c;有目的、有计划的利用多种媒体进行广告传播&#xff0c;触达目标用户。今天媒介盒子就来和大…

管理压力:打工人不难为打工人

写在前面 让时间回到2018年7月末&#xff1a; 事件地点&#xff1a;中国平安办公室 事件经过&#xff1a; 平安产品经理提出一个需求&#xff0c;要求APP开发人员根据用户手机壳自动调整颜色的主题。这个需求被程序员认为是不合理的。双方开始争论&#xff0c;情绪激动&…

私域电商:构建商业新模式的必要性

随着互联网的快速发展&#xff0c;传统的电子商务模式已经无法满足企业对于个性化、精准化服务的需求。在这样的背景下&#xff0c;私域电商应运而生&#xff0c;为企业提供了新的商业机会和增长点。本文将探讨私域电商的必要性及其构建商业新模式的影响。 一、私域电商的概念 …

【Python基础】网络编程之Epoll使用一(符实操:基于epoll实现的实时聊天室)

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

轻盈创新,气膜体育馆

气膜体育馆采用高强度、高柔性的薄膜材料为主要构建元素。其制作过程包括将膜材的外沿固定在地面基础或屋顶结构周边&#xff0c;并搭配智能化的机电设备&#xff0c;通过吹气实现室内空间的密闭。利用密闭空间内的气压支撑原理&#xff0c;当室内气压大于外部气压时&#xff0…

介绍公司的软文怎么写

软文推广成为企业提高知名度和市场竞争力的主要方式之一&#xff0c;通过软文推广&#xff0c;公司能够被更多消费者熟知并在他们心中留下深刻印象&#xff0c;一篇好的软文&#xff0c;不仅能传递公司的产品和服务信息&#xff0c;还可以传递出公司的理念、文化等&#xff0c;…

postgresql数据库优化

目录 概要 优化方法 硬件知识 CPU及服务器体系结构 内存 硬盘 文件系统及I/O调优 文件系统的崩溃恢复 Ext2文件系统 Ext3文件系统 Ext4文件系统 XFS文件系统 Barriers I/O I/O调优的方法 SSD的Trim优化 数据库性能视图 Linux监控工具 数据库内存优化 大页内存配置 vacuum…

C++:对象成员方法的使用

首先复习一下const : //const: //Complex* const pthis1 &ca; //约束指针自身 不能指向其他对象 // pthis1 &cb; err //pthis1->real; //const Complex* const pthis1 &ca;//指针指向 指针自身 都不能改 //pthis1->real; 只可读 …

Jenkins 搭建

GitLab GitLab安装 https://gitlab.cn/install/?versionce CentOS 下安装 1. 安装和配置必须的依赖项 在 CentOS 7上&#xff0c;下面的命令也会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您打算仅从本地网络访问极狐GitLab&#xf…

网易有道上线“易魔声” 开源语音合成引擎 用户可免费下载使用

网易有道上线“易魔声” 开源语音合成引擎 用户可免费下载使用 刚刚&#xff0c;我们上线了「易魔声」开源语音合成&#xff08;TTS&#xff09;引擎&#xff01;&#x1f389;&#x1f389;&#x1f389; 「易魔声」&#xff0c;是一款有道自研TTS引擎&#xff0c;目前支持中…

PNAS | 蛋白质结构预测屈服于机器学习

今天为大家介绍的是来自James E. Rothman的一篇短文。今年的阿尔伯特拉斯克基础医学研究奖表彰了AlphaFold的发明&#xff0c;这是蛋白质研究历史上的一项革命性进展&#xff0c;首次提供了凭借序列信息就能够准确预测绝大多数蛋白质的三维氨基酸排列的实际能力。这一非凡的成就…

react函数式组件props形式子向父传参

父组件中定义 子组件中触发回调传值 import { useState } from "react"; function Son(params) {const [count, setCount] useState(0);function handleClick() {console.log(params, paramsparamsparamsparamsparamsparams);params.onClick(111)setCount(count 1…

leetcode每日一题复盘(11.13~11.19)

leetcode 435 无重叠区间 本题和射气球最小箭数大同小异&#xff0c;但是这一题没做出来&#xff0c;难就难在题目如何理解:移除区间最小数量&#xff0c;使剩下的区间不重叠 那么本质上就是求最少有多少个重叠区间&#xff0c;把重叠区间去掉剩下的区间即不重叠 这里有两种做…

智慧工地管理云平台源码,Spring Cloud +Vue+UniApp

智慧工地源码 智慧工地云平台源码 智慧建筑源码支持私有化部署&#xff0c;提供SaaS硬件设备运维全套服务。 互联网建筑工地&#xff0c;是将互联网的理念和技术引入建筑工地&#xff0c;从施工现场源头抓起&#xff0c;最大程度的收集人员、安全、环境、材料等关键业务数据&am…