定义
启发式过滤是一种技术方法,利用解决问题的技术和算法来识别数据中的模式、趋势或特征。 这种方法通常涉及使用预测分析和近似方法,以便快速做出决策或对信息进行分类。 启发式过滤通常应用于反垃圾邮件软件、防病毒程序和人工智能等领域,以有效检测垃圾邮件、恶意软件或根据以往的数据模式做出明智的决策。
主要启示
- 启发式过滤利用基于以往经验的算法来有效识别和过滤掉不需要的信息。
- 这种方法成本低廉、节省时间,因此对于资源有限的复杂问题很有价值。 然而,启发式过滤的准确性在很大程度上取决于启发式的质量和以往的经验,这可能会导致结果出现误差或偏差。
- 启发式过滤被广泛应用于各种领域,如优化问题、决策支持、自然语言处理和垃圾邮件检测等,因为它能在相对较短的时间内提供可接受水平的结果。
说明
启发式过滤是一种动态技术,用于基于经验驱动的知识或有根据的猜测的模式识别,决策和问题解决。这些方法主要用于不切实际或不必要的情况下。启发式过滤的目的是在分析复杂或大数据集时提供近似值,从而使系统能够快速找到"足够好"的可行解决方案,而不是获得最佳解决方案。
启发式过滤在各个行业中都是有帮助的,尤其是在计算机科学,人工智能(AI)和网络安全应用程序中,因为它们使计算机和算法能够根据一组预定规则或以前的经验快速学习和适应。启发式过滤最常见的应用之一是垃圾邮件检测领域。电子邮件服务提供商采用启发式算法来快速识别和过滤不需要的消息,从而保护用户免受无关或恶意内容的轰炸。
这些过滤器评估传入电子邮件的某些特征,例如主题行,消息内容和发送模式,以确定消息成为垃圾邮件的可能性。通过不断适应新的模式和威胁,启发式过滤器在识别和减少垃圾邮件方面变得越来越有效。此外,相同的概念通常部署在网络安全系统中,在该系统中,防火墙和入侵检测系统使用启发式过滤来检测潜在威胁和漏洞。
总体而言,启发式过滤是应对各种复杂挑战并提供可提高效率,安全性和用户体验的实用解决方案的必不可少的工具。
启发式过滤示例
Heuristic Filtering是一种用于根据特定行为模式或规则识别和过滤不需要的内容,恶意软件或垃圾邮件的技术。这是三个现实世界的例子:
电子邮件垃圾邮件过滤:启发式过滤在电子邮件服务中起着重要作用,因为它有助于识别和过滤垃圾邮件。电子邮件服务提供商(例如Gmail,Yahoo和Outlook)使用启发式过滤来分析电子邮件的内容,发送者和模式,并根据预定义的规则和算法将其分类为垃圾邮件或非垃圾邮件。这有助于减少用户'收件箱中的有害消息数量。
病毒和恶意软件检测:防病毒软件和安全套件经常使用启发式过滤技术来检测恶意软件,病毒和其他潜在有害软件。通过使用启发式分析,该软件可以根据其行为,文件结构或代码模式检测未知威胁。这使安全应用程序可以在可疑软件对系统造成任何损坏之前对其进行阻止或隔离。
在线广告过滤和阻止:Web浏览器和广告阻止扩展还使用启发式过滤来分析和阻止潜在有害或侵入性广告。通过使用模式识别和内容分析,这些工具可以阻止包含特定关键字,源自已知广告服务器或侵犯用户隐私的广告。这有助于为用户提供更清洁,更安全的浏览体验。
常见问题解答--启发式过滤
-
什么是启发式过滤?
启发式过滤是一种在包括计算机科学和网络安全在内的各个领域中用于识别模式并根据一组规则和算法做出决策的技术。在垃圾邮件过滤器或防病毒软件的上下文中,启发式过滤用于根据其特征识别可疑电子邮件或文件,即使以前未将其识别为恶意。
-
启发式过滤如何工作?
启发式过滤通过分析电子邮件或文件的各种特征(例如主题行,文本模式和文件结构)来工作。然后,它使用算法来确定这些特征是否与与垃圾邮件或恶意软件相关的已知模式匹配。如果找到匹配项,则电子邮件或文件被标记为可能不可信任,并且可能被隔离或阻止以保护用户。
-
使用启发式过滤有什么好处?
启发式过滤的主要好处是,它可以识别和阻止以前未遇到的新垃圾邮件或恶意软件威胁,从而为用户提供更高级别的保护。而且,它可以适应不断变化的威胁,因为它会根据新数据不断更新其算法。这使得启发式过滤与其他安全措施(例如基于签名的检测和基于行为的分析)相结合,成为有价值的工具。
-
启发式过滤有什么缺点吗?
启发式过滤在检测和阻止未知威胁方面具有显着优势,但有时可能会产生误报,将合法电子邮件或文件标记为潜在有害。这可能会给用户带来不便,并且可能需要手动干预才能解决。此外,启发式过滤技术可能是资源密集型的,因为它们需要大量的计算能力来分析模式并做出决策。
-
如何在安全软件中实施启发式过滤?
要在安全软件中实施启发式过滤,您需要选择一种将本技术集成到其现有平台中的解决方案,或者找到一个独立的启发式过滤工具。许多防病毒和安全软件提供商将启发式过滤作为其产品中的功能。确保研究可用的选项,并在兼容性,准确性和资源消耗方面选择满足您特定需求的选项。
相关技术条款
- 模式识别
- 异常检测
- 贝叶斯过滤
- 机器学习
- 自适应算法
实例
Nvidia Nemo 分类器和启发式质量筛选
大型数据集通常包含许多被认为是 "低质量 "的文档。 在这种情况下,"低质量 "数据只是指我们不希望下游模型从中学习的数据,而 "高质量 "数据则是我们希望下游模型从中学习的数据。 定义质量的指标可能各不相同。 有一些启发式方法可以通过收集简单的统计数据来衡量质量,比如文档有多少个标点符号、文档有多长以及文档的重复性有多高。 然后,您就可以根据这些统计数据筛选文档。 相反,您可能有一个高质量的数据集,而您希望新的数据集与之保持一致。
NeMo Curator 为这两种过滤提供了模块,并提供了一个简单的界面来添加自己的过滤器或将其与现有的过滤器相结合。 您还可以使用这些模块收集文档的统计数据和元数据,而无需删除任何文档。 有 30 多种过滤器可用于英语、非英语和代码数据集。
使用
ScoreFilter
是 NeMo Curator 过滤功能的核心。 让我们来看看这个小例子:
python
import nemo_curator as nc
from nemo_curator.datasets import DocumentDataset
from nemo_curator.utils.file_utils import get_all_files_paths_under
from nemo_curator.filters import WordCountFilter
files = get_all_files_paths_under("books_dataset/")
books = DocumentDataset.read_json(files, add_filename=True)
filter_step = nc.ScoreFilter(
WordCountFilter(min_words=80),
text_field="text",
score_field="word_count",
)
long_books = filter_step(books)
long_books.to_json("long_books/", write_to_filename=True)
需要重点关注的核心部分是 filter_step 的创建。 WordCountFilter(min_words=80)
创建并配置了一个过滤器对象。 过滤器对象是从抽象基类 nemo_curator.filters.DocumentFilter
继承而来的类。 该基类要求继承者实现 score_document
和 keep_document
这两个方法。 在本例中,我们来看看简化版的 WordCountFilter
。
python
class WordCountFilter(DocumentFilter):
def __init__(self, min_words=50, max_words=100000, lang='en'):
self._min_words = min_words
self._max_words = max_words
self._word_splitter = get_word_splitter(lang)
self._name = 'word_count'
def score_document(self, text: str):
return len(self._word_splitter(text))
def keep_document(self, score: int):
return self._min_words <= score <= self._max_words
score_document
接收文档的文本,并返回文档的字数。 keep_document
接收 score_document
输出的分数(本例中为字数),如果分数表明文档应该保留,则返回 True
;如果文档应该删除,则返回 False
。 现在,需要注意的是,WordCountFilter
和 DocumentFilter
只能对单个文档进行操作。 要将过滤器应用于整个数据集,我们必须使用 ScoreFilter
。
python
filter_step = nc.ScoreFilter(
WordCountFilter(min_words=80),
text_field="text",
score_field="word_count",
)
ScoreFilter
的构造创建了一个可应用于 DocumentDataset
(而非单个文档)的函数。 text_field
指定了数据集中的文档字段,这些文档将被传递给过滤器的 score_document
函数。 score_field
是一个可选参数,允许您在文档的给定元数据字段中记录分数,如果指定了,分数将与其他元数据一起写入磁盘。 在某些情况下,数据集可能带有您想直接过滤的元数据。 或者,你可能只想添加一个新的元数据,而不想对其进行过滤。 过滤模块和评分模块可以分别完成这两项任务。 例如,如果上例中的数据集预先填充了 word_count
字段,则可以重写如下:
python
books = DocumentDataset.read_json(files, add_filename=True)
filter_step = nc.Filter(
WordCountFilter(min_words=80).keep_document,
filter_field="word_count",
)
long_books = filter_step(books)
long_books.to_json("long_books/", write_to_filename=True)
另外,如果您只想跟踪文档中单词的长度,而不想根据它们进行筛选,也可以重写如下:
python
books = DocumentDataset.read_json(files, add_filename=True)
filter_step = nc.Score(
WordCountFilter(min_words=80).score_document,
text_field="text",
score_field="word_count",
)
annotated_books = filter_step(books)
annotated_books.to_json("annotated_books/", write_to_filename=True)
分批过滤
上面定义的评分和过滤函数都是针对单个文档的,而 NeMo Curator 可以利用批处理函数来提高性能。 为此,您可以使用批处理装饰器(batched decorator)对函数进行注释。 该装饰器将导致向函数传递一系列 pandas 文档/分数,而不是单个文档/分数。 下面是重写的 WordCountFilter
,以便在 keep_document
中使用批次。
python
from nemo_curator.utils.decorators import batched
class WordCountFilter(DocumentFilter):
def __init__(self, min_words=50, max_words=100000, lang='en'):
self._min_words = min_words
self._max_words = max_words
self._word_splitter = get_word_splitter(lang)
self._name = 'word_count'
def score_document(self, text: str):
return len(self._word_splitter(text))
@batched
def keep_document(self, scores: pd.Series):
pass_min = self._min_words <= scores
pass_max = score <= self._max_words
return pass_min & pass_max
使用批处理装饰器时,从函数返回的序列索引必须与传入的索引保持一致。 由于在当前过滤器之前应用了过滤器,因此索引可能不连续。 在上述代码中,索引将自动保持不变,因此无需更改。 但是,在编写将序列转换为列表等不同结构的函数时,需要特别注意。 下面的代码示例演示了这种错误的表现形式以及如何解决。
python
class BuggyLengthFilter(DocumentFilter):
@batched
def score_document(self, documents: pd.Series):
scores = []
for document in documents:
scores.append(len(document))
return pd.Series(scores) # Bad! Does not preserve the index
class CorrectLengthFilter(DocumentFilter):
@batched
def score_document(self, documents: pd.Series):
scores = []
for document in documents:
scores.append(len(document))
return pd.Series(scores, index=documents.index) # Good! Preserves the index
分类器过滤
我们所采用的基于分类器的过滤方法与 Brown 等人在 2020 年所使用的方法非常相似,它训练了一个二进制跳序分类器,可用于区分低质量和高质量文档。 为了实现这一点,我们使用了 fastText 提供的函数。 根据 fastText 文档中提供的示例,我们首先创建一个由高质量和低质量训练文档组成的文件。 我们在 examples/classifier_filtering.py 中提供了一个如何训练和使用模型的示例。
我们还为相同功能提供了 CLI 脚本。 prepare_fasttext_training_data 脚本将从输入数据集中随机抽取文档样本,并将其准备用于训练 fasText 跳序分类器。 对于高质量的数据集,我们建议从 OpenWebText2 或维基百科中取样,而对于低质量的数据集,则可以使用未经过滤的 Common Crawl 版本。
bash
prepare_fasttext_training_data \
--input-data-dir=<Specify the path to common-crawl/low-quality data> \
--output-num-samples=<Specify the number of low-quality documents to be used for training> \
--label='__label__cc' \
--output-train-file=${res_dir}/cc_samples.txt \
prepare_fasttext_training_data \
--input-data-dir=<Specify the path to high-quality data> \
--output-num-samples=<Specify the number of high-quality documents to be used for training> \
--label='__label__hq' \
--output-train-file=${res_dir}/hq_samples.txt \
样本准备好并写入 .txt 文件后,用户就可以使用 train_fasttext 脚本读取 .txt 文件中的样本,以训练高质量的分类器。train_fasttext 会读取 .txt 文件中的所有样本,将数据分成训练集和验证集,并训练二进制跳格分类器。 训练完成后,它会在验证样本上评估模型,并将预测结果写入 jsonl 文件,将混淆矩阵打印到 stdout。
bash
train_fasttext \
--fasttext-files-dir=${res_dir} \
--output-train-file=${res_dir}/fasttext_samples.train \
--output-validation-file=${res_dir}/fasttext_samples.valid \
--output-model=${res_dir}/cc_filter_test.bin \
--output-predictions=${res_dir}/preds.jsonl
最后,模型经过训练并能提供质量分数后,就可用于质量过滤。 与 filter_documents 使用 fastText 模型 lid.176.bin 进行语言识别的方式类似,我们提供了一个默认配置,可用于使用 fastText 模型进行基于分类器的质量过滤。 此外,该过滤器还采用了 Brown 等人在 2020 年所描述的基于帕累托的抽样方法。
bash
filter_documents \
--input-data-dir=<Specify the path to common-crawl/uncurated data> \
--filter-config-file=./config/fasttext_quality_filter.yaml \
--output-retained-document-dir=<Output directory to which high-quality documents will be written> \
--output-removed-document-dir=<Output directory to which low-quality documents will be written> \
--log-dir=${log_dir}/fasttext_classifier \
启发式过滤
与其他过滤步骤一样,NeMo Curator 中基于启发式的过滤可以使用 ScoreFilter 或 filter_documents 工具来执行。 在 NeMo Curator 中,可以使用 Sequential 对过滤器进行如下连锁处理。
python
filter_step = nc.Sequential([
ScoreFilter(
WordCountFilter(min_words=80),
score_field="word_count",
),
ScoreFilter(IncompleteStoryFilter()),
ScoreFilter(RepeatingTopNGramsFilter(n=2, max_repeating_ngram_ratio=0.2)),
ScoreFilter(RepeatingTopNGramsFilter(n=3, max_repeating_ngram_ratio=0.18)),
ScoreFilter(RepeatingTopNGramsFilter(n=4, max_repeating_ngram_ratio=0.16)),
])
过滤器配置文件 config/heuristic_filter.yaml 提供了启发式过滤器的通用列表,这些过滤器已经过测试,并被证明可以提供用于训练的文档,从而提高语言模型的下游任务性能。 这些过滤器具有足够的通用性,用户可以随意移除过滤器级联中的某些过滤器,并尝试不同过滤器配置/参数的结果。
此外,这些过滤器还被用于策划高质量的非英语文档。 不过,在应用于非英语数据时,建议用户通过指定 --document-score-dir 参数来写出文档分数。 这样,用户就可以检查某个特定的过滤器是否从语料库中删除了大量文件。
python
filter_documents \
--input-data-dir=<Specify path to input dataset> \
--filter-config-file=./config/heuristic_filter_en.yaml \
--output-retained-document-dir=<Output directory to which high-quality documents will be written> \
--output-removed-document-dir=<Output directory to which low-quality documents will be written> \
--output-document-score-dir=<Output directory to which document scores will be written> \
--log-dir=${log_dir}/heuristic_filter