[PYTHON] J'ai essayé de classer M. Hanyu et M. Hanyu avec le traitement du langage naturel × classificateur Naive Bayes

introduction

Pour promouvoir la compréhension de l'apprentissage automatique Une manière classique de construire automatiquement un modèle de classification à partir de données, J'ai implémenté un classificateur Naive Bayes. Récemment, l'analyse d'image telle que API Cloud Vision est devenue populaire. Le seuil semblait élevé pour les débutants, la première étape est donc le traitement du langage naturel.

Cette fois, nous utiliserons l'API Twitter pour collecter les devis du compte du bot. Implémentation du ** Hanyu classifier ** pour classer Hanyu-san et Hanyu-kun.

Le client API est implémenté dans Ruby et le classificateur est implémenté en Python. MeCab est utilisé pour l'analyse morphologique.

En outre, tous deux devraient s'appeler M. Hanyu, Pour plus de commodité, veuillez autoriser M. Hanyu, un patineur artistique, à être appelé M. Hanyu.

Collectez les données de Tweet

APIClient est implémenté comme suit en utilisant Twitter Ruby Gem. L'API Twitter a une limite sur le nombre d'exécutions par heure appelée Limites de taux. Si vous voulez recevoir beaucoup de tweets, vous devez mettre un intervalle d'environ 15 minutes. Veuillez prendre une pause-café de temps en temps.

Paramètres d'authentification API


require 'twitter'

client = Twitter::REST::Client.new do |config|
  config.consumer_key = 'XXX'
  config.consumer_secret = 'YYY'
  config.access_token = 'hoge'
  config.access_token_secret = 'fuga'
end

Recevez des tweets

client.user_timeline('TwitterUserID',{ count: 150}).each_with_index do |tl,i|
	tw = client.status(tl.id)
	tweet = tw.text
        
	#Élimine la duplication
	if !tweets.include?(tweet)
		puts tweet
	end
end

Analyse morphologique

Maintenant, traitons les données acquises précédemment. Comme cela sera décrit plus loin, afin de quantifier et de classer ** si le tweet contient des mots que M. Hanyu et M. Hanyu sont susceptibles de dire **, décomposez d'abord les tweets collectés en deux tweets. Les 50 premiers mots qui apparaissent fréquemment sont repris, pour un total de 100 mots en tant que variables utilisées pour la classification. (En fait, il y avait des doublons, donc il y a 91 cas.)

Décomposition en mot partiel des tweets avec MeCab

Tout d'abord, cette fois, seuls ** la nomenclature, les verbes et les adjectifs ** ont été comptés. (L'utilisation des verbes et des adjectifs a été corrigée à la forme de base)

Liste de mots exclus

Nomenclature formelle qui ne semble pas pertinente pour le vocabulaire spécifique à la personne, comme indiqué ci-dessous Il semble que cela ait été causé par la division de la nomenclature verbalisée et des adjectifs, J'ai établi des listes de mots qui ne sont pas comptés.

ng_noun = ["chose", "de", "もde", "Il", "Quand", "、", ",", "。", "¡", "(", ")", "."]
ng_verb = ["Faire", "Est", "Devenir", "y a-t-il"]
ng_adjective = ["Yo"]

Compter les mots fréquents

Le package * collections * est utile pour générer des listes contrées (taples). J'ai également utilisé natto pour lier Python et MeCab.


import collections

from sets import Set
from natto import MeCab

