PowerLZY's Blog

本博客主要用于记录个人学习笔记(测试阶段)

网络威胁情报之 STIX 2.1

https://zhuanlan.zhihu.com/p/365563090

一、说明

STIX(Structured Threat Information Expression)是一种用于交换网络威胁情报(cyber threat intelligence,CTI)的语言和序列化格式。STIX的应用场景包括:协同威胁分析、自动化威胁情报交换、自动化威胁检测和响应等。

STIX对网络威胁情报的描述方法如下:
img

STIX Domain Objects(SDO):威胁情报主要的分类对象,包含了一些威胁的behaviors和construct,共有18种类型:Attack Pattern, Campaign, Course of Action, Grouping, Identity, Indicator, Infrastructure, Intrusion Set, Location, Malware, Malware Analysis, Note, Observed Data, Opinion, Report, Threat Actor, Tool, and Vulnerability.

img
img

STIX Cyber-observable Objects(SCO):威胁情报中具体的可观察对象,用于刻画基于主机或基于网络的信息

  • SCO会被多种SDO所使用,以提供上下文支持,如Observed Data SDO,表示在特定时间观察到的raw data;在STIX2.0中,SCO在SDO中出现时只会以Observed Data的形式出现,在STIX2.1则不限于此。
  • SCO本身不包括who,when和why的信息,但是将SCO和SDO关联起来,可能会得到这些信息以及对威胁更高层面的理解。
  • SCO可以捕获的对象包括文件、进程、IP之间的流量等。

STIX Relationship Objects(SRO):用于SDO之间、SCO之间、SDO和SCO之间的关系。SRO的大类包括以下两种:

img

generic SRO(Relationship):大多数关系所采用的类型,其relation_type字段包括:内置关系:如Indicator到Malware之间的关系,可以用indicates 表示,它描述了该Indicator可用于检测对应的恶意软件;自定义关系;

Sighting SRO:用于捕获实体在SDO中出现的案例,如sighting an indicator。没有明确指明连接哪两个object。之所以将其作为独立的SRO,是因为其具有一些独有的属性,如count

除了SRO,STIX还用ID references来表示嵌入关系(embedded relationship)。当使用嵌入关系时,表示该属性时该对象的内置属性,从而不需要使用SRO表示,如create_by_ref。因此,SRO可以视为两个节点直接的边,而embedded relationship则可以视为属性(只不过其表示了二元关系)

  • STIX Meta Objects:用于丰富或扩展STIX Core Objects
  • STIX Bundle Object:用于打包STIX内容

STIX是一种基于图的模型,其中SDO和SCO定义了图的节点,而STIX relationships定义了边

STIX Patterning language:STIX模式语言可以实现网络或终端的威胁检测。该语言目前使用STIX Indicator对象,来匹配时序的observable data。

二、通用数据类型

img

三、 STIX 通用概念

  • STIX common properties

img

四、 STIX Domain Objects

每个SDO对应 交换网络威胁情报CTI中的唯一概念。使用SDO,SCO和SRO作为基本模块,用户可以方便的创建和共享CTI。

SDO

  • Property:通用属性、SDO转专用属性
  • Relationship:embedded relationships、common relationships

一些相似的SDO可以被归为一个大类,如:

  • Attack Pattern, Malware, and Tool可以被归为TTP,因为它们描述了攻击行为和资源
  • Campaign, Intrusion Set, and Threat Actor 可以被描述为“攻击者发动攻击的原因,以及如何组织(why and how)”

4.1 Attack Pattern

TTP类型之一,它描述了攻击者试图破坏目标的方式,对应于TTP中的战术。可用于帮助对攻击进行分类,将特定的攻击概括为其遵循的模式,并提供有关如何进行攻击的详细信息

如spear fishing就是一种攻击模式,而更具体的描述,如被特定攻击者实施的spear fishing也是一种攻击模式。

4.2 Campaign

表示某次具体的攻击活动。A Campaign is a grouping of adversarial behaviors that describes a set of malicious activities or attacks (sometimes called waves) that occur over a period of time against a specific set of targets. Campaigns usually have well defined objectives and may be part of an Intrusion Set.

战役是一组敌对行为,描述了针对特定目标集在一段时间内发生的一组恶意活动或攻击(有时称为WAVE)。活动通常有明确的目标,可能是入侵集的一部分。

4.3 Course of Action (响应的行为)

用于预防攻击或对攻击做出响应的行为,它回包含技术,自动化响应(补丁、重新配置防火墙),或高级别的动作(如员工培训或者策略制定)。

4.4 Grouping

Grouping表示分析和调查过程中产生的数据(待确认的线索数据);还可以用来声明其引用的STIX对象与正在进行的分析过程有关,如当一个安全分析人员正在跟其它人合作,分析一系列Campaigns和Indicators的时,Gouping会引用一系列其它SDO、SCO和SRO(Grouping就表示协作分析吧)。

除了embedded relationship和common relationship之外,没有明确定义Grouping对象和其它STIX对象之间的关系。

4.5 Identity

Identity可以代表特定的个人、组织或团伙;也可以代表一类个人、组织、系统或团伙。Identity SDO可以捕获基本标识信息,联系信息以及Identity所属的部门。 Identity在STIX中用于表示攻击目标,信息源,对象创建者和威胁参与者身份。

4.6 Incident

stub对象,待完善,没有专门定义的property和relationship。

4.7 Indicator

Indicator表示可用于检测可疑行为的模式。如用STIX Patterning Language来描述恶意域名集合(第九章)。

4.8 Infrastructure

TTP的类型之一,用于描述系统、软件服务等其它的物理或虚拟资源;如攻击者使用的C2服务器,防御者使用的设备和服务器,以及作为被攻击目标的数据库服务器等;

基于此我们可以将受保护网络中的设备纳入知识图谱,采用类似于这样的关系:

img

4.9 Intrusion Set

