PowerLZY's Blog

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

PyTorch 资料

  • PyTorch 1.7.0 文档

  • https://www.w3cschool.cn/pytorch/pytorch-mrni3btn.html

  • https://handbook.pytorch.wiki/chapter1/1.1-pytorch-introduction.html

  • LSTM细节分析理解(pytorch版):https://zhuanlan.zhihu.com/p/79064602

  • OLD:https://www.pytorch123.com/SixthSection/Dcgan/

  • PyTorch 学习笔记汇总(完结撒花) - 张贤同学的文章 - 知乎 https://zhuanlan.zhihu.com/p/265394674

PyTorch 学习笔记

在线电子书:https://pytorch.zhangxiann.com/

配套代码:https://github.com/zhangxiann/PyTorch_Practice

一、基本概念

1.1 Pytorch 简介与安装

1.2 Tensor 张量介绍

img

1.2.1 直接创建 Tensor

torch.tensor()

1
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
  • data: 数据,可以是 list,numpy
  • dtype: 数据类型,默认与 data 的一致
  • device: 所在设备,cuda/cpu
  • requires_grad: 是否需要梯度
  • pin_memory: 是否存于锁页内存

torch.from_numpy(ndarray)

从 numpy 创建 tensor。利用这个方法创建的 tensor 和原来的 ndarray 共享内存,当修改其中一个数据,另外一个也会被改动。

img

1.2.2 根据数值创建 Tensor

torch.zeros():根据 size 创建全 0 张量

1
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • size: 张量的形状
  • out: 输出的张量,如果指定了 out,那么torch.zeros()返回的张量和 out 指向的是同一个地址
  • layout: 内存中布局形式,有 strided,sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用。
  • device: 所在设备,cuda/cpu
  • requires_grad: 是否需要梯度

torch.full(),torch.full_like():创建自定义数值的张量

1
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • size: 张量的形状,如 (3,3)
  • fill_value: 张量中每一个元素的值

torch.arange():创建等差的 1 维张量。注意区间为[start, end)。

1
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • start: 数列起始值
  • end: 数列结束值,开区间,取不到结束值
  • step: 数列公差,默认为 1

torch.linspace():创建均分的 1 维张量。数值区间为 [start, end]

1
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • start: 数列起始值
  • end: 数列结束值
  • steps: 数列长度 (元素个数)

1.2.3 根据概率创建 Tensor

torch.normal()

1
torch.normal(mean, std, *, generator=None, out=None)

功能:生成正态分布 (高斯分布)

  • mean: 均值
  • std: 标准差

==1.3 张量操作与线性回归==

==1.3.1 拼接==:cat、stack

torch.cat():将张量按照 dim 维度进行拼接

1
torch.cat(tensors, dim=0, out=None)
  • tensors: 张量序列 [t, t]
  • dim: 要拼接的维度

torch.stack():将张量在==新创建的 dim 维度==上进行拼接,已有维度后移

1
torch.stack(tensors, dim=0, out=None)
  • tensors: 张量序列
  • dim: 要拼接的维度

==1.3.2 切分==:chunk、split

torch.chunk():将张量按照维度 dim 进行平均切分。若不能整除,则最后一份张量小于其他张量。

1
2
torch.chunk(input, chunks, dim=0)
torch.chunk(a, dim=1, chunks=3)
  • input: 要切分的张量
  • chunks: 要切分的份数
  • dim: 要切分的维度

torch.split():将张量按照维度 dim 进行平均切分。可以指定每一个==分量的切分长度==。

1
2
torch.split(tensor, split_size_or_sections, dim=0)
torch.split(t, [2, 1, 2], dim=1)
  • tensor: 要切分的张量
  • split_size_or_sections: 为 int 时,表示每一份的长度,如果不能被整除,则最后一份张量小于其他张量;为 list 时,按照 list 元素作为每一个分量的长度切分。如果 list 元素之和不等于切分维度 (dim) 的值,就会报错。
  • dim: 要切分的维度

==1.3.3 索引==

torch.index_select():在维度 dim 上,按照 index 索引取出数据拼接为张量返回。

1
torch.index_select(input, dim, index, out=None)

功能:在维度 dim 上,按照 index 索引取出数据拼接为张量返回。torch.tensor([0, 2], dtype=torch.long)

  • input: 要索引的张量
  • dim: 要索引的维度
  • index: 要索引数据的序号

torch.mask_select():按照 mask 中的 True 进行索引拼接得到一维张量返回。

1
torch.masked_select(input, mask, out=None)
  • 要索引的张量
  • mask: 与 input 同形状的布尔类型张量

==1.3.4 变换==

torch.reshape():变换张量的形状。当张量在内存中是连续时,返回的张量和原来的张量共享数据内存,改变一个变量时,另一个变量也会被改变。

1
2
torch.reshape(input, shape)
torch.reshape(t, (-1, 2, 2))
  • input: 要变换的张量
  • shape: 新张量的形状

torch.transpose():交换张量的两个维度。常用于图像的变换,比如把c*h*w变换为h*w*c

1
torch.transpose(input, dim0, dim1)
  • input: 要交换的变量
  • dim0: 要交换的第一个维度
  • dim1: 要交换的第二个维度

torch.t():2 维张量转置,对于 2 维矩阵而言,等价于torch.transpose(input, 0, 1)

torch.squeeze():压缩长度为 1 的维度

1
torch.squeeze(input, dim=None, out=None)
  • dim: 若为 None,则移除所有长度为 1 的维度;若指定维度,则当且仅当该维度长度为 1 时可以移除。

torch.unsqueeze():根据 dim 扩展维度,长度为 1。

1
torch.unsqueeze(input, dim)

==1.3.5 张量的数学运算==

