Dans le dernier article, j'ai fait un simple text mining basé sur le travail d'Aozora Bunko. https://qiita.com/ereyester/items/7c220a49c15073809c33 Cette fois, j'aimerais utiliser Word2vec pour explorer la similitude des mots. Il existe de nombreux autres articles sur Word2vec, je ne les expliquerai donc pas en détail. [Comprendre Word2Vec](https://qiita.com/g-k/items/69afa87c73654af49d36 «Comprendre Word2Vec») [Python] Comment utiliser Word2Vec Cette fois, je voudrais me concentrer sur la fonction de word2vec.Word2Vec () dans gensim.models de gensim. Le mécanisme de Word2vec compris par les images
[Matériel de formation des enseignants du Département de l'information du lycée "Information II" (volume principal): Ministère de l'éducation, de la culture, des sports, de la science et de la technologie](https://www.mext.go.jp/a_menu/shotou/zyouhou/detail/mext_00742.html "Département de l'information du lycée Matériel pédagogique "Information II" pour la formation des enseignants (partie principale): Ministère de l'éducation, de la culture, des sports, des sciences et de la technologie ") Chapter 3 Information and Data Science Second Half (PDF: 7.6MB)
Apprentissage 18 Text mining et reconnaissance d'images: "2. Text mining using MeCab"
En python, chargez un package appelé gensim pour l'apprentissage automatique avec Word2vec.
!pip install gensim
Ensuite, téléchargez le dictionnaire des émotions pour une analyse des émotions à effectuer plus tard. L'analyse des émotions est possible en trouvant la distance par rapport aux principaux termes des termes qui indiquent l'émotion avec Word2vec lors de l'analyse des émotions, mais ici, en tant que dictionnaire japonais, l'analyse des émotions est effectuée à l'aide de la table PN de l'Institut de technologie de Tokyo. Je vais.
import urllib.request
import pandas as pd
#Lien de table PN
url = 'http://www.lr.pi.titech.ac.jp/~takamura/pubs/pn_ja.dic'
#Nom de sauvegarde du fichier
file_path = 'pn_ja.dic'
with urllib.request.urlopen(url) as dl_file:
with open(file_path, 'wb') as out_file:
out_file.write(dl_file.read())
#Lisez le dictionnaire
dic = pd.read_csv('/content/pn_ja.dic', sep = ':', encoding= 'shift_jis', names = ('word','reading','Info1', 'PN'))
print(dic)
Le résultat de l'exécution est le suivant.
word reading Info1 PN
0 Excellent excellent verbe 1.000000
1 bon bon adjectif 0.999995
2 Réjouis-toi Verbe joyeux 0.999979
3 louange praise verbe 0.999979
4 Medetai Medetai Adjectif 0.999645
... ... ... ... ...
55120 Non Non Verbe auxiliaire-0.999997
55121 Terribles adjectifs terribles-0.999997
55122 Nomenclature des maladies-0.999998
55123 Die no verbe-0.999999
55124 Mauvais mauvais adjectifs-1.000000
[55125 rows x 4 columns]
Ensuite, installez Mecab.
(Ajouté à 19:00 le 18/09/2020) L'auteur de mecab-python3 a souligné qu'il n'est pas nécessaire d'installer mecab, libmecab-dev et ipadic avec aptitude avant d'installer mecab-python3, je vais donc le réparer.
!pip install mecab-python3
!pip install unidic-lite
Convertissez le texte à analyser en texte séparé et enregistrez-le pour l'apprentissage avec word2vec. Suivez les étapes ci-dessous. (1) Téléchargez et lisez les données textuelles de "Bo-chan" pour effectuer une analyse de texte sur "Bo-chan" de Natsume Soseki. (2) Supprimez le rubis, les annotations, etc. ③ Extrayez la nomenclature, les adjectifs et les verbes du texte de "Bochan", supprimez les nombres et les mots non indépendants, convertissez-les en "écriture séparée" et convertissez-les en un fichier appelé tf.txt.
from collections import Counter
import MeCab #Lisez MeCab
import zipfile
import os.path,glob
import re
#Spécifiez l'URL de "Bochan"
url = 'https://www.aozora.gr.jp/cards/000148/files/752_ruby_2438.zip'
#nom de sauvegarde du fichier zip
file_path = 'temp.zip'
#Ouvrez le fichier du garçon et supprimez le fichier lu
with urllib.request.urlopen(url) as dl_file:
with open(file_path, 'wb') as out_file:
out_file.write(dl_file.read())
with zipfile.ZipFile(file_path) as zf:
listfiles = zf.namelist()
zf.extractall()
os.remove(file_path)
# shift_Lire avec jis
with open(listfiles[0], 'rb') as f:
text = f.read().decode('shift_jis')
#Suppression de rubis, annotations, etc.
text = re.split(r'\-{5,}', text)[2]
text = re.split(r'Livre du bas:', text)[0]
text = re.sub(r'《.+?》', '', text)
text = re.sub(r'[#.+?]', '', text)
text = text.strip()
#Préparez-vous à utiliser MeCab
tagger = MeCab.Tagger()
#Erreur si non initialisé
tagger.parse("")
#Analyse morphologique avec NMeCab
node = tagger.parseToNode(text)
word_list_raw = []
result_dict_raw = {}
#Extraire la nomenclature, les adjectifs et les verbes
wordclass_list = ['nom','adjectif','verbe']
#Exclut les nombres, la non-indépendance, les synonymes et les suffixes
not_fine_word_class_list = ["nombre", "Non indépendant", "Synonyme","suffixe"]
while node:
#Se procurer plus d'information
word_feature = node.feature.split(",")
#Obtenir des mots (en principe, forme de base)
word = node.surface
#Obtenir des paroles de partie
word_class = word_feature[0]
fine_word_class = word_feature[1]
#Spécifiez ce qu'il faut extraire de la pièce et ce qu'il faut exclure
if ((word not in ['', ' ','\r', '\u3000']) \
and (word_class in wordclass_list) \
and (fine_word_class not in not_fine_word_class_list)):
#liste de mots
word_list_raw.append(word)
result_dict_raw[word] = [word_class, fine_word_class]
#Passer au mot suivant
node = node.next
print(word_list_raw)
wakachi_text = ' '.join(word_list_raw);
#nom de sauvegarde du fichier wakachi
file2_path = 'tf.txt'
with open(file2_path, 'w') as out_file:
out_file.write(wakachi_text)
print(wakachi_text)
Le résultat de l'exécution est le suivant.
['un', 'Remise', 'Pistolet sans arme', 'Petite offre', 'Temps', 'perte', 'Shi', 'Est', 'école',…
Arme à main d'un parent, petit service, temps d'école perdu, école de temps et de minute, saut en bas ...
Vient ensuite la construction du modèle par word2vec, qui est la partie principale de cet article.
from gensim.models import word2vec
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentence_data = word2vec.LineSentence('tf.txt')
model_bochan = word2vec.Word2Vec(sentence_data,
sg=1, # Skip-gram
size=100, #Nombre de dimensions
min_count=5, # min_Ignorer les mots moins de fois
window=12, #Nombre maximum de mots en contexte
hs=0, #Hiérarchie Softmax(0 pour un échantillonnage négatif)
negative=5, #Échantillonnage négatif
iter=10 #Nombre d'époque
)
model_bochan.save('test.model')
Importez le word2vec du module gensim et construisez le modèle avec Word2Vec.
Deux modèles d'apprentissage sont disponibles dans word2vec.
Je vais omettre ces deux explications, mais comme le skip-gramme est utilisé dans le matériel didactique, le skip-gram est utilisé en conséquence. (En général, skip-gram montre de meilleures performances en CBOW et skip-gram)
Le nombre de dimensions du mot vecteur est le même que la valeur par défaut, mais il est défini sur 100. La condition pour rejeter des mots est d'ignorer les mots qui apparaissent moins de 5 fois. Le nombre maximum de mots avant et après la reconnaissance en tant que contexte est de 12.
Il existe deux algorithmes qui accélèrent l'apprentissage. -Hierarchical Softmax -Negative Sampling J'omettrai ces deux explications. J'utilise l'échantillonnage négatif ici.
Cette explication est http://tkengo.github.io/blog/2016/05/09/understand-how-to-learn-word2vec/ Est détaillé.
Le nombre d'itérations de corpus est spécifié comme 10. Il s'agit du nombre d'époques indiquant combien de fois une donnée d'apprentissage est entraînée par le réseau neuronal.
Cela nous a permis de construire le modèle.
Ensuite, regardons la similitude des mots ainsi que le matériel pédagogique. Recherchez le mot rouge.
model = word2vec.Word2Vec.load('/content/test.model')
results = model.most_similar(positive=['rouge'], topn=100)
for result in results:
print(result[0], '\t', result[1])
Le résultat de l'exécution est le suivant.
:
2020-09-16 12:30:12,986 : INFO : precomputing L2-norms of word weight vectors
Chemise 0.9854607582092285
Ennuyeux 0.9401918053627014
Prénom 0.9231084585189819
Gorki 0.9050831198692322
Savoir 0.8979452252388
Doux 0.897865891456604
D'accord 0.8932155966758728
Russie Aya 0.8931306004524231
Madone 0.890703558921814
:
Comme mentionné ci-dessus, il s'est avéré que les personnages tels que les chemises rouges venaient au sommet. Ensuite, comme exemple de soustraction des éléments du modèle, soustrayons "chemise" de "madonna".
model = word2vec.Word2Vec.load('/content/test.model')
results = model.most_similar(positive=['Madone'], negative=['chemise'], topn=100)
for result in results:
print(result[0], '\t', result[1])
Le résultat de l'exécution est le suivant.
:
INFO : precomputing L2-norms of word weight vectors
Voix 0.2074282020330429
Geisha 0.1831434667110443
Boulette 0.13945674896240234
Divertissement 0.13744047284126282
Tenfura 0.11241232603788376
Pâte 0.10779635608196259
Enseignant 0.08393052220344543
Esprit 0.08120302855968475
Gentillesse 0.0712042897939682
:
En soustrayant l'élément de chemise de Madonna, nous avons pu extraire des éléments tels que la voix, le professeur, la geisha et la gentillesse.
Ce qui suit est détaillé sur l'addition et la soustraction d'éléments par word2vec. https://www.pc-koubou.jp/magazine/9905
L'analyse des émotions est possible même avec Word2Vec en trouvant la distance des principaux termes de l'émotion, mais ici je voudrais analyser avec le dictionnaire des émotions (PN Table) lu ci-dessus comme dans le matériel pédagogique.
Commencez par convertir le dictionnaire du type dataframe au type dict pour le rendre facile à manipuler.
dic2 = dic[['word', 'PN']].rename(columns={'word': 'TERM'})
#Convertir la table PN du bloc de données en type dict
word_list = list(dic2['TERM'])
pn_list = list(dic2['PN']) #Le type de contenu est numpy.float64
pn_dict = dict(zip(word_list, pn_list))
print(pn_dict)
Le résultat de l'exécution est le suivant.
{'Excellent': 1.0, 'bien': 0.9999950000000001, 'Réjouir': 0.9999790000000001, 'louange': 0.9999790000000001, 'Toutes nos félicitations': 0.9996450000000001,…
Les termes positifs sont définis sur une valeur proche de 1 et les termes négatifs sur une valeur proche de -1.
Ensuite, prenez la nomenclature et les adjectifs de "Bochan" et supprimez les nombres et les suffixes. Essayez d'afficher des mots positifs et négatifs en combinant un tableau de fréquence des mots et un dictionnaire des émotions.
#Préparez-vous à utiliser MeCab
tagger = MeCab.Tagger()
#Erreur si non initialisé
tagger.parse("")
#Analyse morphologique avec NMeCab
node = tagger.parseToNode(text)
word_list_raw = []
extra_result_list = []
#Extraire la nomenclature, les adjectifs et les verbes
wordclass_list = ['nom','adjectif']
#Exclut les nombres, la non-indépendance, les synonymes et les suffixes
not_fine_word_class_list = ["nombre","suffixe", "Non indépendant"]
while node:
#Se procurer plus d'information
word_feature = node.feature.split(",")
#Obtenir des mots (en principe, forme de base)
word = node.surface
#Obtenir des paroles de partie
word_class = word_feature[0]
fine_word_class = word_feature[1]
#Spécifiez ce qu'il faut extraire de la pièce et ce qu'il faut exclure
if ((word not in ['', ' ','\r', '\u3000']) \
and (word_class in wordclass_list) \
and (fine_word_class not in not_fine_word_class_list)):
#liste de mots
word_list_raw.append(word)
#Passer au mot suivant
node = node.next
freq_counterlist_raw = Counter(word_list_raw)
dict_freq_raw = dict(freq_counterlist_raw)
extra_result_list = []
for k, v in dict_freq_raw.items():
if k in pn_dict:
extra_result_list.append([k, v, pn_dict[k]])
extra_result_pn_sorted_list = sorted(extra_result_list, key=lambda x:x[2], reverse=True)
print("Mots positifs")
display(extra_result_pn_sorted_list[:10])
print("Mots négatifs")
display(extra_result_pn_sorted_list[-10:-1])
Le résultat de l'exécution est le suivant.
Mots positifs
[['Toutes nos félicitations', 1, 0.9996450000000001],
['bien', 2, 0.9993139999999999],
['heureux', 1, 0.998871],
['Assortiment', 1, 0.998208],
['Crédit', 2, 0.997308],
['Justice', 1, 0.9972780000000001],
['Impressionné', 10, 0.997201],
['Excusez-moi', 1, 0.9967889999999999],
['Encouragement', 1, 0.9959040000000001],
['pertinence', 1, 0.995553]]
Mots négatifs
[['Rugueux', 13, -0.9993340000000001],
['étroit', 7, -0.999342],
['Du froid', 1, -0.999383],
['Châtiment', 5, -0.9994299999999999],
['ennemi', 3, -0.9995790000000001],
['douloureux', 1, -0.9997879999999999],
['pauvre', 6, -0.9998309999999999],
['Absent', 338, -0.9999969999999999],
['malade', 6, -0.9999979999999999]]
Le deuxième élément de la liste est la fréquence d'apparition (nombre de fois) et le troisième est une valeur qui indique si elle est positive ou négative. Enfin, regardons lequel des mots positifs et négatifs est souvent utilisé pour "Bo-chan" dans son ensemble. (Cependant, la fréquence d'apparition des mots n'est pas utilisée selon le matériel pédagogique)
pos_n = sum(x[2] > 0 for x in extra_result_pn_sorted_list)
print(pos_n)
neg_n = sum(x[2] < 0 for x in extra_result_pn_sorted_list)
print(neg_n)
Le résultat de l'exécution est le suivant.
182
1914
J'ai trouvé que les mots négatifs sont souvent utilisés dans "Bo-chan".
En ce qui concerne le traitement lié à word2vec, des résultats similaires n'ont pas été obtenus avec python et R, donc je vais essayer de trouver la cause si je peux me le permettre à l'avenir.
https://gist.github.com/ereyester/101ae0da17e747b701b67fe9fe137b84
Recommended Posts