笔记记录,持续更新
Union操作和Union All操作
- Union :会对合并后的结果集进行去重操作,也就是会把重复的行去除,只保留其中一行
- 注意:使用Union时,同一个表的数据也会被去重
- Union All :不会进行去重操作 ,它会将所有查询结果集中的行全部保留(可存在重复的行)
- 特别注意:使用Union时,可能出现两个表Union后行数不如两个表分开统计行数的情况
凡事预则立,不预则废
Spring中Logger对象的名称使用的是小写
1 | private static final Logger logger= LoggerFactory.getLogger(BeanFactory.class); |
其他很多公司或者开源工具的代码也跟着这样用,比如美团的RPC开源框架mtthrift
private修饰的常量不用大写?本文是对POMDP这个不常见的概念的一些简单介绍,主要内容参考自POMDP讲解
你真的认识URL了吗?
#字符#在URL中与服务器无关,也就是说正常访问服务器的URL不包含##仅仅与本地浏览器对网页的定位相关#由于不影响对远程服务器的访问,自然也不会存在于软件包的下载连接中参考博客:https://blog.csdn.net/qq_25384945/article/details/81219075
Python
1 | http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+ |
JavaScript
1 | /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/ |
Java
1 | ^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|] |
PyTorch使用笔记,函数持续更新
torch.min与torch.max用法类似用法
1 | torch.max(input) -> Tensor |
input: 一个Tensor的对象input变量中的最大值用法
1 | torch.max(input, dim, keepdim=False, out=None) -> tuple[Tensor, Tensor] |
input: 一个Tensor的对象dim: 指明维度,生成的结果中,indices 用于替换第 0 维度(这对应 gather() 的检索方式)keepdim: 是否保持输出张量的维度与输入张量一致(默认值为 False)keepdim=False示例(包含索引使用示例):
1 | import torch |
keepdim=True示例(包含索引使用示例):
1 | import torch |
用法:
1 | import torch |
以上代码中,x不会被计算梯度,因为z = x + 1处梯度断开了,等价于z = x.detach() + 1
注意,如果调用torch.backward()时,没有任何可以计算的梯度,会报错,如下面的代码:
1 | import torch |
m.detach()后out.backward()就开始报错RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn,因为没有任何梯度可以计算了m = torch.ones(2, 2, requires_grad=True)为m = torch.ones(2, 2, requires_grad=False),也一样会导师没有任何梯度可以计算了,执行out.backward()也会报相同错误torch.nn.Module类对象print(model),默认情况下这个方法会调用model.__str__(),进一步调用model.__repr__(),这个函数会给出一个包含所有被定义为类属性的层的可读表示,但不会包括那些被定义为简单属性或方法的对象,这个方法可以用来查看模型包含哪些网络层1 | import torch |
tensor对象中的单一数值(注意,只能是单一数值,否则会报错) 1 | import torch |
outputs对inputs求导grad_outputs取默认值时,要求outputs必须是标量张量(一维)outputs不是标量张量时,要求grad_outputs与outputs维度一致,指明outputs中每个值对最终梯度的权重,且此时不可省略该参数(否则会报错:“RuntimeError: grad can be implicitly created only for scalar outputs”)1 | import torch |
torch.cat和torch.stack两者都是用来拼接tensor的函数,主要区别是使用 torch.cat 在现有维度上拼接,使用 torch.stack 在新维度上拼接
torch.cat 不新增维度,只在现有维度上拼接torch.stack 会新增一个维度,并在该维度上拼接,torch.stack的工作需要分成两步,第一步是增加维度(比如(3,)经过dim=0会变成(1,3)),第二步是将该维度拼接torch.cat 要求非拼接维度上的形状相同torch.stack 要求所有张量的形状完全一致使用特别说明 :一般使用 torch.cat和torch.stack就够了,torch.hstack和torch.vstack基本可以被torch.cat和torch.stack替代,所以不常用
torch.cat Demo 展示:
1 | import torch |
torch.stack Demo 展示:
1 | import torch |
(3,)经过dim=0后变成(1,3),进一步地两个(1,3)堆叠变成(2,3)(3,)经过dim=1后变成(3,1),进一步地两个(3,1)堆叠变成(3,2)torch.hstack和torch.vstack函数:
torch.hstack:在水平方向(dim=1)处拼接张量,不新增维度dim=0处拼接)torch.vstack:在垂直方向(第 0 维)拼接张量,除了原始输入为 1 维时,不新增维度dim=0增加一维再按照这个维度拼接)1 | import torch |
基本用法
1 | tensor.repeat(*sizes) |
*sizes:一个整数序列,表示每个维度上重复的次数注意事项
repeat 会按照输入的顺序对每个维度进行扩展repeat 不会复制数据,而是通过视图(view)来实现重复。这意味着返回的张量与原始张量共享底层数据sizes 长度大于张量的维度,则会在前面补充新的维度,比如(2,)的原始张量调用repeat(2,3)后,会先扩展成(1,2)的张量,再执行repeat(2,3),但是不建议补充这个功能函数调用Demo:
1 | import torch |
model.parameters():返回模型中所有参数,不返回参数名称model.named_parameters():返回模型中所有参数,同时返回参数名称1 | # 定义一个简单的全连接神经网络 |
torch.empty() 是 PyTorch 中用于创建一个新的张量(tensor)的函数,该张量不会被初始化,即它的元素值是未定义的。这意味着张量中的元素可能是任意值,取决于分配给张量的内存块之前的状态torch.empty() 来快速创建它。这对于只需要分配内存而不必初始化数据的情况非常有用torch.empty() 可以比 torch.zeros() 或 torch.ones() 更快地分配内存,因为它跳过了设置默认值的过程torch.empty() 来预分配显存,避免后续操作中可能出现的内存碎片化问题torch.linspace 和 torch.arange 都是 PyTorch 中用于生成数值序列的函数,但它们在生成数值的方式和使用场景上有一些关键的不同start 到 end(包括两端点)之间等间距分布的 steps 个点start 开始到 end 结束(不包括 end),以步长 step 增长的连续整数或浮点数1 | import torch |
tensor.is_contiguous() 用于检查一个张量(Tensor)是否是连续的(contiguous)。在PyTorch中,张量的存储方式可以分为连续和非连续。一个张量被认为是连续的,如果它的元素在内存中是按行优先顺序(row-major order)依次存放的,也就是说,在内存中这些元素是连续排列的tensor.is_contiguous() 方法时,如果返回值为 True,则表示该张量是连续的;如果返回 False,则表示张量当前不是以连续的方式存储的。如果你需要将一个非连续的张量转换为连续的,可以使用 .contiguous() 方法来创建一个新的、与原张量具有相同数据但存储方式为连续的张量副本1 | import torch |
unsqueeze:在指定维度添加一个维度,且该长度为 1squeeze:去掉指定长度为 1 的维度unsqueeze() 有等价形式,如对于二维的张量:tensor.unsqueeze(dim=0) 等价于 tensor[None] 或 tensor[None,:,:]tensor.unsqueeze(dim=1) 等价于 tensor[:,None] 或 tensor[:,None,:]tensor.unsqueeze(dim=0) 等价于 tensor[:,:,None]unsqueeze() 代码示例: 1 | import torch |
torch.flatten() 和 torch.unflatten()torch.flatten() 基本用法:
1 | torch.flatten(input, start_dim=0, end_dim=-1) |
input:需要被展平的输入张量start_dim:从哪个维度开始展平,默认值为0(即从第0维开始)end_dim:到哪个维度结束展平,默认值为-1(即到最后一维结束)torch.unflatten() 基本用法
1 | torch.unflatten(input, dim, unflattened_size) |
input:需要被处理的输入张量dim:需要被拆分的维度索引unflattened_size:指定拆分后的维度大小,可以是元组或列表1 | import torch |
torch.from_numpy(ndarray):将 NumPy 数组转换为张量,两者共享内存 ,修改NumPy变量会改变Tensor变量,反之亦然
tensor.numpy():将张量转换为 NumPy 数组(仅限 CPU 张量),两者共享内存 ,修改NumPy变量会改变Tensor变量,反之亦然
代码示例:
1 | import torch |
特别注意(其他共享内存相关函数)
torch.Tensor(numpy_array) 得到的变量只有在 numpy_array 的类型为 np.float32 时共享,否则不共享内存的(注意:torch.Tensor() 是无法指定数据类型的,默认类型就是 torch.float32)torch.tensor(numpy_array) 得到的变量总是不共享内存,都是副本inplace参数允许你指定操作是否直接在输入张量上进行而不需要额外的内存分配来存储结果。这对于减少内存使用特别有用,但需要注意的是,这也会覆盖原始数据。下面通过具体的例子说明如何使用inplace参数,以torch.nn.functional.relu为例:代码示例:
1 | import torch |
inplace:当你调用F.relu(input_tensor)时,默认情况下不会修改原始的input_tensor,而是返回一个新的张量output_tensor作为ReLU操作的结果inplace=True:当你指定inplace=True,如F.relu(input_tensor, inplace=True),此时ReLU操作会直接作用于input_tensor本身,即它将所有负值设置为0,并且这个修改是直接在原来的张量上进行的,不会创建新的张量。因此,在执行完这个操作后,原始的input_tensor已经被修改inplace操作可以节省一些内存,因为不需要为输出分配新的空间inplace参数,具体的支持情况可以查阅相关函数的文档说明inplace选项的操作,比如激活函数、归一化等,理解并正确使用inplace可以帮助更有效地管理和优化你的模型训练过程_ 结尾的函数实现 inplace 操作torch.device('cuda')用于设备获取tensor = tensor.to(device)model = model.to(device)model.parameters() 对象来表示(这里面包含模型的所有nn.Parameter对象)。这些参数一般是在模型的 __init__ 方法中定义的torch.nn.BatchNorm2d 层中的 running_mean 和 running_vartensor.view() 和 tensor.reshape() 都可以用来改变张量的形状,但它们之间有一些关键的区别tensor.view() :.view() 会抛出错误。这时你需要先调用 .contiguous() 来确保 tensor 在内存中是连续的,然后才能使用 .view().view() 的性能可能更好,因为它直接改变了对原始数据的视图而没有复制数据tensor.reshape() :tensor.reshape() 等价于 tensor.contiguous().view()tensor.reshape()可以在张量不是连续的情况下工作,因为它会在必要时创建张量的一个副本.reshape() 是自 PyTorch 0.4.0 版本引入的一个函数,旨在提供一种更一致的方式来处理形状变换。无论张量是否连续,它都可以工作.view().reshape() 提供了一个更为方便和灵活的选择.reshape().reshape() 和 .view() 是等价的,无需担心性能torch.topk() 用于获取张量中指定维度上的前 k 个最大/最小值及其索引,常用于分类任务中获取 top-k 的预测结果,其函数定义如下:
1 | torch.topk(input, k, dim=None, largest=True, sorted=True, *, out=None) |
参数说明:
True,则返回最大的 k 个值;如果为 False,则返回最小的 k 个值。默认为 TrueTrue,则返回的结果会按照大小排序;如果为 False,则返回的结果顺序不确定。默认为 True返回值
用法示例
1 | import torch |
self.register_buffer 是一个用于向模块(nn.Module)注册持久化缓冲区(buffer)的方法。它的主要作用是告诉PyTorch某些张量是模型的一部分,但不属于可训练参数(即不需要梯度更新),但这些张量在模型保存或加载时需要被包含进来register_buffer 注册的张量不会被优化器更新(不像 nn.Parameter)running_mean 和 running_var 是统计量,需要跟踪但不参与梯度计算,也属于这一类model.state_dict() 中,因此当调用 torch.save 和 torch.load 时,它们会被自动保存和加载model.to(device) 时,这些buffer会自动移动到对应的设备(如CPU/GPU),与模型的其他参数一致model.state_dict()中1 | class MyModel(nn.Module): |
x.log() == torch.log(x)x.log2() == torch.log2(x)x.log10() == torch.log10(x)1 | import torch |
torch.clip 和 torch.clamptorch.clip 和 torch.clamp 功能完全一样,都能用于将输入张量的数值限制在指定的区间内,从英文含义上看,两者分别是截取和限制的含义,都差不多,但理论上 clip 会更符合原本这个函数“裁剪”的含义torch.clamp 是 PyTorch 从早期就存在的传统函数,一直被广泛运用torch.clip 是在版本 1.7.0 时新增的函数,目的是和 NumPy 的 np.clip 保持 API 一致,方便用户从 NumPy 迁移过来torch.clip,方便阅读,但为了和更早的 torch 版本兼容,还有很多人使用 clamptorch.allclose() 函数用于比较两个张量是否在给定的误差范围内“几乎相等”
基本语法
1 | torch.allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False) |
特别注意:
other 与 input 形状必须相同
equal_nan:若为True,则NaN值被视为相等;若为False,则NaN会导致比较失败
若所有元素的差异都在容差范围内,则返回True;否则返回False。对于每个元素,比较条件为:
1 | |input - other| ≤ atol + rtol * |other| |
容易混淆的相关方法的比较(以下两个方法都是逐个元素比较,返回逐元素结果的)
torch.isclose() :逐元素比较两个张量是否接近,返回与输入形状相同的布尔张量(注意不是只返回一个值,是逐元素比较结果)
1 | torch.isclose(a, b, rtol=1e-5, atol=1e-8, equal_nan=False) |
torch.eq() :严格逐元素相等比较(不考虑容差),返回与输入形状相同的布尔张量
torch.chuck 函数用法torch.chunk 是 PyTorch 中用于将张量按照指定维度拆分成多个子张量的函数,返回一个包含拆分后子张量的元组
torch.chunk 拆分后的数据与原张量共享内存(浅拷贝),修改子张量会影响原张量
函数定义为:
1 | torch.chunk(input, chunks, dim=0) |
input:待拆分的输入张量(torch.Tensor)chunks:拆分的数量(int)。需注意:若输入张量在 dim 维度的大小不能被 chunks 整除,最后一个子张量的大小会略小(其余子张量大小相等)dim:指定拆分的维度(int,默认值为 0)tuple),包含 chunks 个子张量(或最后一个子张量略小)torch.chunk 与 torch.split 的区别:
torch.chunk 按“数量”拆分(chunks 参数),子张量大小尽可能平均; torch.split 按“指定大小”拆分(如 split_size_or_sections=2 表示每个子张量大小为 2)torch.chunk 的一些示例基本用法(1D 张量)
1 | import torch |
高维张量拆分(2D 张量)示例
1 | x = torch.arange(12).reshape(3, 4) # 形状为 (3, 4) 的矩阵 |
torch.where 函数和 tensor.where 函数torch.where() 是 PyTorch 中用于基于条件对张量元素进行选择性替换的方法,类似于“三目运算符”的向量版,语法如下:
1 | torch.where(condition, x, y) |
condition:布尔型张量(与原张量同形状),用于判断每个元素是否满足条件x:当 condition 为 True 时,保留或使用 x 的值(可与原张量同形状,或为标量)y:当 condition 为 False 时,使用 y 的值(可与原张量同形状,或为标量)condition 从 x 或 y 中取值注:x.where(condition, y) 是实例方法,等价于全局函数 torch.where(condition, x, y)
tensor.where(condition, y)(实例方法)张量对象的实例方法,语法为:
1 | result = tensor.where(condition, y) |
condition(必选):布尔型张量(torch.BoolTensor),形状必须与 tensor 相同(或可广播为相同形状)y(必选): 张量(与 tensor 同数据类型)或标量(如 int、float)tensor 相同(或可广播为相同形状);若为标量,会自动广播到 tensor 的形状condition 为 False 时,使用 y 的值(或对应位置的元素)替换 tensor 中的元素torch.where(condition, x, y)(全局函数)PyTorch 的全局函数,语法为:
1 | result = torch.where(condition, x, y) |
condition(必选):布尔型张量(torch.BoolTensor),形状必须与 x、y 相同(或可广播为相同形状)x 或 y 中取值x(必选):张量(与 y 同数据类型)或标量condition 相同(或可广播为相同形状);若为标量,会自动广播到对应形状condition 为 True 时,使用 x 的值(或对应位置的元素)y(必选):张量(与 x 同数据类型)或标量condition 相同(或可广播为相同形状);若为标量,会自动广播到对应形状condition 为 False 时,使用 y 的值(或对应位置的元素)1 | import torch |
torch.size() 函数 和 tensor.size(n)tensor.size() 函数torch.Size 可直接当作 tuple 使用(支持索引、len() 等),例如 len(t2.size()) 会返回张量的维度数(2)tensor.shape(属性,功能与 size() 完全一致,更简洁),例如 t2.shape 与 t2.size() 结果相同tensor.size(n) 函数返回张量第 n 维的元素个数(维度索引从 0 开始)
用法:
1 | tensor.size(dim) # dim:指定维度的索引(0 表示第1维,1 表示第2维,以此类推) |
tensor.size(1) 等价于 tensor.size()[1] 或 tensor.shape[1]维度索引从 0 开始:
size(0) 是第 1 维size(1) 是第 2 维size(-1) 表示最后一维(常用技巧)若指定的维度索引超出张量的维度范围 会抛出 IndexError
size(1) 会抛异常torch.size() 函数 和 tensor.size(n)size():快速查看张量整体形状(例如确认输入数据是否符合模型要求)size(1):常用于提取矩阵的列数、文本张量的词向量维度等(例如 batch_size, seq_len = tensor.size(0), tensor.size(1))1 | import torch |
torch.roll() 函数torch.roll 用于循环移位(滚动)张量元素 ,支持沿指定维度对张量元素进行循环平移,移位后超出边界的元素会从另一侧补回(类似“循环队列”的逻辑)
函数签名为:
1 | torch.roll(input, shifts, dims=None) -> Tensor |
input:Tensor,输入张量(任意维度) |shifts:int / 序列,移位步数:(2, -1)):需与 dims 一一对应,为每个维度指定独立移位步数dims:int / 序列 / None,移位维度:None(默认):先将张量展平为 1D 再移位,最后恢复原形状;(0, 1)):需与 shifts 长度一致,对多个维度依次移位 input 形状、数据类型完全相同的新张量(原张量不改变,除非用 in-place 版本 torch.roll_)1D 张量示例
1 | import torch |
2D 张量示例(注:dim=0(行方向,上下移)、dim=1(列方向,左右移))
1 | # 仅单维度移位示例 |
dims=None(展平后移位,再恢复原来 shape):默认将张量展平为 1D 移位,再恢复原形状,慎用(可能导致元素顺序混乱)
1 | x = torch.tensor([[1, 2], [3, 4]]) |
移位步数可以超界(但不建议) :步数会自动对维度长度取模(如长度为 5 的维度,移位 7 步等价于移位 7%5=2 步)
1 | x = torch.tensor([0,1,2,3,4]) |
原张量不改变 :torch.roll 是“非 in-place”操作,如需修改原张量,使用 torch.roll_(末尾加下划线)
1 | x = torch.tensor([0,1,2]) |
梯度传播 :支持自动求导(梯度会跟随移位逻辑反向传播),可用于神经网络层中
torch.quantile() 函数torch.quantile 是用于计算张量分位数的函数,支持多维张量、指定维度计算、线性插值等功能,适用于统计分析、异常值检测等场景
torch.quantile 支持多维张量、批量分位数、多种插值模式,核心是通过 dim 控制计算维度、q 指定分位数、interpolation 调整插值逻辑
torch.quantile 函数签名
1 | torch.quantile( |
input:Tensorq:float 或 Tensor[0, 1])dim:int 或 Tuple[int, ...]None 表示对整个张量展平后计算keepdim:boolFalse,即压缩维度;True 则维度数不变)interpolation:str'linear'),支持 5 种模式(下文详细说明)'linear'(默认),线性插值:q = i + f 时,结果 = (1-f)*x[i] + f*x[i+1](最常用)'lower',取下界:结果 = x[floor(i + f)](即小于等于目标位置的最大元素)'higher',取上界:结果 = x[ceil(i + f)](即大于等于目标位置的最小元素)'nearest',取最近邻:结果 = x[round(i + f)](四舍五入到最近索引)'midpoint',中点插值:结果 = (x[floor(i + f)] + x[ceil(i + f)]) / 2(上下界平均)1D 张量(展平计算),计算单个分位数(中位数)和多个分位数:
1 | import torch |
多维张量(指定维度计算):对 2D 张量的行/列计算分位数,控制 dim 和 keepdim:
1 | x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=torch.float32) |
input 需为浮点型(float32/float64),整数型张量会自动转换为浮点型q 必须在 [0, 1] 内,否则会抛出 ValueErrortorch.quantile 的参数(如 interpolation)与 numpy.quantile 基本一致,可无缝迁移torch.nn.functional.pad()(简称 F.pad())F.pad() 是用于张量填充的核心函数,支持任意维度的对称/非对称填充、多种填充模式(常数、反射、复制等),
F.pad() 函数签名
1 | import torch.nn.functional as F |
input:torch.Tensorpad:Sequence[int](left0, right0, left1, right1, left2, right2, ...),对应张量从最后一维到第一维的左右填充数left0, right0 表示 dim=-1 的维度(最后一维)的左边和右边分别 pad 数量配置N 维张量,pad 需包含 2*N 个整数(若某维度无需填充,填 0)(left_pad, right_pad),即 左边填充数,右边填充数[L]):pad=(left, right) ,填充后 shape [left + L + right];[H, W]):pad=(left_w, right_w, left_h, right_h),填充后 shape [left_h + H + right_h, left_w + W + right_w][D, H, W]):pad=(left_w, right_w, left_h, right_h, left_d, right_d),填充后 shape [left_d + D + right_d, left_h + H + right_h, left_w + W + right_w]mode:str'constant'),支持 6 种模式'constant'(默认):用固定值 value 填充(如 0 填充)'reflect',反射填充:以张量边缘为对称轴反射(不包含边缘本身);注意,此时张量边缘是对称轴'replicate',复制填充:用张量边缘的元素填充(重复边缘值)'circular',循环填充:将张量视为循环结构,用对侧的元素填充(环绕填充)'edge',等价于 'replicate'(兼容旧版本 PyTorch)'symmetric',对称填充:以张量边缘为对称轴反射(包含边缘本身)value:float mode='constant' 时有效,指定填充的常数(默认 0)**kwargs:reflect/replicate 模式下的 padding_mode 兼容参数,较少用)[[1,2],[3,4]] 为例,左/右/上/下各填充 1 个元素,对比核心模式: 1 | import torch |
pad 维度顺序 :必须是「最后一维 到 第一维」的左右填充,容易混淆(如 2D 张量先 W 后 H),填错会导致尺寸异常F.pad 是可微分操作,填充的常数部分梯度为 0,反射/复制部分梯度会反向传播到原张量边缘元素'constant'/'replicate' 模式效率最高,'reflect'/'symmetric' 稍慢,'circular' 因循环逻辑效率较低(大张量建议提前优化)nn.ZeroPad2d 等层的区别 :nn.ZeroPad2d/nn.ReflectionPad2d 是封装好的层(仅支持特定维度),F.pad 更灵活(支持任意维度和模式),功能完全覆盖前者torch.unbind 函数torch.unbind 是 PyTorch 中用于拆分张量维度的核心函数,作用是将一个张量沿着指定维度(dim)“解绑”(拆分)为多个独立的张量,返回这些张量的元组
简单理解:假设有一个 shape 为 (batch_size, seq_len, hidden_dim) 的张量
dim=0(batch 维度)unbind 后,会得到 batch_size 个 shape 为 (seq_len, hidden_dim) 的张量;dim=1(seq_len 维度)unbind 后,会得到 seq_len 个 shape 为 (batch_size, hidden_dim) 的张量函数签名与核心参数
1 | torch.unbind(input, dim=0) -> tuple[Tensor, ...] |
input:待拆分的输入张量(任意维度)dim:指定拆分的维度(默认 0,即第一个维度)dim 维度上的大小tensor.flip(dims) 函数tensor.flip(dims) 用于沿着指定维度翻转张量(reverse the order of elements),仅改变指定维度上元素的顺序,不改变张量的形状、数据类型和设备
dims 是整数或整数元组,指定要翻转的维度(0=第1维,1=第2维,以此类推)dims 维度反转元素顺序,非指定维度保持不变shape、dtype、device、requires_grad 均不改变注:flip 还有个实现是参数可以是 可变位置参数(即展开的列表/元组)
1 | @overload |
使用示例
1 | import torch |
torch.nn.utils.rnn.pad_sequence 函数torch.nn.utils.rnn.pad_sequence 是 PyTorch 中处理变长序列(Variable-length Sequences) 的工具,用于将一批长度不同的张量(序列)填充到相同长度,以便批量输入 RNN、Transformer 等模型
核心功能是将一个 张量列表(每个张量对应一条变长序列)填充为一个 统一长度的二维/高维张量 ,填充值默认是 0(可自定义);其填充规则为:
batch_first 调整返回值维度顺序);函数签名
1 | torch.nn.utils.rnn.pad_sequence( |
sequences:List[Tensor](seq_len_i,)(如单特征序列);(seq_len_i, feature_dim)(如带特征维度的序列);(seq_len_i, d1, d2, ...)(如序列+多特征维度);batch_first:boolFalse(默认):输出形状 (max_seq_len, batch_size, ...)(适配 PyTorch RNN 层默认输入格式);True:输出形状 (batch_size, max_seq_len, ...)(更直观,适合自定义模型)padding_value:float1D 变长序列(单特征)
1 | import torch |
2D 变长序列(带特征维度):适用于每条序列的每个元素是一个特征向量(如词嵌入后的序列):
1 | # 2D序列:shape (seq_len_i, feature_dim),feature_dim=2(统一) |
torch.randperm 函数torch.randperm 函数 的原型为:
1 | torch.randperm(n, *, generator=None, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False) -> Tensor |
torch.randperm 函数用于生成 0 到 n-1 的随机排列
torch.argsort 函数torch.argsort 用于返回张量元素排序后索引的函数
torch.argsort 函数原型为:
1 | torch.argsort(input, dim=-1, descending=False, stable=False, *, out=None) |
input:输入张量(任意维度,如 1D、2D、3D 等)dim :指定排序的维度(负号表示倒数维度,如 dim=-1 表示最后一维);默认 -1descending:是否降序排序(True 降序,False 升序);默认 Falsestable:是否使用稳定排序(相同元素保留原始顺序,仅对 CPU 有效,GPU 不支持);默认 Falseout:输出张量(可选,用于指定结果存储位置);默认 Noneinput 形状完全相同的整数张量 ,元素为原张量排序后的索引1D 张量示例:对一维张量排序,返回排序后元素的原始索引(升序/降序)
1 | import torch |
torch.randperm 函数 和 torch.argsort 函数 实现打乱再恢复举个直观例子:
[0,1,2,3,4](对应 x 的位置)randperm(5) 生成 shuffle_idx = [3,0,4,1,2](随机打乱)x_shuffled = x[3], x[0], x[4], x[1], x[2]argsort(shuffle_idx) 计算:shuffle_idx 升序排序为 [0,1,2,3,4],其元素对应在 shuffle_idx 中的位置是 [1,3,4,0,2](存储为 restore_idx)x_shuffled[restore_idx] = x[0],x[1],x[2],x[3],x[4](完全恢复原顺序)通过 torch.randperm 打乱 + torch.argsort(shuffle_idx) 恢复的核心是 “索引映射的可逆性”
argsort 还原该映射,与张量值无关,高效且稳定1D 张量示例:
1 | import torch |
注意(对 index 做排序的优点):
x_shuffled 做 argsort 可能因值排序导致恢复失败,但对 shuffle_idx 做 argsort 不受值影响(仅依赖索引映射)len(dataloader) 函数len(dataloader) 得到的是 训练数据加载器(DataLoader)的批次数(batch count),即整个训练数据集被划分为多少个批次(batch)len(dataloader) 可以在任意时刻使用,不会影响 dataloader 数据集的 迭代操作1 | import torch |
tensor.expand() 和 tensor.expand_as() 函数expand() 和 expand_as() 的核心作用是将张量在维度上进行扩展(广播) ,但它并不会复制新的数据,而是返回原张量的一个“视图(view)”基本语法
1 | tensor.expand(*sizes) |
*sizes:传入想要扩展后的张量形状(元组/多个整数)1 的维度,可以扩展为任意正整数;1 的维度,必须和原维度大小一致(不能改);-1 表示“保持原维度大小不变”;1 再扩展代码示例
1 | import torch |
基本语法
1 | tensor.expand_as(other_tensor) |
tensor.expand(other_tensor.size()),即把当前张量扩展为和 other_tensor 相同的形状expand() 完全一致,只是不需要手动写形状,直接复用另一个张量的形状代码示例
1 | import torch |
torch.ge 函数torch.ge 是 用于逐元素比较 的基础函数,核心功能是判断第一个输入张量的元素是否大于或等于第二个输入张量的对应元素,最终返回一个与输入同形状的布尔型张量(dtype=torch.bool),元素值为 True/False 表示对应位置的比较结果torch.ge(input, other, *, out=None)input:torch.Tensor(必选),第一个输入张量(比较的左操作数)other: torch.Tensor, 数值型(int/float)(必选), 第二个输入(比较的右操作数),支持广播机制 torch.greater_equal(与 torch.ge 功能完全一致,可互换使用)input >= other 比较,输出布尔张量(与广播后形状一致),数据类型固定为 torch.bool,每个元素对应 input 和 other 对应位置的 >= 比较结果使用clamscan命令搜索所有文件, clamav详情见我之前的博客clamav安装与杀毒
1 | nohup clamscan / -r --infected -l clamscan.log > clamscan.out & |
查看扫描结果
1 | cat clamscan.log | grep FOUND |
/var/lib/docker/overlay/bdd049c71596d743907224a8dd6fdb3fb4ca76e3af8dfd6eee2d034de2be45a1/merged/tmp/kdevtmpfsi: Multios.Coinminer.Miner-6781728-2 FOUND
/var/lib/docker/overlay/bdd049c71596d743907224a8dd6fdb3fb4ca76e3af8dfd6eee2d034de2be45a1/merged/tmp/red2.so: Unix.Trojan.Gafgyt-6981174-0 FOUND
/var/lib/docker/overlay/bdd049c71596d743907224a8dd6fdb3fb4ca76e3af8dfd6eee2d034de2be45a1/upper/tmp/kdevtmpfsi: Multios.Coinminer.Miner-6781728-2 FOUND
/var/lib/docker/overlay/bdd049c71596d743907224a8dd6fdb3fb4ca76e3af8dfd6eee2d034de2be45a1/upper/tmp/red2.so: Unix.Trojan.Gafgyt-6981174-0 FOUND
删除这四个文件,这里直接到相关目录下查看发现../tmp目录下往往都是病毒文件(与kinsing相关,全部删除)
top查看CPU信息确定挖矿进程kdevtmpfsi的进程号[pid]
确定启动信息中启动命令,并删除(在这里查到的信息是文件已经被删除了)
1 | ls /proc/[pid] -ali |
查找父进程进程号
1 | systemctl status [pid] |
● docker-be9fcab033e6158f8ff7d6ac07d28cfd918375178c27e016aa800cbeef985161.scope - libcontainer container be9fcab033e6158f8ff7d6ac07d28cfd918375178c27e016aa800cbeef985161
Loaded: loaded (/run/systemd/system/docker-be9fcab033e6158f8ff7d6ac07d28cfd918375178c27e016aa800cbeef985161.scope; static; vendor preset: disabled)
Drop-In: /run/systemd/system/docker-be9fcab033e6158f8ff7d6ac07d28cfd918375178c27e016aa800cbeef985161.scope.d└─50-BlockIOAccounting.conf, 50-CPUAccounting.conf, 50-DefaultDependencies.conf, 50-Delegate.conf, 50-Description.conf, 50-MemoryAccounting.conf, 50-Slice.confActive: active (running) since Mon 2019-11-11 11:24:17 UTC; 1 months 27 days ago
Tasks: 38Memory: 2.3G
CGroup: /system.slice/docker-be9fcab033e6158f8ff7d6ac07d28cfd918375178c27e016aa800cbeef985161.scope├─ 4475 redis-server *:6379 ├─ 8528 sh -c /tmp/.ICEd-unix/vJhOU ├─ 8529 /tmp/.ICEd-unix/vJhOU └─22822 /tmp/kdevtmpfsiWarning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
杀死不需要的相关进程,如上面的4475,8528, 8529, 22822
查看是否还有需要杀死的进程,如果有,则杀死该进程
1 | ps -ef | grep kinsing |
top确定挖矿进程已经被杀死
Joint-Bidding-in-Ad-Auctions/JAMA-Algorithm1.png)
- 定理1 :在联合广告系统中,VCG机制具有激励相容性、个体理性,并且可以实现最优社会福利,但不满足弱预算平衡
- 例1中导致负收益的主要原因是,如果没有零售商 \(r_1\) ,价值较高的供应商 \(s_1\) 就会失去竞争机会,从而导致最优社会福利的损失。直观地说,如果论文能够保留供应商 \(s_1\) 为社会福利做贡献的权利,那么零售商 \(r_1\) 的支付就不会为负,进而可以保证弱预算平衡
- 基于上述思路,论文修改VCG机制的支付规则:当关键广告商不参与拍卖时,论文假设其出价为0,并且合作关系仍然保留,而不是直接将其剔除。修改后的支付规则可以写成:
$$p_{i}(\mathbf{b})=SW^{*}\left(0, \mathbf{b}_{-i}\right)-\left[SW^{*}(\mathbf{b})-a_{i}(\mathbf{b}) \cdot b_{i}\right]$$- 论文将具有上述支付规则的VCG机制定义为修正的VCG机制,并证明修正的VCG机制可以保证弱预算平衡
- 定理2 :在联合广告系统中,修正的VCG机制具有激励相容性、个体理性、弱预算平衡,并且可以实现最优社会福利
Joint-Bidding-in-Ad-Auctions/JAMA-Figure2.png)
Joint-Auction-in-the-Online-Advertising-Market/JRegNet-Figure1.png)
Joint-Auction-in-the-Online-Advertising-Market/JRegNet-Figure2.png)
注:论文关注满足占优策略激励相容性(DSIC)和个体理性(IR)的机制
Joint-Auction-in-the-Online-Advertising-Market/JRegNet-Figure3.png)
实现细节
JRegNet与基线的比较
Joint-Auction-in-the-Online-Advertising-Market/JRegNet-Table1.png)
不同价值分布
不同广告位CTR
不同广告位数量
Joint-Auction-in-the-Online-Advertising-Market/JRegNet-Table3.png)