Intrusion set是由某个组织所使用的恶意行为和资源的集合。一个Intrusion Set可能会捕获多个Campaigns,他们共同指向一个Threat Actor。新捕获的活动可以被归因于某个Intrusion Set,而Actors可以在Intrusion之间跳转,甚至从属于多个Intrusion Set。

如在 apt1.json 中,整个报告被打包在bundle中,而Intrusion Set用来指示APT组织:

img

Intrusion Set和Campaigns对比:

如果 Campaigns 是在一段时间内针对一组特定目标进行的一组攻击,以实现某些目标,那么入侵集就是整个攻击包,可以在多个活动中长期使用,以实现潜在的多个目的.由Intrusion Set找出Threat Actors,nation state或者nation state中的某个APT组织,是一个溯源的过程。

4.10 Location

表示具体地点,可以与Identity或Intrusion Set相关联,表示其位置;与Malware或Attack Pattern相关联,表示其目标。

4.11 Malware

TTP类型之一,表示恶意软件或代码。

4.12 Malware Analysis

捕获了在恶意软件实例或恶意软件家族分析过程中,动态分析或静态分析的结果。

4.13 Note

其他对象中不存在的额外信息;例如,分析人员可以在一个Campaign对象中添加注释,以表明他在黑客论坛上看到了与该Campaign相关的帖子。同样,Note对象也没有定义与其他STIX Object之间的关系。

4.14 Observed Data

网络安全相关的可观察对象(raw information)集合,其引用对象为SCO,包含从analyst reports, sandboxes, and network and host-based detection tools等收集的信息。

必须包含objects或者object_refs属性,表示对SCO的引用

Observed Data只有反向关系。此外,还会被Sighting SRO所指向:Sightings represent a relationship between some intelligence entity** that was seen** (e.g., an Indicator or Malware instance), where it was seen, and what evidence was actually seen. The evidence (or raw data) in that relationship is captured as Observed Data(Sighting中的证据就是Observed Data)。

4.15 Opinion

Opinion是对STIX对象中信息正确性的评估。

4.16 Report

威胁情报报告。

4.17 Threat Actor

攻击的个人、团体或组织;其与Intrusion Set不同,Threat Actor会同时支持或附属于不同的Intrusion Set、团体或组织。

4.18 Tool

Tool是威胁参与者可以用来执行攻击的合法软件。与Malware不同,Tool一般是合法软件,如Namp、VNC。

4.19 Vulnerability

漏洞。用于连接相关漏洞的外部描述(external_references),或还没有相关描述的0-day漏洞。

Q&A:

  • Q1:embedded relationship和节点property有啥区别?property是节点属性,embedded relationship是带有二元关系的节点属性
  • Q2:Observed Data和SCO有啥区别?Observed Data观察行为与观察对象的信息,而SCO是具体可观察实体的信息,二者是引用与被引用的关系
  • Q3:Intrusion Set、Identity和Threat Actor的区别?Intrusion Set是最高层的实体,其包括Identity和Threat Actor,如APT1(高层APT组织)为Intrusion Set,其包含一些个人(Ugly Gorilla)或团体(SuperHard)的Threat Actor,而Identity是用真实名称描述的个人或组织(如Ugly Gorilla指向Wang Dong)。由此看来,Threat Actor也可以用真是名称描述(Communist Party of China),但是明显指示了其表示威胁主体,而Identity本身不显示其角色信息。

五、 STIX Relationship Objects

5.1 Relationship

Type Name: relationship

用于连接STIX中的SDO或SCO; STIX中的Relationship在每个SDO或SCO的定义中进行了描述, 用户还可以自定义关系。STIX中所有内置的Relationship详见文档Appendix B。注意, Relationship本身也是一个对象, 因此其也有自身的 Property 和 Relationships。

5.2 Sighting

Type Name: sighting

原文定义:目击(sighting)表示认为在CTI中看到了某些东西(例如指示器、恶意软件、工具、威胁因素等)。目击用于跟踪目标是谁和什么,如何实施攻击,以及跟踪攻击行为的趋势。

A Sighting denotes the belief that something in CTI (e.g., an indicator, malware, tool, threat actor, etc.) was seen. Sightings are used to track who and what are being targeted, how attacks are carried out, and to track trends in attack behavior.

Sighting 没有连接两个对象, 但却被定义为关系, 原因是:目击包括三部分的内容:• 发现的内容,如指示器、恶意软件、活动或其他SDO(sightingfef)•发现者和/或发现地点,表示为身份(whereightedefs)•系统和网络上实际看到的内容,表示为观察数据(SECUREDataefs)

Sighting is captured as a relationship because you cannot have a sighting unless you have something that has been sighted. Sighting does not make sense without the relationship to what was sighted

Sighting包括三部分的内容:

  • What was sighted, such as the Indicator, Malware, Campaign, or other SDO (sighting_of_ref)
  • Who sighted it and/or where it was sighted, represented as an Identity (where_sighted_refs)
  • What was actually seen on systems and networks, represented as Observed Data (observed_data_refs)

Sighting和Observed Data的区别:

目击与观察到的数据不同,因为目击是一种情报断言(“我看到了这个威胁参与者”),而观察到的数据只是信息(“我看到了这个文件”)。当您通过包含来自目击的链接观测数据(Observedataefs)来组合它们时,您可以说“我看到了这个文件,这让我觉得我看到了这个威胁参与者”。

Sighting is distinct from Observed Data in that Sighting is an intelligence assertion ("I saw this threat actor") while Observed Data is simply information ("I saw this file"). When you combine them by including the linked Observed Data (observed_data_refs) from a Sighting, you can say "I saw this file, and that makes me think I saw this threat actor".

RAID-Cyber Threat Intelligence Modeling Based on GCN

[AI安全论文] 05.RAID-Cyber Threat Intelligence Modeling Based on GCN

这篇文章将详细介绍北航老师发表在RAID 2020上的论文《Cyber Threat Intelligence Modeling Based on Heterogeneous Graph Convolutional Network》

原文作者:Jun Zhao, Qiben Yan, Xudong Liu, Bo Li, Guangsheng Zuo 原文链接:https://www.usenix.org/system/files/raid20-zhao.pdf 论文来源:RAID 2020/CCF B