加减乘除,对数,指数,幂函数 和三角函数。

torch.add(): 逐元素计算 input + alpha * other。因为在深度学习中经常用到先乘后加的操作。

1
2
torch.add(input, other, out=None)
torch.add(input, other, *, alpha=1, out=None)
  • input: 第一个张量
  • alpha: 乘项因子
  • other: 第二个张量

torch.addcdiv()

1
torch.addcdiv(input, tensor1, tensor2, *, value=1, out=None)

计算公式为:out [公式] value [公式]

torch.addcmul()

1
torch.addcmul(input, tensor1, tensor2, *, value=1, out=None)

计算公式为:out [公式] input [公式] value [公式] tensor [公式] tensor [公式]

==Pytorch 线性回归==

线性回归是分析一个变量 ([公式]) 与另外一 (多) 个变量 ([公式]) 之间的关系的方法。一般可以写成 [公式]。线性回归的目的就是求解参数 [公式]

线性回归的求解可以分为 3 步:

  1. 确定模型:[公式]
  2. 选择损失函数,一般使用均方误差 MSE:[公式]。其中 [公式] 是预测值,[公式] 是真实值。
  3. 使用梯度下降法求解梯度 (其中 [公式] 是学习率),并更新参数:
  • [公式]
  • [公式]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
代码如下:

import torch
import matplotlib.pyplot as plt
torch.manual_seed(10)

lr = 0.05 # 学习率

# 创建训练数据
x = torch.rand(20, 1) * 10 # x data (tensor), shape=(20, 1)
# torch.randn(20, 1) 用于添加噪声
y = 2*x + (5 + torch.randn(20, 1)) # y data (tensor), shape=(20, 1)

# 构建线性回归参数
w = torch.randn((1), requires_grad=True) # 设置梯度求解为 true
b = torch.zeros((1), requires_grad=True) # 设置梯度求解为 true

# 迭代训练 1000 次
for iteration in range(1000):

# 前向传播,计算预测值
wx = torch.mul(w, x)
y_pred = torch.add(wx, b)

# 计算 MSE loss
loss = (0.5 * (y - y_pred) ** 2).mean()

# 反向传播
loss.backward()

# 更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)

# 每次更新参数之后,都要清零张量的梯度
w.grad.zero_()
b.grad.zero_()

# 绘图,每隔 20 次重新绘制直线
if iteration % 20 == 0:

plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(1.5, 10)
plt.ylim(8, 28)
plt.title("Iteration: {}\nw: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
plt.pause(0.5)

# 如果 MSE 小于 1,则停止训练
if loss.data.numpy() < 1:
break

应该是指可以打通整个项目开发过程的,比如基于BS架构的话,就是熟悉前后端,知道怎么把算法模型部署到后端服务器,熟悉分布式计算,能玩转mapreduce,spark,hadoop,能熟练搭建项目框架

三、大数据(简单了解其中一二个)

Hadoop基础、MapReduce、spark、hive、flink

hadoop和spark的区别和联系

==总结一句话:spark在hadoop肩膀上可以让大数据跑的更快==

一、 hadoop

1.1 hadoop简介

Hadoop是一个由Apache基金会所开发的分布式系统基础架构Hadoop实现了一个分布式文件系统HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的硬件上;而且它提供高吞吐量来访问应用程序的数据,适合那些有着超大数据集的应用程序。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,而MapReduce则为海量的数据提供了计算

1.2 hadoop优点

Hadoop 以一种可靠、高效、可伸缩的方式进行数据处理。

  • 可靠性: Hadoop将数据存储在多个备份,Hadoop提供高吞吐量来访问应用程序的数据。

  • 高扩展性: Hadoop是在可用的计算机集簇间分配数据并完成计算任务的,这些集簇可以方便地扩展到数以千计的节点中。

  • 高效性: Hadoop以并行的方式工作,通过并行处理加快处理速度。

  • 高容错性: Hadoop能够自动保存数据的多个副本,并且能够自动将失败的任务重新分配。

  • 低成本: Hadoop能够部署在低廉的(low-cost)硬件上。

二、spark

2.1 spark简介

Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark拥有Hadoop MapReduce所具有的优点,Spark在Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark性能以及运算速度高于MapReduce。

2.2 spark优点

计算速度快: 因为spark从磁盘中读取数据,把中间数据放到内存中,,完成所有必须的分析处理,将结果写回集群,所以spark更快。

  • Spark 提供了大量的库: 包括Spark Core、Spark SQL、Spark Streaming、MLlib、GraphX。

  • 支持多种资源管理器: Spark 支持 Hadoop YARN,及其自带的独立集群管理器

  • 操作简单: 高级 API 剥离了对集群本身的关注,Spark 应用开发者可以专注于应用所要做的计算本身

三、spark与hadoop的不同点

3.1 应用场景不同

Hadoop和Spark两者都是大数据框架,但是各自应用场景是不同的。Hadoop是一个分布式数据存储架构,它将巨大的数据集分派到一个由普通计算机组成的集群中的多个节点进行存储,降低了硬件的成本Spark是那么一个专门用来对那些分布式存储的大数据进行处理的工具,它要借助hdfs的数据存储

3.2 处理速度不同

hadoop的MapReduce是分步对数据进行处理的,从磁盘中读取数据,进行一次处理,将结果写到磁盘,然后在从磁盘中读取更新后的数据,再次进行的处理,最后再将结果存入磁盘,这存取磁盘的过程会影响处理速度。spark从磁盘中读取数据,把中间数据放到内存中,,完成所有必须的分析处理,将结果写回集群,所以spark更快。

3.3 容错性不同

Hadoop将每次处理后的数据都写入到磁盘上,基本谈不上断电或者出错数据丢失的情况。Spark的数据对象存储在弹性分布式数据集 RDD,RDD是分布在一组节点中的只读对象集合,如果数据集一部分丢失,则可以根据于数据衍生过程对它们进行重建。而且RDD 计算时可以通过 CheckPoint 来实现容错。

四、spark与hadoop的联系

Hadoop提供分布式数据存储功能HDFS,还提供了用于数据处理的MapReduce。 MapReduce是可以不依靠spark数据的处理的。当然spark也可以不依靠HDFS进行运作,它可以依靠其它的分布式文件系统。但是两者完全可以结合在一起,hadoop提供分布式集群和分布式文件系统spark可以依附在hadoop的HDFS代替MapReduce弥补MapReduce计算能力不足的问题。

数据湖(Data Lake) 总结

  • https://zhuanlan.zhihu.com/p/91165577

数据湖从本质上来讲,是一种企业数据架构方法,物理实现上则是一个数据存储平台,用来集中化存储企业内海量的、多来源,多种类的数据,并支持对数据进行快速加工和分析。

数据湖是一种在系统或存储库中以自然格式存储数据的方法,它有助于以各种模式和结构形式配置数据,通常是对象块或文件。数据湖的主要思想是对企业中的所有数据进行统一存储,从原始数据(源系统数据的精确副本)转换为用于报告、可视化、分析和机器学习等各种任务的目标数据。数据湖中的数据包括==结构化数据==(关系数据库数据),==半结构化数据==(CSV、XML、JSON等),==非结构化数据==(电子邮件,文档,PDF)和==二进制数据==(图像、音频、视频),从而形成一个容纳所有形式数据的==集中式数据存储==。

从实现方式来看,目前Hadoop是最常用的部署数据湖的技术,但并不意味着数据湖就是指Hadoop集群。为了应对不同业务需求的特点,MPP数据库+Hadoop集群+传统数据仓库这种“混搭”架构的数据湖也越来越多出现在企业信息化建设规划中。

The Forrester Wave™: Endpoint Detection And Response Providers, Q2 2022

在我们对端点检测和响应提供商的 20 个标准评估中,我们确定了 15 个最重要的——Bitdefender、BlackBerry Cylance、Check Point Software Technologies、CrowdStrike、Cybereason、Elastic、FireEye、Fortinet、McAfee、Microsoft、Palo Alto Networks、SentinelOne 、Sophos、趋势科技和 VMware Carbon Black — 并对它们进行了研究、分析和评分。该报告显示了每个供应商如何衡量并帮助安全专业人员根据他们的需求选择合适的供应商。

image-20220426183404208

CrowdStrike《无文件攻击白皮书》解析

原文链接:https://www.secrss.com/articles/26671

CrowdStrike是端点保护平台(EPP)的最强者,是云交付的下一代端点保护的领导者。由于CrowdStrike邮件推送了“无文件攻击白皮书”《谁需要恶意软件?对手如何使用无文件攻击来规避你的安全措施》(Who Needs Malware? How Adversaries Use Fileless Attacks To Evade Your Security),笔者顺手对其进行了全文翻译

无文件攻击(Fileless attack)不向磁盘写入可执行文件的攻击方法,难以被常规方法检测出来。根据CrowdStrike统计,“10个成功突破的攻击向量中有8个使用了无文件攻击技术。”即 80%的成功入侵都使用了无文件攻击 根据二八原理,这显然是安全人员应该高度关注的技术类型。

无文件攻击白皮书解释了无文件攻击的工作原理、传统解决方案失效的原因,以及CrowdStrike解决该难题的方法。CrowdStrike的解决方案是应用程序清单、漏洞利用阻断、攻击指标(IOA)、托管狩猎、无签名人工智能等技术的集成化方法

除了全文翻译外,笔者主要在文末做了两块内容增补:一是关于CrowdStrikeThreat Graph(威胁图)的技术思想,因为威胁图 是 CrowdStrike Falcon(猎鹰)端点保护平台的“ 大脑” ;二是 关于CrowdStrike提出的攻击指标(IOA)与传统的失陷指标(IOC)的对比。笔者认为,这两类技术领域具有战略价值。如果说全文翻译只花费一小时的话,这些增补内容反而消耗了笔者两个小时。

img

随着安全措施在检测和阻止恶意软件和网络攻击方面越来越出色,对手和网络犯罪分子被迫不断开发新技术来逃避检测。其中一种高级技术涉及 “无文件”(fileless)攻击,即不向磁盘写入可执行文件。这类攻击特别有效地躲避了传统防病毒(AV)解决方案,因为传统防病毒(AV)方法寻找被保存到磁盘上的文件并扫描这些文件以确定它们是否恶意。

虽然无文件攻击并不新鲜,但它们正变得越来越普遍。在2016年的调查中,CrowdStrike Services事件响应团队发现,10个成功入侵的攻击向量中有8个使用了无文件攻击技术。为了帮助您了解无文件攻击所带来的风险,本白皮书解释了无文件攻击的工作原理、当前解决方案对其无能为力的原因,以及CrowdStrike解决这一难题的行之有效的方法。

什么是无文件攻击?

当攻击者通过消除将PE(可移植可执行文件)复制到磁盘驱动器的传统步骤来逃避检测时,就会发生无文件或无恶意软件的攻击。有多种技术可以采取这种方式危害系统

  • 漏洞利用和漏洞利用工具包,通常通过利用操作系统(OS)或已安装应用程序中存在的漏洞,直接在内存中执行攻击。

  • 使用盗用的凭证,是发起无文件攻击的另一种普遍方法。Verizon在其2017年的DBIR(数据泄露调查报告)中发现,81%的数据泄露涉及弱口令、默认口令或被盗口令,比上一年增加了18%。这使得攻击者能够像普通用户一样访问系统。

  • 一旦实现初步突破,对手就可以依赖操作系统本身提供的工具,如Windows管理工具和Windows PowerShell,以执行进一步的操作,而不必将文件保存到磁盘。例如,它们可以通过在注册表、内核中隐藏代码,或者通过创建允许它们随意访问系统的用户帐户来建立持久化,而无需向磁盘写入任何内容。

在安全行业,对上述这些技术的使用,通常被称为“living off the land”(离地生存?生存手段?)。

真实案例:一个无文件入侵的解剖

通过展示CrowdStrike Services事件响应团队发现的一个真实的案例,我们可以检查端到端的无恶意软件入侵是什么样子。

在本例中,首个目标是使用Microsoft ISS并运行SQL服务器数据库的web服务器。对于最初的入侵,攻击者使用了一个web shell,一个可以被上传到web服务器并在其上执行的简短脚本。脚本可以用web服务器支持的任何语言编写,比如Perl、Python、ASP或PHP。Web Shell在此类攻击中很流行,因为它们可以通过利用系统上存在的漏洞直接加载到内存中,而无需将任何内容写入磁盘。在这一特定的攻击中,对手使用SQL注入,将其web shell嵌入到服务器。

WEB Shell允许使用web浏览器来远程访问系统。它们可以用ASP或PHP或任何其他web脚本语言编写,代码可以非常小。如下所示:

img

由于web服务器没有正确检查转义字符,攻击者能够简单地将web shell回传到服务器上。所用的web shell,名为“China Chopper”(中国菜刀/直升机),包含了JavaScript命令,值得注意的是它只使用了72个字符。在内存中执行web shell,使攻击者能够使用Chopper用户界面,对web服务器执行任意命令。通过对web服务器的完全远程访问,攻击者通过执行编码的PowerShell命令,来窃取凭据。

第一步是从远程服务器下载脚本,将脚本直接加载到内存中,然后执行它。这个脚本反过来窃取了缓存在web服务器内存中的所有纯文本密码。在几秒钟内,攻击者获得了系统上所有帐户的多个用户名和密码。

PowerShell是一个合法的Windows工具,它允许攻击者在受损系统上执行任何操作,而不必在磁盘上写入恶意软件。为了进一步做混淆,攻击者可以对其PowerShell脚本进行编码,如下所示:

img

下一步是让攻击者在服务器上实现持久化。为了在不需要任何恶意软件的情况下执行此操作,攻击者使用了一种称为“粘滞键”(Sticky Keys)的技术。通过修改Windows注册表中的一行,攻击者可以使用PowerShell或WMI命令,轻松完成此操作,从而将Windows屏幕键盘进程,设置为调试模式

粘滞键(Sticky Keys)是使攻击者无需登录凭据即可访问命令shell的注册表项。如下所示:

img

当设置为调试模式时,屏幕键盘允许具有远程访问权限的任何人,以系统权限打开命令行,而无需登录。一旦设置了该注册表项,攻击者可以通过打开到web服务器的远程桌面连接,随时返回。此外,访问系统而不在Windows事件历史记录中生成登录事件,会使攻击者的行为几乎无法追踪。

现在小结一下,本案例中,在不同的攻击阶段所使用的文件技术包括:

  • 初始入侵:针对Web服务器的SQL注入攻击;

  • 命令与控制(C2):“中国菜刀/直升机”的Web Shell

  • 提升权限:使用PowerShell脚本转储凭据

  • 建立持久化:修改注册表粘滞键技术。

作案工具:真实世界的无文件恶意软件

无文件恶意软件经常使用的工具和技术包括:

  • 漏洞利用工具包
  • 利用合法工具,如WMI和PowerShell
  • 使用被盗凭证
  • 注册表驻留恶意软件
  • 内存型(Memory-only)恶意软件

1)漏洞利用工具包(Exploit kits)

