word2vec 余弦相似度大于 1 阿拉伯文本

word2vec cosine similarity greater than 1 arabic text

我已经从 gensim 训练了我的 word2vec 模型,我正在为语料库中的一些词获取最近的邻居。以下是相似度分数:

 top neighbors for الاحتلال:
الاحتلال: 1.0000001192092896
الاختلال: 0.9541053175926208
الاهتلال: 0.872565507888794
الاحثلال: 0.8386293649673462
الاكتلال: 0.8209128379821777

相似度大于 1 很奇怪。我不能对我的文本应用任何词干提取,因为该文本包含许多 OCR 拼写错误(我从 ORC-ed 文档中获取文本)。我该如何解决这个问题?

注意我正在使用model.similarity(t1, t2)

这就是我训练 Word2Vec 模型的方式:

    documents = list()
    tokenize = lambda x: gensim.utils.simple_preprocess(x)
    t1 = time.time()
    docs = read_files(TEXT_DIRS, nb_docs=5000)
    t2 = time.time()
    print('Reading docs took: {:.3f} mins'.format((t2 - t1) / 60))
    print('Number of documents: %i' % len(docs))

    # Training the model
    model = gensim.models.Word2Vec(docs, size=EMBEDDING_SIZE, min_count=5)
    if not os.path.exists(MODEL_DIR):
        os.makedirs(MODEL_DIR)
    model.save(os.path.join(MODEL_DIR, 'word2vec'))

    weights = model.wv.vectors
    index_words = model.wv.index2word

    vocab_size = weights.shape[0]
    embedding_dim = weights.shape[1]

    print('Shape of weights:', weights.shape)
    print('Vocabulary size: %i' % vocab_size)
    print('Embedding size: %i' % embedding_dim)

下面是我定义的read_files函数:

def read_files(text_directories, nb_docs):
    """
    Read in text files
    """
    documents = list()
    tokenize = lambda x: gensim.utils.simple_preprocess(x)
    print('started reading ...')
    for path in text_directories:
        count = 0
        # Read in all files in directory
        if os.path.isdir(path):
            all_files = os.listdir(path)
            for filename in all_files:
                if filename.endswith('.txt') and filename[0].isdigit():
                    count += 1
                    with open('%s/%s' % (path, filename), encoding='utf-8') as f:
                        doc = f.read()
                        doc = clean_text_arabic_style(doc)
                        doc = clean_doc(doc)
                        documents.append(tokenize(doc))
                        if count % 100 == 0:
                            print('processed {} files so far from {}'.format(count, path))
                if count >= nb_docs and count <= nb_docs + 200:
                    print('REACHED END')
                    break
        if count >= nb_docs and count <= nb_docs:
            print('REACHED END')
            break

    return documents

我尝试了 this 线程,但它对我没有帮助,因为我宁愿有 arabic 拼写错误 文本

更新 我尝试了以下方法:(获得完全相同单词之间的相似度)

print(model.similarity('الاحتلال','الاحتلال'))

它给了我以下结果:

1.0000001

从定义上讲,余弦相似性度量的最大值应为 1.0。

但实际上,计算机中的浮点数表示在小数位上有微小的不精确性。并且,尤其是当连续进行大量计算时(就像计算这个余弦距离一样),这些计算有时会导致与预期的最大或完全正确的答案“应该”略有偏差。

(类似地:有时,从数学上讲,无论它们如何计算都应该得出完全相同的答案 reordered/regrouped 在以不同的顺序完成时略有偏差。)

但是,由于这些表示错误通常“非常小”,因此通常不会引起实际关注。 (它们在 -1.0 到 1.0 左右的数字范围内特别小,但在处理大数字时会变得非常大。)

在您的原始情况下,偏差仅为 0.000000119209289。在 word-to-itself 的情况下,偏差仅为 0.0000001。也就是说,大约减少了千万分之一。 (您的其他子 1.0 值与完美计算有类似的微小偏差,但它们并不明显。)

在大多数情况下,您应该忽略它。

如果您发现它以数字 displays/logging 分散您或您的用户的注意力,只需选择将所有此类值显示为有限数量的小数点后数字 - 比如 4 甚至 5 或6 – 将隐藏那些嘈杂的数字。例如,使用 Python 3 格式字符串:

sim = model.similarity('الاحتلال','الاحتلال')
print(f"{sim:.6}")

(像 numpy 这样处理大量此类浮点数的库甚至可以设置显示精度的全局默认值 – 参见 numpy.set_print_options – 虽然这不应该影响原始 Python 浮动你正在检查。)

如果出于某种原因您绝对需要将值限制在 1.0,您可以添加额外的代码来执行此操作。但是,通常更好的做法是选择你的测试和打印输出,使其能够稳健地应对与完美数学的如此微小的偏差。