摘要

网络威胁情报(CTI,Cyber Threat Intelligence)已在业界被广泛用于抵御流行的网络攻击,CTI通常被看作将威胁参与者形式化的妥协指标(IOC)。然而当前的网络威胁情报(CTI)存在三个主要局限性:

  • IOC提取的准确性低
  • 孤立的IOC几乎无法描述威胁事件的全面情况
  • 异构IOC之间的相互依存关系尚未得到开发,无法利用它们来挖掘深层次安全知识

本文提出了基于异构信息网络(HIN, Heterogeneous Information Network)的网络威胁情报框架——HINTI,旨在建模异构IOCs之间的相互依赖关系,以量化其相关性,对CTI进行建模和分析。

本文的主要贡献如下:

  • 提出了基于多粒度注意力机制( multi-granular attention)的IOC识别方法,可以从非结构化威胁描述中自动提取网络威胁对象,并提高准确性。
  • 构建一个异构信息网络(HIN)来建模IOCs之间的依赖关系
  • 提出一个基于图卷积网络(Graph Convolutional Networks)的威胁情报计算框架来发现知识
  • 实现了网络威胁情报(CTI)原型系统

实验结果表明,本文提出的IOC提取方法优于现有方法,HINTI可以建模和量化异构IOCs之间的潜在关系,为不断变化的威胁环境提供了新的线索。

IOC(Indicator of Compromise)是MANDIANT在长期的数字取证实践中定义的可以反映主机或网络行为的技术指示器。

一、HINTI工作步骤

  • 通过B-I-O序列标注方法对安全相关帖子进行标注,用于构建IOC提取模型。
  • 将标记的训练样本输入神经网络,训练IOC提取模型
  • HINTI利用句法依赖性解析器(e.g.,主-谓-宾,定语从句等)提取IOC之间的关联关系,每个IOC均表示为三元组(IOCi,relation,IOCj)
  • 最后,HINTI集成了基于异构图卷积网络的CTI计算框架以有效地量化IOC之间的关系进行知识发现。

1.1 HINTI总体架构

HINTI由四个主要部分组成:(a)收集与安全相关的数据并提取即IOC;(b)将IOC之间的相互依存关系建模为异构信息网络;(c)使用基于权重学习的相似性度量将节点嵌入到低维向量空间中;(d)基于图卷积网络和知识挖掘来计算威胁情报。

图片

GPT3

除了BERT以外,还有下一个,也是鼎鼎有名的模型,就是==GPT==系列的模型

image-20220613185324111

BERT做的是填空题,GPT就是改一下我们现在在,self-supervised learning的时候,要模型做的任务

Predict Next Token

GPT要做的任务是:预测接下来,会出现的token是什麼

举例来说,假设你的训练资料裡面,有一个句子是台湾大学,那GPT拿到这一笔训练资料的时候,它做的事情是这样。

你给它BOS这个token,然后GPT output一个embedding,然后接下来,你用这个embedding去预测下一个,应该出现的token是什麼?

image-20220613185452298

那在这个句子裡面,根据这笔训练资料,下一个应该出现的token是"台",所以你要训练你的模型,根据第一个token,根据BOS给你的embedding,那它要输出"台"这个token。

这个部分,详细来看就是这样,你有一个embedding,这边用h来表示,然后通过一个Linear Transform,再通过一个softmax,得到一个distribution,跟一般你做分类的问题是一样的,接下来,你希望你output的distribution,跟正确答案的Cross entropy,越小越好,也就是你要去预测,下一个出现的token是什麼。

好那接下来要做的事情,就是以此类推了,你给你的GPT,BOS跟"台",它產生embedding,接下来它会预测,下一个出现的token是什麼,那你告诉它说,下一个应该出现的token,是"湾"。

image-20220613185654700

好再反覆继续下去,你给它BOS "台"跟"湾",然后预测下一个应该出现的token,它应该要预测"大"。你给它"台"跟"湾"跟"大",接下来,下一个应该出现的token是"学"。

image-20220613185722536

那这边呢,是指拿一笔资料 一个句子,来给GPT训练,当然实际上你不会只用一笔句子,你会用成千上万个句子,来训练这个模型,然后就这样子说完了。它厉害的地方就是,用了很多资料,训了一个异常巨大的模型

GPT的模型像是一个transformer的decoder,不过拿掉BOS的attention这个部分,也就是说,你会做那个mask的attention。

image-20220613185925358

就是你现在在预测给BOS,预测台的时候,你不会看到接下来出现的词汇,给它台要预测湾的时候,你不会看到接下来要输入的词汇,以此类推这个就是GPT

那这个GPT最知名的就是,因為GPT可以预测下一个token,那所以它有生成的能力,你可以让它不断地预测下一个token,產生完整的文章,所以我每次提到GPT的时候,它的形象都是一隻独角兽。

image-20220613190018230

GPT系列最知名的一个例子,就是用GPT写了一篇,跟独角兽有关的新闻,因為他放一个假新闻,然后那个假新闻裡面说,在安地斯山脉发现独角兽等等,一个活灵活现的假新闻。

為了让你更清楚了解,GPT运作起来是什麼样子,那这个线上有一个demo的网页,叫做talk to transformer,就是有人把一个比较小的,不是那个最大的GPT的模型,不是public available的,有人把比较小的GPT模型放在线上,让你可以输入一个句子,让它会把接下来的其餘的内容,把它补完

How to use GPT?

怎麼把它用在downstream 的任务上呢,举例来说,怎麼把它用在question answering,或者是其他的,跟人类语言处理有关的任务上呢?

GPT用的想法跟BERT不一样,其实我要强调一下,GPT也可以跟BERT用一样的做法。在使用BERT时,把BERT model 拿出来,后面接一个简单的linear的classifier,那你就可以做很多事情,你也可以把GPT拿出来,接一个简单的classifier,我相信也是会有效。

