Text mining et topic modeling avec R

your topic modeling is bad and you should feel bad about it (mème)
Auteur : Colin Fay
Tags : Actualités
Date :

Parce que couvrir un sujet aussi large que le text-mining ne pouvait pas se faire en un billet de blog, voici le troisième volet de notre série sur le text-mining avec R.

Topic modeling

Nous avons déjà vu sur ce blog deux approches : comment faire vos premiers pas avec une méthode basique d’analyse fréquentiste, en comparant {tidytext} et {tm} dans notre premier billet. Nous avons poursuivi avec les n-grammes dans notre second numéro. Suite des hostilités aujourd’hui avec le topic modeling.

Avant toute chose, la grande question : qu’est-ce que le topic modeling ? En NLP (Natural Language Processing), un topic model fait référence à un modèle probabiliste, définissant l’appartenance de documents à des topics, ou thèmes. À première vue, ce modèle est assez intuitif, vous allez très vite comprendre pourquoi. Lorsque vous lisez un texte, vous vous attendez à ce que ce document contienne de nombreux n-grammes en rapport avec un sujet spécifique. Car oui, vous partez du postulat qu’un auteur commence à écrire en ayant une ou plusieurs thématique(s) à l’esprit, et qu’il utilise ensuite les mots de sa langue pour parler de cette/ces thématique(s). Par exemple, des livres sur R ont une forte probabilité de contenir des termes en rapport avec le code et la data science, comme “statistiques”, “package”, “fonctions”, etc., à l’inverse d’un roman de Proust. C’est exactement cette idée qui sous-tend le topic modeling : un corpus est une collection de documents, un document est une collection de thématiques, et une thématique est une collection de mots.

Cette approche s’utilise plus particulièrement lors de l’analyse de corpus, afin de découvrir les spécificités propres à chaque document de la collection, afin de les regrouper par similarité. L’objectif étant de pouvoir trier, comprendre, indexer et résumer de larges séries de documents.

Le topic modeling, dans son ensemble, se découpe en trois étapes :
+ Découvrir les topics contenus dans une collection.
+ Annoter les documents en fonction de ces topics.
+ Utiliser ces annotations pour organiser et de répertorier les documents.

Par exemple, le topic modeling est utilisé par les moteurs de recherche, afin d’indexer et classer les pages qu’il rencontre, dans le but ultime de répondre de la manière la plus juste lorsque vous effectuez une requête.

Un peu de théorie

Il existe de nombreux algorithmes pour créer ces modèles, et nous allons aujourd’hui nous concentrer sur le plus utilisé d’entre eux : l’Allocation de Dirichlet latente.

Derrière ce nom un peu barbare se cache un modèle probabiliste expliquant des observations à l’aide de groupes (non observés) de données similaires. Il s’agit d’un algorithme d’apprentissage automatique non supervisé, les classes de sortie n’étant pas étiquetées. En clair, l’algorithme n’est pas à même de vous dire “ah dis donc, je pense que ces articles parlent de finance, et ceux-là de planche à voile”. Il sera “seulement” en mesure de vous dire “ces documents me semblent faire partie d’un même thème 1, dont voici les termes principaux, et celui d’un même thème 2, dont voici les termes principaux” . Oui, comme le k-mean clustering, tout à fait.

Comment ça marche ? On commence par définir un nombre k de thèmes. Ensuite, l’algorithme ira partitionner les documents, et vous répondra de deux manières :
+ en attribuant à chaque mot une probabilité d’avoir été généré par chaque thème.
+ en attribuant à chaque document une probabilité d’appartenance à chaque thème.

Et ce qu’il se passe, sous le capot :
+ LDA assigne aléatoirement à chaque mot un topic (admettons A ou B).
+ LDA parcourt chaque document mot à mot, et met à jour les topics de chaque entrée, par un calcul de probabilité dont nous vous épargnons le détail ici (mais si vous êtes un peu maso / curieux : Latent Dirichlet Allocation).
+ Ce processus d’assignation est répété de nombreuses fois jusqu’à stabilité du modèle (et… oui, comme le k-mean clustering, tout à fait).

But… why?

Pourquoi choisir cet algorithme ? La force du LDA est qu’il considère qu’un document est une composition de topics, et que ces topics peuvent être distribués sur plusieurs documents : un document A peut-être composé de 30 % de topic 1 et de 70 % de topic 2, et un document B peut-être composé de 80 % de topic 1 et de 20% de topic 2. Et non, pas comme le k-mean, cette fois : le LDA autorise un “overlap” des topics d’un document à l’autre, pour une catégorisation plus souple, et donc plus précise.

Dans R, une fois votre algorithme tourné, vous obtiendrez une liste de résultats, avec deux matrices à regarder :

  • beta, qui contient les probabilités de chaque mot d’avoir été généré par un topic.
  • gamma, avec la probabilité de chaque document d’appartenir à un topic.

Encore un peu vague ? Mettons les mains dans le code, cela sera plus clair !

En pratique

Pour réaliser le topic modeling, nous aurons besoin du package {topicmodels}. Et pour l’exemple, commençons par un corpus de documents simple : quatre pages Wikipédia avec quatre topics très différents.

