优化的解决方案:Hadoop数据收集系统—Flume
优采云 发布时间: 2022-12-20 16:54优化的解决方案:Hadoop数据收集系统—Flume
水槽OG
OG:《初代》
0.9.x 或 cdh3 及更早版本
由agent、collector、master等组件组成
水槽天然气
NG:“下一代”
1.x 或 cdh4 及更高版本
由Agent、Client等组件组成
为什么推出NG版本
简化代码
架构简化
Flume OG 基本架构
代理人
用于采集数据
产生数据流的地方
通常由两部分组成:source和sink
Source用于获取数据,可以从文本文件、syslog、HTTP等获取数据;
Sink将Source获取到的数据进一步传输给后续的Collector。
Flume 带有许多源和*敏*感*词*实现
系统日志 Tcp (5440) | agentSink("localhost",35856)
尾巴(“/etc/service_files”) | agentSink("localhost",35856)
集电极
汇总多个 Agent 结果
将汇总结果导入后端存储系统,如HDFS、HBase
Flume 带有许多采集器实现
采集器来源(35856) | 安慰
采集器来源(35856) | collectorSink("file:///tmp/flume/collected", "syslog");
采集器来源(35856) | collectorSink("hdfs://namenode/user/flume/","syslog");
代理与收款人往来
代理与收款人往来
可手动指定或自动匹配
在自动匹配的情况下,master会在采集器之间进行负载均衡。
问:为什么要引入Collector?
汇总Agent数据,避免生成过多的小文件;
避免多个代理连接对Hadoop造成过大的压力;
中间件,屏蔽了agent和hadoop的异构性。
掌握
管理和协调agent和collector的配置信息;
Flume集群的控制器;
跟踪数据流的最终确认信息并通知代理;
通常需要配置多个master来防止单点故障;
在 zookeeper 的帮助下管理多个 Master。
容错机制
三个可靠性级别
agentE2ESink[("机器"[, 端口])]
代理收到确认消息就认为数据发送成功,否则重试。
agentDFOSink[("机器"[, 端口])]
当agent发现采集器操作失败时,agent写入本地硬盘,待采集器恢复时重新发送数据。
agentBESink[("机器"[, 端口])]
效率是最好的。 代理不会在本地写入任何数据。 如果采集器发现处理失败,则直接删除该消息。
搭建基于Flume的数据采集系统
1. Agent和Collector都可以动态配置
2.可以通过命令行或网页界面进行配置
3.命令行配置
在启动的master节点上依次输入“flume shell”→“connect localhost”
比如执行exec config a1 'tailDir("/data/logfile")' 'agentSink'
4.网页界面
选择节点,填写source、sink等信息
通用架构示例——拓扑 1
agentA : tail("/ngnix/logs") | agentSink("采集器",35856);
agentB : tail("/ngnix/logs") | agentSink("采集器",35856);
agentC : tail("/ngnix/logs") | agentSink("采集器",35856);
agentD : tail("/ngnix/logs") | agentSink("采集器",35856);
agentE : tail("/ngnix/logs") | agentSink("采集器",35856);
agentF : tail("/ngnix/logs") | agentSink("采集器",35856);
采集器:采集器来源(35856)| collectorSink("hdfs://namenode/flume/","srcdata");
通用架构示例——拓扑 2
代理A:源| agentE2ESink("collectorA",35856);
代理B:源| agentE2ESink("collectorA",35856);
代理C:源| agentE2ESink("collectorB",35856);
代理D:源| agentE2ESink("collectorB",35856);
代理E:源| agentE2ESink("collectorC",35856);
代理F:源| agentE2ESink("collectorC",35856);
采集器A:采集器来源(35856)| collectorSink("hdfs://...","src");
采集器 B:采集器来源(35856)| collectorSink("hdfs://...","src");
采集器C:采集器来源(35856)| collectorSink("hdfs://...","src");
通用架构示例——拓扑 3
代理A:源| agentE2EChain("collectorA:35856","collectorB:35856");
代理B:源| agentE2EChain("collectorA:35856","collectorC:35856");
代理C:源| agentE2EChain("collectorB:35856","collectorA:35853");
代理D:源| agentE2EChain("collectorB:35853","collectorC:35853");
代理E:源| agentE2EChain("collectorC:35853","collectorA:35853");
代理F:源| agentE2EChain("collectorC:35853","collectorB:35853");
采集器A:采集器来源(35853)| collectorSink("hdfs://...","src");
采集器 B:采集器来源(35853)| collectorSink("hdfs://...","src");
采集器C:采集器来源(35853)| collectorSink("hdfs://...","src");
解决方法:停用词(Stop Words)的价值、收集与使用
摘要:停用词(Stop Words)是自然语言处理领域的重要工具,通常用来提高文本特征的质量,或者降低文本特征的维度。这里简单介绍一下停用词的由来和定义词,并以信息检索和主题建模的例子论证了停用词的价值,然后介绍了几种简单的停用词构造方法,最后给出
1 简介
当我刚接触自然语言处理时,我做的第一个动手任务是文本分类。 在构建特征时,我选择了词袋模型,按照课本上建议的方法,过滤掉词汇表中一些不重要的词,最终得到了千维(远小于中文词汇表的大小)特征。 特征工程的结果如表1-1所示。 老实说,过滤掉低分词后,分类器的性能有了很大的提升。
表1-1 词是否进入特征列表
序列号
字
分数
是否使用
1个
必须
555
是的
2个
给
222
不
3个
县长
666
是的
4个
一
233
不
5个
个别的
333
不
6个
惊喜
996
是的
……
……
……
……
这个练习让我意识到,在某些NLP任务中,有些词并不能提供有价值的信息,可以忽略不计。 这种情况在生活中也很常见。 当我们的任务是判断图1-1所示信息的友好度时,虽然橙色的“up”字很显眼,但帮助不大——我们只需要分析“我从来没见过这么厚颜无耻的.. ”,你就知道宰相是用嘴在骂人。
图1-1 丞相大杀(电视剧《三国志》)
在信息检索领域,我们将上述可以忽略的词称为停用词。
我们和机器在处理文本时忽略停用词的操作是否合理? 这个操作是怎么来的? 有没有一套方法可以帮助我们合理判断停用词呢? 这篇文章就是对这些问题的简单回答。
二、停止词的价值与应用
在计算机科学发展的早期,先辈们的一项重要任务就是设计一个足够优秀的信息检索系统,以支持大家从成千上万的文档中找到自己需要的。 HP Luhn 叔叔 (Uncle HP Luhn, 1957) 发现在我们的交流中,有些词比其他词携带更重要的信息。 Luhn(1958)改变了思路,认为我们在表达信息时,会用到一些出现频率高但与“噪音”一样不重要的词。 后来的学者给这个高频低价值的词起了个名字,就是上面说的“停用词”。
停用词提出后,经过从业者几十年的发展,几乎应用于每一个信息检索系统。
2.1 停用词和信息检索系统
如表 3-1 所示,假设我们的文档库中只有 3 个文档。 一般来说,我们会使用倒排索引来存储文档特征与文档编号的映射关系,从而实现一个比较快速的信息检索系统。 如表2-2所示,就是我为表2-1所示的文档库建立的倒排索引。 看来这种倒排索引不但不会提高检索速度,反而会增加检索的复杂度——随着文档库规模的增大,倒排索引的作用会逐渐由负向正向转变。
表2-1 文档库内容
文件号码
文件内容
分词结果
1个
神木是个好地方。
榆林/of/Shenmu/是/一个/好/地方/。
2个
神木的红烧肉很好吃。
神木/的/干烧红烧肉/好/香/。
3个
神木中学是一所好学校。
莎木中学/是/一所/好/学校/。
表2-2 倒排索引的内容
钥匙
价值
玉林
[1]
的
[1,2]
神木
[1, 2]
是的
[1,3]
个别的
[1,3]
这很好
[1,2,3]
地方
[1]
.
[1,2,3]
红烧肉
[2]
可口的
[2]
神木中学
[3]
学校
[3]
仔细分析表2-2,我们会发现“.”这个词。 对检索没有帮助。 在这种情况下,句号不提供任何语义信息,也不能帮助检索系统判断文档与查询的匹配程度。 例如,对于“神木是个好地方吗?”这两个查询。 和“神木是个好地方”,检索到的文档完全一样,都是[1,2,3]。 根据我们自己处理文本信息的经验,我们可以做出这样的决定,即删除“.”这样“无益”的词。 在词汇中。
为什么信息内容是“.” 低的? 到处。 “.”的出现率如此之高以至于 key="." 的值在倒排索引中几乎收录了所有文档。 即使是一个比较小的信息检索系统,要处理的数据量级也是数以万计。 一旦查询语句中收录“.”,检索系统会召回几乎所有的文档,并计算这些文档与查询的匹配度——此时,用户不得不等待很长时间,直到出现砸电脑的冲动在脑海中,如图2-1所示。 用户也可以卸载我们的软件。
图2-1 用户经过漫长的等待()
在这种情况下,“。” 出现在每个文档中,这是一个人为的角落案例。 在实际应用中,我们经常会遇到某些词出现在大部分或几乎所有文档中的情况。 这些信息量不大的词或多或少对检索效果有帮助(短文本除外),有一定的价值——但一般情况下,我们需要删除它们。 在我接触过的短文本检索任务中,去除停用词后,召回率可以提高1%以上(应该是几个百分点,这里保守一点)。
停用词的存在不仅使搜索的计算复杂度接近于穷举搜索,而且使搜索的空间复杂度失控。 假设我们有10000篇文档(据我所知,最小垂直领域收录文档的数量级),词汇表收录700个停用词(哈尔滨工业大学停用词表的容量),那么在极端情况下(每个文档出现停用词),倒排索引可能收录700*10000=7000,000个文档id,至少会消耗7000,000*32*2 bytes=420,000,000 bytes=420MB。 如果文档数越大(一个垂直领域的文档数一般在百万以上),倒排索引消耗的存储空间就更大。
如表2-2所示的倒排索引在删除停用词后,变成了更小的数据,如表2-3所示。
表2-3 去除停用词后的倒排索引
钥匙
价值
玉林
[1]
神木
[1, 2]
地方
[1]
红烧肉
[2]
可口的
[2]
神木中学
[3]
学校
[3]
2.2 停用词和主题模型
在构建主题模型的过程中,我们会发现“de”、“land”、“get”等词对表达一个主题没有帮助——因为这样的词太多了,它们在主题中起到了重要的作用话题位置的词分布,给我们概括一个话题的意思造成很大的困难。 这时候,就需要去掉这些价值不大、负面影响大的词了。
如图2-2所示,是使用LDA从新闻标题数据中学习到的主题。 可以看出,每个主题的词分布以标点符号、词、以及“?”等信息含量较低的词为主。 和“的”。 这使我们无法根据单词分布来总结主题的含义(换句话说,主题没有意义)。
图2-2 未过滤停用词时的主题
为了提高出题效果,我在语料库中过滤停用词,然后训练LDA,如图2-3所示。 可以看到每个topic的高权重词的意思都比较明确,似乎可以概括一些topic。 如果要解释停用词过滤为什么会提高LDA的训练效果,需要用到LDA的基本原理——我还没有推导出来,暂时无法解释。
图2-3 过滤停用词后计算的主题 3. 如何建立停用词列表
前面提到,停用词是使用词袋模型时必须谨慎处理的现象,而直接根据停用词列表过滤掉停用词是一种非常有效的处理方式。 那么问题来了,如图3-1所示。
图 3-1 我在哪里可以获得停用词列表? (电影《唐伯虎点秋香》截图)
停止词汇不需要购买。 自己做。
据我所知,没有一种放之四海而皆准的方法可以保证我们一定能够构建出完美的停用词表。 我们能做的就是结合我们要解决的问题,选择合适的方法来构建一个“尽可能好”或者“更好”的停用词表。
3.1 统计数据
注意,本节为了方便记忆,我选择从信息熵的角度来理解TF-IDF。 这是一种称为“强制解释”的操作。
对于停用词我们不能只说“信息量小”,要有依据。 “信息量”的通俗说法是“权重”或“影响力”。 注意:“信息量”和“权重”不是完全相同的概念。 由于(在少数场景下)两者的大小成正比,即使在普通应用中混淆,也不会造成重大损失。
最经典的信息量度量,当然是香农提出的信息熵(以前写作“香农”;“香农”是标准化翻译。感谢CBG同志提醒)。 我们假设说或写是这样一种操作:按照一定的概率,从词汇表中选出词,添加到句子或文章中。在生成文本的过程中,假设第i个词出现的概率为
,则该项带来的不确定性的期望值为
. 该指标的含义是:乘号左边的项代表一个词出现的概率; 右边的词表示一个词(在词汇表中)(存在)带来的不确定性。
那么如何获取一个词出现的概率呢? 我们可以根据一个语料数据集来估算。如果我是做马哲相关领域的研究或者应用,那么我可以找几本马哲教材的电子版,解析出里面的文字段落,然后得到下面两个数字通过统计:(1)数据中“物质”一词在簇中出现的次数
;(2) 整个数据集中的总词数N。 那么,“物质”一词出现的概率为:
,“物质”这个词的熵是
有人选择用另一种思维方式来衡量词的信息含量。他们认为,如果一个词 i 在文档中普遍存在,则意味着这个词的存在带来的不确定性很低——这种不确定性可以表示为
. 文档频率(Document Frequency)表示收录词i的文档的数量。因此,词i引入的不确定性的期望值为
——这个指标非常有名,它的全称是Term Frequency-Inverse Document Frequency。
我们可以找出K个TF-IDF值很低的词,这是一个初步停止词表。 接下来,我们会请领域专家或工程师从第一版停用词列表中去除一些有价值的词,从而获得更高的质量水平(高精度)可能无法覆盖足够多的停用词(召回率更低)停止单词列表。 在使用停止词表的过程中,我们会发现一些对任务帮助不大的词,比如3.1节和3.2节中展示的低信息词,可以逐渐加入停止词表; 另外,如果一些停用词的存在导致任务失败。 例如,如果没有检索到文档,那么我们需要重新激活这些停用词,使它们成为普通词。
3.2 使用领域知识
领域知识可以支持我们做一些细化的操作,比如采集停用词。 在特定领域中,某些词提供的信息量较低,不应用作特征。 假设我们在做一个诗歌知识服务工具,那么图3-2中的“火星人”这个词肯定是收录在停止词表中的——目前为止,我还没有听说过用火星人诗歌写作。
图 3-2 “我家住在黄土高原”。 Martian 3.3版本开源停用词列表
一般来说,我们在项目前期可以考虑使用开源的停用词,比如funNLP在gitee开源的四个停用词(
). 四个停用词表分别是:(1)中文停用词库; (2)哈尔滨工业大学停用词表; (3) 四川大学停用词表; (4) 百度停用词列表。
4. 停用词表的使用 4.1 信息检索系统的查询是否也需要去除停用词?
在信息检索任务中,我们从倒排索引的键或文档特征中删除停用词。 那么,我们是不是也需要对用户的query进行同样的操作,来维持query和文档之间相同的分布关系呢? 倒排中没有停用词。 即使查询特征中存在停用词,系统也不会召回无用的文档。 似乎没有必要去除查询的停用词。
事实上,事情并没有那么简单。 一般的信息检索系统会考虑未注册词的存在,在计算query和candidate documents的相关性时(比如TF-IDF的各种smoothing operations),会为未收录在词汇表中的词分配一个默认的权重——如果特征query 收录停用词,系统会将这些停用词视为未注册词,并为其分配权重(非 0)。 这样一来,停用词就影响了搜索结果,与我们的计划发生了冲突。 因此,查询特征也需要去除停用词。
4.2 什么时候需要去掉停用词
在任何使用词袋模型表示文本数据的场景下,都需要考虑是否需要去除停用词。 近年来,我们经常使用词粒度语言模型,如 BERT 和 GPT 来做 NLP 任务。 这类模型需要考虑到句子中的所有成分,从而更准确地描述语言规则。 深度学习时代不需要停用词吗? 需要。 深度学习模型并不能胜任所有任务,词袋模型仍然存在,我们将继续使用停用词。
5 结论
停用词列表是一个非常宝贵的工具。 它的价值需要通过使用停止列表的系统来体现。 我们在构建停用词表时,必须紧紧围绕任务目标来定义评价指标和规则。
最近在参与一个信息检索模块的构建时,发现停用词、同义词、关联词等数据可以帮助我们构建良好的文本表示,从而提高系统的召回率。 当然,还有很多数据和方法可以用来提高信息检索系统的召回率。 至此,我终于明白了大厂土豪的行为,就是动不动就派几百甚至几千人去做搜索或者推荐。 有庞大的精神资源支撑。
注:本文为知乎(知乎个人主页/people/py-li-34)原创,受版权相关法律法规保护。 如需引用或转载,请注明出处信息:(1)作者姓名,即“李鹏宇”; (2) 原网页链接,即当前页面地址。 如有任何问题,请发邮件至我的邮箱:。
参考
[1] 拉尼 R,洛比亚尔 DK。 具有印地语停用词列表的文本挖掘模型的性能评估[J]。 2020.
[2] 卢恩·惠普。 文学信息机械化编码与检索的统计方法[J]. IBM 研究与开发杂志,1957 年,1(4):309-317。
[3] Luhn, H. P. 文献摘要的自动生成[J]. IBM 研究与开发杂志,1958 年,2(2):P.159-165。