但是在GPT的论文中,它没有这样做,它有一个更狂的想法,為什麼会有更狂的想法呢,因為首先就是,BERT那一招BERT用过了嘛,所以总不能再用一样的东西,这样写paper就没有人觉得厉害了,然后再来就是,GPT这个模型,也许真的太大了,大到连fine tune可能都有困难

我们在用BERT的时候,你要把BERT模型,后面接一个linear classifier,然后BERT也是你的,要train的model的一部分,所以它的参数也是要调的,所以在刚才助教公告的,BERT相关的作业裡面,你还是需要花一点时间来training,虽然助教说你大概20分鐘,就可以train完了,因為你并不是要train一个,完整的BERT的模型,BERT的模型在之前,在做这个填空题的时候,已经训练得差不多了,你只需要微调它就好了,但是微调还是要花时间的,也许GPT实在是太过巨大,巨大到要微调它,要train一个epoch,可能都有困难,所以GPT系列,有一个更狂的使用方式。

这个更狂的使用方式和人类更接近,你想想看假设你去考,譬如说托福的听力测验,你是怎麼去考。

image-20220613190341900

“In-context” Learning

“Few-shot” Learning

举例来说假设要GPT这个模型做翻译:

image-20220613190432234

  • 你就先打Translate English to French

  • 就先给它这个句子,这个句子代表问题的描述

  • 然后给它几个范例跟它说,sea otter然后=>,后面就应该长这个样子

  • 或者是这个什麼plush girafe,plush girafe后面,就应该长这个样子等等

  • 然后接下来,你问它说cheese=>,叫它把后面的补完,希望它就可以產生翻译的结果

不知道大家能不能够了解,这一个想法是多麼地狂,在training的时候,GPT并没有教它做翻译这件事,它唯一学到的就是,给一段文字的前半段,把后半段补完,就像我们刚才给大家示范的例子一样,现在我们直接给它前半段的文字,就长这个样子,告诉它说你要做翻译了,给你几个例子,告诉你说翻译是怎麼回事,接下来给它cheese这个英文单字,后面能不能就直接接出,法文的翻译结果呢

这个在GPT的文献裡面,叫做==Few-shot Learning==,但是它跟一般的Few-shot Learning,又不一样,所谓Few Shot的意思是说,确实只给了它一点例子,所以叫做Few Shot,但是它不是一般的learning,这裡面完全没有gradient descent,完全没有要去调,GPT那个模型参数的意思,所以在GPT的文献裡面,把这种训练给了一个特殊的名字,它们叫做==In-context Learning==,代表说它不是一种,一般的learning,它连gradient descent都没有做

“One-shot” Learning “Zero-shot” Learning

当然你也可以给GPT更大的挑战,我们在考托福听力测验的时候,都只给一个例子而已,那GPT可不可以只看一个例子,就知道它要做翻译这件事,这个叫One-shot Learning。

image-20220613190603332

还有更狂的,是Zero-shot Learning,直接给它一个叙述,说我们现在要做翻译了,GPT能不能够自己就看得懂,就自动知道说要来做翻译这件事情呢,那如果能够做到的话,那真的就非常地惊人了,那GPT系列,到底有没有达成这个目标呢,这个是一个见仁见智的问题啦。

image-20220613190625552

它不是完全不可能答对,但是正确率有点低,相较於你可以微调模型,正确率是有点低的,那细节你就再看看GPT那篇文章。

第三代的GPT,它测试了42个任务,这个纵轴是正确率,这些实线 这三条实线,是42个任务的平均正确率,那这边包括了Few Shot,One Shot跟Zero Shot,三条线分别代表Few Shot,One Shot跟Zero Shot,横轴代表模型的大小,它们测试了一系列不同大小的模型,从只有0.1个billion的参数,到175个billion的参数,那从只有0.1个billion的参数,到175个billion的参数,我们看Few Shot的部分,从20几%的正确率 平均正确率,一直做到50几%的平均正确率,那至於50几%的平均正确率,算是有做起来 还是没有做起来,那这个就是见仁见智的问题啦。

目前看起来状况是,有些任务它还真的学会了,举例来说2这个加减法,你给它一个数字加另外一个数字,它真的可以得到,正确的两个数字加起来的结果,但是有些任务,它可能怎麼学都学不会,譬如说一些跟逻辑推理有关的任务,它的结果就非常非常地惨,好 那有关GPT3的细节,这个就留给大家再自己研究,然后这边有一个过去上课的录影,我把连结放在这边给大家参考。

Beyond Text

到目前為止我们举的例子,都是只有跟文字有关,但是你不要误会说,这种self-supervised learning的概念,只能用在文字上

在CV, CV就是computer vision,也就是影像,在语音跟影像的应用上也都可以用,self-supervised learning的技术,那其实今天,self-supervised learning的技术,非常非常地多,我们讲的BERT跟GPT系列,它只是三个类型的,这个self-supervised learning的方法,的其中一种,它们是属於prediction那一类。

image-20220613190824763

那其实还有其他的类型,那就不是我们这一堂课要讲的,那接下来的课程,你可能会觉得有点流水帐,就是我们每一个主题呢,就是告诉你说这个主题裡面,有什麼 但是细节这个更多的知识,就留给大家自己来做更进一步的研究,所以这些投影片,只是要告诉你说,在self-supervised learning这个部分,我们讲的只是整个领域的其中一小块,那还有更多的内容,是等待大家去探索的。

Image - SimCLR

好那有关影像的部分呢,我们就真的不会细讲,我这边就是放两页投影片带过去,告诉你说有一招非常有名的,叫做SimCLR,它的概念也不难,我相信你自己读论文,应该也有办法看懂它。

image-20220613190911297

Image - BYOL

那还有很奇怪的,叫做BYOL。BYOL这个东西呢,我们是不太可能在上课讲它,為什麼呢,因為根本不知道它為什麼会work,不是 这个是很新的论文,这个是去年夏天的论文,那这个论文是,假设它不是已经发表的文章,然后学生来跟我提这个想法,我一定就是,我一定不会让他做,这不可能会work的,这是个不可能会实现的想法,不可能会成功的,这个想法感觉有一个巨大的瑕疵,但不知道為什麼它是work的,而且还曾经一度得到,state of the art的结果,deep learning就是这麼神奇。