漏洞利用是一种允许攻击者利用操作系统或应用程序漏洞来访问系统的技术。漏洞利用是一种高效的无文件技术,因为它们可以直接注入内存中,而无需将任何内容写入磁盘。

通过允许攻击者自动化和大规模执行初始突破,漏洞利用工具包使得攻击者的生活更轻松、工作更高效。所需要做的只是,诱使受害者进入漏洞利用工具包服务器,办法通常是网络钓鱼或社会工程。

这些工具包通常提供对许多漏洞的攻击,以及一个管理控制台,一旦成功利用漏洞,攻击者就可以控制失陷的系统。有些漏洞利用工具包甚至提供了扫描受害者系统中的漏洞的功能,因此可以快速构建并启动成功的漏洞攻击。

2)注册表驻留恶意软件

注册表驻留恶意软件是安装在Windows注册表中的恶意软件,以便在逃避检测的同时,保持持久性。第一种是Poweliks,此后就出现了许多变体。一些变体,如Kovter,使用了类似的注册表隐藏技术,来保持不被发现。Poweliks调用C2(命令和控制)服务器,攻击者可以从该服务器向受损系统发送进一步的指令。所有这些操作,都可以在没有任何文件写入磁盘的情况下进行。

3)内存型(Memory-only)恶意软件

有些恶意软件只存在于内存中,以逃避检测。新版本的Duqu蠕虫就是这种情况,它只驻留在内存中,不会被发现。Duqu 2.0有两个版本:第一个是后门,它允许攻击者在组织中站稳脚跟。如果攻击者认为目标值得攻击,他可以使用Duqu 2.0的高级版本,该版本提供了诸如侦察、横向移动、数据渗出等附加功能。Duqu2.0以成功攻破电信行业的公司以及至少一家知名的安全软件提供商而闻名。

