La recherche et le développement de l'intelligence artificielle sont devenus un boom ces dernières années, et divers résultats ont été obtenus dans divers domaines. La technologie de synthèse automatique de documents est également dans le domaine de l'IA dans un large cadre, et techniquement dans le domaine du traitement du langage naturel. Les résumés de documents sont souvent utilisés pour les tableaux d'affichage électriques sur le Shinkansen et les titres des actualités Web, mais je pense que leur utilisation ne se limite pas à des documents soignés tels que les actualités.
Dans cet article, j'aimerais utiliser l'algorithme de synthèse de documents LexRank pour visualiser rapidement les avis types des acheteurs en résumant les avis produits sur le site CE (Rakuten).
LexRank LexRank est un algorithme de synthèse de documents proposé par Erkan et al. Basé sur le concept de PageRank.
Article original: LexRank: La centralité lexicale basée sur des graphes comme importance dans la synthèse de texte
Je vais omettre les détails, mais il n'y a que deux concepts importants dans LexRank.
Le graphique ci-dessous montre les deux concepts ci-dessus. (dXsY: Yème phrase du document X)
Figure: Exemple de graphe de similarité (extrait de [Erkan 04])
Le nœud avec le bord épais est d'une grande importance, et le nœud avec le bord du nœud avec la plus grande importance est également considéré comme étant de grande importance.
Lorsque j'utilise Amazon ou Rakuten, je ressens souvent cela.
―― Le nombre d'avis est extrêmement important et il semble très crédible, mais je ne sais pas à quel avis me référer! ――Vous pouvez voter si cela a été utile, mais l'avis utile est long ...
Par conséquent, cette fois, le but est de ** produire une phrase récapitulative comprenant la partie que tout le monde examine en n phrases à partir d'un grand nombre de phrases de révision **. Cela devrait vous faire économiser beaucoup d'énergie et avoir une idée des critiques, que vous ayez des centaines de critiques ou de longues critiques!
Ce script dépend des packages suivants. Tous peuvent être facilement installés avec pip install / conda install.
Le code principal du LexRank créé est le suivant. Cet algorithme est basé sur l'algorithme 3 de l'article original.
lexrank.py
def lexrank(sentences, N, threshold, vectorizer):
CosineMatrix = np.zeros([N, N])
degree = np.zeros(N)
L = np.zeros(N)
if vectorizer == "tf-idf":
vector = tfidf.compute_tfidf(sentences)
elif vectorizer == "word2vec":
vector = tfidf.compute_word2vec(sentences)
# Computing Adjacency Matrix
for i in range(N):
for j in range(N):
CosineMatrix[i,j] = tfidf.compute_cosine(vector[i], vector[j])
if CosineMatrix[i,j] > threshold:
CosineMatrix[i,j] = 1
degree[i] += 1
else:
CosineMatrix[i,j] = 0
# Computing LexRank Score
for i in range(N):
for j in range(N):
CosineMatrix[i,j] = CosineMatrix[i,j] / degree[i]
L = PowerMethod(CosineMatrix, N, err_tol=10e-6)
return L
Input: --texts: Liste des phrases d'entrée --N: nombre de phrases d'entrée --threshold: seuil de similarité lors de la création d'une matrice adjacente (graphe de similarité) --vectorizer: méthode de vectorisation des instructions (tf-idf / word2vec)
Output: --L: score Lex Rank (importance de chaque phrase)
Le score LexRank L fait référence au vecteur propre. Dans le papier d'origine, il est calculé à l'aide de la méthode d'alimentation (méthode d'alimentation).
PowerMethod
def PowerMethod(CosineMatrix, N, err_tol):
p_old = np.array([1.0/N]*N)
err = 1
while err > err_tol:
err = 1
p = np.dot(CosineMatrix.T, p_old)
err = np.linalg.norm(p - p_old)
p_old = p
return p
Input: --CosineMatrix: matrice adjacente --N: nombre de phrases d'entrée --err_tol: tolérance d'erreur pour déterminer la convergence par PowerMethod
Output: --p: vecteur unique (score LexRank)
Cette fois, je voudrais résumer les critiques des machines de jeu suivantes exposées à Rakuten. (Pour le moment, je cacherai quel produit est juste le nom du modèle)
tf-idf model Voici un résumé du modèle qui a créé une matrice adjacente en vectorisant des phrases à l'aide de tf-idf. À propos, dans l'article original, la matrice adjacente est créée par le modèle tf-idf. (Il n'y avait pas de word2vec à ce moment-là)
1: J'avais un jeu vidéo d'un autre fabricant il y a longtemps, et je suis surpris qu'il ait autant évolué! Sans parler de la belle image, elle a diverses fonctions, alors j'ai pensé que ce prix ne pouvait pas être aidé. Cette boutique a beaucoup de points et de coupons, donc c'était moins cher que ce à quoi je m'attendais et c'était bien de l'acheter. 2: je l'ai acheté ici. 3: Ma famille l'a acheté, mais je suis surpris de ses performances élevées.
1: J'ai commandé la Nintendo New 3DS pour le cadeau de Noël de mon frère. Il est arrivé plus tôt que prévu après l'avoir commandé. Puisqu'il s'agit d'une machine de jeu, j'ai pensé que j'aimerais que l'emballage soit un peu plus sûr, mais c'est correct car il n'y avait pas de défauts ou de rayures initiaux sur la boîte (rires) Aussi, s'il y a quelque chose, merci. 2: J'avais un 3DS, mais le cristal liquide s'est cassé et je l'ai réparé une fois, mais il s'est encore cassé et j'ai dû acheter un nouveau 3DS. J'ai acheté LL parce que je pensais qu'il serait préférable d'en acheter un avec un écran plus grand la prochaine fois. 3: Nous avons acheté pour le cadeau de Noël de l'enfant.
La caractéristique de la PS4 est la haute performance, et il est entendu que 3DS est souvent acheté comme cadeau pour les enfants. En revanche, la révision de la première phrase étant redondante pour les deux produits, il semble nécessaire de considérer un peu plus de segments. De plus, comme les informations de la deuxième phrase de PS4 ne contiennent pas d'informations particulièrement utiles, on considère qu'elles ne doivent pas être extraites dans cette tâche.
word2vec model Voici un résumé du modèle qui a créé une matrice adjacente en vectorisant des phrases à l'aide de word2vec. Le centre de gravité de tous les mots contenus dans une phrase est utilisé comme vecteur de phrase par le vecteur de mot pré-appris.
1: j'ai utilisé des points mais j'avais l'impression d'avoir perdu quelque chose 2: Peut être utilisé sans problèmes ♪ 3: L'écran du téléviseur est assez propre.
1: Pour les enfants, ce serait bien s'il y avait un type pliable comme 3DS, avec une fonction simple comme 2DS qui est sorti il y a quelque temps, et un peu moins cher. 2: Je suis heureux que vous l'ayez expédié immédiatement. 3: C'est un remplacement de LL pressé.
Par rapport au résumé du modèle tf-idf, j'ai l'impression qu'il s'agit d'un résumé plus concis. Cependant, certains résumés ne sont pas des critiques de produits. Étant donné que le score de phrases sémantiquement similaires à de nombreuses phrases est élevé, on peut dire que de nombreux résumés de sortie sont plausibles dans un sens, mais il semble qu'une certaine ingéniosité soit requise pour cette tâche.
Cette fois, nous avons examiné et résumé le site EC à l'aide de l'algorithme de synthèse automatique LexRank. En résumant un grand nombre d'avis, il semble que nous serons en mesure d'appréhender efficacement les caractéristiques du produit. D'un autre côté, j'ai senti qu'il était nécessaire d'en imaginer un peu plus, comme la réduction des segments de phrases et la redondance. Je voudrais recréer ce point la prochaine fois.
Le code de la méthode de calcul vectoriel (tf-idf, word2vec) pour calculer la similitude de chaque phrase est indiqué ci-dessous. Ce script lui-même est appelé dans lexrank.py. (vecteur = tfidf.compute_tfidf (phrases)) Vous pouvez l'exécuter en effectuant l'importation tfidf dans lexrank.py. De plus, le modèle vectoriel de mot ('../ models / wiki_sg_d100.bin') appelé par le modèle word2vec est un vecteur de mot appris à partir du texte intégral de Wikipedia japonais.
tfidf.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import numpy as np
import fasttext as ft
from scipy.spatial import distance
def word2id(bow, word_id):
for w in bow:
if word_id.has_key(w) == False:
word_id[w] = len(word_id)
return word_id
def compute_tf(sentences, word_id):
tf = np.zeros([len(sentences), len(word_id)])
for i in range(len(sentences)):
for w in sentences[i]:
tf[i][word_id[w]] += 1
return tf
def compute_df(sentences, word_id):
df = np.zeros(len(word_id))
for i in range(len(sentences)):
exist = {}
for w in sentences[i]:
if exist.has_key(w) == False:
df[word_id[w]] += 1
exist[w] = 1
else:
continue
return df
def compute_idf(sentences, word_id):
idf = np.zeros(len(word_id))
df = compute_df(sentences, word_id)
for i in range(len(df)):
idf[i] = np.log(len(sentences)/df[i]) + 1
return idf
def compute_tfidf(sentences):
word_id = {}
for sent in sentences:
word_id = word2id(sent, word_id)
tf = compute_tf(sentences, word_id)
idf = compute_idf(sentences, word_id)
tf_idf = np.zeros([len(sentences), len(word_id)])
for i in range(len(sentences)):
tf_idf[i] = tf[i] * idf
return tf_idf
def compute_cosine(v1, v2):
return 1 - distance.cosine(v1, v2)
def sent2vec(bow, model_w):
vector = np.zeros(100)
N = len(bow)
for b in bow:
try:
vector += model_w[b]
except:
continue
vector = vector / float(N)
return vector
def compute_word2vec(sentences):
model_w = ft.load_model('../models/wiki_sg_d100.bin')
vector = np.zeros([len(sentences), 100])
for i in range(len(sentences)):
vector[i] = sent2vec(sentences[i], model_w)
return vector
if __name__ == "__main__":
pass
Recommended Posts