Ici, intuitivement, nous trouvons 4 topics. Toujours pour l’exemple, nous allons voir comment, même si nous n’avions pas l’intuition de ces topics, l’algorithme est en mesure de nous livrer un modèle qui classera chaque page dans un topic différent.

[pastacode lang=”R” manual=”%23%20Si%20besoin%20%0Ainstall.packages(%22topicmodels%22)%0Ainstall.packages(%22tidytext%22)%0Ainstall.packages(%22tidyverse%22)%0Ainstall.packages(%22rvest%22)%0A%0A%23%20Charger%20les%20packages%20%0Alibrary(tidytext)%0Alibrary(topicmodels)%0Alibrary(tidyverse)%0Alibrary(rvest)%0A%0A%23%20Cr%C3%A9er%20le%20tibble%20avec%20les%20textes%0A%0A%23%23%20Une%20fonction%20pour%20scraper%20et%20cr%C3%A9er%20un%20df%20%0A%0Ascrape_wiki%20%3C-%20function(url)%7B%0A%20%20url%20%3C-%20read_html(url)%0A%20%20df%20%3C-%20tibble(text%20%3D%20url%20%25%3E%25%20html_nodes(%22p%22)%20%25%3E%25%20html_text()%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%20%3D%20url%20%25%3E%25%20html_nodes(%22h1%22)%20%25%3E%25%20html_text())%0A%20%20return(df)%0A%7D%0Aurl_list%20%3C-%20c(%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMarcel_Proust%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FNatural_logarithm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FKreator%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FOpen-source_model%22)%0Adata%20%3C-%20map_df(.x%20%3D%20url_list%2C%20.f%20%3D%20scrape_wiki)” message=”” highlight=”” provider=”manual”/]

 

Nous voici donc avec un corpus de 4 documents. Le package {topicmodel} travaillant avec des DocumentTermMatrix, nous devons faire appel à la fonction cast_dtm, de {tidytext}. (Si vous avez besoin de vous rafraîchir la mémoire sur tidytext, nous vous conseillons de relire les deux billets que nous avons cités dans l’introduction ;))

[pastacode lang=”R” manual=”%23%20G%C3%A9n%C3%A9rons%20le%20tibble%20avec%20le%20compte%20des%20mots%2C%20avant%20de%20le%20transformer%20en%20DTM%0Adtm%20%3C-%20data%20%25%3E%25%0A%20%20unnest_tokens(word%2C%20text)%20%25%3E%25%0A%20%20count(name%2C%20word%2C%20sort%20%3D%20TRUE)%20%25%3E%25%0A%20%20anti_join(tidytext%3A%3Astop_words)%20%25%3E%25%0A%20%20%23Tranformer%20en%20DocumentTermMatrix%0A%20%20cast_dtm(name%2C%20term%20%3D%20word%2C%20value%20%3D%20n)%0A%0Aclass(dtm)%0A%5B1%5D%20%22DocumentTermMatrix%22%20%20%20%20%22simple_triplet_matrix%22%0A%23%20Cr%C3%A9er%20le%20mod%C3%A8le%0Alda_model%20%3C-%20LDA(x%20%3D%20dtm%2C%20k%20%3D%204%2C%20control%20%3D%20list(seed%20%3D%202811))” message=”” highlight=”” provider=”manual”/]

Une fois ce modèle en place, nous pouvons le faire “revenir dans le tidyverse” grâce à la fonction tidy, exportée du package {broom}.

[pastacode lang=”R” manual=”%23%20Avec%20la%20matrice%20beta%0A%0Atidy_model_beta%20%3C-%20tidy(lda_model%2C%20matrix%20%3D%20%22beta%22)%0A%0A%23%20Quelle%20est%20la%20probabilit%C3%A9%20que%20le%20terme%20logarithm%20soit%20g%C3%A9n%C3%A9r%C3%A9%20par%20%0A%23%20un%20des%20quatre%20topics%20%3F%20%0A%0Atidy_model_beta%20%25%3E%25%20%0A%20%20filter(term%20%3D%3D%20%22logarithm%22)%0A%0A%23%20A%20tibble%3A%204%20x%203%0A%20%20topic%20%20%20%20%20%20term%20%20%20%20%20%20%20%20%20beta%0A%20%20%3Cint%3E%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A1%20%20%20%20%201%20logarithm%203.803857e-32%0A2%20%20%20%20%202%20logarithm%201.261209e-37%0A3%20%20%20%20%203%20logarithm%203.377426e-35%0A4%20%20%20%20%204%20logarithm%205.313589e-02″ message=”” highlight=”” provider=”manual”/]

Ici, nous avons un data.frame contenant les probabilités que le mot “logarithm” ait été généré par chaque topic : 5% pour le topic 4, et… très peu pour les autres.

[pastacode lang=”R” manual=”%23%20M%C3%AAme%20chose%2C%20avec%20le%20terme%20%22metal%22%0Atidy_model_beta%20%25%3E%25%20%0A%20%20filter(term%20%3D%3D%20%22metal%22)%0A%0A%23%20A%20tibble%3A%204%20x%203%0A%20%20topic%20%20term%20%20%20%20%20%20%20%20%20beta%0A%20%20%3Cint%3E%20%3Cchr%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A1%20%20%20%20%201%20metal%202.434275e-02%0A2%20%20%20%20%202%20metal%205.532748e-37%0A3%20%20%20%20%203%20metal%205.660067e-36%0A4%20%20%20%20%204%20metal%203.729133e-31″ message=”” highlight=”” provider=”manual”/]