4)无文件型勒索软件

甚至勒索软件攻击者,现在也在使用无文件技术,来实现他们的目标。在这类勒索软件中,恶意代码要么嵌入文档中以使用本机脚本语言(如宏),要么使用漏洞直接写入内存。然后,勒索软件使用合法的管理工具如PowerShell,来加密人质文件,而所有这些都不需要写入磁盘。

为何传统技术无法抵御无文件攻击

由于传统安全解决方案极难检测到无文件攻击,因此无文件攻击正在增加。让我们来看看,为什么当今市场上的一些端点保护技术,对这些无恶意软件入侵如此脆弱。

1)传统防病毒(AV)旨在寻找已知恶意软件的特征码。由于无文件攻击没有恶意软件,所以AV没有可检测的特征码。

2)基于机器学习(ML)的反恶意软件方法,在应对无文件攻击时,面临着与传统AV相同的挑战。ML动态分析未知文件,并将其区分为好的或坏的。但是我们已经注意到,在无文件攻击中,没有要分析的文件,因此ML无法提供帮助。

3)白名单方法包括列出一台机器上所有良好的进程,以防止未知进程执行。无文件攻击的问题在于,它们利用易受攻击的合法白名单应用程序,并利用内置的操作系统可执行文件。阻止用户和操作系统共同依赖的应用程序,并不是一个好的选项。

4)使用失陷指标(IOC)工具来防止无文件攻击也不是很有效。本质上,IOC类似于传统的AV签名,因为它们是攻击者留下的已知恶意制品。然而,由于它们利用合法的进程,并且在内存中操作,所以无文件攻击不会留下制品,因此IOC工具几乎找不到任何东西。

5)另一种方法涉及沙箱,它可以采取多种形式,包括基于网络的爆破和微虚拟化。由于无文件攻击不使用PE文件,因此沙盒没有什么可爆破的。即便真有东西被发送到沙箱,因为无文件攻击通常会劫持合法进程,大多数沙箱也都会忽略它。

CrowdStrike的解决方案

正如我们所看到的,如果您依赖基于签名的方法、沙盒、白名单甚至机器学习保护方法,那么想检测无文件技术是非常有挑战性的。

为了抵御秘密的、无文件的攻击,CrowdStrike独特地将多种方法结合到一个强大的集成式方法中,提供了无与伦比的端点保护。CrowdStrikeFalcon平台通过单个的轻量级代理提供了云原生的下一代端点保护,并提供一系列互补的预防和检测方法:

  • 应用程序清单(Application inventory):可以发现在您的环境中运行的任何应用程序,帮助您找到漏洞,以便您可以修补或更新它们,使之不会成为漏洞利用工具包的目标。

  • 漏洞利用阻断(Exploit blocking):通过未修补漏洞的漏洞利用方法,来阻断无文件攻击的执行。

  • 攻击指标(IOA,Indicators of Attack):在攻击的早期阶段,识别并阻止恶意活动,以免其完全执行并造成损害。此能力还可以防止那些新的勒索软件类别,那些勒索软件不使用文件加密受害者系统。**

  • 托管狩猎(Managed hunting):全天候地主动搜索由于无文件技术而产生的恶意活动。

IOA(攻击指标)的力量

IOA检测恶意软件或攻击完成其任务所必须执行的事件序列, IOA关注的是所执行的行为、它们之间的关系、它们的顺序、它们的依赖性,将它们视为揭示一系列事件背后真实意图和目的的指标。IOA不关注攻击者使用的特定工具和恶意软件。

IOA之所以引人注目,是因为它们提供了针对无文件攻击的独特的主动预防能力IOA寻找攻击可能正在进行的迹象,而不是关心攻击的步骤是如何执行的迹象可以包括代码执行、试图隐身、横向移动等等如何启动或执行这些步骤对IOAs来说并不重要

IOA关注的是所执行的行为、它们之间的关系、它们的顺序、它们的依赖性,将它们视为揭示一系列事件背后真实意图和目的的指标。IOA不关注攻击者使用的特定工具和恶意软件。

此外,在无文件攻击的情况下,恶意代码可以利用诸如PowerShell之类的合法脚本语言,而无需写入磁盘。正如我们所看到的,这对于基于签名的方法、白名单、沙箱甚至机器学习来说都是一个挑战。相比之下,IOA检测恶意软件或攻击完成其任务所必须执行的事件序列。这可以暴露最隐秘的无文件方法,因此它们可以被迅速处理。

最后,由于IOA会查看意图、上下文、活动序列,因此即使恶意活动是使用合法帐户实施的,也可以检测和阻止这些活动,攻击者使用窃取的凭据时通常会出现这种情况。

所有这些使得IOA成为防止无文件恶意软件攻击的突破口。IOA不再基于磁盘上可执行文件的存在与否,来开展无文件攻击这场徒劳的战斗,而是在造成任何损害之前监视、检测、阻止此类攻击的影响

托管狩猎

托管狩猎(Managed Hunt)是针对文件攻击的另一种独特而有效的防御措施。Falcon OverWatch(猎鹰看守)是Falcon平台的威胁搜索组件,它提供了一个额外的保护层,来抵御无文件攻击。

利用Falcon平台的强大功能,OverWatch(看守)团队全天候主动狩猎威胁,监控客户的环境,并狩猎那些标准安全技术无法检测到但可能表明正在发生攻击的狡猾活动。Falcon OverWatch确保即使是最复杂和最隐蔽的攻击,也能在发生时被发现。它通过狩猎和识别难以检测的、复杂的、尖端的攻击,生成有意义的警报和精确的指导性补救建议,从而提高您对抗无文件技术的效率。

