Ich möchte ein neues Wort definieren, das Zählwerte aus zwei (oder mehr) verschiedenen Wörtern enthält. Zum Beispiel:

Words Frequency
0   mom 250
1   2020    151
2   the 124
3   19  82
4   mother  81
... ... ...
10  London  6
11  life    6
12  something   6

Ich möchte Mutter als mom + mother definieren:

Words Frequency
0   mother  331
1   2020    151
2   the 124
3   19  82
... ... ...
9   London  6
10  life    6
11  something   6

Dies ist eine Möglichkeit, eine Gruppe von Wörtern mit einer bestimmten Bedeutung zu definieren (zumindest für meinen Zweck).

Jeder Vorschlag wäre dankbar.

22
user13623188 2 Sept. 2020 im 15:44

6 Antworten

Beste Antwort

UPDATE 21.10.2020

Ich habe beschlossen, ein Python-Modul zu erstellen, um die in dieser Antwort beschriebenen Aufgaben zu erledigen. Das Modul heißt wordhoard und kann von pypi


Ich habe versucht, Word2vec und WordNet in Projekten zu verwenden, in denen ich die Häufigkeit eines Schlüsselworts (z. B. Gesundheitswesen) und die Synonyme des Schlüsselworts (z. B. Wellness-Programm, Präventivmedizin) bestimmen musste. Ich stellte fest, dass die meisten NLP-Bibliotheken nicht die gewünschten Ergebnisse lieferten, und entschied mich daher, ein eigenes Wörterbuch mit benutzerdefinierten Schlüsselwörtern und Synonymen zu erstellen. Dieser Ansatz hat sich in mehreren Projekten sowohl für die Analyse als auch für die Klassifizierung von Text bewährt.

Ich bin mir sicher, dass jemand, der sich mit NLP-Technologie auskennt, möglicherweise eine robustere Lösung hat, aber die folgende ist eine ähnliche, die immer wieder für mich funktioniert hat.

Ich habe meine Antwort so codiert, dass sie mit den Worthäufigkeitsdaten übereinstimmt, die Sie in Ihrer Frage hatten. Sie kann jedoch geändert werden, um einen beliebigen Datensatz für Schlüsselwörter und Synonyme zu verwenden.

import string

# Python Dictionary
# I manually created these word relationship - primary_word:synonyms
word_relationship = {"father": ['dad', 'daddy', 'old man', 'pa', 'pappy', 'papa', 'pop'],
          "mother": ["mamma", "momma", "mama", "mammy", "mummy", "mommy", "mom", "mum"]}

# This input text is from various poems about mothers and fathers
input_text = 'The hand that rocks the cradle also makes the house a home. It is the prayers of the mother ' \
         'that keeps the family strong. When I think about my mum, I just cannot help but smile; The beauty of ' \
         'her loving heart, the easy grace in her style. I will always need my mom, regardless of my age. She ' \
         'has made me laugh, made me cry. Her love will never fade. If I could write a story, It would be the ' \
         'greatest ever told. I would write about my daddy, For he had a heart of gold. For my father, my friend, ' \
         'This to me you have always been. Through the good times and the bad, Your understanding I have had.'

# converts the input text to lowercase and splits the words based on empty space.
wordlist = input_text.lower().split()

# remove all punctuation from the wordlist
remove_punctuation = [''.join(ch for ch in s if ch not in string.punctuation) 
for s in wordlist]

# list for word frequencies
wordfreq = []

# count the frequencies of a word
for w in remove_punctuation:
wordfreq.append(remove_punctuation.count(w))

word_frequencies = (dict(zip(remove_punctuation, wordfreq)))

word_matches = []

# loop through the dictionaries
for word, frequency in word_frequencies.items():
   for keyword, synonym in word_relationship.items():
      match = [x for x in synonym if word == x]
      if word == keyword or match:
        match = ' '.join(map(str, match))
        # append the keywords (mother), synonyms(mom) and frequencies to a list
        word_matches.append([keyword, match, frequency])

