Bei der Implementierung transformatorbasierter Modellarchitekturen für maschinelles Lernen sind in der Regel feste Positionseinbettungen erforderlich, um die Place von Eingabetokens in der Verarbeitung natürlicher Sprache zu erfassen.
Hier ist eine Schritt-für-Schritt-Methode zum Generieren fester Positionseinbettungen mithilfe sinusförmiger Einbettungen:
1. Berechnen Sie Umkehrfrequenzen
Wir wollen höherdimensionalen Positionen niedrigere Frequenzen und niedrigerdimensionalen Positionen höhere Frequenzen zuordnen. Die folgende Formel erfasst wirkungsvoll die Vorstellung, dass niederdimensionale Positionen langsamere Schwingungen in den sinusförmigen Einbettungen aufweisen sollten.
inv_freq = 1.0 / (10000 ** (torch.arange(0, dim, 2) / dim)) # the place dim is dimension of enter
Lassen Sie uns einige Werte übergeben und die Ausgabe sehen:
dim = 7print(torch.arange(0, dim, 2) / dim)
print(10000 ** (torch.arange(0, dim, 2) / dim))
print(1.0 / (10000 ** (torch.arange(0, dim, 2) / dim)))
Output:
tensor([0.0000, 0.2857, 0.5714, 0.8571])
tensor([1.0000e+00, 1.3895e+01, 1.9307e+02, 2.6827e+03])
tensor([1.0000e+00, 7.1969e-02, 5.1795e-03, 3.7276e-04])
Darstellung der Umkehrfrequenzen für verschiedene Dimensionen,
dim = 10 # and 100
plt.plot(np.arange(0, dim, 2), 1.0 / (10000 ** (torch.arange(0, dim, 2) / dim)))
plt.title(f"dim:{dim}")
2. Erstellen Sie einen sinusförmigen Eingang
Als nächstes multiplizieren Sie die Umkehrfrequenzen mit einem Wertebereich von 0 bis zur Sequenzlänge (seq_len
). Diese Multiplikation kombiniert die Positionsinformationen (0 bis seq_len
) mit den variierenden Frequenzen, die durch die Umkehrfrequenzen bestimmt werden. Jeder Place entlang der Sequenz ist eine einzigartige Sinuswellenform zugeordnet.
# Matrix multiplication
sinusoid_inp = (
torch.einsum("i , j -> i j", torch.arange(seq_len), inv_freq)
.float()
)
Hier ist ein Beispiel:
dim = 10
seq_len = 5inv_freq = 1.0 / (10000 ** (torch.arange(0, dim, 2) / dim))
sinusoid_inp = torch.einsum("i , j -> i j", torch.arange(seq_len), inv_freq).float()
print(sinusoid_inp)
# Output:
tensor([[0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00],
[1.0000e+00, 1.5849e-01, 2.5119e-02, 3.9811e-03, 6.3096e-04],
[2.0000e+00, 3.1698e-01, 5.0238e-02, 7.9621e-03, 1.2619e-03],
[3.0000e+00, 4.7547e-01, 7.5357e-02, 1.1943e-02, 1.8929e-03],
[4.0000e+00, 6.3396e-01, 1.0048e-01, 1.5924e-02, 2.5238e-03]])
3. Erstellen Sie Sinus- und Cosinus-Einbettungen
Bewerben Sie sich abschließend torch.sin
Und torch.cos
Funktionen für den Sinus-Eingangstensor zur Erzeugung separater Tensoren für die Sinus- und Kosinus-Einbettungen. Durch die Verwendung von Sinus und Cosinus des Sinuseingangs erhält die Funktion zwei komplementäre Wellenformen, die Positionsinformationen kontinuierlich und periodisch erfassen.
dim = 10
seq_len = 5inv_freq = 1.0 / (10000 ** (torch.arange(0, dim, 2) / dim))
sinusoid_inp = torch.einsum("i , j -> i j", torch.arange(seq_len), inv_freq).float()
sin_emb = torch.sin(sinusoid_inp)
cos_emb = torch.cos(sinusoid_inp)
print(sin_emb, "nn", cos_emb)
#Output:
tensor([[ 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00],
[ 8.4147e-01, 1.5783e-01, 2.5116e-02, 3.9811e-03, 6.3096e-04],
[ 9.0930e-01, 3.1170e-01, 5.0217e-02, 7.9621e-03, 1.2619e-03],
[ 1.4112e-01, 4.5775e-01, 7.5285e-02, 1.1943e-02, 1.8929e-03],
[-7.5680e-01, 5.9234e-01, 1.0031e-01, 1.5924e-02, 2.5238e-03]])
tensor([[ 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
[ 0.5403, 0.9875, 0.9997, 1.0000, 1.0000],
[-0.4161, 0.9502, 0.9987, 1.0000, 1.0000],
[-0.9900, 0.8891, 0.9972, 0.9999, 1.0000],
[-0.6536, 0.8057, 0.9950, 0.9999, 1.0000]])
Bitte beachten Sie, dass die spezifischen Werte der Eingabesequenzen für die Generierung der festen Positionseinbettungen nicht wichtig sind. Das Einzige, was zählt, ist die Dimension und Länge der Eingabesequenzen.
Zeichnen von Meshgrids zur Visualisierung des oben Gesagten,
# Convert tensors to numpy arrays
sin_emb_np = sin_emb.numpy()
cos_emb_np = cos_emb.numpy()# Create a grid of positions for the heatmap
x = np.arange(seq_len) # x-axis positions
y = np.arange(dim // 2) # y-axis positions
# Create a meshgrid from the positions
X, Y = np.meshgrid(x, y)
# Plot the sine embedding heatmap
plt.determine(figsize=(6, 4))
plt.title("Sine Embedding Heatmap")
plt.xlabel("Place")
plt.ylabel("Dimension")
plt.pcolormesh(X, Y, sin_emb_np, cmap='viridis')
plt.colorbar(label='Sine Worth')
# Plot the cosine embedding heatmap
plt.determine(figsize=(6, 4))
plt.title("Cosine Embedding Heatmap")
plt.xlabel("Place")
plt.ylabel("Dimension")
plt.pcolormesh(X, Y, cos_emb_np, cmap='viridis')
plt.colorbar(label='Cosine Worth')