Quant à “metal”, la probabilité la plus élevée revient au topic 1 ! Visualisons les 10 termes qui participent le plus à chaque topic :

[pastacode lang=”R” manual=”tidy_model_beta%20%25%3E%25%0A%20%20group_by(topic)%20%25%3E%25%0A%20%20top_n(10%2C%20beta)%20%25%3E%25%0A%20%20ungroup()%20%25%3E%25%0A%20%20arrange(topic%2C%20-beta)%20%25%3E%25%0A%20%20ggplot(aes(reorder(term%2C%20beta)%2C%20beta%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col(show.legend%20%3D%20FALSE)%20%2B%0A%20%20facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20scale_fill_viridis_d()%20%2B%20%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Topic%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22beta%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%204%20wikipedia%20web%20pages%22)” message=”” highlight=”” provider=”manual”/]

Bien, intéressons-nous maintenant à la matrice gamma. Cette dernière contient la probabilité de chaque document d’appartenir à un topic.

[pastacode lang=”R” manual=”tidy_model_gamma%20%3C-%20tidy(lda_model%2C%20matrix%20%3D%20%22gamma%22)%0Atidy_model_gamma%0A%23%20A%20tibble%3A%2016%20x%203%0A%20%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20Open-source%20model%20%20%20%20%201%201.592595e-05%0A%202%20Natural%20logarithm%20%20%20%20%201%203.082349e-05%0A%203%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%201%209.998966e-01%0A%204%20%20%20%20%20Marcel%20Proust%20%20%20%20%201%203.123151e-05%0A%205%20Open-source%20model%20%20%20%20%202%209.999522e-01%0A%206%20Natural%20logarithm%20%20%20%20%202%203.082349e-05%0A%207%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%202%203.445458e-05%0A%208%20%20%20%20%20Marcel%20Proust%20%20%20%20%202%203.123151e-05%0A%209%20Open-source%20model%20%20%20%20%203%201.592595e-05%0A10%20Natural%20logarithm%20%20%20%20%203%203.082349e-05%0A11%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%203%203.445458e-05%0A12%20%20%20%20%20Marcel%20Proust%20%20%20%20%203%209.999063e-01%0A13%20Open-source%20model%20%20%20%20%204%201.592595e-05%0A14%20Natural%20logarithm%20%20%20%20%204%209.999075e-01%0A15%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%204%203.445458e-05%0A16%20%20%20%20%20Marcel%20Proust%20%20%20%20%204%203.123151e-05%0A%23%20Le%20topic%20principal%20%3A%20%0Atidy_model_gamma%20%25%3E%25%20%0A%20%20group_by(topic)%20%25%3E%25%20%0A%20%20arrange(desc(gamma))%20%25%3E%25%20%0A%20%20top_n(1)%20%0A%0A%23%20A%20tibble%3A%204%20x%203%0A%23%20Groups%3A%20%20%20topic%20%5B4%5D%0A%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%3Cdbl%3E%0A1%20Open-source%20model%20%20%20%20%202%200.9999522%0A2%20Natural%20logarithm%20%20%20%20%204%200.9999075%0A3%20%20%20%20%20Marcel%20Proust%20%20%20%20%203%200.9999063%0A4%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%201%200.9998966%0A%0A%23%20En%20le%20visualisant%20%0A%0Atidy_model_gamma%20%25%3E%25%0A%20%20ggplot(aes(document%2C%20gamma%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col()%20%2B%0A%20%20scale_fill_viridis_d()%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Corpus%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%204%20wikipedia%20web%20pages%22)” message=”” highlight=”” provider=”manual”/]

Bon, ici, c’était plutôt facile : nous avions quatre articles très différents, et les résultats sont très tranchés, avec des proba de plus de 99,99 % d’appartenance. Qui plus est, nous avions 1 document pour 1 topic, le décompte était presque trop simple. Car oui, dans la vraie vie, le nombre de documents est plus élevé ; et nous ne chercherons pas forcément à modeler “un topic pour un document” : l’idée était plutôt, ici, d’illustrer le fonctionnement.

Bien, donnons un peu plus de grain à moudre à notre algorithme, et essayons avec 8 articles sur deux thématiques distinctes, autrement dit 4 documents pour 1 topic.

[pastacode lang=”R” manual=”url_list_long%20%3C-%20c(%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FKreator%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMunicipal_Waste_(band)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FHavok_(band)%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FExodus_(American_band)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMarcel_Proust%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FJean-Paul_Sartre%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FLouis-Ferdinand_C%25C3%25A9line%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAlbert_Camus%22)%0A%0Adata_long%20%3C-%20map_df(.x%20%3D%20url_list_long%2C%20.f%20%3D%20scrape_wiki)%0A%0Adtm_long%20%3C-%20data_long%20%25%3E%25%0A%20%20unnest_tokens(word%2C%20text)%20%25%3E%25%0A%20%20count(name%2C%20word%2C%20sort%20%3D%20TRUE)%20%25%3E%25%0A%20%20anti_join(tidytext%3A%3Astop_words)%20%25%3E%25%0A%20%20cast_dtm(name%2C%20term%20%3D%20word%2C%20value%20%3D%20n)%0A%0Alda_model_long%20%3C-%20LDA(x%20%3D%20dtm_long%2C%20k%20%3D%202%2C%20control%20%3D%20list(seed%20%3D%202811))%0A%0Atidy_model_long_beta%20%3C-%20tidy(lda_model_long%2C%20matrix%20%3D%20%22beta%22)%0A%0Atidy_model_long_beta%0A%0A%23%20A%20tibble%3A%208%2C386%20x%203%0A%20%20%20topic%20%20%20%20%20%20%20%20term%20%20%20%20%20%20%20%20%20%20beta%0A%20%20%20%3Cint%3E%20%20%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20%20%20%20%201%20%20%20%20%20%20year’s%204.156572e-151%0A%202%20%20%20%20%202%20%20%20%20%20%20year’s%20%201.575276e-04%0A%203%20%20%20%20%201%20%20%20%20%20%20trache%202.901503e-150%0A%204%20%20%20%20%202%20%20%20%20%20%20trache%20%201.575276e-04%0A%205%20%20%20%20%201%20%20%20%20%20%20%20%20tony%201.992552e-150%0A%206%20%20%20%20%202%20%20%20%20%20%20%20%20tony%20%201.575276e-04%0A%207%20%20%20%20%201%20%20%20%20%20%20titles%204.143461e-150%0A%208%20%20%20%20%202%20%20%20%20%20%20titles%20%201.575276e-04%0A%209%20%20%20%20%201%20thrashing’s%201.072752e-147%0A10%20%20%20%20%202%20thrashing’s%20%201.575276e-04%0A%23%20…%20with%208%2C376%20more%20rows%0A%0Atidy_model_long_beta%20%25%3E%25%0A%20%20group_by(topic)%20%25%3E%25%0A%20%20top_n(10%2C%20beta)%20%25%3E%25%0A%20%20ungroup()%20%25%3E%25%0A%20%20arrange(topic%2C%20-beta)%20%25%3E%25%0A%20%20ggplot(aes(reorder(term%2C%20beta)%2C%20beta%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col(show.legend%20%3D%20FALSE)%20%2B%0A%20%20facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20scale_fill_viridis_d()%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Topic%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22beta%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%20Wikipedia%20pages%3A%20thrash-metal%20bands%20vs%2020th%20century%20literature%22)” message=”” highlight=”” provider=”manual”/]

Et que donne gamma ?

[pastacode lang=”R” manual=”tidy_model_long_gamma%20%3C-%20tidy(lda_model_long%2C%20matrix%20%3D%20%22gamma%22)%0Atidy_model_long_gamma%0A%23%20A%20tibble%3A%2016%20x%203%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20Municipal%20Waste%20(band)%20%20%20%20%201%201.365814e-04%0A%202%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%201%209.999618e-01%0A%203%20Louis-Ferdinand%20C%C3%A9line%20%20%20%20%201%203.370056e-05%0A%204%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%201%204.216601e-05%0A%205%20%20%20%20%20%20%20Jean-Paul%20Sartre%20%20%20%20%201%202.206303e-01%0A%206%20%20%20%20%20%20%20%20%20%20%20Havok%20(band)%20%20%20%20%201%204.466137e-01%0A%207%20Exodus%20(American%20band)%20%20%20%20%201%202.704922e-05%0A%208%20%20%20%20%20%20%20%20%20%20%20Albert%20Camus%20%20%20%20%201%209.999793e-01%0A%209%20Municipal%20Waste%20(band)%20%20%20%20%202%209.998634e-01%0A10%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%202%203.822138e-05%0A11%20Louis-Ferdinand%20C%C3%A9line%20%20%20%20%202%209.999663e-01%0A12%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%202%209.999578e-01%0A13%20%20%20%20%20%20%20Jean-Paul%20Sartre%20%20%20%20%202%207.793697e-01%0A14%20%20%20%20%20%20%20%20%20%20%20Havok%20(band)%20%20%20%20%202%205.533863e-01%0A15%20Exodus%20(American%20band)%20%20%20%20%202%209.999730e-01%0A16%20%20%20%20%20%20%20%20%20%20%20Albert%20Camus%20%20%20%20%202%202.073066e-05%0A%0A%23%20Le%20topic%20principal%20%3A%20%0Atidy_model_long_gamma%20%25%3E%25%20%0A%20%20group_by(document)%20%25%3E%25%20%0A%20%20arrange(desc(gamma))%20%25%3E%25%20%0A%20%20top_n(1)%20%25%3E%25%20%0A%20%20arrange(topic)%0A%0A%23%20A%20tibble%3A%208%20x%203%0A%23%20Groups%3A%20%20%20document%20%5B8%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%3Cdbl%3E%0A1%20%20%20%20%20%20%20%20%20%20%20Albert%20Camus%20%20%20%20%201%200.9999793%0A2%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%201%200.9999618%0A3%20Exodus%20(American%20band)%20%20%20%20%202%200.9999730%0A4%20Louis-Ferdinand%20C%C3%A9line%20%20%20%20%202%200.9999663%0A5%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%202%200.9999578%0A6%20Municipal%20Waste%20(band)%20%20%20%20%202%200.9998634%0A7%20%20%20%20%20%20%20Jean-Paul%20Sartre%20%20%20%20%202%200.7793697%0A8%20%20%20%20%20%20%20%20%20%20%20Havok%20(band)%20%20%20%20%202%200.5533863%0A%0A%23%20En%20le%20visualisant%20%0A%0Atidy_model_long_gamma%20%25%3E%25%0A%20%20ggplot(aes(document%2C%20gamma%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col()%20%2B%0A%20%20%23facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20scale_fill_viridis_d(name%20%3D%20%22Topic%22)%20%2B%0A%20%20labs(x%20%3D%20%22Corpus%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%204%20wikipedia%20web%20pages%22)” message=”” highlight=”” provider=”manual”/]

Intéressant ! On voit ici que l’algorithme ne fait pas un choix tranché pour certaines pages, comme celles de Havok et de Jean Paul Sartre, qui participent chacun à leur échelle aux deux topic.

Que se passe-t-il si nous lui donnons plus de 2 thématiques ?

[pastacode lang=”R” manual=”lda_model_long%20%3C-%20LDA(x%20%3D%20dtm_long%2C%20k%20%3D%204%2C%20control%20%3D%20list(seed%20%3D%202811))%0A%0Atidy_model_long_beta%20%3C-%20tidy(lda_model_long%2C%20matrix%20%3D%20%22beta%22)%0A%0Atidy_model_long_beta%0A%0A%23%20A%20tibble%3A%2016%2C772%20x%203%0A%20%20%20topic%20%20%20term%20%20%20%20%20%20%20%20%20beta%0A%20%20%20%3Cint%3E%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20%20%20%20%201%20year’s%202.569750e-55%0A%202%20%20%20%20%202%20year’s%207.440476e-04%0A%203%20%20%20%20%203%20year’s%201.933550e-60%0A%204%20%20%20%20%204%20year’s%202.396715e-65%0A%205%20%20%20%20%201%20trache%201.793795e-54%0A%206%20%20%20%20%202%20trache%207.440476e-04%0A%207%20%20%20%20%203%20trache%203.941331e-60%0A%208%20%20%20%20%204%20trache%202.716720e-66%0A%209%20%20%20%20%201%20%20%20tony%201.231878e-54%0A10%20%20%20%20%202%20%20%20tony%207.440476e-04%0A%23%20…%20with%2016%2C762%20more%20rows%0A%0Atidy_model_long_beta%20%25%3E%25%0A%20%20group_by(topic)%20%25%3E%25%0A%20%20top_n(10%2C%20beta)%20%25%3E%25%0A%20%20ungroup()%20%25%3E%25%0A%20%20arrange(topic%2C%20-beta)%20%25%3E%25%0A%20%20ggplot(aes(reorder(term%2C%20beta)%2C%20beta%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col(show.legend%20%3D%20FALSE)%20%2B%0A%20%20facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20scale_fill_viridis_d()%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Topic%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22beta%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%20Wikipedia%20pages%3A%20thrash-metal%20bands%20vs%2020th%20century%20literature%22)” message=”” highlight=”” provider=”manual”/]

Et avec gamma ?

[pastacode lang=”R” manual=”tidy_model_long_gamma%20%3C-%20tidy(lda_model_long%2C%20matrix%20%3D%20%22gamma%22)%0Atidy_model_long_gamma%0A%23%20A%20tibble%3A%2032%20x%203%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20Municipal%20Waste%20(band)%20%20%20%20%201%208.921420e-05%0A%202%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%201%202.496750e-05%0A%203%20Louis-Ferdinand%20C%C3%A9line%20%20%20%20%201%202.201440e-05%0A%204%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%201%202.754419e-05%0A%205%20%20%20%20%20%20%20Jean-Paul%20Sartre%20%20%20%20%201%201.167548e-05%0A%206%20%20%20%20%20%20%20%20%20%20%20Havok%20(band)%20%20%20%20%201%209.998127e-01%0A%207%20Exodus%20(American%20band)%20%20%20%20%201%209.999470e-01%0A%208%20%20%20%20%20%20%20%20%20%20%20Albert%20Camus%20%20%20%20%201%201.354211e-05%0A%209%20Municipal%20Waste%20(band)%20%20%20%20%202%209.997324e-01%0A10%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%202%202.496750e-05%0A%23%20…%20with%2022%20more%20rows%0A%0A%23%20Le%20topic%20principal%20%3A%20%0Atidy_model_long_gamma%20%25%3E%25%20%0A%20%20group_by(document)%20%25%3E%25%20%0A%20%20arrange(desc(gamma))%20%25%3E%25%20%0A%20%20top_n(1)%20%0A%0A%23%20A%20tibble%3A%208%20x%203%0A%23%20Groups%3A%20%20%20document%20%5B8%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document%20topic%20%20%20%20%20gamma%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%20%3Cint%3E%20%20%20%20%20%3Cdbl%3E%0A1%20%20%20%20%20%20%20Jean-Paul%20Sartre%20%20%20%20%204%200.9999650%0A2%20%20%20%20%20%20%20%20%20%20%20Albert%20Camus%20%20%20%20%204%200.9999594%0A3%20Exodus%20(American%20band)%20%20%20%20%201%200.9999470%0A4%20Louis-Ferdinand%20C%C3%A9line%20%20%20%20%204%200.9999340%0A5%20%20%20%20%20%20%20%20%20%20Marcel%20Proust%20%20%20%20%203%200.9999251%0A6%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Kreator%20%20%20%20%202%200.9999174%0A7%20%20%20%20%20%20%20%20%20%20%20Havok%20(band)%20%20%20%20%201%200.9998127%0A8%20Municipal%20Waste%20(band)%20%20%20%20%202%200.9997324%0A%0A%23%20En%20le%20visualisant%20%0A%0Atidy_model_long_gamma%20%25%3E%25%0A%20%20ggplot(aes(document%2C%20gamma%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col()%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20scale_fill_viridis_d()%20%2B%0A%20%20labs(x%20%3D%20%22Corpus%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%204%20wikipedia%20web%20pages%22)” message=”” highlight=”” provider=”manual”/]

Ici, le découpage est un peu plus net ! Passons maintenant à une plus grosse échelle.

Un dernier pour la route ?

Bon, donnons lui encore plus à manger, avec un corpus plus volumineux, et avec des contenus qui seront plus similaires : si on comparait des lyrics de Kreator, Motörhead, Pantera et Iron Maiden ?

[pastacode lang=”R” manual=”%23%23%20Une%20fonction%20pour%20scraper%20et%20cr%C3%A9er%20un%20df%20depuis%20metrolyrics.com%0A%0Ascrape_lyrics_url%20%3C-%20function(url)%7B%0A%20%20url%20%3C-%20read_html(url)%0A%20%20df%20%3C-%20tibble(text%20%3Durl%20%25%3E%25%20html_nodes(%22.songs-table%22)%20%25%3E%25%20html_nodes(%22a%22)%20%25%3E%25%20html_attr(%22href%22)%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%20%3D%20url%20%25%3E%25%20html_nodes(%22h1%22)%20%25%3E%25%20html_text())%0A%20%20return(df)%0A%7D%0A%0Ascrape_lyrics_page%20%3C-%20function(url)%7B%0A%20%20url%20%3C-%20read_html(url)%0A%20%20df%20%3C-%20tibble(text%20%3D%20url%20%25%3E%25%20html_nodes(%22%23lyrics-body-text%22)%20%25%3E%25%20html_text()%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20band%20%3D%20url%20%25%3E%25%20html_nodes(%22h2%22)%20%25%3E%25%20html_nodes(%22a%22)%20%25%3E%25%20html_text()%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20song%20%3D%20url%20%25%3E%25%20html_nodes(%22h1%22)%20%25%3E%25%20html_text())%20%0A%20%20df%24song%20%3C-%20gsub(pattern%20%3D%20%22%20Lyrics%22%2C%20%22%22%2C%20df%24song)%0A%20%20return(df)%0A%7D%0A%0Asong_index%20%3C-%20c(%22http%3A%2F%2Fwww.metrolyrics.com%2Fkreator-lyrics.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fkreator-alpage-2.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fkreator-alpage-3.html%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Firon-maiden-lyrics.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Firon-maiden-alpage-2.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Firon-maiden-alpage-3.html%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fmotrhead-lyrics.html%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fmotrhead-alpage-2.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fmotrhead-alpage-3.html%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fpantera-lyrics.html%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fwww.metrolyrics.com%2Fpantera-alpage-2.html%22)%0Aurl_list%20%3C-%20map_df(song_index%2C%20scrape_lyrics_url)%0A%0Adata_m%20%3C-%20map_df(.x%20%3D%20url_list%24text%2C%20.f%20%3D%20scrape_lyrics_page)%0Adim(data_m)%0A%5B1%5D%20698%20%20%203″ message=”” highlight=”” provider=”manual”/]

Nous voilà donc avec 698 morceaux, soit 698 documents. Pour mettre l’algorithme à l’épreuve, nous allons lui fournir un corpus avec juste les chansons, et lui demander de les classer en quatre thèmes. En clair, imaginons que nous ayons perdu la colonne contenant le nom des groupes, et que nous tentions de les retrouver en les classant par topic.

Une fois notre test fait, nous vérifierons en croisant avec le nom des groupes, afin de voir si les topics se fondent avec les groupes.

[pastacode lang=”R” manual=”dtm_m%20%3C-%20data_m%20%25%3E%25%0A%20%20unnest_tokens(word%2C%20text)%20%25%3E%25%0A%20%20count(song%2C%20word%2C%20sort%20%3D%20TRUE)%20%25%3E%25%0A%20%20anti_join(tidytext%3A%3Astop_words)%20%25%3E%25%0A%20%20cast_dtm(song%2C%20term%20%3D%20word%2C%20value%20%3D%20n)%0A%0Alda_model_m%20%3C-%20LDA(x%20%3D%20dtm_m%2C%20k%20%3D%204%2C%20control%20%3D%20list(seed%20%3D%202811))%0A%0Atidy_model_m_beta%20%3C-%20tidy(lda_model_m%2C%20matrix%20%3D%20%22beta%22)%0A%0Atidy_model_m_beta%0A%0A%23%20A%20tibble%3A%2031%2C672%20x%203%0A%20%20%20topic%20%20%20%20%20%20term%20%20%20%20%20%20%20%20%20%20beta%0A%20%20%20%3Cint%3E%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%20%3Cdbl%3E%0A%201%20%20%20%20%201%20riotevery%205.307780e-143%0A%202%20%20%20%20%202%20riotevery%20%201.211671e-10%0A%203%20%20%20%20%203%20riotevery%20%205.992365e-05%0A%204%20%20%20%20%204%20riotevery%202.273045e-144%0A%205%20%20%20%20%201%20%20%20riotall%201.608980e-142%0A%206%20%20%20%20%202%20%20%20riotall%20%201.284382e-10%0A%207%20%20%20%20%203%20%20%20riotall%20%205.992364e-05%0A%208%20%20%20%20%204%20%20%20riotall%202.341197e-144%0A%209%20%20%20%20%201%20%20patriots%201.807062e-142%0A10%20%20%20%20%202%20%20patriots%20%202.247364e-10%0A%23%20…%20with%2031%2C662%20more%20rows%0A%0Atidy_model_m_beta%20%25%3E%25%0A%20%20group_by(topic)%20%25%3E%25%0A%20%20top_n(10%2C%20beta)%20%25%3E%25%0A%20%20ungroup()%20%25%3E%25%0A%20%20arrange(topic%2C%20-beta)%20%25%3E%25%0A%20%20ggplot(aes(reorder(term%2C%20beta)%2C%20beta%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col(show.legend%20%3D%20FALSE)%20%2B%0A%20%20facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20scale_fill_viridis_d()%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Topic%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22beta%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%20698%20songs%20by%20Iron%20Maiden%2C%20Kreator%2C%20Mot%C3%B6rhead%20and%20Pantera%22)” message=”” highlight=”” provider=”manual”/]

Ici, la matrice gamma contenue dans notre modèle va nous donner la participation de chaque morceau aux différents topics. Ce que nous voulons, c’est connaître la participation de chaque groupe à chaque topic. C’est pourquoi nous devons commencer par recréer le tableau avec les noms des bands.

[pastacode lang=”R” manual=”tidy_model_m_gamma%20%3C-%20tidy(lda_model_m%2C%20matrix%20%3D%20%22gamma%22)%0Atidy_model_m_gamma%20%3C-%20tidy_model_m_gamma%20%25%3E%25%20%0A%20%20rename(song%20%3D%20document)%20%25%3E%25%0A%20%20left_join(data_m%2C%20by%20%3D%20%22song%22)%20%25%3E%25%20%0A%20%20select(topic%2C%20gamma%2C%20band%2C%20song)%0A%0Atidy_model_m_gamma%0A%23%20A%20tibble%3A%202%2C792%20x%204%0A%20%20%20topic%20%20%20%20%20%20%20%20gamma%20%20%20%20%20%20%20%20band%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20song%0A%20%20%20%3Cint%3E%20%20%20%20%20%20%20%20%3Cdbl%3E%20%20%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%0A%201%20%20%20%20%201%200.0005307050%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Zero%20To%20None%0A%202%20%20%20%20%201%200.0005456218%20%20%20%20%20Pantera%20You’ve%20Got%20To%20Be%20Belong%20To%20It%0A%203%20%20%20%20%201%200.0005614014%20%20%20%20%20Pantera%20%20%20%20You’ve%20Got%20To%20Belong%20To%20It%0A%204%20%20%20%20%201%200.0002268342%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20World%20War%20Now%0A%205%20%20%20%20%201%200.0004843583%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WORLD%20BEYOND%0A%206%20%20%20%20%201%200.0003400971%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20%20%20%20Women%20in%20Uniform%0A%207%20%20%20%20%201%200.0003876368%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20%20%20Winter%20Martyrium%0A%208%20%20%20%20%201%200.0006563044%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Wildest%20Dreams%0A%209%20%20%20%20%201%200.9984904258%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20%20%20Where%20Eagles%20Dare%0A10%20%20%20%20%201%200.0005456218%20Iron%20Maiden%20%20%20%20%20%20%20When%20Two%20Worlds%20Collide%0A%23%20…%20with%202%2C782%20more%20rows%0A%0A%23%20En%20le%20visualisant%20%0A%0Atidy_model_m_gamma%20%25%3E%25%0A%20%20ggplot(aes(band%2C%20gamma))%20%2B%0A%20%20geom_boxplot(show.legend%20%3D%20FALSE)%20%2B%0A%20%20facet_wrap(~%20topic%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Corpus%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%20698%20songs%20by%20Iron%20Maiden%2C%20Kreator%2C%20Mot%C3%B6rhead%20and%20Pantera%22)” message=”” highlight=”” provider=”manual”/]

Ici, notre modèle ne permet pas de déterminer quel groupe génère quel topic. En effet, chaque morceau génère un pourcentage de participation à plusieurs topics. Par exemple, la chanson “Childhood’s End” de Iron Maiden apparaît sur 3 des 4 topic :

[pastacode lang=”R” manual=”tidy_model_m_gamma%20%25%3E%25%0A%20%20filter(song%20%3D%3D%20%22Childhood’s%20End%22)%20%25%3E%25%0A%20%20ggplot(aes(topic%2C%20gamma%2C%20fill%20%3D%20factor(topic)))%20%2B%0A%20%20geom_col()%20%2B%0A%20%20%23facet_wrap(~%20factor(topic)%2C%20scales%20%3D%20%22free%22)%20%2B%0A%20%20scale_fill_viridis_d(name%20%3D%20%22Topic%22)%20%2B%20%0A%20%20coord_flip()%20%2B%20%0A%20%20labs(x%20%3D%20%22Topic%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Topic%20modeling%20of%20Childhood’s%20End%20%22)%20%2B%20%0A%20%20theme_minimal()” message=”” highlight=”” provider=”manual”/]

Pour nous représenter plus globalement ce classement, nous pouvons regarder du côté de tous les scores gamma :

[pastacode lang=”R” manual=”tidy_model_m_gamma%20%25%3E%25%0A%20%20ggplot(aes(gamma))%20%2B%20%0A%20%20geom_histogram(bins%20%3D%20100)%20%2B%20%0A%20%20scale_y_log10()%20%2B%20%0A%20%20labs(x%20%3D%20%22Gamma%20score%22%2C%20%0A%20%20%20%20%20%20%20y%20%3D%20%22Count%22%2C%20%0A%20%20%20%20%20%20%20title%20%3D%20%22Gamma%20score%20in%20metal%20songs%20topic%20modeling%22)%20%2B%20%0A%20%20theme_minimal()” message=”” highlight=”” provider=”manual”/]

Comment lire ce graphique ? Lorsqu’un topic model offre un découpage bien tranché, les deux modes sont autour de 0 et de 1. En effet, un document classé de manière nette dans 4 topics va afficher des scores gamma, par exemple, de 0.99 / 0.001 / 0.002 / 0.007. Un document “mal classé” va plutôt afficher des scores de 0.30 / 0.20 / 0.25 / 0.25. Vous avez compris l’idée 🙂

Bien, mais alors, quel intérêt de ce topic modeling s’il n’est pas tranché ? Eh bien, imaginons que vous soyez un moteur de recherche (très (très)) rudimentaire qui conseille des chansons, par similarité de parole. Vous pourriez simplement proposer de filtrer les chansons avec du topic modeling :

[pastacode lang=”R” manual=”chanson_de_depart%20%3C-%20%22Where%20Eagles%20Dare%22%0Aconseil%20%3C-%20function(chanson)%20%7B%0A%20%20topic%20%3C-%20filter(tidy_model_m_gamma%2C%20song%20%3D%3D%20chanson)%20%25%3E%25%0A%20%20%20%20pull(topic)%0A%20%20filter(tidy_model_m_gamma%2C%20topic%20%3D%3D%20topic)%20%25%3E%25%0A%20%20%20%20arrange(desc(gamma))%20%25%3E%25%0A%20%20%20%20unique()%20%25%3E%25%0A%20%20%20%20slice(1%3A5)%20%25%3E%25%0A%20%20%20%20select(band%2C%20song)%0A%7D%0A%0Aconseil(%22Where%20Eagles%20Dare%22)%0A%23%20A%20tibble%3A%205%20x%202%0A%20%20%20%20%20%20%20%20%20band%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20song%0A%20%20%20%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%0A1%20Iron%20Maiden%20Rime%20of%20The%20Ancient%20Mariner%0A2%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20The%20Book%20Of%20Souls%0A3%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20Replicas%20Of%20Life%0A4%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20The%20Legacy%0A5%20%20%20%20%20Pantera%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Shedding%20Skin%0A%0Aconseil(%22Hordes%20of%20Chaos%22)%0A%20A%20tibble%3A%205%20x%202%0A%20%20%20%20%20%20%20%20%20band%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20song%0A%20%20%20%20%20%20%20%20%3Cchr%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cchr%3E%0A1%20Iron%20Maiden%20Rime%20of%20The%20Ancient%20Mariner%0A2%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20The%20Book%20Of%20Souls%0A3%20%20%20%20%20Kreator%20%20%20%20%20%20%20%20%20%20%20%20Replicas%20Of%20Life%0A4%20Iron%20Maiden%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20The%20Legacy%0A5%20%20%20%20%20Pantera%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Shedding%20Skin” message=”” highlight=”” provider=”manual”/]

Alors, ça ne vous donne pas envie de vous lancer dans le text-mining ? Parfait, vous êtes prêt à en parler 😉

Source :
+ Text Mining with R
+ Learning Social Media Analytics with
+ Online Inference of Topics with Latent Dirichlet Allocation


Commentaires


À lire également

Nos formations Certifiantes à R sont finançables à 100% via le CPF

Nos formations disponibles via moncompteformation.gouv.fr permettent de délivrer des Certificats reconnues par l’état, enregistrées au répertoire spécifique de France Compétences. 3 niveaux de certifications existent :

Contactez-nous pour en savoir plus.