# used to hold the final keyword and frequencies
final_results = {}

# list comprehension to obtain the primary keyword and its frequencies
synonym_matches = [(keyword[0], keyword[2]) for keyword in word_matches]

# iterate synonym_matches and output total frequency count for a specific keyword
for item in synonym_matches:
  if item[0] not in final_results.keys():
    frequency_count = 0
    frequency_count = frequency_count + item[1]
    final_results[item[0]] = frequency_count
  else:
    frequency_count = frequency_count + item[1]
    final_results[item[0]] = frequency_count

 
print(final_results)
# output
{'mother': 3, 'father': 2}

Andere Methoden

Im Folgenden finden Sie einige andere Methoden und deren Out-of-Box-Ausgabe.


NLTK WORDNET

In diesem Beispiel habe ich die Synonyme für das Wort "Mutter" nachgeschlagen. Beachten Sie, dass in WordNet die Synonyme "Mutter" oder "Mutter" nicht mit dem Wort "Mutter" verknüpft sind. Diese beiden Wörter befinden sich in meinem obigen Beispieltext. Beachten Sie auch, dass das Wort "Vater" als Synonym für "Mutter" aufgeführt ist.

from nltk.corpus import wordnet

synonyms = []
word = 'mother'
for synonym in wordnet.synsets(word):
   for item in synonym.lemmas():
      if word != synonym.name() and len(synonym.lemma_names()) > 1:
        synonyms.append(item.name())

print(synonyms)
['mother', 'female_parent', 'mother', 'fuss', 'overprotect', 'beget', 'get', 'engender', 'father', 'mother', 'sire', 'generate', 'bring_forth']

PyDictionary

In diesem Beispiel habe ich die Synonyme für das Wort "Mutter" mithilfe von PyDictionary nachgeschlagen, das synonym.com abfragt. Die Synonyme in diesem Beispiel umfassen die Wörter "Mutter" und "Mutter". Dieses Beispiel enthält auch zusätzliche Synonyme, die WordNet nicht generiert hat.

ABER PyDictionary hat auch eine Synonymliste für "Mama" erstellt. Was nichts mit dem Wort "Mutter" zu tun hat. Es scheint, dass PyDictionary diese Liste aus dem Adjektivabschnitt der Seite anstelle des Nomenabschnitts gezogen hat. Für einen Computer ist es schwierig, zwischen dem Adjektiv Mutter und dem Substantiv Mutter zu unterscheiden.

from PyDictionary import PyDictionary
dictionary_mother = PyDictionary('mother')

print(dictionary_mother.getSynonyms())
# output 
[{'mother': ['mother-in-law', 'female parent', 'supermom', 'mum', 'parent', 'mom', 'momma', 'para I', 'mama', 'mummy', 'quadripara', 'mommy', 'quintipara', 'ma', 'puerpera', 'surrogate mother', 'mater', 'primipara', 'mammy', 'mamma']}]

dictionary_mum = PyDictionary('mum')

print(dictionary_mum.getSynonyms())
# output 
[{'mum': ['incommunicative', 'silent', 'uncommunicative']}]

Einige der anderen möglichen Ansätze sind die Verwendung der Oxford Dictionary-API oder die Abfrage von thesaurus.com. Beide Methoden haben auch Fallstricke. Beispielsweise erfordert die Oxford Dictionary-API einen API-Schlüssel und ein kostenpflichtiges Abonnement basierend auf Abfragenummern. Und auf thesaurus.com fehlen potenzielle Synonyme, die beim Gruppieren von Wörtern hilfreich sein könnten.

https://www.thesaurus.com/browse/mother
synonyms: mom, parent, ancestor, creator, mommy, origin, predecessor, progenitor, source, child-bearer, forebearer, procreator

AKTUALISIEREN