def mostFrequentWords(file, num):
  words = collections.Counter()

  f = open(file)
  line = f.readline()
  while line:
    #nom:surface="patin", feature="nom,Général,*,*,*,*,patin,patin,patin"
    #verbe:surface="Caleçon", feature="verbe,Indépendance,*,*,Un pas,Forme imparfaite,Caleçonる,Esclave,Esclave"
    for node in mecab.parse(line, as_nodes=True):
      features = node.feature.split(",")
    
      if features[0] == "nom" and node.surface not in ng_noun:
        words[node.surface] += 1
      elif features[0] == "verbe" and features[6] not in ng_verb:
        words[features[6]] += 1
      elif features[0] == "adjectif" and features[6] not in ng_adjective:
        words[features[6]] += 1

    line = f.readline()
    return words.most_common(num


words["hanyu"] = mostFrequentWords("hanyu_train.txt", 50)
words["habu"] = mostFrequentWords("habu_train.txt", 50)

tpl = words["hanyu"] + words["habu"]
vocabulary = set([])
for word in tpl:
  vocabulary.add(word[0])

Classificateur Naive Bayes

Voici une brève explication du contexte mathématique.

Théorème de Bayes

Premièrement, le classificateur Naive Bayes est un classificateur basé sur les probabilités. Ce que je veux demander cette fois, c'est quand un certain document (ici, chaque tweet) * d * est donné. S'il a une forte probabilité d'appartenir à quelle classe (M. Hanyu ou M. Hanyu) * c *. Cela peut être exprimé comme * P (c | d) * comme une probabilité conditionnelle étant donné un tweet. Cependant, comme il est difficile d'obtenir directement cette probabilité postérieure, elle est calculée à l'aide du ** théorème de Bayes **.

P(c|d) = \frac{P(c)P(d|c)}{P(d)}

Ici, calculez le côté droit pour chaque classe, c'est-à-dire Hanyu-san / Hanyu-kun, Découvrez à laquelle le tweet est le plus susceptible d'appartenir. Cependant, le dénominateur * P (d) * est constant quelle que soit la classe une fois que le classificateur est construit. ** Il serait bon de ne calculer que la molécule **.

P(c) Cette fois, nous avons reçu 100 tweets pour chacun de M. Hanyu et M. Hanyu, et 70 étaient des données d'entraînement pour la construction d'un classificateur. 30 cas sont utilisés comme données de test pour vérifier l'exactitude du classificateur.

P(d|c) Maintenant, si vous pensez à la signification de cette probabilité conditionnelle * P (d | c) *, M. Hanyu, Hanyu-kun, selon la combinaison des types de mots que chacun peut dire Vous devez trouver la probabilité que chaque tweet se produise, mais c'est impossible. Par conséquent, il est exprimé à l'aide d'un modèle simplifié adapté à la classification des documents. Ici, ** À propos de l'ensemble des mots * V * que M. Hanyu et M. Hanyu sont susceptibles de dire Vérifiez s'ils sont inclus ou non dans les tweets classifiés **.

Modèle Bernoulli multivarié

La distribution des variables stochastiques qui prennent deux valeurs, comme dire / ne pas dire, est la ** distribution de Bernoulli **.

{P_{w,c}}^{\delta_{w,d}}(1-{P_{w,c}})^{1-\delta_{w,d}}

Cette partie exponentielle est appelée fonction delta, et 0 est émis lorsque * w * = * d *, et 1 est émis sinon. Tu le penses bien.

Ici, considérons la distribution de Bernoulli pour chaque mot * w * appartenant à l'ensemble * V *. Le ** modèle de Bernoulli multivarié ** représente * P (d | c) *.

\prod_{w \in V}{P_{w,c}}^{\delta_{w,d}}(1-{P_{w,c}})^{1-\delta_{w,d}}

À propos, les deux points suivants peuvent être lus à partir de ce qui précède comme les caractéristiques du modèle multivarié de Bernoulli.

--Le nombre d'occurrences de mots dans un document n'est pas pris en compte --Le phénomène selon lequel le mot "ne se produit pas" dans le document est souligné

Méthode la plus probable

En résumé, cela peut être exprimé comme suit, alors calculez le côté droit pour chacun de M. Hanyu et M. Hanyu. Valeur plus élevée = ** Détermine quelle hypothèse est la plus susceptible de générer des données **. Ce «produit des probabilités que l'observation d se produise sous l'hypothèse c» est appelé ** vraisemblance **, et l'approche pour trouver le c le plus probable qui maximise cette probabilité est la ** méthode la plus probable **. Est appelé.

P(D) = {P(c)P(d|c)} = p_c\prod_{w \in V}({P_{w,c}}^{\delta_{w,d}}(1-{P_{w,c}})^{1-\delta_{w,d}})

Puisque la description de la formule n'est pas le but, la formule est pliée au milieu, mais si elle est transformée,

\log P(D) = \sum N_c \log p_c + \sum_c \sum_{w \in V} N_{w,c} \log p_{w,c} + \sum_c \sum_{w \in V} (N_c - N_{w,c}) \log(1 - p_{w,c})

Ce sera comme ça. Cela ressemble à l'endroit où la fonction delta est allée, mais comme mentionné ci-dessus, elle a la propriété d'être 0 lorsque * w * = * d *, et 1 sinon, donc le mot * w * et la classe * c * coexistent. Il est exprimé en multipliant le nombre de fois. Cela peut sembler difficile à lire, mais le fait est que la distribution est déterminée par deux paramètres, ** Pw, c et Pc **.

Ce serait bien de trouver c qui maximise le logP (D) ci-dessus lorsqu'on leur donne les données à classer. Ici, on suppose que tous les tweets du monde sont écrits par M. Hanyu ou M. Hanyu **. Il est nécessaire de satisfaire la contrainte exprimée par la formule suivante que la somme des probabilités d'être classé dans chaque classe est 1.

\sum_c p_c = 1

(Ce n'est pas non plus le sujet principal, je vais donc le replier.) Pour la fonction de Lagrange définie par la méthode appelée méthode du multiplicateur indéterminé de Lagrange, La valeur maximale peut être obtenue comme suit en prenant un différentiel partiel pour chaque paramètre.


p_{w,c} = \frac {N_{w,c}} {N_c} , p_c = \frac {N_c} {\sum_c N_c}

Implémentation du classificateur

Maintenant que nous savons comment trouver les paramètres, il est temps de commencer à mettre en œuvre.

Génération de données

À propos, les données d'entraînement suivantes ont été générées à partir des tweets soumis à une analyse morphologique.


cls = ["habu", "hanyu"]

#C'est une image car je ne peux pas la montrer par commodité. Comme mentionné ci-dessus, le tweet est généré en appliquant une analyse morphologique.
vocabulary = ["patin", "Pruschenko", "Jeu", "Le geste de Dieu"] 

#De même
documents["habu"] = [["Tenant du titre ","70", "Homme", "Moitié", "Hanyu"],[...]]
documents["hanyu"] = [["Génial","4 rotations", "Réussi", "Gagnant"],[...]]

Calcul de la probabilité simultanée * p (w, c) *

À partir des données ci-dessus et de la formule calculée, calculez la probabilité simultanée * p (w, c) * qu'un mot se produise dans chaque classe.

def train(cls, vocabulary, documents):

  #Nombre d'occurrences de chaque document de formation
  n_cls = {}
  total = 0.0
  for c in cls:
    n_cls[c] = len(documents[c])
    total += n_cls[c]

  #Probabilité d'occurrence de chaque document de formation
  p_cls = {}
  for c in cls:
    p_cls[c] = n_cls[c] / total

  #Nombre d'occurrences de mots pour chaque classe
  for c in cls:
    for d in documents[c]:
      for word in vocabulary:
        if word in d:
          n_word[c][word] += 1

 #Probabilité d'occurrence des mots pour chaque classe
  for c in cls:
    p_word[c] = {}
    for word in vocabulary:
      p_word[c][word] = \
        (n_word[c][word] + 1) / (n_cls[c] + 2)

Lissage

C'est un peu à part. Dans la partie où la probabilité d'occurrence d'un mot pour chaque classe est calculée, 1 est ajouté à la molécule et 2 est ajouté au dénominateur. C'est le produit de la probabilité et lorsqu'un mot du vocabulaire * V * n'apparaît pas dans le tweet Cela évite que la probabilité que le résultat de l'intégration devienne 0. (Puisqu'il devient une très petite valeur, il se présente sous la forme d'une somme en prenant une valeur logarithmique dans l'implémentation. Puisque 0 n'existe pas dans la zone de définition logarithmique, le programme sera moussé avec une erreur de domaine mathématique)

Par conséquent, nous supposons généralement une distribution de probabilité appelée distribution de Diricre, ce qui rend difficile de prendre 0 pour la facilité d'apparition des mots. C'est ce qu'on appelle le ** lissage ** car il permet d'adoucir les valeurs extrêmes souvent produites par la méthode la plus probable.

De plus, cette approche qui tente de maximiser la probabilité après que les données soient données en tenant compte de la distribution antérieure plutôt que de la facilité d'apparition des données exactes est appelée ** estimation MAP **.

Résultat d'exécution

Maintenant que nous avons enfin construit un classificateur, exécutons-le.

Fonction de classification

En utilisant le classificateur construit, les tweets donnés étaient M. Hanyu et M. Hanyu, Une fonction qui classe par quel document a été écrit.


def classify(data):
  #LogP pour chaque classe(D)Cherchant
  pp = {}
  for c in cls:
    pp[c] = math.log(p_cls[c])
    for word in vocabulary:
      if word in data:
        pp[c] += math.log(p_word[c][word])

      else:
        pp[c] += math.log((1 - p_word[c][word]))

 #Obtenu logP(D)Lequel d'entre eux est le plus grand
 for c in cls:
   maxpp = maxpp if 'maxpp' in locals() else pp[c]
   maxcls = maxcls if 'maxcls' in locals() else c

   if maxpp < pp[c]:
     maxpp = pp[c]
     maxcls =c
                
   return (maxcls, maxpp)

Vérification de la précision du modèle

Parmi les tweets acquis, appliquons les tweets de 30 x 2 personnes enregistrées pour la vérification de l'exactitude au classificateur.

def test(data, label):
  i = 0.0
  for tweet in data:
    if nb.classify(tweet)[0] == label:
      i += 1
  return (i / len(data))

# bags_of_words renvoie un tableau bidimensionnel de parties de chaque tweet
test(bags_of_words("hanyu_test.txt"), "hanyu")
test(bags_of_words("habu_test.txt"), "habu")
classe ① Nombre de données de test ② Nombre de bonnes réponses Taux de réponse correct(②/①)
M. Hanyu 30 28 93.33%
Hanyu-kun 30 28 93.33%

Il peut être déterminé avec une précision assez élevée, Il semble que ce soit parce que M. Hanyu et M. Hanyu contenaient beaucoup de vocabulaire unique. Parce qu'il est significatif de classer les données avec des distributions qui ont le même vocabulaire mais des fréquences différentes. À cet égard, les données du test peuvent ne pas être très bonnes.

à partir de maintenant

Ensuite, analysez Image de M. Hanyu et M. Hanyu Je veux l'essayer.

Les références

Introduction à l'apprentissage automatique pour le traitement du langage Différence entre Yuzuru Hanyu et Zenji Hanyu

Recommended Posts

J'ai essayé de classer M. Hanyu et M. Hanyu avec le traitement du langage naturel × classificateur Naive Bayes
J'ai essayé le traitement du langage naturel avec des transformateurs.
J'ai essayé de juger Tundele avec Naive Bays
J'ai essayé d'extraire des expressions uniques avec la bibliothèque de traitement du langage naturel GiNZA
Analyse des émotions avec traitement du langage naturel! J'ai essayé de prédire l'évaluation à partir du texte de l'avis
J'ai essayé l'expression des nombres naturels et le traitement arithmétique uniquement avec le traitement de liste
[Python] J'ai joué avec le traitement du langage naturel ~ transformers ~
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2 2
J'ai essayé d'implémenter et d'apprendre DCGAN avec PyTorch
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2
J'ai essayé d'implémenter Grad-CAM avec keras et tensorflow
J'ai essayé de comparer la vitesse de traitement avec dplyr de R et pandas de Python
J'ai essayé 100 traitements linguistiques Knock 2020
J'ai essayé de prédire et de soumettre les survivants du Titanic avec Kaggle
J'ai essayé d'illustrer le temps et le temps du langage C
[Python] Essayez de classer les boutiques de ramen par traitement du langage naturel
J'ai essayé de classer MNIST par GNN (avec PyTorch géométrique)
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
J'ai essayé d'écrire dans un modèle de langage profondément appris
[Réunion de changement d'emploi] Essayez de classer les entreprises en traitant le bouche-à-oreille en langage naturel avec word2vec
[Traitement du langage naturel] J'ai essayé de visualiser les sujets d'actualité cette semaine dans la communauté Slack
[Traitement du langage naturel] J'ai essayé de visualiser les remarques de chaque membre de la communauté Slack
Étudiez le traitement du langage naturel avec Kikagaku
traitement pour utiliser les données notMNIST en Python (et essayé de les classer)
J'ai essayé de visualiser les signets volant vers Slack avec Doc2Vec et PCA
[Traitement du langage naturel] Prétraitement avec le japonais
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 3
J'ai essayé de résoudre 100 traitements linguistiques Knock 2020 version [Chapitre 2: Commandes UNIX 10 à 14]
Logivan du langage artificiel et traitement du langage naturel (traitement du langage artificiel)
J'ai essayé de créer un traitement par lots sans serveur pour la première fois avec DynamoDB et Step Functions
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'écrirai une explication détaillée à mort en résolvant 100 traitements de langage naturel Knock 2020 avec Python
J'ai essayé de détecter facilement les points de repère du visage avec python et dlib
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 1
J'ai essayé de résoudre 100 traitements linguistiques Knock 2020 version [Chapitre 2: Commandes UNIX 15-19]
Résumez comment prétraiter le texte (traitement du langage naturel) avec l'api tf.data.Dataset
Se préparer à démarrer le traitement du langage naturel
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 2
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 4
J'ai essayé d'exprimer de la tristesse et de la joie face au problème du mariage stable.
Enseigner les bonnes et les mauvaises machines avec le classificateur Naive Bayes (phase de draft)
J'ai essayé de résoudre 100 traitements linguistiques Knock version 2020 [Chapitre 3: Expressions régulières 25-29]
J'ai essayé de convertir la chaîne datetime <-> avec tzinfo en utilisant strftime () et strptime ()
J'ai essayé d'apprendre l'angle du péché et du cos avec le chainer
J'ai essayé de créer le téléchargement CSV, le traitement des données, la fonction de téléchargement avec Django
J'ai essayé de classer Oba Hanana et Otani Emiri par apprentissage profond
[Traitement du langage naturel] Extraire les mots-clés de la base de données Kakenhi avec MeCab-ipadic-neologd et termextract
J'ai essayé de contrôler la bande passante et le délai du réseau avec la commande tc
3. Traitement du langage naturel avec Python 1-2. Comment créer un corpus: Aozora Bunko
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé de visualiser AutoEncoder avec TensorFlow
J'ai essayé de commencer avec Hy
J'ai essayé de classer le texte en utilisant TensorFlow
3. Traitement du langage naturel par Python 2-1. Réseau de co-occurrence
3. Traitement du langage naturel par Python 1-1. Word N-gram
J'ai essayé un langage fonctionnel avec Python
J'ai essayé d'implémenter CVAE avec PyTorch
J'ai essayé de résoudre TSP avec QAOA
Introduction à la création d'IA avec Python! Partie 3 J'ai essayé de classer et de prédire les images avec un réseau de neurones convolutifs (CNN)