结论

由于漏洞利用工具包的存在,导致了攻击组合的高效性和易创建性,很可能会提高无文件黑客技术的普及率。不幸的是,鉴于传统杀毒软件无法阻止无文件攻击,犯罪黑客越来越可能将注意力集中在这些隐形技术上。因此,安全专家需要在他们的安全策略中,考虑无文件恶意软件和无文件攻击的存在。

正如本文所解释的那样,传统的安全措施在面对无文件攻击时可能不够有效,需要新的保护方法。CrowdStrike Falcon(猎鹰平台)提供了一种全面的解决方案,不仅可以防御无文件攻击,而且还可以很好地防御已知和未知的恶意软件威胁。

威胁图和攻击指标

CrowdStrike将自身定位为云交付下一代端点保护的领导者。CrowdStrike是第一家也是唯一一家统一了下一代防病毒、端点检测和响应(EDR)、IT卫生、漏洞评估、全天候托管狩猎服务的公司——全部通过一个轻量级代理提供,彻底革新了端点保护。CrowdStrike的端点保护平台(EPP)如下图所示:

img

威胁图(Threat Graph)

CrowdStrike Falcon(猎鹰)平台由两种紧密集成的专有技术组成:一个是易于部署的智能轻量级代理;另一个是基于云的动态图数据库,即上面提到的威胁图(Threat Graph)。

下表进一步梳理了威胁图的主要特性

img

https://www.crowdstrike.com/cybersecurity-101/indicators-of-compromise/ioa-vs-ioc/

总结:

  • SGD为随机梯度下降,每一次迭代计算数据集的mini-batch的梯度,然后对参数进行更新。
  • Momentum参考了物理中动量的概念,前几次的梯度也会参与到当前的计算中,但是前几轮的梯度叠加在当前计算中会有一定的衰减。
  • Adagard在训练的过程中可以自动变更学习的速率,设置一个全局的学习率,而实际的学习率与以往的参数模和的开方成反比。
  • Adam利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率,在经过偏置的校正后,每一次迭代后的学习率都有个确定的范围,使得参数较为平稳。

引言

最优化问题是计算数学中最为重要的研究方向之一。而在深度学习领域,优化算法的选择也是一个模型的重中之重。即使在数据集和模型架构完全相同的情况下,采用不同的优化算法,也很可能导致截然不同的训练效果。

梯度下降是目前神经网络中使用最为广泛的优化算法之一。为了弥补朴素梯度下降的种种缺陷,研究者们发明了一系列变种算法,从最初的 SGD (随机梯度下降) 逐步演进到 NAdam。然而,许多学术界最为前沿的文章中,都并没有一味使用 Adam/NAdam 等公认“好用”的自适应算法,很多甚至还选择了最为初级的 SGD 或者 SGD with Momentum 等

阅读全文 »

一、激活函数

激活函数简述激活函数是向神经网络中引入非线性因素,通过激活函数神经网络就可以拟合各种曲线。激活函数主要分为饱和激活函数(Saturated Neurons)和非饱和函数(One-sided Saturations)。Sigmoid和Tanh是饱和激活函数,而ReLU以及其变种为非饱和激活函数。非饱和激活函数主要有如下优势:

  • 非饱和激活函数可以解决梯度消失问题
  • 非饱和激活函数可以加速收敛
img
阅读全文 »

同一个主题,在不同的文章中,他出现的比例(概率)是不同的,看到这里,读者可能已经发现,文档和主题之间的关系和主题和词汇的关系是多么惊人的类似!

LDA于2003年由 David Blei, Andrew Ng和 Michael I. Jordan提出,因为模型的简单和有效,掀起了主题模型研究的波浪。虽然说LDA模型简单,但是它的数学推导却不是那么平易近人,一般初学者会深陷数学细节推导中不能自拔。于是牛人们看不下去了,纷纷站出来发表了各种教程。国内方面rickjin有著名的《LDA数学八卦》,国外的Gregor Heinrich有著名的《Parameter estimation for text analysis》。其实有了这两篇互补的通俗教程,大家沉住心看个4、5遍,基本就可以明白LDA为什么是简单的了。那么其实也没我什么事了,然而心中总有一种被大牛点播的豁然开朗的快感,实在是不吐不快啊。

RNN

史上最详细循环神经网络讲解(RNN/LSTM/GRU):https://zhuanlan.zhihu.com/p/123211148

一、什么是循环神经网络

RNN对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,利用了RNN的这种能力,使深度学习模型在解决语音识别、语言模型、机器翻译以及时序分析等NLP领域的问题时有所突破。

我们需要重点来了解一下RNN的特点这句话,什么是序列特性呢?我个人理解,就是符合时间顺序,逻辑顺序,或者其他顺序就叫序列特性,举几个例子:

  • 拿人类的某句话来说,也就是人类的自然语言,是不是符合某个逻辑或规则的字词拼凑排列起来的,这就是符合序列特性。
  • 语音,我们发出的声音,每一帧每一帧的衔接起来,才凑成了我们听到的话,这也具有序列特性、
  • 股票,随着时间的推移,会产生具有顺序的一系列数字,这些数字也是具有序列特性。

二、为什么要发明循环神经网络

我们先来看一个NLP很常见的问题,命名实体识别,举个例子,现在有两句话:

第一句话:I like eating apple!(我喜欢吃苹果!)

第二句话:The Apple is a great company!(苹果真是一家很棒的公司!)