Das Erstellen einer genauen Synonymliste für jedes potenzielle Wort in Ihrem Korpus ist schwierig und erfordert einen Ansatz mit mehreren Zinken. Der folgende Code verwendet WordNet und PyDictionary, um eine Obermenge von Synonymen zu erstellen. Wie alle anderen Antworten führt auch diese Kombinationsmethode zu einer Überzählung der Worthäufigkeiten. Ich habe versucht, diese Überzählung zu reduzieren, indem ich Schlüssel- und Wertepaare in meinem endgültigen Synonymwörterbuch kombinierte. Das letztere Problem ist viel schwieriger als erwartet und erfordert möglicherweise, dass ich meine eigene Frage öffne, um es zu lösen. Letztendlich denke ich, dass Sie basierend auf Ihrem Anwendungsfall bestimmen müssen, welcher Ansatz am besten funktioniert und wahrscheinlich mehrere Ansätze kombinieren muss.

Vielen Dank, dass Sie diese Frage gestellt haben, da ich mir andere Methoden zur Lösung eines komplexen Problems ansehen konnte.

from string import punctuation
from nltk.corpus import stopwords
from nltk.corpus import wordnet
from PyDictionary import PyDictionary

input_text = """The hand that rocks the cradle also makes the house a home. It is the prayers of the mother
         that keeps the family strong. When I think about my mum, I just cannot help but smile; The beauty of
         her loving heart, the easy grace in her style. I will always need my mom, regardless of my age. She
         has made me laugh, made me cry. Her love will never fade. If I could write a story, It would be the
         greatest ever told. I would write about my daddy, For he had a heart of gold. For my father, my friend,
         This to me you have always been. Through the good times and the bad, Your understanding I have had."""


def normalize_textual_information(text):
   # split text into tokens by white space
   token = text.split()

   # remove punctuation from each token
   table = str.maketrans('', '', punctuation)
   token = [word.translate(table) for word in token]

   # remove any tokens that are not alphabetic
   token = [word.lower() for word in token if word.isalpha()]

   # filter out English stop words
   stop_words = set(stopwords.words('english'))

   # you could add additional stops like this
   stop_words.add('cannot')
   stop_words.add('could')
   stop_words.add('would')

   token = [word for word in token if word not in stop_words]

   # filter out any short tokens
   token = [word for word in token if len(word) > 1]
   return token


def generate_word_frequencies(words):
   # list to hold word frequencies
   word_frequencies = []

   # loop through the tokens and generate a word count for each token
   for word in words:
      word_frequencies.append(words.count(word))

   # aggregates the words and word_frequencies into tuples and coverts them into a dictionary
   word_frequencies = (dict(zip(words, word_frequencies)))

   # sort the frequency of the words from low to high
   sorted_frequencies = {key: value for key, value in 
   sorted(word_frequencies.items(), key=lambda item: item[1])}

 return sorted_frequencies


def get_synonyms_internet(word):
   dictionary = PyDictionary(word)
   synonym = dictionary.getSynonyms()
   return synonym

 
words = normalize_textual_information(input_text)

all_synsets_1 = {}
for word in words:
  for synonym in wordnet.synsets(word):
    if word != synonym.name() and len(synonym.lemma_names()) > 1:
      for item in synonym.lemmas():
        if word != item.name():
          all_synsets_1.setdefault(word, []).append(str(item.name()).lower())

all_synsets_2 = {}
for word in words:
  word_synonyms = get_synonyms_internet(word)
  for synonym in word_synonyms:
    if word != synonym and synonym is not None:
      all_synsets_2.update(synonym)

 word_relationship = {**all_synsets_1, **all_synsets_2}

 frequencies = generate_word_frequencies(words)
 word_matches = []
 word_set = {}
 duplication_check = set()

 for word, frequency in frequencies.items():
    for keyword, synonym in word_relationship.items():
       match = [x for x in synonym if word == x]
       if word == keyword or match:
         match = ' '.join(map(str, match))
         if match not in word_set or match not in duplication_check or word not in duplication_check:
            duplication_check.add(word)
            duplication_check.add(match)
            word_matches.append([keyword, match, frequency])

 # used to hold the final keyword and frequencies
 final_results = {}

 # list comprehension to obtain the primary keyword and its frequencies
 synonym_matches = [(keyword[0], keyword[2]) for keyword in word_matches]

 # iterate synonym_matches and output total frequency count for a specific keyword
 for item in synonym_matches:
    if item[0] not in final_results.keys():
      frequency_count = 0
      frequency_count = frequency_count + item[1]
      final_results[item[0]] = frequency_count
 else:
    frequency_count = frequency_count + item[1]
    final_results[item[0]] = frequency_count

