[Python] [Traitement du langage naturel] J'ai essayé le Deep Learning ❷ fait de toutes pièces en japonais ①

introduction

N'est-il pas le plus difficile pour les débutants (en particulier ceux qui étudient eux-mêmes) de collecter un corpus (une grande quantité de phrases) lorsqu'ils effectuent un traitement du langage naturel à l'aide d'algorithmes d'apprentissage automatique en japonais?

Dans le sujet "Deep Learning from scratch ❷ ~ Natural language processing ~" et d'autres livres, la gestion du corpus anglais est fondamentalement au centre de l'attention, et le corpus japonais a une habitude différente de l'anglais. La situation actuelle est qu'il est difficile de faire l'expérience du traitement des fichiers. (Au moins, j'ai eu beaucoup de problèmes parce que je ne pouvais pas du tout collecter de corpus japonais.)

Donc, cette fois, j'ai utilisé l'article de "liveoor news" (communication allemande), et probablement si vous êtes un apprenant machine, vous l'avez obtenu une fois. Je voudrais mettre en œuvre un bon livre "Deep Learning from scratch ❷ ~ Natural language processing ~" en japonais.

Traitement du langage naturel basé sur le nombre

Cette fois, je remplacerai le corpus par le japonais et l'implémenterai pour la gamme suivante de "Deep Learning ❷ made from scratch". Dans le cas du japonais, contrairement à l'anglais, le prétraitement est gênant, veuillez donc vous concentrer sur ce domaine.
Cible
Objet: "Deep Learning from scratch" Portée de cette période: Chapitre 2 Représentation distribuée du langage naturel et des mots 2.3 Méthode basée sur le comptage ~ 2.4.5 Évaluation avec l'ensemble de données PTB

environnement

Mac OS(Mojave) Python3(Python 3.7.4) jupiter Notebook

0. Préparation préalable

Les données d'origine sont un fichier texte créé pour chaque date de livraison d'article, ce qui est gênant comme tel (probablement plus de 100 fichiers), alors combinez d'abord tous les fichiers texte dans un nouveau fichier texte .. Vous pouvez combiner plusieurs fichiers texte avec la commande suivante (pour mac).

Terminal