image-20220613190925800

Speech

那在语音的部分,你也完全可以使用,self-supervised learning的概念。

image-20220613191009513

你完全可以试著训练,语音版的BERT。那怎麼训练语音版的BERT呢,你就看看文字版的BERT,是怎麼训练的,譬如说做填空题,语音也可以做填空题,就把一段声音讯号盖起来,叫机器去猜盖起来的部分是什麼嘛,语音也可以预测接下来会出现的内容,讲GPT就是预测,接下来要出现的token嘛,那语音你也可以叫它预测,叫模型预测接下来会出现的声音去套,所以你也可以做语音版的GPT,不管是语音版的BERT,语音版的GPT,其实都已经有很多相关的研究成果了。

Speech GLUE - SUPERB

不过其实在语音上,相较於文字处理的领域,还是有一些比较缺乏的东西,那我认為现在很缺乏的一个东西,就是像GLUE这样子的benchmark corpus。

在自然语言处理的领域,在文字上有GLUE这个corpus,我们在这门课的刚开头,这个投影片的刚开头,就告诉你说有一个,这个基準的资料库叫做GLUE,它裡面有九个NLP的任务,今天你要知道BERT做得好不好,就让它去跑那九个任务在去平均,那代表这个self-supervised learning,模型的好坏。

但在语音上 到目前為止,还没有类似的基準的资料库,所以我们实验室就跟其他的研究团队,共同开发了一个语音版的GLUE。

image-20220613191139242

我们叫做SUPERB,它是Speech processing Universal,PERformance Benchmark的缩写,你知道今天你做什麼模型,都一定要硬凑梗才行啦,所以这边也是要硬凑一个梗,把它叫做SUPERB。

那其实我们已经準备了差不多了,其实网站都已经做好了,只等其他团队的人看过以后,就可以上线了,所以现在虽然还没有上线,但是再过一阵子,你应该就可以找得到相关的连结。

在这个基準语料库裡面,包含了十个不同的任务,那语音其实有非常多不同的面向,很多人讲到语音相关的技术,都只知道语音辨识把声音转成文字,但这并不是语音技术的全貌,语音其实包含了非常丰富的资讯,它除了有内容的资讯,就是你说了什麼,还有其他的资讯,举例来说这句话是谁说的,举例这个人说这句话的时候,他的语气是什麼样,还有这句话背后,它到底有什麼样的语意,所以我们準备了十个不同的任务,这个任务包含了语音不同的面向,包括去检测一个模型,它能够识别内容的能力,识别谁在说话的能力,识别他是怎麼说的能力,甚至是识别这句话背后语意的能力,从全方位来检测一个,self-supervised learning的模型,它在理解人类语言上的能力。

而且我们还有一个Toolkit,这个Toolkit裡面就包含了,各式各样的,self-supervised learning的模型:

image-20220613191333351

还有这些,self-supervised learning的模型,它可以做的,各式各样语音的下游的任务,然后把连结放在这边给大家参考。讲这些只是想告诉大家说,self-supervised learning的技术,不是只能被用在文字上,在这个影像上 在语音上,都仍然有非常大的空间可以使用,self-supervised learning的技术,好 那这个,self-supervised learning的部分呢,这个BERT跟GPT我们就讲到这边。

FastText

  • FastText代码详解(一) - BlockheadLS的文章 - 知乎 https://zhuanlan.zhihu.com/p/52154254
  • 【DL&NLP】fasttext不仅仅只做文本分类 - 叮当猫的文章 - 知乎 https://zhuanlan.zhihu.com/p/442768234
  • fastText原理及实践 - 陈运文的文章 - 知乎 https://zhuanlan.zhihu.com/p/32965521

Abstract

“本文探索了一种简单有效的文本分类基准(方法)。我们的实验表明,我们的快速文本分类器fastText在准确性方面与深度学习分类器平分秋色,其训练和评估速度(相比深度学习模型更是)要快许多个数量级。我们可以使用标准的多核CPU在不到10分钟的时间内用fastText训练超过10亿个单词,并在一分钟之内将50万个句子在31万2千个类中做分类。”

作者中又出现了托老师,不知道是不是受他影响,这篇文章在表述上也很有word2vec的味道,更不用说模型本身。fastText和word2vec的卖点都是简单高效(快)。

一、什么是fastText?

先说结论,fastText在不同语境中至少有两个含义:

  1. 在文章Bag of Tricks for Efficient Text Classification[1]中,fastText是作者提出的文本分类器的名字。与sub-word无关!也不是新的词嵌入训练模型!是word2vec中CBOW模型的简单变种。
  2. 作为Facebook开源包,fastText是用来训练词嵌入或句嵌入的,其不仅包括1中论文的代码实现,还包括Enriching Word Vectors with Subword Information[2]及FastText.zip: Compressing text classification models[3]两文的代码实现。

本来觉得这些含义区别不重要,直到连我自己都被弄迷糊了。在写这篇解读前,我心中的fastText一直是第三种含义:用sub-word信息加强词嵌入训练,解决OOV(Out-Of-Vocabulary)表征的方法。结果带着这个预先的理解读Bag of Tricks for Efficient Text Classification,越读越迷惑。

为理清思路,fastText(一)中我们就先讲讲Bag of Tricks for Efficient Text Classification中的fastText,fastText(二)则围绕Enriching Word Vectors with Subword Information。

二、一句话介绍fastText

word2vec的CBOW模型中将中心词替换为类别标签就得到了fastText。

具体到一些小区别:

  • CBOW中词袋的大小由window_size决定,而fastText中就是整个要分类的文本。
  • CBOW实际运行中用Hierarchical softmax,fastText用softmax或Hierarchical softmax,具体试类的数量决定。

