J'ai créé un algorithme de recherche en utilisant word2vec avec l'espoir que non seulement les mots exacts, mais aussi les synonymes seront atteints. En conséquence, les informations word2vec seules n'étaient pas satisfaisantes, mais il semble que l'effet attendu sera atteint, j'ai donc pensé qu'il serait utile de les combiner avec d'autres méthodes.
macOS Catalina 10.15.4 python 3.8.0
Je laisserai la méthode détaillée à d'autres articles. J'ai téléchargé le texte intégral de wikipedia, je l'ai partagé avec mecab-ipadic-neologd et j'ai appris word2vec avec gensim. Le code au moment de l'apprentissage est le suivant. J'ai emprunté le code à Création d'un modèle word2vec en utilisant le corpus Wikipedia | Journal de dévotion adhésif.
from gensim.models import word2vec
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus('./wiki_wakati_neologd.txt')
model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15)
model.save("./wiki_neologd.model")
Calculez la similitude entre le texte d'entrée et la liste des documents à rechercher par la méthode suivante pour obtenir le texte avec la similitude la plus élevée.
Le code qui réalise ce qui précède est ci-dessous.
import re
import neologdn
import MeCab, jaconv
import pandas as pd
from gensim.models import word2vec
#chargement du modèle word2vec
MODEL_PATH = "wiki_neologd.model"
model = word2vec.Word2Vec.load(MODEL_PATH)
#Objet pour analyse morphologique
m = MeCab.Tagger()
#Objet pour le traitement normal des expressions
re_kana = re.compile('[a-zA-Z\u3041-\u309F]')
re_num = re.compile('[0-9]+')
#Documenter la fonction de normalisation avant l'analyse morphologique
def format_text(text):
text = neologdn.normalize(text)
return text
#Fonction pour extraire le prototype du mot indépendant de la phrase, à l'exclusion d'un caractère alphanumérique
def extract_words(text):
words = []
for token in m.parse(text).splitlines()[:-1]:
if '\t' not in token: continue
surface = token.split('\t')[0]
pos = token.split('\t')[1].split(',')
ok = (pos[0]=='nom' and pos[1] in ['Général','固有nom','Changer de connexion','Racine du verbe adjectif'])
ok = (ok or (pos[0]=='adjectif' and pos[1] == 'Indépendance'))
ok = (ok or (pos[0]=='adverbe' and pos[1] == 'Général'))
ok = (ok or (pos[0]=='verbe' and pos[1] == 'Indépendance'))
if ok == False: continue
stem = pos[-3]
if stem == '*': stem = surface
if stem == '-': continue
if re_kana.fullmatch(stem) and len(stem)==1: continue
if re_num.fullmatch(stem): continue
if stem == '': continue
words.append(stem)
return words
#Extraire des mots indépendants d'un ensemble de documents et créer une base de données.
def get_document_db(documents):
id_list = list(range(len(documents)))
words_list = []
for d in documents:
d = format_text(d)
words = extract_words(d)
#Exclure les doublons
words = set(words)
#Exclure les mots qui ne sont pas dans word2vec
words = [w for w in words if w in model.wv.vocab]
words_list.append(words)
db = pd.DataFrame({"id":id_list, "text":documents, "word":words_list})
return db
#Renvoie la similitude entre la liste de mots A et la liste de mots B
def calc_similarity(words1, words2):
total = 0
for w1 in words1:
if w1 not in model.wv.vocab: continue
max_sim = 0
for w2 in words2:
if w2 not in model.wv.vocab: continue
sim = model.wv.similarity(w1=w1, w2=w2)
max_sim = max(max_sim, sim)
total += max_sim
return total
#Calcule et renvoie la similitude entre l'instruction d'entrée et chaque document dans db
def add_similarity_to_db(text, db):
text = format_text(text)
words1 = extract_words(text)
#Exclure les doublons
words1 = set(words1)
words1 = [w for w in words1 if w in model.wv.vocab]
similarity = []
for words2 in db.word:
sim = calc_similarity(words1, words2)
similarity.append(sim)
similarity_df = pd.DataFrame({"similarity": similarity})
db2 = pd.concat([db,similarity_df], axis=1)
db2 = db2.sort_values(["similarity"], ascending=False)
db2 = db2.reset_index()
return db2
#Contrôle de sortie
#Ensemble de documents à rechercher
#Faites une liste de documents, un élément à la fois. Ici, à titre d'exemple, j'utilise des phrases qui sont correctement extraites de mes articles précédents.
documents = [
'J'ai créé une fonction pour obtenir la prononciation japonaise en kana avec MeCab et Python. Par exemple, si vous saisissez «J'ai bien dormi aujourd'hui», il renverra «Kyowayokunemashita».',
'J'ai créé une fonction python qui divise le japonais (chaîne de caractères katakana) en unités de mora (division mora). Mora et syllabes sont des unités de division typiques de la phonologie japonaise. Mora est un délimiteur lors du comptage des soi-disant «5, 7, 5» dans le haïku, et les sons longs (-), les sons d'incitation (tsu) et le répulsif sonore (n) sont également comptés comme un battement. Par contre, dans les syllabes, les notes longues, les sons incitatifs et les sons répulsifs ne sont pas comptés individuellement, mais sont considérés comme un battement avec le kana qui peut être une seule syllabe juste avant.',
'J'ai créé une fonction python qui divise le japonais (chaîne de caractères katakana) en unités syllabiques (division syllabique). Mora et syllabes sont des unités de division typiques de la phonologie japonaise. Mora est un délimiteur lors du comptage des soi-disant «5, 7, 5» dans le haïku, et les sons longs (-), les sons d'incitation (tsu) et le répulsif sonore (n) sont également comptés comme un battement. Par contre, dans les syllabes, les notes longues, les sons incitatifs et les sons répulsifs ne sont pas comptés individuellement, mais sont considérés comme un battement avec le kana qui peut être une seule syllabe juste avant. Si un son long, un son incitatif et une répulsion sonore sont continus comme "brûler", le nombre de mora de 3 ou plus devient une syllabe.',
'En Python, j'ai créé une fonction qui divise (la dernière ligne du tableau ci-dessous) par phrase et non par mot (partie).',
'"Trouvez le nombre de 25 trillions de chiffres du plancher de 100 trillions(J'ai essayé de résoudre le problème "la notation est un système décimal)" avec python. (L'histoire originale est la fameuse question "Le 25 trillionième numéro de la droite des 100 trillions d'étages est-il pair ou impair?")',
'Le dictionnaire par défaut de MeCab est mecab-ipadic-Ceci est un mémo de ce que j'ai fait dans mon environnement (macOS) pour passer à NEologd. Comme beaucoup de gens l'ont déjà écrit, le dictionnaire par défaut peut être changé en éditant un fichier appelé mecabrc, mais dans mon environnement il y a plusieurs mecabrc et je me demandais lequel éditer, donc lequel J'écris sur la façon dont cela fonctionnait réellement, y compris comment savoir si un fichier doit être modifié.'
]
db = get_document_db(documents)
input_texts = ["Japonais séparé","Calcul du plancher","Séparer le japonais avec Mora", "Séparer le japonais par syllabes"]
for text in input_texts:
print(text)
result = add_similarity_to_db(text, db)
for sim, d in list(zip(result.similarity, result.text))[:10]:
disp = d
if len(d)>20: disp = d[:20]+"..."
print(sim, disp)
La sortie est ci-dessous. Le nombre de documents est petit et il est difficile de comprendre comme exemple, mais les deux premiers résultats sont comme ça. Dans les deux derniers, les scores étaient exactement les mêmes pour Mora et syllabes. Il semble que Mora et les syllabes aient coexisté dans cet ensemble de documents. Inclure le poids des mots dans chaque document dans le calcul à l'aide de tfidf, etc. peut être mieux, mais j'aimerais le vérifier à l'avenir.
Japonais séparé
2.593316972255707 Minutes japonaises (chaîne de caractères Katakana) en unités Mora...
2.593316972255707 japonais (chaîne de caractères katakana) divisé par syllabe...
1.6599590480327606 Prononciation japonaise avec MeCab et Python...
1.5144233107566833 Le dictionnaire par défaut de MeCab est mecab-...
1.4240807592868805 En Python, pas une unité de mots (parties)...
1.18932443857193 "Trouvez les 25 trillions de chiffres de l'étage de 100 trillions...
Calcul du plancher
1.4738755226135254 "Trouvez le nombre de 25 billions de chiffres de l'étage de 100 billions de dollars...
1.1860262751579285 prononciation japonaise avec MeCab et Python...
1.1831795573234558 Minutes japonaises (chaîne de caractères Katakana) en unités Mora...
1.1831795573234558 Japonais (chaîne de caractères katakana) divisé par syllabe...
1.1831795573234558 En Python, ce n'est pas une unité de mots (parties)...
0.7110081613063812 Le dictionnaire par défaut de MeCab est mecab-...
Séparer le japonais avec Mora
3.0 minute de japonais (chaîne de caractères Katakana) en unités Mora...
3.0 Le japonais (chaîne de caractères katakana) est-il divisé en unités syllabiques?...
1.754945456981659 Prononciation japonaise avec MeCab et Python...
1.6068530082702637 En Python, pas en mots (parties)...
1.226668268442154 Le dictionnaire par défaut de MeCab est mecab-...
1.1506744921207428 "Trouvez les 25 billions de chiffres de l'étage de 100 billions...
Séparer le japonais par syllabes
3.0 minute de japonais (chaîne de caractères Katakana) en unités Mora...
3.0 Le japonais (chaîne de caractères katakana) est-il divisé en unités syllabiques?...
1.862914353609085 prononciation japonaise avec MeCab et Python...
1.6907644867897034 En Python, pas en mots (parties)...
1.2761026918888092 Le dictionnaire par défaut de MeCab Mecab-...
1.2211730182170868 "Trouvez le nombre de 25 billions de chiffres de l'étage de 100 billions de dollars...
Recommended Posts