Bonjour, vous copiez et collez un scientifique de données.
Il y a environ 3 ans, j'ai fait un drôle de LT appelé "Ramen and Natural Language Processing", mais maintenant il est embarrassant, donc Python J'ai essayé de le refaire avec.
Nous utilisons une technique appelée analyse statistique du sens latent. En gros, cela vous donne une idée du sujet du document et de quoi il parle.
Étant donné que le rapport alloué à chaque thème peut être calculé avec l'image suivante, il est possible de calculer que A et B sont proches dans l'exemple suivant.
Il n'est pas utilisé comme ci-dessus, mais je pense que les exemples d'application et les livres suivants seront utiles.
Ça fait tellement longtemps Tout d'abord, je vais énumérer le flux général.
#Lecture des données documentaires collectées
from io_modules import load_data #Bibliothèque de lecture DB personnalisée
rows = load_data(LOAD_QUERY, RAMEN_DB)
#Extraire le mot radical avec la fonction racine de l'article de référence
from utils import stems #Mise en œuvre de l'article de référence Presque tel quel
docs = [stems(row) for row in rows]
"""
docs = [
['Grande portion', 'Impressions', 'Direction', 'Meilleur', 'ramen', ...
['ramen', 'queue', 'Du froid', 'Chaud', 'joie', ...
...
]
"""
À partir de là, nous effectuerons réellement LDA en utilisant gensim. Tout d'abord, créez un dictionnaire et un corpus pour gensim.
from gensim import corpora, models
C'est déroutant, mais ce n'est pas le dictionnaire utilisateur utilisé pour séparer dans MeCab, mais le gensim pour mapper les mots apparaissant et les identifiants de mot dans le document.
dictionary = gensim.corpora.Dictionary(docs)
dictionary.save_as_text('./data/text.dict') #sauvegarder
# gensim.corpora.Dictionary.load_from_text('./data/text.dict') #Le fichier peut être chargé la prochaine fois
"""
Nombre d'apparences Word ID Word
1543 Asari 731
62 Facile 54934
952 Chaud 691
672 chaud 1282
308 Merci 4137
・
・
"""
Le premier bouche à oreille recueilli sera conservé sous forme de corpus et utilisé pour l'apprentissage du classificateur.
corpus = [dictionary.doc2bow(doc) for doc in docs]
gensim.corpora.MmCorpus.serialize('./data/text.mm', corpus) #sauvegarder
# corpus = gensim.corpora.MmCorpus('./data/text.mm') #Le chargement du fichier est possible à partir de la prochaine fois
"""\
doc_id word_fréquence d'occurrence id
6 150 3 # word_id=150:Moyashi
6 163 9 # word_id=163:sauce soja
6 164 1
6 165 1
・
・
"""
Il y a un débat sur la nécessité, Cette fois, nous effectuerons le traitement TFIDF sur le corpus et effectuerons le LDA.
tfidf = gensim.models.TfidfModel(corpus)
corpus_tfidf = tfidf[corpus]
#Je l'ai calculé, alors enregistrez-le dans pickle
import pickle
with open('./data/corpus_tfidf.dump', mode='wb') as f:
pickle.dump(corpus_tfidf, f)
#Vous pouvez le charger la prochaine fois
# with open('./data/corpus_tfidf.dump', mode='rb') as f:
# corpus_tfidf = pickle.load(f)
Maintenant que nous sommes prêts, nous allons réellement faire du LDA avec gensim. Cette fois, j'ai essayé de le classer en 50 sujets.
#Selon la quantité de documents, cela peut prendre plusieurs heures.
# '18/12/03 post-scriptum:L'augmentation du nombre de travailleurs dans LdaMulticore peut être beaucoup plus rapide
lda = gensim.models.LdaModel(corpus=corpus_tfidf, id2word=dictionary,
num_topics=50, minimum_probability=0.001,
passes=20, update_every=0, chunksize=10000)
lda.save('./data/lda.model') #sauvegarder
# lda = gensim.models.LdaModel.load('./data/lda.model') #Peut être chargé la prochaine fois
Maintenant, affichons le contenu du modèle appris.
Bien que certains sujets qui expriment des impressions (# 0, # 36, # 42, etc.) soient mitigés, ce sont généralement des sujets qui expriment le goût du ramen (# 2: miso, # 49: lignée familiale, etc.). Il semble que le classifieur de soit fait.
for i in range(50):
print('tpc_{0}: {1}'.format(i, lda.print_topic(i)[0:80]+'...'))
==============
tpc_0: 0.019*Impressionné+ 0.014*impact+ 0.013*Recherché depuis longtemps+ 0.012*Difficulté+ 0.012*délicieux+ 0.011*ramen+ 0.010*Émotion profonde+...
tpc_1: 0.035*Porc grillé+ 0.022*nouilles chinoises réfrigérées+ 0.018*chaud+ 0.010*Addictif+ 0.009*Têtu+ 0.008*délicieux+ 0.008*bien...
tpc_2: 0.050*miso+ 0.029*Miso+ 0.017*gingembre+ 0.013*beurre+ 0.012*Moyashi+ 0.011*saindoux+ 0.009*blé+...
tpc_3: 0.013*Saveur+ 0.010*Ail+ 0.010*Riches+ 0.009*filet de porc rôti+ 0.008*pétrole+ 0.008*Riches+ 0.008*...
tpc_4: 0.010*Sauce soja+ 0.009*utilisation+ 0.009*varech+ 0.008*Matériel+ 0.007*soupe+ 0.007*Fruit de mer+ 0.007*filet de porc rôti...
tpc_5: 0.015*Viens+ 0.014*Un sari+ 0.012*Mince+ 0.010*ramen+ 0.010*popularité+ 0.010*Ça fait du bien+ 0.010*...
tpc_6: 0.047*Crevette+ 0.046*crevette+ 0.014*sésame+ 0.014*crevette+ 0.012*Addictif+ 0.008*délicieux+ 0.008*Sukiyaki...
tpc_7: 0.016*Désagréable+ 0.015*Attentes+ 0.013*mal+ 0.012*Pardon+ 0.012*délicieux+ 0.011*d'habitude+ 0.011*ramen...
tpc_8: 0.070*Soba+ 0.015*Soboro+ 0.013*Attacher+ 0.012*Mentaiko+ 0.012*poulet+ 0.010*Riches+ 0.010*délicieux+...
tpc_9: 0.041*Citron+ 0.024*Style japonais+ 0.017*Ragoût+ 0.010*Trèfle+ 0.010*la vie+ 0.009*délicieux+ 0.009*Fruit de mer+...
tpc_10: 0.040*Des légumes+ 0.027*Ail+ 0.018*Supplémentaire+ 0.013*Carotte+ 0.010*Moyashi+ 0.010*Moins+ 0.009*Californie...
tpc_11: 0.026*Fait main+ 0.023*Avoir+ 0.016*Gingembre+ 0.010*épicé+ 0.010*ramen+ 0.009*délicieux+ 0.008*Sentiment...
tpc_12: 0.031*Sarrasin+ 0.030*Soba+ 0.029*chinois+ 0.016*Shirayu+ 0.011*Poulet de guerre+ 0.008*délicieux+ 0.007*ramen+...
tpc_13: 0.057*noir+ 0.023*noir+ 0.020*Noir+ 0.018*Sauce soja+ 0.011*endurance+ 0.010*huître+ 0.009*Apparence...
tpc_14: 0.060*Tanmen+ 0.048*crevette+ 0.019*Des légumes+ 0.014*chou chinois+ 0.011*Tsumire+ 0.009*Gyoza+ 0.007*délicieux...
tpc_15: 0.073*Épicé+ 0.015*Épicé+ 0.012*miso+ 0.011*le Chili+ 0.011*Sansho+ 0.010*Épicé+ 0.010*辛miso+ 0...
tpc_16: 0.031*Aoba+ 0.029*Engrener+ 0.019*double+ 0.012*Fruit de mer+ 0.010*tendance+ 0.009*instant+ 0.009*Rame...
tpc_17: 0.041*Balle de remplacement+ 0.017*Balle de remplacement+ 0.014*Tonkotsu+ 0.014*Épicé+ 0.010*Extra fin+ 0.010*ramen+ 0.009*rouge...
tpc_18: 0.032*Nostalgique+ 0.023*Facile+ 0.016*sens+ 0.012*ramen+ 0.011*amical+ 0.010*Sentiment+ 0.010*Ah...
tpc_19: 0.027*citron+ 0.016*Ordinaire+ 0.011*cran+ 0.009*Regrettable+ 0.009*steak+ 0.008*Riches+ 0.008*Délicieux...
tpc_20: 0.088*Bouilli+ 0.009*Soba+ 0.008*fragrance+ 0.008*ramen+ 0.008*soupe+ 0.007*filet de porc rôti+ 0.007*Sauce soja...
tpc_21: 0.023*Sushi+ 0.015*conseillé+ 0.012*préféré+ 0.010*ramen+ 0.009*délicieux+ 0.008*Élevé+ 0.008*...
tpc_22: 0.025*Frit+ 0.021*À la mode+ 0.017*À la mode+ 0.016*Café+ 0.014*À la mode+ 0.014*atmosphère+ 0.011*...
tpc_23: 0.024*valeur+ 0.022*Miso blanc+ 0.018*miso+ 0.014*赤miso+ 0.010*ultime+ 0.010*délicieux+ 0.009*brûlé+...
tpc_24: 0.095*Riz sauté+ 0.040*ensemble+ 0.017*mini+ 0.013*Gyoza+ 0.012*ramen+ 0.011*délicieux+ 0.009*...
tpc_25: 0.024*Oden+ 0.015*Nostalgique+ 0.013*Viande grillée+ 0.011*plat+ 0.010*Bouche foncée+ 0.010*ramen+ 0.009...
tpc_26: 0.010*De+ 0.009*ramen+ 0.009*délicieux+ 0.008*sérieux+ 0.008*Délicieux+ 0.008*Bruyant+ 0.008...
tpc_27: 0.073*Mochi+ 0.032*Kimchi+ 0.012*Miso épicé+ 0.010*Délicieux+ 0.010*délicieux+ 0.008*filet de porc rôti+ 0.00...
tpc_28: 0.021*Sudachi+ 0.019*Shichimi+ 0.018*Hommes+ 0.015*oignon+ 0.011*Oignon+ 0.010*Décevant+ 0.010*Attacher...
tpc_29: 0.079*Gyoza+ 0.026*Bière+ 0.011*délicieux+ 0.010*ramen+ 0.009*生Bière+ 0.009*Sauce soja+ 0.008...
tpc_30: 0.021*Contraction+ 0.018*Asexué+ 0.018*germe+ 0.015*Lies de saké+ 0.010*Cuit dans l'eau+ 0.009*Crabe+ 0.009*Riches+ 0....
tpc_31: 0.051*Champon+ 0.024*étudiant+ 0.015*Tantan+ 0.011*Fruit de mer+ 0.009*choc+ 0.009*Authentique+ 0.009*Délicieux...
tpc_32: 0.025*odeur+ 0.023*odeur+ 0.016*odeur+ 0.010*secret+ 0.010*Délicieux+ 0.010*ramen+ 0.010*Tsuyu...
tpc_33: 0.010*Sauce soja+ 0.009*filet de porc rôti+ 0.008*Fruit de mer+ 0.008*goût+ 0.007*soupe+ 0.007*Menma+ 0.007*bien...
tpc_34: 0.074*curry+ 0.040*Riz grillé+ 0.015*Ganso+ 0.011*épices+ 0.010*ensemble+ 0.008*délicieux+ 0.008*La...
tpc_35: 0.068*Tomate+ 0.031*fromage+ 0.015*italien+ 0.014*Pâtes+ 0.011*hormone+ 0.011*Risotto+ 0.00...
tpc_36: 0.038*Collègue+ 0.014*le plus fort+ 0.010*dur+ 0.010*ramen+ 0.010*Dantotsu+ 0.009*délicieux+ 0.009*sujet...
tpc_37: 0.059*Tonkotsu+ 0.026*sauce soja+ 0.025*les enfants+ 0.015*Délicieux+ 0.012*Boueux+ 0.012*ramen+ 0.01...
tpc_38: 0.027*riz+ 0.025*balle de riz+ 0.022*riz+ 0.016*Cuisine diversifiée+ 0.014*riz+ 0.012*cornichons+ 0.011*ensemble...
tpc_39: 0.026*Yuzu+ 0.019*pâle+ 0.009*Vieillissement+ 0.009*Porc grillé+ 0.008*Sauce soja+ 0.008*filet de porc rôti+ 0.007*soupe...
tpc_40: 0.042*Udon+ 0.012*Katsuo+ 0.009*Ouais+ 0.009*tempura+ 0.009*ramen+ 0.008*délicieux+ 0.008*Sentiment...
tpc_41: 0.023*Salé+ 0.020*Qui+ 0.012*déchet+ 0.012*Attacher+ 0.009*français+ 0.008*chef+ 0.008*Ra...
tpc_42: 0.029*ami+ 0.028*Délicieux+ 0.015*queue+ 0.015*délicieux+ 0.013*ramen+ 0.013*Facile+ 0.012*...
tpc_43: 0.012*Menma+ 0.011*filet de porc rôti+ 0.010*Sauce soja+ 0.009*Negi+ 0.009*bien+ 0.008*Fruit de mer+ 0.008*soupe...
tpc_44: 0.040*Attacher+ 0.014*Riches+ 0.013*Visqueux+ 0.013*Divisé+ 0.013*Fruit de mer+ 0.013*Farine de poisson+ 0.011*Premier+ 0....
tpc_45: 0.019*Mauvais goût+ 0.017*Colle de roche+ 0.017*Harukiku+ 0.012*N ° 1 au Japon+ 0.010*délicieux+ 0.009*ramen+ 0.008*ligne...
tpc_46: 0.074*Wantan+ 0.045*Hommes+ 0.015*filet de porc rôti+ 0.009*délicieux+ 0.008*Boisson nuage+ 0.008*Sauce soja+ 0.007*...
tpc_47: 0.027*habituellement+ 0.019*séries+ 0.017*Sheng soba+ 0.012*Mariné+ 0.010*vieux+ 0.010*Délicieux+ 0.010*Dur...
tpc_48: 0.018*moitié+ 0.014*salade+ 0.014*dessert+ 0.014*cuisine+ 0.013*Taverne+ 0.012*Tofu+ 0.010*ensemble...
tpc_49: 0.068*Famille+ 0.019*épinard+ 0.013*Algue+ 0.010*Sauce soja+ 0.010*filet de porc rôti+ 0.010*Sombre+ 0.010*La...
Maintenant que vous avez appris le classificateur, vous pouvez diviser le magasin en sujets (calcul de vecteur de sujet) en passant les avis du magasin via ce classificateur.
Tout d'abord, entrons dans une revue de collecte de journaux alimentaires de "Shinfukusaikan Main Store @ Kyoto" que j'aime depuis que je suis lycéen et assistons à la performance. Mais avant cela, je vais partager le type de ramen proposé par Shinfukusaikan pour faciliter la compréhension de ce qui suit.
«Shinfukusaikan Kyoto»
C'est noir ... C'est un ramen noir.
Cependant, contrairement à son apparence, il s'agit d'un délicieux ramen à la sauce soja étonnamment léger et riche.
Maintenant, quel genre de résultat le classificateur construit cette fois retournera-t-il?
#Source du devis: http://tabelog.com/kyoto/A2601/A260101/26000791/dtlrvwlst/763925/
#Au fait, je préfère personnellement ne pas mettre d'œufs crus lol
>> str="Lorsque j'étais en voyage d'affaires à Kyoto, je me suis arrêté au magasin principal de Shinfukusaikan, que j'avais désiré ardemment.(Omission)Après tout, la soupe est ajustée, les nouilles sont bouillies, les ingrédients sont servis, le charbon de bois est délicieux et le magasin principal est encore plus délicieux! J'ai ressenti cela. Quoi qu'il en soit, c'est bon marché à 650 yens. "Chuka Soba" à Shinfukusaikan est caractérisé par une soupe noire comme le bouillon de charbon de bois et les oignons Kujo avec beaucoup de lui. Bien sûr, "Yakimeshi" est irrésistible.(Omission)J'ai soudainement vu la commande du client sur le chemin du retour (j'ai vu la critique ici plus tard et j'ai découvert que c'était "extra large Shinfuku soba"), et j'aime les œufs crus. Puis, j'ai été choqué, "Oh, aurais-je pu faire ça?" Cela semble aller bien avec la soupe de Shinfukusaikan, et je la demanderai certainement la prochaine fois."
>> vec = dictionary.doc2bow(utils.stems(str))
#Affichage des résultats de classification
>> print(lda[vec])
[(0, 0.28870310712135505), (8, 0.25689765230576195), (13, 0.3333132412551591), (31, 0.081085999317724824)]
#Contenu de chaque sujet/Par ordre décroissant d'influence
>> lda.print_topic(13) #Les caractéristiques des ramen noirs de Shinfukusaikan sont capturées
0.057*noir+ 0.023*noir+ 0.020*Noir+ 0.018*Sauce soja+ 0.011*endurance+ 0.010*huître+ 0.009*Apparence+ 0.008*Sombre+ 0.008*ramen+ 0.008*délicieux
>> lda.print_topic(0)
0.019*Impressionné+ 0.014*impact+ 0.013*Recherché depuis longtemps+ 0.012*Difficulté+ 0.012*délicieux+ 0.011*ramen+ 0.010*Émotion profonde+ 0.010*queue+ 0.010*Délicieux+ 0.008*délicieux
>> lda.print_topic(8)
0.070*Soba+ 0.015*Soboro+ 0.013*Attacher+ 0.012*Mentaiko+ 0.012*poulet+ 0.010*Riches+ 0.010*délicieux+ 0.008*filet de porc rôti+ 0.008*Facile+ 0.007*riz
>> lda.print_topic(31)
0.051*Champon+ 0.024*étudiant+ 0.015*Tantan+ 0.011*Fruit de mer+ 0.009*choc+ 0.009*Authentique+ 0.009*délicieux+ 0.008*ramen+ 0.008*Des légumes+ 0.008*Spécial
Les ramen noirs sont sortis correctement.
Maintenant que nous savons que cela fonctionne, concaténons des centaines de phrases sur le Web qui mentionnent le magasin principal de Shinfukusaikan et les mettons dans le classificateur.
>> str = "Phrases collectées sur le WEB"
>> sinpuku_vec = dictionary.doc2bow(utils.stems(str))
>> print(lda[sinpuku_vec])
[(0, 0.003061940579476011), (5, 0.001795672854987279), (7, 0.016165280743592875), (11, 0.0016683462844631061), (13, 0.387457274481951), (16, 0.048457912903426922), (18, 0.025816920842756448), (19, 0.0014647251485231138), (20, 0.0018013651819984121), (21, 0.001155430885775867), (24, 0.11249915373166983), (25, 0.0030405756373518885), (26, 0.0031413889216075561), (27, 0.0030955757983300515), (29, 0.0021349369911582098), (32, 0.006158571006380364), (34, 0.061260735988294568), (36, 0.0023903609848973475), (37, 0.020874795314517719), (41, 0.0018301667593946488), (42, 0.27803177713836785), (45, 0.0055461332216832828), (46, 0.0016396961473594117), (47, 0.0056507918659765869)]
>> lda.print_topic(13) #valeur: 0.38
0.057*noir+ 0.023*noir+ 0.020*Noir+ 0.018*Sauce soja+ 0.011*endurance+ 0.010*huître+ 0.009*Apparence+ 0.008*Sombre+ 0.008*ramen+ 0.008*délicieux
>> lda.print_topic(42) #valeur: 0.27
0.029*ami+ 0.028*Délicieux+ 0.015*queue+ 0.015*délicieux+ 0.013*ramen+ 0.013*Facile+ 0.012*sensationnel+ 0.011*Sentiment+ 0.011*Célèbre+ 0.011*Beaucoup
>> lda.print_topic(24) #valeur: 0.11
0.095*Riz sauté+ 0.040*ensemble+ 0.017*mini+ 0.013*Gyoza+ 0.012*ramen+ 0.011*délicieux+ 0.009*Délicieux+ 0.009*Un seul article+ 0.008*commande+ 0.008*filet de porc rôti
Le résultat est un peu difficile à voir, mais le riz frit est apparu dans le troisième sujet en conséquence qui reflète de nombreuses opinions.
Il semble que la personne qui a écrit la première critique n'ait pas été interrogée, mais en fait Shinfukusaikan est également célèbre pour son riz frit noir. À partir de cela (?), Il a été constaté que la division thématique des magasins de ramen par des connaissances collectives fonctionne.
Maintenant, le classificateur peut maintenant calculer le vecteur de sujet de n'importe quel magasin de ramen. Enfin, j'aimerais utiliser ce classificateur pour trouver des magasins similaires.
En théorie, vous pouvez trouver un magasin similaire à n'importe quel magasin, mais je reprendrai le contenu de la section précédente et chercherai un magasin similaire au magasin principal Shinfukusaikan.
Bien que le code détaillé soit cassé, en général, le calcul du sujet LDA des magasins de ramen dans tout le pays → le calcul de similitude avec le sujet LDA du magasin principal de Shinfukusaikan est effectué comme suit.
#divers paramètres
MIN_SIMILARITY = 0.6 #Seuil de similarité
RELATE_STORE_NUM = 20 #Nombre de magasins similaires extraits
#Calcul des thèmes LDA des magasins de ramen à l'échelle nationale
from my_algorithms import calc_vecs
(names, prefs, vecs) = calc_vecs(reviews, lda, dictionary)
#Calculez la similitude entre le magasin principal Shinfukusaikan et les sujets LDA des magasins de ramen dans tout le pays
from sklearn.metrics.pairwise import cosine_similarity
similarities = cosine_similarity(sinpuku_vec, vecs)
#Afficher les magasins similaires
import pandas as pd
df = pd.DataFrame({'name': names,
'pref': prefs,
'similarity': similarities})
relate_store_list = df[df.similarity > MIN_SIMILARITY] \
.sort_values(by="similarity", ascending=False) \
.head(RELATE_STORE_NUM)
print(relate_store_list)
==============
id similarity pref name
0 0.934 toyama Makoto
1 0.898 hokkaido Isono Kazuo
2 0.891 shiga Kinkuemon Mitsui Outlet Park Shiga Ryuo
3 0.891 kyoto Shinfukusaikan Higashi Tsuchikawa store
4 0.888 magasin Osaka Kinkuemon Dotonbori
5 0.886 ramen au charbon de bois chiba
6 0.874 Osaka Kinkuemon Esaka magasin
7 0.873 Magasin principal toyama Iroha Iroha
8 0.864 Osaka Kinkuemon Umeda store
9 0.861 mie Hayashiya
10 0.847 niigata Ramen Tsuriyoshi
11 0.846 Magasin principal d'Osaka Kinkuemon
12 0.838 toyama Menhachi Gotabiya
13 0.837 aichi Kikuya Hanten
14 0.820 hyogo Nakanoya
15 0.814 kyoto Kinkuemon Kyoto Saiin store
16 0.807 aichi Yokoji
17 0.804 kumamoto magasin de ramen préféré
18 0.792 kyoto Shinfukusaikan magasin Kumiyama
19 0.791 niigata Goingoin
Prenons quelques-uns et vérifions le résultat.
«Makoto et Tomiyama»
«Isono Kazuo Hokkaido»
«Magasin Shiga Ryuo du parc Kanekuemon Mitsui Outlet Park»
C'est noir ... c'est superbement noir. J'ai aussi vérifié d'autres choses, mais tous étaient des ramen noirs sauf Nakanoya à Hyogo.
Shinfukusaikan a plusieurs succursales, et je pense que c'est un bon point que les résultats sont arrivés correctement même si le nom du magasin a été complètement supprimé et analysé.
En parlant de ramen noir, Toyama Black est célèbre et certains sont apparus, mais je me demande si le goût de Shinfukusaikan est un peu différent de celui de Toyama Black. Il est indéniable qu'un magasin similaire a été choisi en raison de la noirceur des ramen plutôt que du goût. Je voudrais considérer la complexité de ce domaine comme un point à améliorer à l’avenir.
Cette fois, en utilisant les ramen comme thème, nous avons présenté comment obtenir divers résultats à partir de données de personnages se trouvant sur le net sans intervention humaine (presque).
Cela peut sembler un résultat très peu fiable par rapport à la méthode de classification basée sur des données supervisées créées par intervention humaine, mais le résultat qui peut être facilement obtenu en utilisant la bibliothèque existante de Python n'est pas si bon. Je pense.
Bien sûr, non seulement les ramen, mais aussi diverses choses peuvent être traitées s'il y a un certain nombre de phrases ou plus. Si vous le souhaitez, essayez-le avec divers documents.
Recommended Posts