现在的任务是要给apple打Label,我们都知道第一个apple是一种水果,第二个apple是苹果公司,假设我们现在有大量的已经标记好的数据以供训练模型,当我们使用全连接的神经网络时,我们做法是把apple这个单词的特征向量输入到我们的模型中(如下图),在输出结果时,让我们的label里,正确的label概率最大,来训练模型,但我们的语料库中,有的apple的label是水果,有的label是公司,这将导致,模型在训练的过程中,预测的准确程度,取决于训练集中哪个label多一些,这样的模型对于我们来说完全没有作用。问题就出在了我们没有结合上下文去训练模型,而是单独的在训练apple这个单词的label,这也是全连接神经网络模型所不能做到的,于是就有了我们的循环神经网络。

img

三、循环神经网络的结构及原理:

img

上图就是RNN的结构,我第一次看到这图的第一反应是,不是说好的循环神经网络么,起码得是神经网络啊,神经网络不是有很多球球么,也就是神经元,这RNN咋就这几个球球,不科学啊,看不懂啊!!!!随着慢慢的了解RNN,才发现这图看着是真的清楚,因为RNN的特殊性,如果展开画成那种很多神经元的神经网络,会很麻烦。

我们先来讲解一下上面这幅图,首先不要管右边的W,只看X,U,S,V,O,这幅图就变成了,如下:

img

不看W的话,上面那幅图展开就是全连接神经网络,其中X是一个向量,也就是某个字或词的特征向量,作为输入层,如上图也就是3维向量,U是输入层到隐藏层的参数矩阵,在上图中其维度就是3X4,S是隐藏层的向量,如上图维度就是4,V是隐藏层到输出层的参数矩阵,在上图中就是4X2,O是输出层的向量,在上图中维度为2。

弄懂了RNN结构的左边,那么右边这个W到底是什么啊?把上面那幅图打开之后,是这样的: img

等等,这又是什么??别慌,很容易看,举个例子,有一句话是,I love you,那么在利用RNN做一些事情时,比如命名实体识别,上图中的 [公式] 代表的就是I这个单词的向量, [公式] 代表的是love这个单词的向量, [公式] 代表的是you这个单词的向量,以此类推,我们注意到,上图展开后,W一直没有变,W其实是每个时间点之间的权重矩阵,我们注意到,RNN之所以可以解决序列问题,是因为它可以记住每一时刻的信息,==每一时刻的隐藏层不仅由该时刻的输入层决定,还由上一时刻的隐藏层决定==,公式如下,其中 [公式] 代表t时刻的输出, [公式] 代表t时刻的隐藏层的值:

img

值得注意的一点是,在整个训练过程中,每一时刻所用的都是同样的W。

四、举个例子,方便理解:

假设现在我们已经训练好了一个RNN,如图,我们假设每个单词的特征向量是二维的,也就是输入层的维度是二维,且隐藏层也假设是二维,输出也假设是二维,所有权重的值都为1且没有偏差且所有激活函数都是线性函数,现在输入一个序列,到该模型中,我们来一步步求解出输出序列:

img

你可能会好奇W去哪了?W在实际的计算中,在图像中表示非常困难 ,所以我们可以想象上一时刻的隐藏层的值是被存起来,等下一时刻的隐藏层进来时,上一时刻的隐藏层的值通过与权重相乘,两者相加便得到了下一时刻真正的隐藏层,如图 [公式] , [公式] 可以看做每一时刻存下来的值,当然初始时[公式] , [公式]是没有存值的,因此初始值为0:

img

当我们输入第一个序列,【1,1】,如下图,其中隐藏层的值,也就是绿色神经元,是通过公式 [公式] 计算得到的,因为所有权重都是1,所以也就是 [公式] (我把向量X拆开计算的,由于篇幅关系,我只详细列了其中一个神经元的计算过程,希望大家可以看懂,看不懂的请留言),输出层的值4是通过公式 [公式] 计算得到的,也就是 [公式] (同上,也是只举例其中一个神经元),得到输出向量【4,4】:

img

当【1,1】输入过后,我们的记忆里的 [公式] 已经不是0了,而是把这一时刻的隐藏状态放在里面,即变成了2,如图,输入下一个向量【1,1】,隐藏层的值通过公式[公式] 得到, [公式] ,输出层的值通过公式[公式],得到 [公式] ,最终得到输出向量【12,12】:

img

同理,该时刻过后 [公式] 的值变成了6,也就是输入第二个【1,1】过后所存下来的值,同理,输入第三个向量【2,2】,如图,细节过程不再描述,得到输出向量【32,32】:

img

由此,我们得到了最终的输出序列为:

img

至此,一个完整的RNN结构我们已经经历了一遍,我们注意到,每一时刻的输出结果都与上一时刻的输入有着非常大的关系,如果我们将输入序列换个顺序,那么我们得到的结果也将是截然不同,这就是RNN的特性,可以处理序列数据,同时对序列也很敏感。

Python多进程[可以多核] 多线程【No】协程

multiprocessing --- 基于进程的并行:https://docs.python.org/zh-cn/3/library/multiprocessing.html

Python进阶:https://ebook-python-study.readthedocs.io/zh_CN/latest/index.html

一、进程的定义

进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元。
线程:操作系统能够进行运算调度的最小单位
协程:协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

https://anchorety.github.io/2018/12/30/python%E5%A4%9A%E8%BF%9B%E7%A8%8B/

在介绍Python中的线程之前,先明确一个问题,Python中的多线程是假的多线程! 为什么这么说,我们先明确一个概念,全局解释器锁(GIL)。

Python代码的执行由Python虚拟机(解释器)来控制。Python在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在CPU中运行。同样地,虽然Python解释器可以运行多个线程,只有一个线程在解释器中运行。

对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python虚拟机按照以下方式执行。

1.设置GIL。

2.切换到一个线程去执行。

3.运行。

4.把线程设置为睡眠状态。

5.解锁GIL。

6.再次重复以上步骤。

对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行

如果某线程并未使用很多I/O操作,它会在自己的时间片内一直占用处理器和GIL。也就是说,I/O密集型的Python程序比CPU密集型的Python程序更能充分利用多线程的好处。

任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

1.1 multiprocessing

1.2 joblib

Python之并行--基于joblib - 半个冯博士的文章 - 知乎 https://zhuanlan.zhihu.com/p/180347090

首先joblib里面最常用到的一个类和一个方法分别是ParalleldelayedParallel主要用于初始化并行计算时需要用到的参数,而delayed则主要用来指定需要被并行的参数。比如官方给出的以下示例:

1
2
3
4
from math import sqrt
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(sqrt)(i ** 2) for i in range(10))
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

这段代码其实已经基本看出方法的主要使用模式了。

解释一下:

  • Parallel(n_jobs=2): 指定两个CPU(默认是分配给不同的CPU)
  • 后面的delayed(sqrt)表示要用的函数是sqrt,这里这种用法就非常类似C++里面的委托(delegate)
  • (i ** 2) for i in range(10): 这里注意(i**2)的括号和delayed(sqrt)是紧挨着的。这一小段表示要传递给delayed中指定的函数的参数是i^2

那么结合这么一小段程序,其实已经能大致理解它的使用方法了。这里最开始可能主要不习惯的是要用到了Python里面的内部函数机制。

二、多进程应用

2.1、python多进程读写公共数据 - 异步读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import multiprocessing, os, time  
import numpy as np

#公共数据
temp = np.zeros((4,12))
# 回调函数,用于多进程读写公共数据的,我的理解:多进程在回调函数这里是串行的,否则同时读写会乱掉
# 回调函数必须只有一个输入参数
def mycallback(index):
i,j = index[0],index[1]
temp[i,j] = i+j
# 多进程处理的耗时的算法函数
def multiprocess(i,j):
print("子进程开始执行>>> pid={},ppid={},编号{}".format(os.getpid(), os.getppid(), i))
time.sleep(2)
return (i,j)
if __name__ == '__main__':
time_start = time.time()
MultiP = multiprocessing.Pool(2) # 多进程

for i in range(3):
for j in range(4):
print("主进程开始执行>>> parent_pid={}".format(os.getpid()))
MultiP.apply_async(multiprocess, args=(i, j), callback=mycallback)

# 关闭进程池,停止接受其它进程
MultiP.close()
# 阻塞进程 等待进程池中的所有进程执行完毕,必须在close()之后调用
MultiP.join()
print("主进程终止")
time_end = time.time()
print('totally cost', time_end - time_start)
print(temp)
异步非阻塞式:

正因为是异步非阻塞式的,不用等待当前运行的子进程执行完毕,随时根据系统调度来进行进程切换。基本上主进程和三个子进程,四个进程是同时运行的。

2.2 python中多进程读取excel文件 - 异步读取,返回值管理

https://blog.csdn.net/hynkoala/article/details/93895004

首先准备:当前文件上级目录下有个excels目录,目录里存在15份.xls文件,每个文件1000条数据,需要通过多进程对这些文件读取为pandas的dataframe格式

进程池最大数量设为10:6.580815315246582

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# @datetime:6/26/0026
"""通过多进程加速读取excel的测试"""
__author__ = "hanyaning@deri.energy"
import os.path
import time
from service import logger
import pandas as pd
from multiprocessing import Pool

logger = logger.MyLogger("multi_process").getLogger()

def getExcelData(path):
logger.info("开始读取excel,当前进程pid:" + str(os.getpid()))
data = pd.DataFrame()
if not os.path.exists(path):
raise FileNotFoundError()
if os.path.isfile(path):
logger.info("读取Excel文件完毕,当前进程pid:" + str(os.getpid()))
return data.append(pd.read_excel(path, skiprows=1, skipfooter=1), sort=False)

if __name__ == "__main__":
excel_path = os.path.join(os.getcwd(), "../excels")
xls_names = [x for x in os.listdir(excel_path) if x.endswith(".xls")]
startTime = time.time()

p_list = []
# 使用进程池Pool
pool = Pool(processes=10)
pool_data_list = []
data = pd.DataFrame()
for file_name in xls_names:
# 需要注意不能直接在这里调用get方法获取数据,原因是apply_async后面 get()等待线程运行结束才会下一个,这里多进程会变成阻塞执行
pool_data_list.append(pool.apply_async(getExcelData, (os.path.join(excel_path, file_name))))
pool.close()
# 需要阻塞以下,等所有子进程执行完毕后主线程才继续执行
pool.join()
for pool_data in pool_data_list:
# 这里再使用get()方法可以获取返回值
data = data.append(pool_data.get())
endTime = time.time()
print(endTime - startTime)
print(len(data))

单进程读取对照测试

耗时:12.019948959350586

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class ExcelReader:

def __init__(self, path, file_suffix=".xls"):
self.path = path
self.file_suffix = file_suffix

def getData(self):
if not os.path.exists(self.path):
raise FileNotFoundError()
data = pd.DataFrame()
if os.path.isdir(self.path):
xls_names = [x for x in os.listdir(self.path) if x.endswith(self.file_suffix)]
logger.info("开始")
for xls_name in xls_names:
df = pd.read_excel(os.path.join(self.path, xls_name), skiprows=1, skipfooter=1)
data = data.append(df, sort=False)
logger.info("读取Excel文件完毕,共读取" + str(xls_names.__len__()) + "个文件")
return data


if __name__ == "__main__":
start = time.time()
reader = ExcelReader(os.path.join(os.getcwd(), "../excels"))
data = reader.getData()
end = time.time()
print(end - start)
print(len(data))