2020-12-20 13:15:07 +08:00
|
|
|
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
2020-10-10 15:51:54 +08:00
|
|
|
import math
|
2020-12-03 14:54:32 +08:00
|
|
|
import numpy as np
|
2020-10-10 15:51:54 +08:00
|
|
|
import paddle
|
|
|
|
from paddle.nn import functional as F
|
|
|
|
|
2020-12-21 17:41:18 +08:00
|
|
|
__all__ = ["sinusoid_positional_encoding"]
|
2020-12-03 14:54:32 +08:00
|
|
|
|
2020-12-20 13:15:07 +08:00
|
|
|
|
2020-12-21 17:41:18 +08:00
|
|
|
def sinusoid_positional_encoding(start_index, length, size, dtype=None):
|
2020-12-18 15:30:56 +08:00
|
|
|
r"""Generate standard positional encoding matrix.
|
|
|
|
|
|
|
|
.. math::
|
2020-10-10 15:51:54 +08:00
|
|
|
|
2020-12-18 15:30:56 +08:00
|
|
|
pe(pos, 2i) = sin(\frac{pos}{10000^{\frac{2i}{size}}}) \\
|
|
|
|
pe(pos, 2i+1) = cos(\frac{pos}{10000^{\frac{2i}{size}}})
|
2020-10-10 15:51:54 +08:00
|
|
|
|
2020-12-18 15:30:56 +08:00
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
start_index : int
|
|
|
|
The start index.
|
|
|
|
length : int
|
|
|
|
The timesteps of the positional encoding to generate.
|
|
|
|
size : int
|
|
|
|
Feature size of positional encoding.
|
2020-10-10 15:51:54 +08:00
|
|
|
|
2020-12-18 15:30:56 +08:00
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
Tensor [shape=(length, size)]
|
|
|
|
The positional encoding.
|
|
|
|
|
|
|
|
Raises
|
|
|
|
------
|
|
|
|
ValueError
|
|
|
|
If ``size`` is not divisible by 2.
|
2020-10-10 15:51:54 +08:00
|
|
|
"""
|
|
|
|
if (size % 2 != 0):
|
|
|
|
raise ValueError("size should be divisible by 2")
|
2020-10-14 10:05:26 +08:00
|
|
|
dtype = dtype or paddle.get_default_dtype()
|
2020-12-03 14:54:32 +08:00
|
|
|
channel = np.arange(0, size, 2)
|
|
|
|
index = np.arange(start_index, start_index + length, 1)
|
2020-12-20 13:15:07 +08:00
|
|
|
p = np.expand_dims(index, -1) / (10000**(channel / float(size)))
|
2020-12-03 14:54:32 +08:00
|
|
|
encodings = np.zeros([length, size])
|
|
|
|
encodings[:, 0::2] = np.sin(p)
|
|
|
|
encodings[:, 1::2] = np.cos(p)
|
|
|
|
encodings = paddle.to_tensor(encodings)
|
2020-10-10 15:51:54 +08:00
|
|
|
return encodings
|