$ cat ~/Nom du répertoire/*.txt >Nouveau nom de fichier texte.txt


Référence
https://ultrabem-branch3.com/informatics/commands_mac/cat_mac [De côté] C'est vraiment juste un aparté, mais j'ai personnellement eu du mal avec le processus ci-dessus. .. Au début, je me suis déplacé vers le fichier et j'ai exécuté la commande " cat * .txt> new text file name.txt`` ", mais le processus était complètement terminé probablement parce que le nom du répertoire n'était pas spécifié. (Peut-être que le joker essayait de lire tous les fichiers texte sur mon PC?), Et à la fin, j'ai reçu un avertissement en claquant en disant «Pas assez d'espace! .. .. S'il vous plaît soyez prudente.

1. 1. Prétraitement des données

** ⑴ Séparation des phrases **

python


import sys
sys.path.append('..')
import re
import pickle
from janome.tokenizer import Tokenizer
import numpy as np
import collections

with open("corpus/dokujo-tsushin/dokujo-tsushin-half.txt", mode="r",encoding="utf-8") as f: #Note 1)
    original_corpus = f.read()
    
text = re.sub("http://news.livedoor.com/article/detail/[0-9]{7}/","", original_corpus) #Note 2)
text = re.sub("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{4}","", text) #Note 3)
text = re.sub("[\f\n\r\t\v]","", text)
text = re.sub(" ","", text)
text = re.sub("[「」]","", text)
text = [re.sub("[()]","", text)]

#<Point>
t = Tokenizer()

words_list = []
for word in text:
    words_list.append(t.tokenize(word, wakati=True))
    
with open("words_list.pickle",mode='wb') as f:
    pickle.dump(words_list, f)

Note 1) Cette fois, contrairement à "Deep Learning ❷ made from scratch", nous préparons le corpus nous-mêmes, nous allons donc lire le corpus cible. De plus, cette fois, il lit "dokujo-tsushin-half.txt", mais bien que j'essayais à l'origine de lire "dokujo-tsushin-all.txt", un avertissement a été émis indiquant qu'il ne pouvait pas être lu en raison d'une surcapacité. Par conséquent, j'ai abandonné "tout" et utilisé "la moitié" (⓪ la combinaison de fichiers texte pré-préparés n'a exécuté que la moitié de tous les fichiers).

** ** Puisque le traitement du langage naturel japonais est effectué cette fois, les phrases ne peuvent pas être décomposées en mots par la méthode décrite dans le livre (divisée en mots par des espaces). Donc, cette fois, j'ai installé janome, une bibliothèque tierce, et j'ai décomposé (séparés) des phrases japonaises en mots. De plus, comme le nombre de phrases est important et le nombre de mots qui en résulte, j'ai décidé d'utiliser pickle pour enregistrer le résultat de l'exécution afin de ne pas avoir à l'exécuter à partir de l'endroit où j'écris chaque minute. Le fichier pickle peut être appelé en procédant comme suit et peut être chargé beaucoup plus rapidement que le fractionnement à partir de zéro.


with open('words_list.pickle', mode='rb') as f:
    words_list = pickle.load(f)

print(words_list) #Si vous n'avez pas besoin d'afficher le résultat du chargement, cette description est inutile

# =>production
#[['ami', 'représentant', 'de', 'discours', '、', 'Allemagne', 'femme', 'Est', 'Comment', 'Faire', 'main', 'Est', '?', 'bientôt', 'juin', '・', 'la mariée', 'Quand', 'Appel', 'Être', 'juin', '。', 'Allemagne', 'femme', 'de', 'Pendant ~', 'À', 'Est', 'moi même', 'de', 'formule', 'Est', 'encore', 'Nana', 'deÀ', 'Appel', 'Ré', 'main', 'Juste', '…', '…', 'QuandjeU', 'fête', 'La pauvreté', 'Statut', 'de', 'Homme', 'Aussi', 'Beaucoup', 'de', 'alors', 'Est', 'Nanaje', 'je me demande', 'U', 'Ou', '?', 'SaらÀ', 'Présence', 'Nombre de fois', 'À', 'Empiler', 'main', 'Aller', 'Quand', '、', 'こHmmNana', 'S'il vous plaît', 'ごQuand', 'À', 'Sa', 'Être', 'こQuand', 'Aussi', '少Nanaく', 'Nanaje', '。', 'S'il vous plaît', 'Mais', 'y a-t-il', 'Hmm', 'Est', 'mais', '…', '…', 'ami', 'représentant', 'de', 'discours', '、', 'finalement', 'main', 'くRé', 'Nanaje', 'Ou', 'Nana', '?', 'Samain', 'そHmmNana', 'Quandき', '、', 'Allemagne', 'femme', 'Est', 'Comment', 'Correspondance', 'Shi', 'Tara', 'Bien', 'Ou', '?', 'Récemment', 'Est', 'Quand', 'l'Internet', 'etc', 'alors', 'Chercher', 'すRé', 'Si', 'ami', 'représentant', 'discours', 'pour', 'de', 'Exemple de phrase', 'site', 'Mais', 'TaくSaHmm', 'En dehors', 'main', 'viens', 'dealors', '、', 'そRéら', 'À', 'référence', 'À', 'すRé', 'Si', '、', 'Sûr', 'Nana', 'Ausside', 'Est', 'Qui', 'alorsAussi', 'Créer', 'alorsきる', '。', 'ShiOuShi', 'Yuri', 'SaHmm', '33', 'âge', 'Est', 'Net', 'À', 'référence', 'À', 'Shi', 'main', 'Créer', 'Shi', 'Ta', 'Aussidede', 'こRé', 'alors', '本当À', 'Bien', 'de', 'Ou', 'anxiété', 'alorsShi', 'Ta', '。', '一Homme暮らShi', 'Nana', 'dealors', '聞Ou', 'Ensemble', 'main', 'Impressions', 'À', 'Ichi', 'main', 'くÊtre', 'Homme', 'Aussi', 'je', 'Nanaje', 'Shi', '、', 'Ou', 'Quand', 'Ichi', 'main', 'autre', 'de', 'ami', 'À', 'Prends la peine', '聞Ou', 'Ensembleる', 'de', 'Aussi', 'Comment', 'Ou', 'Quand',・ ・ ・ Omis ci-dessous

** ⑵ Créez une liste avec des identifiants pour les mots **

def preprocess(text):
    word_to_id = {}
    id_to_word = {}
    
    #<Point>
    for words in words_list:
        for word in words:
            if word not in word_to_id:
                new_id = len(word_to_id)
                word_to_id[word] = new_id
                id_to_word[new_id] = word
                
    corpus = [word_to_id[w] for w in words for words in words_list]
    
    return corpus, word_to_id, id_to_word

corpus, word_to_id, id_to_word = preprocess(text)

print('corpus size:', len(corpus))
print('corpus[:30]:', corpus[:30])
print()
print('id_to_word[0]:', id_to_word[0])
print('id_to_word[1]:', id_to_word[1])
print('id_to_word[2]:', id_to_word[2])
print()
print("word_to_id['femme']:", word_to_id['femme'])
print("word_to_id['mariage']:", word_to_id['mariage'])
print("word_to_id['mari']:", word_to_id['mari'])

# =>production
# corpus size: 328831
# corpus[:30]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 5, 6, 2, 22, 23, 7, 24, 2]

# id_to_word[0]:ami
# id_to_word[1]:représentant
# id_to_word[2]:de

# word_to_id['femme']: 6
# word_to_id['mariage']: 456
# word_to_id['mari']: 1453


Point
-La fonction de prétraitement est fondamentalement la même que celle de ce livre, mais cette fois, la division des mots de la phrase a déjà été effectuée, de sorte que la partie a été supprimée, et contrairement à ce livre, la phrase for est tournée deux fois. Le but est de donner un identifiant. La raison pour laquelle la phrase for est tournée deux fois est que le mot est inclus dans la liste double parce que le mot est divisé par la division, qui est différente de ce livre.

2. Évaluation

Je vais omettre les détails de ce qui suit car il y a de nombreuses parties qui chevauchent le contenu du livre, mais je vous serais reconnaissant si vous pouviez vous y référer car il contient des commentaires à certains endroits.

#Créer une matrice de cooccurrence
def create_co_matrix(corpus, vocab_size, window_size=1):
    corpus_size = len(corpus)
    co_matrix = np.zeros((vocab_size, vocab_size), dtype=np.int32)
    
    for idx, word_id in enumerate(corpus):
        for i in range(1, window_size + 1):
            left_idx = idx - i
            right_idx = idx + i
            
            if left_idx >= 0:
                left_word_id = corpus[left_idx]
                co_matrix[word_id, left_word_id] += 1
                
            if right_idx < corpus_size:
                right_word_id = corpus[right_idx]
                co_matrix[word_id, right_word_id] += 1
            
    return co_matrix

#Jugement de similitude entre les vecteurs (similitude cos)
def cos_similarity(x, y, eps=1e-8):
    nx = x / (np.sqrt(np.sum(x ** 2)) + eps)
    ny = y / (np.sqrt(np.sum(y ** 2)) + eps)
    return np.dot(nx, ny)

#Classement de la similitude entre les vecteurs
def most_similar(query, word_to_id, id_to_word, word_matrix, top=5):
    if query not in word_to_id:
        print('%s is not found' % query)
        return

    print('\n[query] ' + query)
    query_id = word_to_id[query]
    query_vec = word_matrix[query_id]

    vocab_size = len(id_to_word)

    similarity = np.zeros(vocab_size)
    for i in range(vocab_size):
        similarity[i] = cos_similarity(word_matrix[i], query_vec)

    count = 0
    for i in (-1 * similarity).argsort():
        if id_to_word[i] == query:
            continue
        print(' %s: %s' % (id_to_word[i], similarity[i]))

        count += 1
        if count >= top:
            return

#Améliorer les indicateurs de pertinence des mots à l'aide d'informations mutuelles positives (PPMI)
def ppmi(C, verbose=False, eps = 1e-8):
    M = np.zeros_like(C, dtype=np.float32)
    N = np.sum(C)
    S = np.sum(C, axis=0)
    total = C.shape[0] * C.shape[1]
    cnt = 0

    for i in range(C.shape[0]):
        for j in range(C.shape[1]):
            pmi = np.log2(C[i, j] * N / (S[j]*S[i]) + eps)
            M[i, j] = max(0, pmi)

            if verbose:
                cnt += 1
                if cnt % (total//100) == 0:
                    print('%.1f%% done' % (100*cnt/total))
    return M

window_size = 2
wordvec_size = 100

corpus, word_to_id, id_to_word = preprocess(text)
vocab_size = len(word_to_id)
print('counting  co-occurrence ...')
C = create_co_matrix(corpus, vocab_size, window_size)
print('calculating PPMI ...')
W = ppmi(C, verbose=True)

print('calculating SVD ...')
try:
    #Réduction de dimension par SVD en utilisant sklearn
    from sklearn.utils.extmath import randomized_svd
    U, S, V = randomized_svd(W, n_components=wordvec_size, n_iter=5,
                             random_state=None)
except ImportError:
    U, S, V = np.linalg.svd(W)

word_vecs = U[:, :wordvec_size]

querys = ['Femme', 'mariage', 'il', 'Mote']
for query in querys:
    most_similar(query, word_to_id, id_to_word, word_vecs, top=5)

# =>Ci-dessous, le résultat de sortie
"""
[query]Femme
Masculin: 0.6902421712875366
Etc.: 0.6339510679244995
modèle: 0.5287646055221558
génération: 0.5057054758071899
couche: 0.47833186388015747

[query]mariage
amour: 0.5706729888916016
Sortir ensemble: 0.5485040545463562
Adversaire: 0.5481910705566406
 ?。: 0.5300850868225098
Dix: 0.4711574614048004

[query]il
Petite amie: 0.7679144740104675
copain: 0.67448890209198
mari: 0.6713247895240784
parent: 0.6373711824417114
Ancien: 0.6159241199493408

[query]Mote
Ru: 0.6267833709716797
Considération: 0.5327887535095215
Minet: 0.5280393362045288
Les filles: 0.5190156698226929
vélo: 0.5139431953430176
"""
​

Recommended Posts

[Python] [Traitement du langage naturel] J'ai essayé le Deep Learning ❷ fait de toutes pièces en japonais ①
Python: apprentissage profond du traitement du langage naturel: principes de base
Deep Learning 2 from scratch 1.3 Traitement du langage naturel 1.3 Résumé
[Deep Learning from scratch] J'ai essayé d'expliquer le décrochage
Python: Apprentissage en profondeur dans le traitement du langage naturel: Implémentation d'un système de sélection de phrases de réponses
Mémo d'apprentissage profond créé à partir de zéro
J'ai essayé d'implémenter Perceptron Part 1 [Deep Learning from scratch]
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 7]
Deep learning / Deep learning made from scratch Chapitre 6 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [Chapitre 5]
[Deep Learning from scratch] J'ai essayé d'expliquer la confirmation du gradient d'une manière facile à comprendre.
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 6]
"Deep Learning from scratch" avec Haskell (inachevé)
Deep learning / Deep learning made from scratch Chapitre 7 Mémo
J'ai essayé le traitement du langage naturel avec des transformateurs.
[Mémo d'apprentissage] Deep Learning fait de zéro [~ Chapitre 4]
[Deep Learning from scratch] J'ai essayé d'implémenter la couche sigmoïde et la couche Relu
[Python] J'ai joué avec le traitement du langage naturel ~ transformers ~
Résumé Python vs Ruby "Deep Learning from scratch"
Python: traitement du langage naturel
Apprentissage profond à partir de zéro
J'ai essayé le deep learning
[Deep Learning from scratch] Accélération du réseau de neurones J'ai expliqué le traitement de la propagation arrière
[Pour les débutants] Après tout, qu'est-ce qui est écrit dans Deep Learning fait à partir de zéro?
[Deep Learning from scratch] J'ai implémenté la couche Affine
Application de Deep Learning 2 à partir de zéro Filtre anti-spam
Apprentissage profond à partir de zéro 1 à 3 chapitres
J'ai écrit python en japonais
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 16) J'ai essayé de créer SimpleConvNet avec Keras
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 17) J'ai essayé de créer DeepConvNet avec Keras
J'ai essayé 100 traitements linguistiques Knock 2020
Je comprends Python en japonais!
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 1
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 3
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 7
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 5
Un amateur a trébuché dans le Deep Learning à partir de zéro.
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 2
J'ai essayé d'écrire dans un modèle de langage profondément appris
[Traitement du langage naturel] J'ai essayé de visualiser les sujets d'actualité cette semaine dans la communauté Slack
Analyse des émotions avec traitement du langage naturel! J'ai essayé de prédire l'évaluation à partir du texte de l'avis
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 8) J'ai dessiné le graphique du chapitre 6 avec matplotlib
[Deep Learning from scratch] Implémentez le traitement de rétropropagation dans le réseau neuronal par la méthode de propagation de retour d'erreur
[Traitement du langage naturel] J'ai essayé de visualiser les remarques de chaque membre de la communauté Slack
[Traitement du langage naturel] Prétraitement avec le japonais
Apprentissage profond à partir de zéro (calcul des coûts)
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 3
Le débutant en Python a essayé 100 traitements de langage Knock 2015 (05 ~ 09)
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 1
J'ai essayé l'apprentissage en profondeur avec Theano
J'ai essayé la notification de ligne en Python
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 2
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 4
Le débutant en Python a essayé 100 traitements de langage Knock 2015 (00 ~ 04)
Traitement du langage naturel japonais utilisant Python3 (4) Analyse des émotions par régression logistique
Dockerfile avec les bibliothèques nécessaires pour le traitement du langage naturel avec python
Pourquoi ModuleNotFoundError: Aucun module nommé'dataset.mnist 'n'apparaît dans "Deep Learning from scratch".
Écrivez vos impressions sur l'édition du framework Deep Learning 3 créée à partir de zéro
[Deep Learning from scratch] À propos des couches requises pour implémenter le traitement de rétropropagation dans un réseau neuronal
Chapitre 1 Introduction à Python Découpez uniquement les bons points de Deeplearning à partir de zéro