这就是一个标配版且可以实际应用的fastText了,我要再强调三点它和CBOW无区别的地方,因为在别的讲该论文的文章中看到了一些错误的理解:

  • CBOW和fastText都是用平均值来预测的。(CBOW不是求和,是求平均)
  • N-gram对于CBOW和fastText都是锦上添花的元素,不是标配。
  • 词向量初始化都是随机的,fastText并没有在word2vec预训练词嵌入的基础上再训练。

文本相似度匹配

from 《Scaling Up All Pairs Similarity Search》

海量文本的成对相似度的高性能计算(待续) - 马东什么的文章 - 知乎 https://zhuanlan.zhihu.com/p/457947482

摘要:

对于高维空间中的大量稀疏向量数据,我们研究了寻找相似性分数(由余弦距离等函数确定)高于给定阈值的所有向量对的问题。我们提出了一个简单的算法,基于新的索引和优化策略,解决了这个问题,而不依赖于近似方法或广泛的参数调整。我们展示了该方法在广泛的相似阈值设置中有效地处理各种数据集,与以前的最先进的方法相比有很大的加速。

(海量成对文本相似度问题对于反欺诈而言非常重要,因为无论是电商中重要的地址信息,还是设备或用户的离散features之间的相似度计算和构图,都依赖于高性能的文本相似度计算方法,在实践中,我们不可能直接写双循环去做计算,即使是离线也往往需要耗费大量的时间)

一、介绍

许多现实世界的应用程序需要解决一个相似度搜索问题,在这个问题中,人们对所有相似度高于指定阈值的对象对都感兴趣。

  • web搜索的查询细化:搜索引擎通常会建议其他查询公式(例如你在百度中输入百,会给你推荐百度)。生成此类查询建议的一种方法是根据查询[19]的搜索结果的相似性来查找所有的相似查询对。由于目标是只提供高质量的建议,所以我们只需要找到相似度高于阈值的查询对(topk问题)。
  • 协同过滤:协同过滤算法通过确定哪些用户有相似的品味来进行推荐。因此,算法需要计算相似度高于某个阈值的相似用户对。
  • 接近重复的文档检测和消除:特别是在文档索引领域,检测和清除等价的文档是重要的。在许多情况下,由于简单的相等性检验不再满足要求,微小修改的存在使这种检测变得困难。通过具有很高的相似度阈值的相似度搜索,可以实现近重复检测(这方面的工作之前看过simhash,google做海量网页去重的方法)。
  • 团伙检测:最近的工作已经应用算法在一个应用程序中寻找所有相似的用户,以识别点击欺诈者[13]团伙。

Python 函数装饰器和闭包

函数装饰器用于在源码中“标记”函数,以某种方式增强函数的行为。这是一项强大的功能,但是若想掌握,必须理解闭包。

修饰器和闭包经常在一起讨论, 因为修饰器就是闭包的一种形式. 闭包还是回调式异步编程函数式编程风格的基础.装饰器是语法糖, 它其实是将函数作为参数让其他函数处理. 装饰器有两大特征:

  • 把被装饰的函数替换成其他函数
  • 装饰器在加载模块时立即执行

一、装饰器基础知识

装饰器可调用的对象, 其参数是另一个函数(被装饰的函数). 装饰器可能会处理被装饰的函数, 然后把它返回, 或者将其替换成另一个函数或可调用对象.

1
2
3
@decorate
def target():
print('running target()')复制代码

这种写法与下面写法完全等价:

1
2
3
def target():
print('running target()')
target = decorate(target)

要理解立即执行看下等价的代码就知道了, target = decorate(target) 这句调用了函数. 一般情况下装饰函数都会将某个函数作为返回值.

二、变量作用域规则

要理解装饰器中变量的作用域, 应该要理解闭包, 我觉得书里将闭包和作用域的顺序换一下比较好. 在python中, 一个变量的查找顺序是 LEGB (L:Local 局部环境,E:Enclosing 闭包,G:Global 全局,B:Built-in 内置).

1
2
3
4
5
6
7
8
9
10
base = 20 # 3
def get_compare():
base = 10 # 2
def real_compare(value):
base = 5 # 1
return value > base
return real_compare

compare_10 = get_compare()
print(compare_10(5))复制代码

在闭包的函数 real_compare 中, 使用的变量 base 其实是 base = 10 的. 因为base这个变量在闭包中就能命中, 而不需要去 global 中获取.

三、闭包

闭包其实挺好理解的, 当匿名函数出现的时候, 才使得这部分难以掌握. 简单简短的解释闭包就是:

名字空间与函数捆绑后的结果被称为一个闭包(closure).

这个名字空间就是 LEGB 中的 E . 所以闭包不仅仅是将函数作为返回值. 而是将名字空间和函数捆绑后作为返回值的. 多少人忘了理解这个 "捆绑" , 不知道变量最终取的哪和哪啊. 哎.

标准库中的装饰器

python内置了三个用于装饰方法的函数: propertyclassmethodstaticmethod . 这些是用来丰富类的.

1
2
3
4
class A(object):
@property
def age():
return 12

四、应用

非常适合有切面需求的场景,比如权限校验,日志记录和性能测试等等。比如你想要执行某个函数前记录日志或者记录时间来统计性能,又不想改动这个函数,就可以通过装饰器来实现。

不用装饰器,我们会这样来实现在函数执行前插入日志:
1
2
3
4
5
def foo():
print('i am foo')
def foo():
print('foo is running')
print('i am foo')

虽然这样写是满足了需求,但是改动了原有的代码,如果有其他的函数也需要插入日志的话,就需要改写所有的函数,不能复用代码。可以这么写

1
2
3
4
5
6
def use_logg(func):
logging.warn("%s is running" % func.__name__)
func()
def bar():
print('i am bar')
use_log(bar) #将函数作为参数传入

这样写的确可以复用插入的日志,缺点就是显示的封装原来的函数,我们希望透明的做这件事。用装饰器来写:

