侧边栏壁纸
  • 累计撰写 55 篇文章
  • 累计创建 34 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

Python工具学习记录(持续更新)

NormanZhu
2020-11-19 / 0 评论 / 0 点赞 / 675 阅读 / 3,843 字
温馨提示:
本文最后更新于 2020-11-25,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

最后更新于2020.11.19

PyTorch

理解nn.Embedding 的参数和维度变换

总结自:

通俗讲解pytorch中nn.Embedding原理及使用

最常用的前两个参数是 num_embeddingsembedding_dim ,含义分别是词典大小和编码后的维度。词典大小是指这段输入中有多少个不同的词,也要包括pad一个,比如有5000个不同的单词就可以传入5000,此时的编号则是0~4999。

另外,第三个参数 padding_idx 默认为0,所以默认情况下idx=0的那个元素将会被当作padding

  • 这个模型定义好了以后,输入的内容如何确定?输出又是什么?懒得举例子了,仔细读完一定能懂
    1. 首先肯定需要一个word2id词典,储存单词到词典序号的映射,假设现在我希望输入n个句子,句子的长度可能不一致。
    2. 此时是单词表示的,所以先要对输入进行标准化,也就是大写转小写、标点分离、分词,例如可以用nltktokenize做。接着把这些句子按照长度从大到小排序,也需要一个list,存储每个句子的长度。
    3. 然后用上面的词典把这些句子的单词转换为序号,这样输入就全部变成了数字。
    4. 之后把每个句子后面加上一个EOS表示句子结束,假设我使用idx=1表示EOS。
    5. 因为句子长度不一致,所以要做padding,假设我使用idx=0作为paddding_idx,那么所有句子现在的长度都变成了跟原先最长的句子一样长了,原本较短的句子后面全都被补上了0
    6. 上面所说的n个句子就能够看作一个batch一起进行训练,但是现在还不能直接作为Embedding层的输入。现在如果把这n个句子组织成Tensor,那么一行是一个句子,一共n行,假设shape[n, k]。因为RNN的每一步的输入是一批单词,一共是batch_size个,所以要做一个类似转置的操作,这样每个句子都变成了一列,变成[k, n],然后就能够作为Embedding的输入了。
    7. 输出可见多了一个第三维,这就决定于刚才定义的embedding_size参数是多少了。

补充来自 关于nn.embedding的维度的定义,函数的理解,一些需要注意的点 的注意之处:

nn.embedding的输入只能是编号,不能是隐藏变量,比如one-hot,或者其它,这种情况,可以自己建一个自定义维度的线性网络层,参数训练可以单独训练或者跟随整个网络一起训练(看实验需要)

如果你指定了padding_idx,注意这个padding_idx也是在num_embeddings尺寸内的,比如符号总共有500个,指定了padding_idx,那么num_embeddings应该为501

embedding_dim的选择要注意,根据自己的符号数量,举个例子,如果你的词典尺寸是1024,那么极限压缩(用二进制表示)也需要10维,再考虑词性之间的相关性,怎么也要在15-20维左右,虽然embedding是用来降维的,但是也要注意这种极限维度,结合实际情况,合理定义

bmm()函数

首先是mm(),用于二位矩阵的乘法,bmm就是加上了batch(是不是可以理解为有一批的二维矩阵进行计算?)

(如果猜想没错,那么就比如三维*三维,需要第一个维度相同,因为是一批,后面两个维度就是真正的矩阵,和二维矩阵相乘的要求一样了)

11.11 补充:上面的说法没错,如(bnm) 与 (bmp) 就能够用bmm作乘法,结果是(bnp)

其他乘法的函数:torch.mm(), torch.matmul(), torch.mul()等等

mm 仅用于二维矩阵,matmul用于二维以上;

mul是点乘,可以用 * 代替。

这篇博客总结得更为详细

torch.mul、torch.mm、torch.bmm、torch.matmul的区别_给时光以生命-CSDN博客

squeeze和unsqueeze

  1. squeeze类似于删掉一个维度,比如有一个shape为 [1, 2, 1, 4] 的tensor,对他用 squeeze(0) 就会把他变成 [2, 1, 4] 的shape。如果不指定参数dim,则会把所有1维度的给去掉,就会变成 [2, 4] 。如果传入了参数dim,但是实际上那个维度不是1,那么会不做任何操作,这与numpy 不同,numpy会报错。

    注意:官方给了Note和Warning:

    Note:

    The returned tensor shares the storage with the input tensor, so changing the contents of one will change the contents of the other. 说的大概是共享内存。

    Warning:

    If the tensor has a batch dimension of size 1, then squeeze(input) will also remove the batch dimension, which can lead to unexpected errors. 说的是如果batch维度是1,则会被去掉,导致一些其他错误。

  2. unsqueeze就是反操作

torch.chunk函数

这个函数有三个参数:

  • input (Tensor) – the tensor to split
  • chunks (int) – number of chunks to return
  • dim (int) – dimension along which to split the tensor

用处是:把input在dim维度上分成chunk个片,如果这个维度的元素(tensor长度)不能整除chunk,那么最后的一个分片会被舍弃掉

torch.index_select函数

三个参数:

torch.index_select(x, 0, indices),indices是tensor,这里会起一个索引的作用,把x在0维度上取出indices对应位置的元素

>>> x = torch.randn(3, 4)
>>> x
tensor([[ 0.1427,  0.0231, -0.5414, -1.0009],
        [-0.4664,  0.2647, -0.1228, -1.1068],
        [-1.1734, -0.6571,  0.7230, -0.6004]])
>>> indices = torch.tensor([0, 2])
>>> torch.index_select(x, 0, indices)
tensor([[ 0.1427,  0.0231, -0.5414, -1.0009],
        [-1.1734, -0.6571,  0.7230, -0.6004]])
>>> torch.index_select(x, 1, indices)
tensor([[ 0.1427, -0.5414],
        [-0.4664, -0.1228],
        [-1.1734,  0.7230]])
0

评论区