# do something with the final results
7
Life is complex 21 Okt. 2020 im 19:47

Matthew Reagan / Webster's English Dictionary

Die Idee ist, dieses Wörterbuch zu verwenden, um ähnliche Wörter zu identifizieren.

Kurz gesagt: Führen Sie einen Algorithmus zur Entdeckung von Wissen aus, der Wissen gemäß der englischen Grammatik extrahiert

Hier ist ein Thesaurus: 18 MB.

HIER ist ein Auszug aus dem Thesaurus. Sie können versuchen, die Wortalternativen über einen Algorithmus abzugleichen.

{"word": "ma", "key": "ma_1", "pos": "noun", "synonyms": ["mamma", "momma", "mama", "mammy", "mummy", "mommy", "mom", "mum"]}

Für eine schnelle Lösung mit externer API ist hier der Link: Sie ermöglichen es, viel mehr mit API zu tun, wie Synonyme zu erhalten, mehrere Definitionen zu finden, Reimwörter zu finden und vieles mehr.

WORDAPI

-1
nikhil swami 19 Sept. 2020 im 00:03

Sie können Worteinbettungsvektoren generieren und einen Clustering-Algorithmus verwenden. Am Ende müssen Sie die Hyperparameter des Algorithmus anpassen, um das Ergebnis mit hoher Genauigkeit zu erzielen.

from sklearn.cluster import DBSCAN
from sklearn.decomposition import PCA

import spacy

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Load the large english model
nlp = spacy.load("en_core_web_lg")

tokens = nlp("dog cat banana apple teaching teacher mom mother mama mommy berlin paris")

# Generate word embedding vectors
vectors = np.array([token.vector for token in tokens])
vectors.shape
# (12, 300)

Verwenden wir den Algorithmus zur Hauptkomponentenanalyse, um unsere Einbettungen im dreidimensionalen Raum zu visualisieren:

pca_vecs = PCA(n_components=3).fit_transform(vectors)
pca_vecs.shape
# (12, 3)

fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
xs, ys, zs = pca_vecs[:, 0], pca_vecs[:, 1], pca_vecs[:, 2]
_ = ax.scatter(xs, ys, zs)

for x, y, z, lable in zip(xs, ys, zs, tokens):
    ax.text(x+0.3, y, z, str(lable))

enter image description here

Verwenden wir den DBSCAN-Algorithmus, um Wörter zu gruppieren:

model = DBSCAN(eps=5, min_samples=1)
model.fit(vectors)

for word, cluster in zip(tokens, model.labels_):
    print(word, '->', cluster)

Ausgabe:

dog -> 0
cat -> 0
banana -> 1
apple -> 2
teaching -> 3
teacher -> 3
mom -> 4
mother -> 4
mama -> 4
mommy -> 4
berlin -> 5
paris -> 6
1
Mykola Zotko 10 Sept. 2020 im 09:44

Was Sie erreichen möchten, ist semantische Textähnlichkeit .

Ich möchte auf Tensorflow Universal Sentence Encoder empfehlen

Zum Beispiel :

#@title Load the Universal Sentence Encoder's TF Hub module
from absl import logging

import tensorflow as tf

import tensorflow_hub as hub
import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
import re
import seaborn as sns

