fastText 嵌入句子向量?

ryu*_*nho 13 python fasttext

我想了解创建句子的 fastText 向量的方式。根据这个问题309,通过平均单词的向量来获得句子的向量。

为了确认这一点,我编写了以下脚本:

import numpy as np
import fastText as ft

# Loading model for Finnish.
model = ft.load_model('cc.fi.300.bin')

# Getting word vectors for 'one' and 'two'.
one = model.get_word_vector('yksi')
two = model.get_word_vector('kaksi')

# Getting the sentence vector for the sentence "one two" in Finnish.
one_two = model.get_sentence_vector('yksi kaksi')
one_two_avg = (one + two) / 2

# Checking if the two approaches yield the same result.
is_equal = np.array_equal(one_two, one_two_avg)

# Printing the result.
print(is_equal)

# Result: FALSE
Run Code Online (Sandbox Code Playgroud)

但是,似乎获得的向量并不相似。

为什么两个值不一样?它会与我平均向量的方式有关吗?或者,也许我遗漏了什么?

mal*_*oro 21

首先,您错过了get_sentence_vector不仅仅是简单“平均值”的部分。FastText 在对每个词向量求和之前,先将每个向量除以它的范数(L2 范数),然后平均过程只涉及具有正 L2 范数值的向量。

其次,一个句子总是以 EOS 结尾。因此,如果您尝试手动计算,则需要在计算平均值之前放置 EOS。

试试这个(我假设每个词的 L2 范数是正数):


def l2_norm(x):
   return np.sqrt(np.sum(x**2))

def div_norm(x):
   norm_value = l2_norm(x)
   if norm_value > 0:
       return x * ( 1.0 / norm_value)
   else:
       return x

# Getting word vectors for 'one' and 'two'.
one = model.get_word_vector('yksi')
two = model.get_word_vector('kaksi')
eos = model.get_word_vector('\n')

# Getting the sentence vector for the sentence "one two" in Finnish.
one_two = model.get_sentence_vector('yksi kaksi')
one_two_avg = (div_norm(one) + div_norm(two) + div_norm(eos)) / 3
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看源代码也可以在此处查看讨论。

  • 它或多或少是一个平均值,而是单位向量的平均值。 (2认同)
  • 请注意,l2 范数不能为负数:它是 0 或正数。如果 l2 范数为 0,除以它就没有意义。 (2认同)

小智 0

您可能会遇到浮点数学问题 - 例如,如果在 CPU 上完成一项加法,而在 GPU 上完成一项加法,则它们可能会有所不同。

检查它是否按照您想要的方式执行的最佳方法是确保向量几乎完全相同。

您可能想要打印出两个向量并手动检查它们,或者对其本身进行 one_two 减去 one_two_avg 的点积(即两者之间差异的长度)。