Partage
  • Partager sur Facebook
  • Partager sur Twitter

[COURS] Analysez vos données textuelles

Il serait bien de corriger le cours ou le mettre à jour

    2 novembre 2021 à 11:23:20

    Bonjour,

    1. En première partie de cours, il n'y a pas de pistes comment se procurer d'une jeu de données pour travailler avec. J'ai bien compris que partager la base de données est interdit à cause de droits d'auteurs. Par contre avec quoi va-t-on travailler? J'ai regardé sur le forum - il a pas mal de plaintes sur ce sujet et aucune solution.

    Il serait bien de partager le code pour scraper les données, soit donner les pistes comment charger un jeu de données de texte dans la bibliothèque nltk. Et non pas juste le mentionner comme il est fait dans le cours, "téléchargez dans la bibliothèque nltk, c'est simple". Eh non. Si c'était simple, je n'avais pas besoin de passer ce cours.

    2. En troisième partie de cours, on utilise le sous-module "ap" de module "tools". Sauf que ce module est obsolète (deprecated). https://pypi.org/project/tools/

    c'est normal, ça arrive que les module viellissent et sont supprimés ou remplacés. Alors il serait bien de mettre à jour le code correspondant. Sinon il devient impossible de suivre le cours, sauf pour les étudiants qui savent déjà comment ça fonctionne et qui n'ont donc pas forcement besoin de ce cours.

    Merci!

    • Partager sur Facebook
    • Partager sur Twitter

    Veronika Berezhnaia

      19 janvier 2022 à 6:53:31

      Bonjour,

      je partage entièrement l'avis de Veronika (sans compter les nombreuses fautes d'orthographe...).

      Ce cours n'est pas du tout pédagogique : pré-requis non dits nécessaires (comme scrapper les données), des TPs qui devraient être là pour nous aider à comprendre la démarche et comment utiliser les outils, alors qu'on passe son temps à corriger les bugs de code ou à trouver les bons modules...

      Merci de repenser ce cours !

      • Partager sur Facebook
      • Partager sur Twitter
        23 janvier 2022 à 17:06:26

        Par la remarque sur l'orthographe je deduis que vous m'avez pris pour quelqu'un qui avait étudié la grammaire frnçaise pendant 11 ans à l'école durant toute mon enfance et l'adolescence, comme le font les locuteurs natifs français (French native speakers). Ou au moins les gens qui font leur études d'école en France. Hah, je suis flattée alors :) Mais en fait non, c'est juste une illusion : je n'ai pas investi 11 ans dans l'apprentissage de grammaire française.

        L'orthographe n'est pas sacrée, elle peut aussi être repensée et modifiée. Comme ce cours :) Déjà des bons efforts dans cette direction étaient fait en 1990, puis en 2018. Une piste géniale, qu'on ne peut que saluer et encourager. Et un avis est surtout le sens transmi et non pas l'orthographe.

        Sinon, sur le fond de sujet - peut-être le cours est abandonné par les créateurs, nous avons beau de crier dans le vide. Tous les cours listés avec ce proffesseur datent de quelques ans. Au plus probablement, il ne coopère plus avec Openclassroms, il a quitté cet organisme.

        Sauf si quelqu'un d'autre qui est maintenant responsable pour le bon fonctionnement de Parcours Data Scientist, pourrait assurer que les étudiants sont munis de matériel de qualité.

        • Partager sur Facebook
        • Partager sur Twitter

        Veronika Berezhnaia

          28 janvier 2022 à 1:43:19

          VeronikaBerezhnaia a écrit:

          Par la remarque sur l'orthographe je deduis que vous m'avez pris pour quelqu'un qui avait étudié la grammaire frnçaise pendant 11 ans à l'école durant toute mon enfance et l'adolescence, comme le font les locuteurs natifs français (French native speakers). Ou au moins les gens qui font leur études d'école en France. Hah, je suis flattée alors :) Mais en fait non, c'est juste une illusion : je n'ai pas investi 11 ans dans l'apprentissage de grammaire française.

          L'orthographe n'est pas sacrée, elle peut aussi être repensée et modifiée. Comme ce cours :) Déjà des bons efforts dans cette direction étaient fait en 1990, puis en 2018. Une piste géniale, qu'on ne peut que saluer et encourager. Et un avis est surtout le sens transmi et non pas l'orthographe.

          Sinon, sur le fond de sujet - peut-être le cours est abandonné par les créateurs, nous avons beau de crier dans le vide. Tous les cours listés avec ce proffesseur datent de quelques ans. Au plus probablement, il ne coopère plus avec Openclassroms, il a quitté cet organisme.

          Sauf si quelqu'un d'autre qui est maintenant responsable pour le bon fonctionnement de Parcours Data Scientist, pourrait assurer que les étudiants sont munis de matériel de qualité.

          Bonjour Veronika,

          je me suis très mal exprimée dans mon précédent message et je m'en excuse !!!

          Les fautes d'orthographe concernaient bien sur le cours et pas du tout votre message !!!

          Je suis sincèrement désolée de ce malentendu. 



          • Partager sur Facebook
          • Partager sur Twitter
            1 février 2022 à 19:18:43

            Alors je vous prie d'accepter mes excuses également! Pardon! Si j'avais un ton pas gentil, incorrect, imposant - toutes mes excuses.
            • Partager sur Facebook
            • Partager sur Twitter

            Veronika Berezhnaia

              30 mars 2022 à 11:09:06

              Bonjour,
              Vos commentaires vont m'éviter de perdre un temps précieux, merci!
              J'en déduis donc que le plus simple est de zapper les parties techniques du cours et de faire ses armes sur les projets directement...

              Dommage, il est toujours utiles de faire de petits TP rapides pour prendre les choses en main.

              Dommage que le cours ne semble donc pas maintenu... On est quand même sur un métier d'actualité ...

              • Partager sur Facebook
              • Partager sur Twitter
                25 avril 2022 à 11:20:35

                Je partage les avis qui ont été exprimés jusqu'à présent. Malheureusement, ça semble être une constante pour tous les cours de Yannis Chaouche que j'ai pu suivre jusqu'à présent : TP non-reproduisibles, nombreuses fautes dans le cours et les énoncés (grammaticales ou erreurs pures et simples), approche pédagogique mal pensée etc. etc.
                Il serait pertinent de revoir ce cours (parmi d'autres) en profondeur...

                -
                Edité par NathanLorber 25 avril 2022 à 11:20:56

                • Partager sur Facebook
                • Partager sur Twitter
                  9 mai 2022 à 18:59:39

                  Bonjour,

                  comme les autres étudiants, je constate que l'obtention des paroles de rap n'est pas du tout documentée. Même si ça ne sert pas tant que ça pour la suite, j'ai pris l'initiative d'écrire un scraper qui extrait la liste des rappeurs français de Wikipédia, puis qui scrape Genius.com pour récupérer les paroles des chansons.

                  Je vous fournis ici mon code.

                  1/ Créer un fichier extract_rappers.py et copier le code ci-dessous:

                  import numpy as np
                  import os
                  import scrapy
                  
                  from scrapy.crawler import CrawlerProcess
                  from scrapy.utils.project import get_project_settings
                  
                  project_settings = get_project_settings()
                  project_settings["FEEDS"] = { "rappeurs.json": {"format": "json"} }
                  
                  class RapperSpider(scrapy.Spider):
                      name = 'rappeurs français'
                      start_urls = [
                          'https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Rappeur_fran%C3%A7ais',
                      ]
                  
                      def parse(self, response):
                          for category_group in response.css('div.mw-category-group'):
                              for letter_group in category_group.xpath('ul/li/a'):
                         
                                  yield {
                                      'rappeur': letter_group.css('::text').get()
                                  }
                  
                          next_page = response.xpath('//div[@id="mw-pages"]/a').attrib["href"]
                          if next_page is not None:
                              yield response.follow(next_page, self.parse)
                  
                      def stop(self):
                          self.crawler.engine.close_spider(self, 'timeout')
                  
                  process_1 = CrawlerProcess(settings=project_settings )
                  process_1.crawl(RapperSpider, start_urls=["https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Rappeur_fran%C3%A7ais"])
                  process_1.start(stop_after_crawl=True)

                  2/ Créer un autre fichier nommé extract_single_rapper_songs.py et insérer le code ci-dessous

                  import scrapy, json, os, re, requests, sys
                  import numpy as np
                  
                  from scrapy.crawler import CrawlerRunner
                  from scrapy.utils.project import get_project_settings
                  from twisted.internet import reactor
                  
                  # Ici lire les rappeurs du fichier rappeurs.json
                  rappeurs = []
                  for dico in json.load(open('rappeurs.json')):
                      rappeurs.append(dico["rappeur"])
                  
                  # Supprimer les parenthèses (exemple : "Abd al Malik (artiste)") + éventuels doublons + trier
                  rappeurs = list(map (lambda name : re.sub(pattern="\((.*)\)",repl='',string=name).rstrip()  , rappeurs  ) )
                  rappeurs = list(dict.fromkeys(rappeurs))
                  rappeurs.sort()
                  
                  def get_songs_of_rapper( name ):
                      """ Fonction permettant d'aller lire sur genius.com la liste des chansons attribuées à ce rappeur """
                  
                      GENIUS_CLIENT_ACCESS_TOKEN = "<votre client access token de Genius.com>"
                  
                      rx = requests.get("https://api.genius.com/search?q="+ name.replace(' ','%20'), headers={"Authorization":"Bearer " + GENIUS_CLIENT_ACCESS_TOKEN})
                  
                      only_unique_artist_query_songs = [ e for e in rx.json()["response"]["hits"] if e["result"]["artist_names"] == name ]
                      if only_unique_artist_query_songs == []:
                          return []
                      artist_api_path = only_unique_artist_query_songs[0]["result"]["primary_artist"]["api_path"]
                  
                      rx = requests.get("https://api.genius.com" + artist_api_path +"/songs?sort=popularity&per_page=50&page=1", headers={"Authorization":"Bearer " + GENIUS_CLIENT_ACCESS_TOKEN})
                  
                      # Ne garder que les morceaux dont le rappeur est l'unique artiste
                      artist_songs = [ e for e in rx.json()["response"]["songs"] if e["primary_artist"]["api_path"] == artist_api_path ]
                  
                      songs = list(map( lambda e : ( e["title"], e["path"] ) ,artist_songs) )
                  
                      return songs
                  
                  # Créer un répertoire "/paroles" pour contenir les fichiers des paroles
                  if os.path.isdir("paroles") == False:
                      path = os.path.join(os.curdir, "paroles")
                      os.mkdir(path)
                  
                  # Définition d'un Spider Scrapy custom (pour extraire les paroles de N chansons d'un même rappeur)
                  class SongSpider(scrapy.Spider):
                      name = 'paroles de chansons'
                  
                      def __init__(self, song_paths=[], *args, **kwargs):
                          super(SongSpider, self).__init__(*args, **kwargs)
                          self.start_urls = ["https://genius.com" + song_path for song_path in song_paths]
                  
                      def parse(self, response):
                          """ Parser le fichier HTML de sorte à extraire les paroles """
                          song_lyrics = []
                          for lyrics_container in response.xpath("//div[@data-lyrics-container='true']"):
                              for highlighted_verse in lyrics_container.xpath("a"):
                                  song_lyrics += highlighted_verse.xpath("span//text()").getall()
                              
                              song_lyrics += lyrics_container.xpath("text()").getall()
                         
                          yield {
                              response.url.split("/")[-1] : song_lyrics
                          }
                  
                  
                  offset = int(sys.argv[1])
                  
                  if offset >= len(rappeurs): exit()
                  
                  rappeur_name = rappeurs[offset]
                  
                  songs_of_a_rapper = get_songs_of_rapper( rappeur_name )
                  
                  if songs_of_a_rapper == []:
                      exit()
                  
                  project_settings = get_project_settings()
                  project_settings["FEEDS"] = { "paroles/" + rappeur_name + ".json": {"format": "json"} }
                  
                  runner = CrawlerRunner(settings=project_settings)
                  
                  song_paths_of_a_rapper = list(np.array(songs_of_a_rapper).T[1])
                  runner.crawl(SongSpider, song_paths=song_paths_of_a_rapper )
                  
                  deferred = runner.join()
                  
                  deferred.addBoth(lambda _: reactor.stop())
                  reactor.run()

                  3/ Se connecter à genius.com, et créer un compte (gratuit).

                  Aller sur leur API Client management page, et créer un client (plus d'infos ici : https://docs.genius.com/ ).

                  Cliquez sur "Generate Access Token" et en sauvegardez le client access token sur un bloc-note.

                  4/ Mettez à jour le client access token dans le fichier extract_single_rapper_songs.py

                  Cela se fait en remplaçant la valeur "<votre client access token de Genius.com>" par votre client access token pour la variable GENIUS_CLIENT_ACCESS_TOKEN. (ligne 23)

                  5/ Voilà, c'est prêt. Il ne vous reste plus qu'à exécuter le fichier suivant (nommez-le "install.py" par exemple):

                  import os, json
                  
                  os.system("python extract_rappers.py")
                  
                  rappeurs = []
                  for dico in json.load(open('rappeurs.json')):
                      rappeurs.append(dico["rappeur"])
                  
                  for idx, rappeur_name in enumerate(rappeurs):
                      os.system("python extract_single_rapper_songs.py "+str(idx))


                  Mon code n'est pas du tout optimisé ni commenté convenablement, mais ça devrait marcher. Une exécution de python extract_single_rapper_songs.py <idx> devrait aller chercher toutes les paroles du rappeur index <idx>. Malheureusement, j'ai dû boucler sur tous les rappeurs au lieu de faire ça en une seule fois, car je ne connais pas trop scrapy, et je n'ai pas trop le temps de comprendre pourquoi plusieurs CrawlerRunner s'interbloquent entre eux. Je me doute que c'est dû à twisted.internet.reactor, mais bon, le code quick&dirty fait ce qu'on lui demande.

                   6/ Le code du TP devrait être à peu près celui-là:

                  import os, json, re
                  import pandas as pd
                  import matplotlib.pyplot as plt
                  import nltk
                  
                  files_name = os.listdir("paroles")
                  os.chdir("paroles")
                  
                  # Dictionnaire contenant 
                  # - en clé : le nom du rappeur
                  # - en item : une liste de tous les couplets de toutes ses chansons 
                  artistes = {}
                  
                  for file_name in files_name:
                      rappeur_songs = json.load(open(file_name))
                  
                      lyrics_of_a_single_rapper = []
                      for song in rappeur_songs:
                          song_title, song_lyrics = list(song.items())[0]
                          song_lyrics = list(map(  lambda str: re.sub( "\[(.*)\]", '', str ).strip(),  song_lyrics ))
                          song_lyrics = [ verse for verse in song_lyrics if len(verse) > 0 ]
                          lyrics_of_a_single_rapper += song_lyrics
                  
                      artistes[ file_name[0:-5] ] = lyrics_of_a_single_rapper 
                  
                  
                  words_used_by_rappeurs = {}
                  tokenizer = nltk.RegexpTokenizer(r'\w+')
                  for rappeur in artistes.keys():
                      words_used_by_rappeurs[rappeur] = []
                  
                      for verse in artistes[rappeur]:
                          words_used_by_rappeurs[rappeur] +=  tokenizer.tokenize(verse.lower())   
                  
                  single_words_used_by_rappeurs = {}
                  for rappeur in words_used_by_rappeurs.keys():
                      single_words_used_by_rappeurs[rappeur] = list(dict.fromkeys(words_used_by_rappeurs[rappeur]))
                   
                  lexical_variety_of_rappeurs = {}
                  for rappeur in words_used_by_rappeurs.keys():
                      lexical_variety_of_rappeurs[rappeur] = len (single_words_used_by_rappeurs[rappeur] ) / len(words_used_by_rappeurs[rappeur])
                  
                  ### Obtenir le classement des artistes avec le plus de variété lexicale
                  df_lexical_variety =pd.DataFrame( index=lexical_variety_of_rappeurs.keys(), data=lexical_variety_of_rappeurs.values(), columns=["variété lexicale"] )
                  df_lexical_variety_sorted = df_lexical_variety.sort_values(by="variété lexicale", ascending=False)
                  
                  ### Afficher le classement des artistes avec le plus de variété lexicale
                  fig = plt.figure(figsize=(25,5))
                  plt.bar(height=df_lexical_variety_sorted[0:20].values.T[0], x=df_lexical_variety_sorted[0:20].index )
                  
                  
                  ### Mots les plus utilisés par rappeur
                  sw = set()
                  sw.update(tuple(nltk.corpus.stopwords.words('french')))
                  sw.update(["a","ça","va","quand","comme"])
                  
                  most_used_words = {}
                  for rappeur in words_used_by_rappeurs.keys():
                  
                      single_words = [ e for e in words_used_by_rappeurs[rappeur] if e not in sw ]
                  
                      most_used_words[rappeur] = [ a for a, in pd.DataFrame(single_words).value_counts().index.values ]

                  Christophe

                  • Partager sur Facebook
                  • Partager sur Twitter
                    22 juin 2022 à 15:01:23

                    Il serait vraiment pas mal d'avoir un embryon du début d'une ébauche d'exemple pour les TPs de ce cours. Comme indiqué ci-dessus, pour ceux pour qui c'est une première que de traiter du texte, le premier tp est un peu un écueil...

                    N'existe-il pas une base de données plus simple que le scrapping proposé dans le cours pour expliquer les différents principes et rendre le cours plus interactif??? C'est vraiment dommage

                    -
                    Edité par AmauryLecoq 22 juin 2022 à 15:04:41

                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 juillet 2022 à 11:11:15

                      Je suis d'accord à propos des paroles de rap, j'ai tout de suite laissé tomber et je me suis fait mon propre corpus à partir de discours politiques mais j'ai perdu du temps et ce n'était pas aussi intéressant d'un point de vue pédagogique...

                      J'ai des remarques à faire également sur la partie Représentez votre corpus en "bag of words" :

                      1) je trouve que la structure du cours n'est pas claire : le bag-of-words, l'utilisation de n-grams et le TF-IDF semble en première lecture des étapes ou des façons de faire différentes alors qu'on peut utiliser le TF-IDF sur des n-grams. Une structure plus claire serait :

                      •  qu'est-ce qu'un bag of words ou bags of n-grams ? Introduire d'abord le principe de n-grams puis insister sur le fait qu'avec n=1 on appelle ça "bag of words"
                      • "pondérer l'importance de chaque n-grams" , découpée elle-même en : 1)la probabilité de co-occurence 2) TF-IDF

                      2) Reprendre absolument les formules poids=fréquence du terme×indicateur similarité et poids=frequence du n-gram×idf(n-gramme) qui ne sont  pas claires. Dans certains autres cours de machine learning, chaque item est bien défini et a sa propre notation. Ici,on utilise "poids" pour deux choses différentes, on ne précise pas si "fréquence" signifie "fréquence dans le document" ou "fréquence dans le corpus", etc. Ça pourrait donner :

                      On note W le poids d'un n-gram G dans un document D : W(G,D) = TF(G,D) * S avec

                      TF(G,D) : la fréquence du n-gram G dans le document D

                      S : un indice de similarité à travers les autres corpus

                      Dans le cas particulier de la méthode TF-IDF, on choisit l'Inverse Document Frequency comme indice de similarité. On a donc :

                      S = IDF(G) c'est-à-dire l'Inverse Document Frequency du n-gram G dans tout le corpus qui peut s'écrire ainsi :

                      IDF(G) = log( N / n(G) ) avec  N = le nombre total de documents dans le corpus  et n(G) = le nombre de documents dans lesquels le n-gram G apparaît.

                      Notre poids devient : W(G,D) = TF(G,D) * IDF(G) = TF(G,D) * log ( N / n(G) ) et c'est ce poids qui est une feature souvent appelée TF-IDF(G,D). Et qui n'est pas une soustraction de TF et IDF, d'ailleurs.

                      Si j'ai fait une erreur, n'hésitez pas à me corriger ;)

                      Sinon, la page wikipédia peut éclaircir les esprits : https://fr.wikipedia.org/wiki/TF-IDF

                      Y a-t-il vraiment quelqu'un chez OpenClassRooms qui regarde nos commentaires dans l'optique d'améliorer les cours ? Il serait intéressant d'avoir un lien vers un formulaire de remarques sur chaque page de cours. On pourrait catégoriser en : fautes d'orthographes, propositions, ressenti, etc.

                      Merci !

                      • Partager sur Facebook
                      • Partager sur Twitter

                      [COURS] Analysez vos données textuelles

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown