文章目录
- 维度相关
- 运算
- 其他
- 损失函数
- numpy
- 神经网络架构相关
维度相关
将tensor转为连续的
Tensor.contiguous() → Tensor
- 若Tensor不是连续的,则开辟一片新的连续内存,返回与self数据相同的tensor,若本身就是连续的,则返回本身。
- 关于Pytorch中 tensor 是否连续的一个很好的知乎介绍:https://zhuanlan.zhihu.com/p/64551412
判断tensor是否是连续的
Tensor.is_contiguous() → bool
- Returns True if self tensor is contiguous in memory in C order.
- 直观来说:Tensor底层一维数组元素的存储顺序与Tensor按行优先一维展开的元素顺序是否一致。
这里行优先就指的是上面的 C order,即C语言存储数组就是按行优先
- tensor的形状由一个元信息定义
求tensor地址
Tensor.data_ptr()
求tensor每个维度的步长(底层存储的步长)
Tensor.stride(dim) → tuple or int
- 返回 tensor 指定维度的stride(即该维度上的两个元素之间相隔多远),若不输入dim,则返回一个tuple表示所有维度的stride。显然,一定会有一个维度的 stride = 0.
- 若对于所有 i,满足第 i 维的stride等于 i + 1 维的stride乘以第 i+1 维元素数目,且最后一维的 stride 为1,则该tensor是连续的。
- numpy 中张量是否连续的定义:对于任意的 N 维张量 t ,如果满足第 k 维相邻元素间隔 = 第 K+1维 至 最后一维的长度的乘积,则 t 是连续的。
- s k r o w s_k^{row} skrow表示行优先模式下,第k维相邻两个元素之间相隔的字节数
- itemsize 表示每个元素的字节数
- d j d_j dj表示固定其他维度时,第 j j j 维元素的个数,即
t.shape[j]
Pytorch 和 numpy 中对于连续定义的区别:
两者本质上是一样的,对于 stride的定义指的都是某维度下,相邻元素之间的间隔
Pyotorch中指的是逻辑步长,即相隔的元素位数,而numpy中指的是物理步长,即相隔的字节数
两者转换为: s t r i d e n u m p y = s t r i d e p y t o r c h ∗ i t e m s i z e stride_{numpy} = stride_{pytorch} * itemsize stridenumpy=stridepytorch∗itemsize
tensor形状变化
torch.transpose(input, dim0, dim1) → Tensor
Tensor.transpose(dim0, dim1) → Tensor
- Returns a tensor that is a transposed version of input. The given dimensions dim0 and dim1 are swapped.
- 返回的tensor与原tensor底层使用的是同一份数据,改变其中之一,另一个也会改变
- 只是新建了一份Tensor元信息,并在新的元信息中重新指定 stride
tensor形状变化
Tensor.permute(*dims) → Tensor
- *dims (python:int…) – The desired ordering of dimensions
- 同样不改变底层一维数组存储,只是新建了一份Tensor元信息,并在新的元信息中重新指定 stride
- 和transpose一样,因为改变了 stride,因此在其之后不能使用 view
tensor形状变化
Tensor.view(*shape) → Tensor
shape (torch.Size or python:int…) – the desired size
- 输入的形状可以是torch.size() 或者 int。
- 使用view之前,tensor必须是连续的(contiguous),因此在使用 view 之前可能要先使用 contiguous(),可以直接使用 reshape() , 即reshape 等价于 contiguous + view。是否调用contiguous 取决于输入是否是contiguous的
- view 方法约定了不修改数组本身,只是使用新的形状查看数据
- transpose 和 permute 用来调换维度,view用来将数据按行优先排列后指定新的维度
tensor形状变化
torch.reshape(input, shape) → Tensor
- 返回数据与input相同,形状为shape的tensor
- 若input为 contiguous 的,则不会进行复制,即输出的tensor 和input指向同一块内存。否则将会进行复制。
去掉某个大小为1的维度
torch.squeeze(input, dim=None, out=None) → Tensor
Tensor.squeeze(dim=None) → Tensor
- 返回一个tensor,这个tensor是将input的所有维度大小为1维度去掉得到的
- 若不指定dim,则去掉所有维度为1的维度,若指定维度,且该维度为1,则去掉这个维度
增加一个维度
torch.unsqueeze(input, dim, out=None) → Tensor
Tensor.unsqueeze(dim=None) → Tensor
- 返回一个tensor,这个tensor是在input的dim位置增加一个维度得到的
tensor堆积
torch.stack(tensors, dim=0, out=None) → Tensor
- tensors (sequence of Tensors) – sequence of tensors to concatenate
- 根据指定的维度,将所有的tensor拼接起来,所有tensor的形状应该相同,dim不能超过tensor的维度
- 举个例子:若 d = torch.stack([a,b],dim = x)
- 若x = 0,则结果为 d[0] = a, d[1] = b
- 若x = 1,则结果为 d[0] = [a[0], b[0]], d[1] = [a[1],b[1]]
- 若x = 2,则结果为 d[0] = [ a[0][0] b[0][0], a[0][1] b[0][1],···]
- 即将dim维度拼接起来。
- 一个具体的解释:https://blog.csdn.net/Teeyohuang/article/details/80362756
tensor划分
torch.split(tensor, split_size_or_sections, dim=0)
- 沿着维度dim将tensor划分成 chunk,若split_size_or_sections 为整数,则等大小划分,最后一块可能会小一些。若为list,则按照list指定的大小进行划分。返回值是一个tuple,每个位置是划分好的tensor
tensor拼接
torch.cat(tensors, dim=0, out=None) → Tensor
- 参数解释
- 使用示例
运算
tensor点乘
torch.mul(input, other, out=None)
Tensor.mul(other) → Tensor
- input 为输入的tensor,other可以是一个缩放因子,与tensor所有元素相乘,也可以是另一个tensor,实现矩阵点乘。
- 若两个tensor形状能broadcast,则形状可以不同,如(1,4) 和 (4,1)。
矩阵乘法
torch.mm(input, mat2, out=None) → Tensor
Tensor.mm(mat2) → Tensor
各种乘法
torch.matmul(input, other, out=None) → Tensor
- 较为复杂,下图为一些例子
batch矩阵乘法
torch.bmm(input, mat2, out=None) → Tensor
- batch 矩阵乘法
其他
PyTorch 中,nn 与 nn.functional 有很多相同的函数,它们有什么区别?
- 知乎回答:https://www.zhihu.com/question/66782101
- 简单来说,nn不需要自己管理参数,而后者需要自己管理参数,且后者不能与nn.Sequential合用。
- 推荐具有学习参数的使用nn,无学习参数的使用nn.functional
- 注意
dropout
,当使用model.eval()后,nn.functional.dropout()是不会自动关闭的。
python 3.7 中可以对函数定义进行注释
一个简单的例子:def function(a: int = 4, b: str =“nihao”) -> str
- 详细请看博客:https://blog.csdn.net/finalkof1983/article/details/87943032
list, numpy, pytorch 相互转化
- list转numpy:
ndarray = np.array(list)
- list转torch.Tensor:
tensor=torch.Tensor(list)
- numpy 转torch.Tensor:
tensor = torch.from_numpy(ndarray)
- numpy 转 list:
list = ndarray.tolist()
- torch.Tensor 转 numpy:
ndarray = tensor.numpy()
- gpu上的tensor不能直接转为numpy:
ndarray = tensor.cpu().numpy()
- torch.Tensor 转 list:
list = tensor.numpy().tolist()
先转numpy后转list
解决 tqdm 一直往下滚动
是因为进度条太长了,设置nclos即可
for i in tqdm(range(100),ncols=80)
j = i*i
损失函数
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=‘mean’)
- 用于多分类。参数不常用,这里不介绍了。
- 一个介绍:https://blog.csdn.net/geter_CS/article/details/84857220
- 输入输出格式
- 使用示例
numpy
np.allclose(matrix1, matrix2)
- 比较两个矩阵所有元素是否相同,误差在 1e-5 之内
神经网络架构相关
线性层
torch.nn.Linear(in_features, out_features, bias=True)
- 输入的最后一个维度与 in_features 相等,将其转化为 out_features
- Linear的参数形状为(out_features, in_features)
LSTM
torch.nn.LSTM(*args, **kwargs)
- 参数:(input_size, hidden_size, num_layers):输入维度,隐藏层维度,层数
- 层数表示多层LSTM stack在一起,后一层以前一层的隐藏层输出为输入
- 其余参数有:bias(True False)、batch_first(如果为真,则输入输出的格式为(batch, seq, feature))、dropout(层与层之间的dropout,最后一层无,默认为0)、bidirectional
- Inputs: input, (h_0, c_0):
- input:(seq_len, batch, input_size)
- h_0 :(num_layers * num_directions, batch, hidden_size)
- c_0 : (num_layers * num_directions, batch, hidden_size)
- 若h_0 和 c_0 没有提供,则初始化为0
- Outputs: output, (h_n, c_n):
- output:(seq_len, batch, num_directions * hidden_size)
- h_n: (num_layers * num_directions, batch, hidden_size)
- c_n: (num_layers * num_directions, batch, hidden_size)
- 注:输入也可以是 packed variable length sequence 见 torch.nn.utils.rnn.pack_padded_sequence()
RNN的输入处理
torch.nn.utils.rnn.pack_padded_sequence(input, lengths, batch_first=False, enforce_sorted=True)
- 一个详细的介绍:https://zhuanlan.zhihu.com/p/34418001
- 将padded过的序列进行“打包”,即将padded过的数据进行压缩,经过LSTM时不会用到padded位置的数据。具体参数含义见下图
RNN的输出处理
torch.nn.utils.rnn.pad_packed_sequence(sequence, batch_first=False, padding_value=0.0, total_length=None)
- 是
pack_padded_sequence()
的逆操作,将压缩后的序列重新“解压”,即重新进行padded。具体参数见下图
- 返回值为一个tuple(包含所有tensor)和一个包含每一个序列长度的tensor
- Tuple of Tensor containing the padded sequence, and a Tensor containing the list of lengths of each sequence in the batch.
一维卷积
torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’)
- 参数说明
- in_channels (int):输入信号的通道,在NLP中就是词向量(/嵌入)维度。
- out_channels (int):输出信号的通道,即filter的个数,在NLP中指输出的维度。
- kernel_size (int or tuple):卷积核的大小,在NLP中指扫过几个词。若将序列的词向量展开,则卷积核大小为 kernel_size * in_channels,就像二维卷积一样
- stride(int or tuple, optional) :步长
- padding (int or tuple, optional) :输入的每一条边补充0的层数
- dilation(int or tuple, `optional``) – 卷积核元素之间的间距
- bias(bool, optional) :添加偏置
- 输入:(batch_size, in_channels, seq_len)
- 输出:(batch_size, out_channels, seq_len_out)
- seq_len_out 计算: s e q _ l e n − k e r n e l _ s i z e s t r i d e + 1 \frac{seq\_len - kernel\_size}{stride} + 1 strideseq_len−kernel_size+1
最大池化
torch.nn.MaxPool1d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
- kernel_size:window的大小。其他参数如下
- 输入与输出的形状
- 使用示例
平均池化
torch.nn.AvgPool1d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)
- 使用示例
LSTMCell
torch.nn.LSTMCell(input_size, hidden_size, bias=True)
- 参数与LSTM类似
- 输入输出格式如下
- 使用示例
- 若每个时间步的输入与上一时间步的输出有关系(若seq2seq的解码器),则使用LSTMCell。当然也可以使用LSTM,输入为(seq_len, batch_size, input_features),其中的 seq_len = 1 即可。
嵌入查询表
torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False, _weight=None)
- 经常用来存储词向量,输入下标即可得到对应的词向量
- 参数:
- num_embeddings (python:int) :词表大小
- embedding_dim (python:int):嵌入维度
- padding_idx (python:int, optional):若给出,则在对应index进行pad,默认为0
- max_norm (python:float, optional) :若给出,若词向量中存在大于max_norm的数,则将其变为 max_norm
- 词向量被初始化为标准正态分布
- 输入与输出
- 使用示例
nn.EMbedding()的类方法
from_pretrained(embeddings, freeze=True, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False)
- 重要的参数含义
- 使用示例