1
2
3
4
5
6
7
8
9
10
11
def use_log(func):
def wrapper(*args,**kwargs):
logging.warn('%s is running' % func.__name___)
return func(*args,**kwargs)
return wrapper

def bar():
print('I am bar')

bar = use_log(bar)
bar()

use_log() 就是装饰器,它把真正我们想要执行的函数 bar() 封装在里面,返回一个封装了加入代码的新函数,看起来就像是 bar() 被装饰了一样。这个例子中的切面就是函数进入的时候,在这个时候,我们插入了一句记录日志的代码。这样写还是不够透明,通过@语法糖来起到 bar = use_log(bar) 的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bar = use_log(bar)def use_log(func):
def wrapper(*args,**kwargs):
logging.warn('%s is running' % func.__name___)
return func(*args,**kwargs)
return wrapper

@use_log
def bar():
print('I am bar')

@use_log
def haha():
print('I am haha')

bar()
haha()
装饰器也是可以带参数的,这位装饰器提供了更大的灵活性。
1
2
3
4
5
6
7
8
9
10
11
12
13
def use_log(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper
return decorator

@use_log(level="warn")
def foo(name='foo'):
print("i am %s" % name)
foo()

实际上是对装饰器的一个函数封装,并返回一个装饰器。这里涉及到作用域的概念,之前有一篇博客提到过。可以把它看成一个带参数的闭包。当使用 @use_log(level='warn') 时,会将 level 的值传给装饰器的环境中。它的效果相当于 use_log(level='warn')(foo) ,也就是一个三层的调用。

这里有一个美中不足,decorator 不会改变装饰的函数的功能,但会悄悄的改变一个 __name__ 的属性(还有其他一些元信息),因为 __name__ 是跟着函数命名走的。 可以用 @functools.wraps(func) 来让装饰器仍然使用 func 的名字。functools.wraps 也是一个装饰器,它将原函数的元信息拷贝到装饰器环境中,从而不会被所替换的新函数覆盖掉。

1
2
3
4
5
6
7
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper

柳星-我对安全与NLP的实践和思考

404notf0und/FXY

一、个人思考

通过对安全与NLP的实践和思考,有以下三点产出:

  • 首先,产出一种通用解决方案和轮子,一把梭实现对各种安全场景的安全检测。通用解决方案给出一类安全问题的解决思路,打造轮子来具体解决这一类问题,而不是使用单个技术点去解决单个问题。具体来说,将安全与NLP结合,在各种安全场景中,将其安全数据统一视作文本数据,从NLP视角,统一进行文本预处理、特征化、预训练和模型训练。例如,在Webshell检测中,Webshell文件内容,在恶意软件检测中,API序列,都可以视作长文本数据,使用NLP技术进行分词、向量化、预训练等操作,同理,在Web安全中,SQl、XSS等URL类安全数据,在DNS安全中,DGA域名、DNS隧道等域名安全数据,同样可以视作短文本数据。因此,只要安全场景中安全数据可以看作文本数据,FXY:Security-Scenes-Feature-Engineering-Toolkit 中,内置多种通用特征化方法和多种通用深度学习模型,以支持多种安全场景的特征化和模型训练,达到流水线式作业。
  • 其次,是对应用能力和底层能力的思考。之前写过一篇文章《应用型安全算法工程师的自我修养》,在我当时预期想法中,我理解的应用型,重点在于解决实际安全问题,不必苛求于对使用技术本身的理解深度,可以不具备研究型、轮子型的底层能力。映射到我自身,我做安全和算法,最初想法很好,安全和算法两者我都要做好,这里做好,仅仅指用好。之后,面试时暴露了问题,主管给出的建议是两者都要做好。这里做好,不单单指用好,还要知其所以然。举个例子,就是不仅要调包调参玩的6,还要掌握算法的底层原理,这就是底层能力。当时,懂,也不懂,似懂非懂,因为,说,永远是别人的,悟,才是自己的。在实现通用解决方案和轮子的过程中,遇到关于word2vec底层的非预期问题,才深刻体会到,底层能力对应用能力的重要性。过程中遇到的预期和非预期问题,下文会详述。现在我理解的应用型,重点还是在解决安全问题,以及对安全问题本身的理解,但应用型还需具备研究型、轮子型等上下游岗位的底层能力。安全算法是这样,其他细分安全领域也是一样,都需要底层能力,以发展技术深度。
  • 最后,带来思考和认识的提升。从基于机器学习的XX检测,基于深度学习的XX检测,等各种单点检测,到基于NLP的通用安全检测,是一个由点到面的认知提升。从安全和算法都要做好,到安全和算法都要做好,其中蕴含着认知的提升。从之前写过一篇安全与NLP的文章《当安全遇上NLP》,到现在这篇文章。对一件事物的认识,在不同阶段应该是不一样的,甚至可能完全推翻自己之前的认识。我们能做的,是保持思考,重新认识过去的经历,提升对事物的认知和认知能力。这个提升认知的过程,类似boosting的残差逼近和强化学习的奖惩,是一个基于不知道不知道->知道不知道>知道知道->不知道知道的螺旋式迭代上升过程。

二、预期问题

2.1 分词粒度

首先是分词粒度,粒度这里主要考虑字符粒度和词粒度。在不同的安全场景中,安全数据不同,采用的分词粒度也可能不同:

  • 恶意样本检测的动态API行为序列数据,需要进行单词粒度的划分。
  • 域名安全检测中的域名数据,最好采用字符粒度划分。
  • URL安全检测中的URL数据,使用字符和单词粒度划分都可以。
  • XSS检测文中,是根据具体的XSS攻击模式,写成正则分词函数,对XSS数据进行划分,这是一种基于攻击模式的词粒度分词模式,但这种分词模式很难扩展到其他安全场景中。

FXY特征化类wordindex和word2vec中参数char_level实现了该功能。在其他安全场景中,可以根据此思路,写自定义的基于攻击模式的分词,但适用范围有限。我这里提供了两种通用词粒度分词模式,第一种是忽略特殊符号的简洁版分词模式,第二种是考虑全量特殊符号的完整版分词模式,这两种分词模式可以适用于各种安全场景中。FXY特征化类word2vec中参数punctuation的值‘concise’,‘all’和‘define’实现了两种通用分词和自定义安全分词功能。下文的实验部分,会测试不同安全场景中,使用字符粒度和词粒度,使用不同词粒度分词模式训练模型的性能对比。

2.2 语料库

关于预训练前字典的建立(语料库)。特征化类word2vec的预训练需求直接引发了字典建立的相关问题。在word2vec预训练前,需要考虑预训练数据的产生。基于深度学习的XSS检测文中,是通过建立一个基于黑样本数据的指定大小的字典,不在字典内的数据全部泛化为一个特定词,将泛化后的数据作为预训练的数据。这里我们将此思路扩充,增加使用全量数据建立任意大小的字典。具体到word2vec类中,参数one_class的True or False决定了预训练的数据来源是单类黑样本还是全量黑白样本,参数vocabulary_size的值决定了字典大小,如果为None,就不截断,为全量字典数据。下文的实验部分会测试是单类黑样本预训练word2vec好,还是全量数据预训练更占优势,是字典截断好,还是用全量字典来预训练好。

2.3 序列

关于序列的问题,具体地说,是长文本数据特征化需求webshell检测等安全场景,引发了序列截断和填充的问题。短文本数据的特征化,可以保留所有原始信息。而在某些安全场景中的长文本数据,特征化比较棘手,保留全部原始信息不太现实,需要对其进行截断,截断的方式主要有字典截断、序列软截断、序列硬截断

  • 序列软截断是指对不在某个范围内(参数num_words控制范围大小)的数据,直接去除或填充为某值,长文本选择直接去除,缩短整体序列的长度,尽可能保留后续更多的原始信息。如果长本文数据非常非常长,那么就算有字典截断和序列软截断,截断后的序列也可能非常长,超出了模型和算力的承受范围;
  • 序列硬截断(参数max_length控制)可以发挥实际作用,直接整整齐齐截断和填充序列,保留指定长度的序列数据。这里需要注意的是,为了兼容后文将说到的“预训练+微调”训练模式中的预训练矩阵,序列填充值默认为0。

2.4 词向量

词向量的问题,具体说,是词嵌入向量问题。词嵌入向量的产生有三种方式:

  • 词序列索引+有嵌入层的深度学习模型
  • word2vec预训练产生词嵌入向量+无嵌入层的深度学习模型
  • word2vec预训练产生预训练矩阵+初始化参数为预训练矩阵的嵌入层的深度学习模型。

这里我把这三种方式简单叫做微调、预训练、预训练+微调,从特征工程角度,这三种方式是产生词嵌入向量的方法,从模型角度,也可以看作是模型训练的三种方法。第一种微调的方式实现起来比较简单,直接使用keras的文本处理类Tokenizer就可以分词,转换为词序列,得到词序列索引,输入到深度学习模型中即可。第二种预训练的方式,调个gensim库中word2vec类预训练,对于不在预训练字典中的数据,其词嵌入向量直接填充为0,第三种预训练+微调的方式,稍微复杂一点,简单来说就是前两种方式的组合,用第二种方式得到预训练矩阵,作为嵌入层的初始化权重矩阵参数,用第一种方式得到词序列索引,作为嵌入层的原始输入。下文的实验部分会测试并对比按这三种方式训练模型的性能,先说结论:预训练+微调>预训练>微调

三、非预期问题

3.1 已知的库和函数不能满足我们的需求

使用keras的文本处理类Tokenizer预处理文本数据,得到词序列索引,完全没有问题。但类Tokenizer毕竟是文本数据处理类,没有考虑到安全领域的需求。 + 类Tokenizer的单词分词默认会过滤所有的特殊符号,仅保留单词,而特殊符号在安全数据中是至关重要的,很多payload的构成都有着大量特殊符号,忽略特殊符号会流失部分原始信息。 + 首先阅读了keras的文本处理源码和序列处理源码,不仅搞懂了其结构和各函数的底层实现方式,还学到了一些trick和优质代码的特性。搞懂了其结构和各函数的底层实现方式,还学到了一些trick和优质代码的特性。下图为Tokenizer类的结构。借鉴并改写Tokenizer类,加入了多种分词模式,我们实现了wordindex类。

img

3.2 对word2vec的理解不到位

第二个非预期问题是,对word2vec的理解不到位,尤其是其底层原理和代码实现,导致会有一些疑惑,无法得到验证,这是潜在的问题。虽然可以直接调用gensim库中的word2vec类暂时解决问题,但我还是决定把word2vec深究深究,一方面可以答疑解惑,另一方面,就算不能调用别人的库,自己也可以造轮子自给自足。限于篇幅问题,不多讲word2vec的详细原理,原理是我们私下里花时间可以搞清楚的,不算是干货,对原理有兴趣的话,这里给大家推荐几篇优质文章,在github仓库Always-Learning中。

word2vec本质上是一个神经网络模型,具体来说此神经网络模型是一个输入层-嵌入层-输出层的三层结构,我们用到的词嵌入向量只是神经网络模型的副产物,是模型嵌入层的权重矩阵。以word2vec实现方式之一的skip-gram方法为例,此方法本质是通过中心词预测周围词。如果有一段话,要对这段话训练一个word2vec模型,那么很明显需要输入数据,还要是打标的数据。以这段话中的某个单词为中心词为例,在一定滑动窗口内的其他单词都默认和此单词相关,此单词和周围其他单词,一对多产生多个组合,默认是相关的,因此label为1,即是输入数据的y为1,而这些单词组合的one-hot编码是输入数据的x。那么很明显label全为1,全为positive sample,需要负采样来中和。这里的负采样不是简单地从滑动窗口外采样,而是按照词频的概率,取概率最小的一批样本来做负样本(这个概念下面马上要用到),因为和中心词毫不相关,自然label为0。

tensorflow中的nce_loss函数实现了负采样。