** Cet article est l'article du 4ème jour de Real Escape Advent Calendar 2013. ** **
Article du jour 2 utilise le code HTML récupéré à l'aide de l'API Bing, donc Jour 2 Il est plus facile de comprendre si vous lisez d'abord / items / 62291ba328de9d12bd30).
-J'ai vérifié une bibliothèque Python appelée scikit-learn -Calculé le tf-idf du mot dans le html enregistré au Jour 2
scikit-learn officiel, document d'extraction d'identité textuelle
Calcul Tfidf des mots dans Tweet à l'aide de scikit-learn
https://github.com/katryo/tfidf_with_sklearn
Fork me!
--tf-idf est la valeur de ** tf * idf **. Attaché à un mot d'un document dans un ensemble de documents. Les mots avec un tf-idf élevé peuvent être considérés comme importants. Il peut être utilisé pour pondérer des mots dans la recherche d'informations. --tf (Fréquence du terme) est ** le nombre d'occurrences du mot (Terme) dans le document / le nombre total de tous les mots apparus dans le document **. Il se développe lorsque le mot est utilisé plusieurs fois dans le document. --idf (Inverse Document Frequency) est l'inverse de df. Cependant, en réalité, le journal est utilisé pour faciliter le calcul. Cela devient donc ** log (1 / df) **. Le bas du journal est généralement 2, mais il peut être e ou 10. Devrait être. --df (Fréquence des documents) est ** le nombre de documents dans lesquels le mot apparaît / le nombre total de documents **. Il grandit lorsque le mot est utilisé dans un large éventail de sujets. «Ha» et «o», et en anglais, «is» et «that» sont très grands. La valeur attachée à un mot dans un ensemble de documents.
En traduisant partiellement le contenu de scikit-learn officiel, document d'extraction d'identité textuelle, comprenez le vôtre De plus, il sera décrit.
Lors de l'extraction de l'identité du texte avec scikit-learn, trois processus sont nécessaires.
-tokenizing: Convertit le texte en sac de mots. Dans le cas de l'anglais, il est acceptable de diviser par un espace blanc, puis de supprimer le bruit comme les symboles, mais lorsque vous le faites en japonais, utilisez un analyseur morphologique tel que MeCab ou KyTea. Comme scikit-learn n'inclut pas d'analyseur morphologique japonais, ce processus est requis séparément. --counting: compte la fréquence d'occurrence de chaque mot pour chaque document.
Dans scikit-learn, les trois étapes ci-dessus sont appelées collectivement ** vectorisation **, c'est-à-dire "vectorisation". Le dernier Vectorizer Tfidf peut effectuer les trois étapes. Si vous avez déjà terminé la procédure à mi-chemin, vous pouvez calculer à partir du milieu ou de la moitié.
À propos, scikit-learn peut non seulement faire un sac de mots mais aussi un calcul tfidf avec n-gramme se concentrant sur la suite de deux mots ou plus, mais je ne le ferai pas cette fois.
CountVectorizer Le vecteur de décompte dans sklearn.feature_extraction.text peut tokenize et compter. Puisque le résultat du comptage est représenté par un vecteur, Vectorizer.
La documentation officielle l'explique ici.
TfidfTransformer Le transformateur Tfidf, également dans sklearn.feature_extraction.text, est responsable de la normalisation. La méthode fit_transform calcule tfidf en se basant uniquement sur la "fréquence d'occurrence de mot pour chaque document" et le normalise même. Ici dans la documentation officielle.
TfidfVectorizer Existence qui a les fonctions de Count Vectorizer et Tfidf Transformer. Forme Trinity, exactement la trinité. Ceci est pratique lors de l'extraction de l'identité du texte brut.
Le sujet principal est d'ici. 36934 types de mots dans 400 pages Web récupérés par 8 requêtes. À partir de ceux-ci, imprimez "les mots avec tfidf supérieur à 0,1 dans le document apparaissant".
Tout d'abord, le calcul de tfidf est assez cher, calculons donc le tfidf, puis décapons le résultat.
set_tfidf_with_sklearn_to_fetched_pages.py
import utils
import constants
import pickle
import os
from sklearn.feature_extraction.text import TfidfVectorizer
def is_bigger_than_min_tfidf(term, terms, tfidfs):
'''
[term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)]Utiliser dans
Une fonction qui devine dans l'ordre à partir de la liste des valeurs tfidf des mots.
La valeur de tfidf est MIN_Renvoie True si supérieur à TFIDF
'''
if tfidfs[terms.index(term)] > constants.MIN_TFIDF:
return True
return False
def tfidf(pages):
#analyseur est une fonction qui renvoie une liste de chaînes de caractères lorsqu'une chaîne de caractères est saisie.
vectorizer = TfidfVectorizer(analyzer=utils.stems, min_df=1, max_df=50)
corpus = [page.text for page in pages]
x = vectorizer.fit_transform(corpus)
#À partir de maintenant, cela n'a rien à voir avec la valeur renvoyée. Je voulais juste voir à quoi ressemblent les hauts mots de tfidf
terms = vectorizer.get_feature_names()
tfidfs = x.toarray()[constants.DOC_NUM]
print([term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)])
print('total%je sortes de mots%Trouvé à partir de la page i.' % (len(terms), len(pages)))
return x, vectorizer #x est tfidf_Recevoir en principal comme résultat
if __name__ == '__main__':
utils.go_to_fetched_pages_dir()
pages = utils.load_all_html_files() #les pages récupèrent du HTML et le définissent sur du texte
tfidf_result, vectorizer = tfidf(pages) # tfidf_result est le x de la fonction tfidf
pkl_tfidf_result_path = os.path.join('..', constants.TFIDF_RESULT_PKL_FILENAME)
pkl_tfidf_vectorizer_path = os.path.join('..', constants.TFIDF_VECTORIZER_PKL_FILENAME)
with open(pkl_tfidf_result_path, 'wb') as f:
pickle.dump(tfidf_result, f)
with open(pkl_tfidf_vectorizer_path, 'wb') as f:
pickle.dump(vectorizer, f)
Dans la fonction tfidf
vectorizer = TfidfVectorizer(analyzer=utils.stems, min_df=1, max_df=50)
C'est dit. l'analyseur met une fonction qui renvoie une liste de chaînes lorsque vous mettez une chaîne. Par défaut, il est divisé par un espace blanc et un seul symbole de caractère est supprimé, mais lorsque vous le faites en japonais, il est nécessaire de créer et de définir une fonction à l'aide d'un analyseur morphologique par vous-même. La fonction utils.stems est une fonction qui effectue une analyse morphologique avec MeCab, la convertit en une racine et la renvoie sous forme de liste, écrite dans utils.py, qui sera décrite plus loin.
Ce qui est imprimé dans la fonction tfidf est un mot dont la valeur tfidf est de 0,1 ou plus parmi les mots que l'on peut trouver dans l'une des pages de résultats recherchées par "penchant l'estomac". Le résultat de ceci sera décrit plus loin.
Les utilitaires qui apparaissent dans le code sont les suivants et constituent une collection de fonctions utiles qui peuvent être utilisées dans diverses situations.
utils.py
import MeCab
import constants
import os
import pdb
from web_page import WebPage
def _split_to_words(text, to_stem=False):
"""
contribution: 'Tout à moi'
production: tuple(['tout', 'moi même', 'de', 'Comment', 'Quoi'])
"""
tagger = MeCab.Tagger('mecabrc') #Vous pouvez utiliser un autre Tagger
mecab_result = tagger.parse(text)
info_of_words = mecab_result.split('\n')
words = []
for info in info_of_words:
#Si vous divisez par macab, "" est à la fin de la phrase, avant cela'EOS'Arrive
if info == 'EOS' or info == '':
break
# info => 'Nana\t assistant,Aide finale,*,*,*,*,Nana,N / a,N / a'
info_elems = info.split(',')
#Sixièmement, il y a des mots qui ne sont pas utilisés. Si le sixième est'*'Si tel est le cas, entrez le 0e
if info_elems[6] == '*':
# info_elems[0] => 'Van Rossam\t substantif'
words.append(info_elems[0][:-3])
continue
if to_stem:
#Convertir en racine de mot
words.append(info_elems[6])
continue
#La parole telle qu'elle est
words.append(info_elems[0][:-3])
return words
def words(text):
words = _split_to_words(text=text, to_stem=False)
return words
def stems(text):
stems = _split_to_words(text=text, to_stem=True)
return stems
def load_all_html_files():
pages = []
for query in constants.QUERIES:
pages.extend(load_html_files_with_query(query))
return pages
def load_html_files_with_query(query):
pages = []
for i in range(constants.NUM_OF_FETCHED_PAGES):
with open('%s_%s.html' % (query, str(i)), 'r') as f:
page = WebPage()
page.html_body = f.read()
page.remove_html_tags()
pages.append(page)
return pages
def load_html_files():
"""
À utiliser en supposant que le fichier HTML se trouve dans le répertoire
"""
pages = load_html_files_with_query(constants.QUERY)
return pages
def go_to_fetched_pages_dir():
if not os.path.exists(constants.FETCHED_PAGES_DIR_NAME):
os.mkdir(constants.FETCHED_PAGES_DIR_NAME)
os.chdir(constants.FETCHED_PAGES_DIR_NAME)
Et les constantes sont les suivantes.
constants.py
FETCHED_PAGES_DIR_NAME = 'fetched_pages'
QUERIES = 'La pollinose des dents de ver penchée de l'estomac mesure la dépression Fracture mécanique Épaule raide Documents'.split(' ')
NUM_OF_FETCHED_PAGES = 50
NB_PKL_FILENAME = 'naive_bayes_classifier.pkl'
DOC_NUM = 0
MIN_TFIDF = 0.1
TFIDF_RESULT_PKL_FILENAME = 'tfidf_result.pkl'
TFIDF_VECTORIZER_PKL_FILENAME = 'tfidf_vectorizer.pkl'
Si vous regardez l'ordre des QUERIES, vous pouvez voir que la catégorie «estomac penché» vient en premier. La constante DOC_NUM a été créée pour cette expérience et a été utilisée pour spécifier le 0ème fichier dans la catégorie "estomac penché", c'est-à-dire le fichier nommé "estomac penché_0.html".
Maintenant. Exécutons ce code.
$ python set_tfidf_with_sklearn_to_fetched_pages.py
Même si vous utilisez scikit-learn, le calcul de tfidf prend du temps. Cela a pris 25,81 secondes dans mon environnement. résultat.
['gaJsHost', 'https', 'Égouttage', 'Brûler', 'Avaler de l'air', 'Hyperacidité', 'Sein', 'cuisine', 'Produit alimentaire', 'Hernie de la fissure œsophagienne']
Un total de 36934 mots ont été trouvés sur 400 pages.
C'est un mot qui ressemble à un mal de ventre. Il a été constaté que parmi les mots de l'estomac rest_0.html, les 10 types de mots ci-dessus ont un tfidf supérieur à 0,1.
gaJsHost et https semblent faire partie du code JavaScript. Hmmm. Je veux me débarrasser de tout ce bruit, mais je ne vois pas de bon moyen. Mieux encore, il peut être préférable d'éliminer les mots qui ne sont que alphabétiques.
À propos, des mots comme «hernie de la fissure œsophagienne» ne sont pas inclus dans l'IPADIC de MeCab (voir cet article pour l'origine de l'IPADIC), donc Wikipedia Il faut le renforcer en mettant les mots du mot-clé Hatena dans le dictionnaire. S'il vous plaît google comment faire.
J'ai lu la page officielle, mais le résultat du calcul de tfidf est sorti dans le type de csr_matrix de scipy. Il s'agit d'une matrice clairsemée (principalement 0) qui représente le mot tf-idf dans chaque document sous la forme d'une fraction de 0 à 1.
(Pdb) type(x)
<class 'scipy.sparse.csr.csr_matrix'>
Je ne savais pas ce que l'ensemble de valeurs tfidf était associé au mot (je l'ai découvert plus tard), j'ai donc fait une expérience simple en utilisant pdb.set_trace ().
TfidfVectorizer a la méthode à utiliser
Et scipy.sparse.csr_matrix a
Est.
Premièrement, quand j'ai vérifié la page Web avec le numéro de document 0, c'était une page appelée Stomach leaning.com. Découvrez comment les mots qui apparaissent sur cette page sont représentés.
Après avoir décapé le résultat du calcul de tfidf, le code suivant a été exécuté.
play_with_tfidf.py
# -*- coding: utf-8 -*-
import pickle
import constants
import pdb
def is_bigger_than_min_tfidf(term, terms, tfidfs):
'''
[term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)]Utiliser dans
Une fonction qui devine dans l'ordre à partir de la liste des valeurs tfidf des mots.
La valeur de tfidf est MIN_Renvoie True si supérieur à TFIDF
'''
if tfidfs[terms.index(term)] > constants.MIN_TFIDF:
return True
return False
if __name__ == '__main__':
with open(constants.TFIDF_VECTORIZER_PKL_FILENAME, 'rb') as f:
vectorizer = pickle.load(f)
with open(constants.TFIDF_RESULT_PKL_FILENAME, 'rb') as f:
x = pickle.load(f)
pdb.set_trace()
terms = vectorizer.get_feature_names()
for i in range(3):
tfidfs = x.toarray()[i]
print([term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)])
Vous pouvez utiliser pdb.set_trace comme point d'arrêt, et à partir de là, vous pouvez générer des valeurs dans un environnement interactif, afin de pouvoir effectuer diverses tâches de confirmation.
(Pdb) vectorizer.inverse_transform(x)[0]
> array(['Hernie de la fissure œsophagienne', 'Produit alimentaire', 'remède diététique', 'Opération', 'Œsophagite par reflux', 'cuisine', 'Sein', 'Hyperacidité', 'Douleur d'estomac',
'Ulcère gastrique', 'Ptose gastrique', 'Cancer de l'estomac', 'Avaler de l'air', 'Phytothérapie chinoise', 'Construction', 'Gastrite chronique', 'L'ulcère duodénal', 'assurance médicale',
'Avertissement', 'Information d'entreprise', 'polype', 'pot', 'se soucier', 'Compagnie d'assurance-vie familiale américaine', 'Aflac', 'aller',
'Brûler', 'En ce qui concerne', 'Égouttage', 'unescape', 'try', 'ssl', 'protocol',
'javascript', 'inquiry', 'https', 'gaJsHost', 'ga', 'err',
'comCopyright', 'analytics', 'Inc', 'Cscript', 'CROSSFINITY',
'=\'"', "='", ':"', '.")', '."', ')\u3000', '(("', '("%', "'%",
'"))'],
dtype='<U26')
Le terme «hernie de la fissure œsophagienne» est rare et semble rarement apparaître sur les autres pages, j'ai donc décidé de l'utiliser comme marqueur.
(Pdb) vectorizer.get_feature_names().index('Hernie de la fissure œsophagienne')
36097
Il s'est avéré être le 36097e mot. Alors, quelle est la valeur de tfidf pour le 36097ème mot dans le 0ème document (c'est-à-dire, estomac upset.com)?
(Pdb) x.toarray()[0][36097]
0.10163697033184078
Assez cher. Dans le document numéro 0, le mot portant le numéro 36097 a un tfidf de 0,10163697033184078. Je ne pense pas qu'une valeur tfidf aussi élevée (d'abord et avant tout non nulle) apparaisse au mot numéro 36097. x.toarray () est une matrice très clairsemée, dont la plupart devrait être 0. Par conséquent, on peut considérer que l'ordre de la liste de mots qui peut être prise par vectorizer.get_feature_names () et l'ordre des mots qui ont tfidf qui peuvent être pris par x.toarray () sont les mêmes.
De cette manière, il a été confirmé que la liste de mots était conservée dans le même ordre. Je pense qu'il est dit quelque part dans la documentation officielle que «l'ordre des mots est conservé».
Après cela, j'ai supprimé pdb.set_trace () et relancé play_with_tfidf.py.
['gaJsHost', 'https', 'Égouttage', 'Brûler', 'Avaler de l'air', 'Hyperacidité', 'Sein', 'cuisine', 'Produit alimentaire', 'Hernie de la fissure œsophagienne']
['Égouttage', 'Répugnant', 'Brûler', 'Douleur d'estomac', 'Sein', 'Passer']
['TVCM', 'Gusuru', 'Égouttage', 'Nomu', 'もÉgouttage', 'Brûler', 'Brûlerる', 'Ri', 'action', 'Science', 'Sacron', 'Cerbère', 'tripler', 'Voile', 'gueule de bois', 'Faible', 'Organiser', 'mucus', 'Douleur d'estomac', 'Médecine de l'estomac', 'Sein', 'Plénitude']
Ces mots ont un tfidf élevé (qui semble être très élevé) et sont considérés comme utiles comme base de calcul de la similitude entre les documents et la catégorie de penchant d'estomac.
scikit-learn Pratique.
J'ai posté le code sur Github.
https://github.com/katryo/tfidf_with_sklearn
Je veux implémenter la fonction de calcul de tfidf et la comparer avec scicit-learn.
Recommended Posts