module_url = "https://tfhub.dev/google/universal-sentence-encoder/4" #@param ["https://tfhub.dev/google/universal-sentence-encoder/4", "https://tfhub.dev/google/universal-sentence-encoder-large/5"]
model = hub.load(module_url)
print ("module %s loaded" % module_url)
def embed(input):
  return model(input)

def plot_similarity(labels, features, rotation):
  corr = np.inner(features, features)
  sns.set(font_scale=1.2)
  g = sns.heatmap(
      corr,
      xticklabels=labels,
      yticklabels=labels,
      vmin=0,
      vmax=1,
      cmap="YlOrRd")
  g.set_xticklabels(labels, rotation=rotation)
  g.set_title("Semantic Textual Similarity")

def run_and_plot(messages_):
  message_embeddings_ = embed(messages_)
  plot_similarity(messages_, message_embeddings_, 90)

messages = [
    "Mother",
    "Mom",
    "Mama",
    "Dog",
    "Cat"
]

run_and_plot(messages)

enter image description here

Das Beispiel ist in Python geschrieben, aber ich habe auch ein Beispiel zum Laden des Modells in JVM-basierte Sprachen erstellt

https://github.com/ntedgi/universal-sentence-encoder

1
Naor Tedgi 7 Sept. 2020 im 15:40

Eine andere verrückte Möglichkeit, dies zu beheben, um die gute alte PyDictionary-Bibliothek zu verwenden. Du kannst den ... benutzen

dictionary.getSynonyms()

Funktion zum Durchlaufen aller Wörter in Ihrer Liste und zum Gruppieren. Alle verfügbaren verfügbaren Synonyme werden abgedeckt und einer Gruppe zugeordnet. Dort können Sie die endgültige Variable zuweisen und die Synonyme zusammenfassen. In deinem Beispiel. Sie wählen das letzte Wort als Mutter, das die endgültige Anzahl der Synonyme anzeigt.

2
Ares Zephyr 7 Sept. 2020 im 06:58

Es ist ein schwieriges Problem und die beste Lösung hängt von dem Anwendungsfall ab, den Sie lösen möchten. Es ist ein schwieriges Problem, denn um Wörter zu kombinieren, muss man die Semantik des Wortes verstehen. Sie können mom und mother miteinander kombinieren, da sie semantisch miteinander verbunden sind.

Eine Möglichkeit, zu identifizieren, ob zwei Wörter semantisch realisiert sind, besteht darin, die verteilten Worteinbettungen (Vektoren) wie word2vec, Glove, fasttext et. Sie können die Kosinusähnlichkeit zwischen den Vektoren aller Wörter in Bezug auf ein Wort finden und können die obersten 5 nahen Wörter aufnehmen und neue Wörter erstellen.

Beispiel mit word2vec

# Load a pretrained word2vec model
import gensim.downloader as api
model = api.load('word2vec-google-news-300')

vectors = [model.get_vector(w) for w in words]
for i, w in enumerate(vectors):
   first_best_match = model.cosine_similarities(vectors[i], vectors).argsort()[::-1][1]
   second_best_match = model.cosine_similarities(vectors[i], vectors).argsort()[::-1][2]
   
   print (f"{words[i]} + {words[first_best_match]}")
   print (f"{words[i]} + {words[second_best_match]}")  

Ausgabe:

mom + mother
mom + teacher
mother + mom
mother + teacher
london + mom
london + life
life + mother
life + mom
teach + teacher
teach + mom
teacher + teach
teacher + mother

Sie können versuchen, den Schwellenwert für die Kosinusähnlichkeit festzulegen, und nur diejenigen auswählen, deren Kosinusähnlichkeit größer als dieser Schwellenwert ist.

Ein Problem mit semantischer Ähnlichkeit ist, dass sie semantisch entgegengesetzt sein können und daher ähnlich sind (Mann - Frau), andererseits (Mann - König) semantisch ähnlich sind, weil sie gleich sind.

4
mujjiga 7 Sept. 2020 im 14:14