Advertisement
Guest User

Untitled

a guest
Jan 16th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.75 KB | None | 0 0
  1. ---
  2. title: "Séance de travaux pratiques 5 : Défi analyse d'opinion (IMDB)"
  3. output:
  4. html_document: default
  5. html_notebook: default
  6. ---
  7.  
  8. ** **
  9.  
  10. #### [Tutoriaux et introductions à R](https://cran.r-project.org/doc/manuals/r-release/R-intro.pdf)
  11.  
  12. * Livre en français de [Vincent Goulet](https://cran.r-project.org/doc/contrib/Goulet_introduction_programmation_R.pdf)
  13.  
  14. * R pour les débutants [Emmanuel Paradis](https://cran.r-project.org/doc/contrib/Paradis-rdebuts_fr.pdf)
  15.  
  16.  
  17. * Liste des [fonctions de base](https://stat.ethz.ch/R-manual/R-devel/library/base/html/00Index.html).
  18.  
  19. ** **
  20. Ce TP sera réalisé en plus grande autonomie que les précédents et les codes seront moins guidés. La note attribuée au rendu de ce TP aura un poids plus important que celles concernant les TPs précédents.
  21.  
  22. Le rendu comportera en particulier
  23.  
  24. - Un fichier intitulé "Rendu_TP5.html" correspond au document "Rendu_TP5.Rmd" complété et commenté. Ce fichier décrira le modèle de prédiction choisi pour le défi de classification.
  25.  
  26. - Un "objet" R sauvé sous forme compressée contenant le modèle choisi pour être évalué par l'enseignant sur l'ensemble test. Le fichier compressé devra être sauvé sous le format RDS ou hdf5. Son intitulé devra être personnalisé sous la forme "my_login_bestmodel.ext" ("ext" désigne une extension particulière, "hdf5" ou "rds", voir les exemples à la fin du TP).
  27.  
  28. - Un script R, contenant une fonction permettant d'évaluer le modèle (voir les exemples à la fin du TP).
  29.  
  30.  
  31. ** **
  32.  
  33. L'objectif de cette séance de travaux pratiques est de répondre à un défi de classification portant sur l'analyse d'opinion à partir de documents textuels ("natural language processing").
  34.  
  35. Les documents analysés sont des critiques de films écrites par des utilisateurs du site web "Internet Movie Data Base" (IMBD). À chaque critique est associée une note donnée par l'utilisateur du site. Seules les notes extrêmes ont été conservées et converties en valeurs binaires représentant des opinions positives ou négatives envers le film.
  36.  
  37. La base de données comporte 50000 critiques de films. Chaque document est prétraité et représenté sous le format d'un _sac de mots_ ("bag of words") pour en faciliter l'analyse. Un sac de mots peut être vu comme une représentation des termes d'un document partir de leur fréquence d'occurrence.
  38.  
  39.  
  40. Dans cette séance de TP, nous téléchargerons un échantillon de la base de données et constituerons un échantillon comportant 10000 documents annotés. Chaque document est associée à une évaluation traduisant une opinion positive (valeur 0) ou négative (valeur 1) des utilisateurs.
  41.  
  42. Le but de ce TP est de prédire le mieux possible l'opinion ou le _sentiment_ des utilisateurs à partir des fréquences d'occurrence de certains termes apparaissant dans les textes. Un échantillon de test comportant 5000 critiques indépendantes sera utilisé par l'enseignant pour évaluer la méthode sélectionnée.
  43.  
  44.  
  45.  
  46. ```{r}
  47. library(magrittr)
  48. library(keras)
  49. ```
  50.  
  51. #### Index de termes et sacs de mots.
  52.  
  53. À chaque terme d'un texte (aussi appelé _document_) est associé une fréquence d'apparition globale dans la base de données IMBD. Les termes sont référencés dans un index à l'aide d'un nombre indiquant leur rang d'apparition dans la base de données. Dans l'index, les termes sont triés du plus fréquent au moins fréquent.
  54.  
  55. L'index peut être consulté à partir de la bibliothèque `keras`, sous forme de liste dont les attributs sont les termes utilisés dans la base de données. Pour cela, on utlise la fonction `dataset_imdb_word_index()`. L'index est illustré ci-dessous.
  56.  
  57. Le numéro trouvé dans l'index correspond au rang d'un terme donné. Pour trouver le mot le plus fréquemment utilisé dans l'IMDB, on peut chercher le terme dont la valeur est égale au rang 1.
  58.  
  59.  
  60. ```{r}
  61. index <- keras::dataset_imdb_word_index()
  62. #names(index[index == 1])
  63. ```
  64.  
  65. Sans surprise, le terme le plus fréquemment utilisé est l'article "the". Sa valeur dans l'index est donc égale à 1.
  66.  
  67. L'article "the" se retrouve à la position 85976 dans l'index. L'index n'est donc pas ordonné par la fréquence des termes, mais par une permutation arbitraire. Nous pouvons utiliser la fonction `order()` pour réordonner l'index et trouver les 10 termes les plus utilisés dans l'ensemble des critiques de films.
  68.  
  69. ```{r}
  70. o <- as.numeric(index) %>% order()
  71. index[o[1:10]] %>% names()
  72. ```
  73.  
  74. Nous voyons qu'il s'agit d'articles, de prépositions ou de termes non-informatifs, comme par exemple, des éléments extraits des balises html. Il sera peut-être préférable de filtrer les termes les plus utilisés. L'entrée 49 correspond au terme "good", nous nous arrêtons juste avant et nous filtrons les 48 premières entrées.
  75.  
  76. Pour réduire le temps de calcul, nous conservons les 2000 termes les plus fréquents. Dans la suite, chaque document sera représenté par une suite de fréquences de termes représentés par les codes de l'index. Le jeu de données résultant de cette étape est nommé `ìmbd`.
  77.  
  78. ```{r}
  79. imbd <- keras::dataset_imdb(path = "imdb.npz",
  80. num_words = 2048,
  81. skip_top = 48)
  82. ```
  83.  
  84. Les données enregistrées dans l'objet `imbd` se présentent sous la forme de listes de documents (train et test). On utilisera les "double-crochets" ou le symbole dollar pour accéder aux attributs de ces listes.
  85.  
  86. ```{r}
  87. summary(imbd)
  88. ```
  89.  
  90.  
  91. Par exemple le document numéro 13 dans l'ensemble d'apprentissage est lu de la manière suivante.
  92.  
  93. ```{r}
  94. document13 <- imbd$train$x[[13]]
  95. document13
  96. ```
  97.  
  98. Nous voyons que le terme d'indice 2 n'a pas été filtré correctement (nous l'enlèverons plus tard). Les fréquences des termes apparaissant dans le document 13 peuvent être données par la fonction `table()`. Cette fonction utilise l'ordre alphabétique pour représenter les comptages de chaque terme.
  99.  
  100. ```{r}
  101. index[o[document13]] %>% names() %>% table()
  102. ```
  103.  
  104. Le document 13 contient les termes "beautiful", "happy", "interesting", "love", "laugh" mais aussi "rubbish" et "sad". On peut penser qu'il est plutôt associé à une opinion positive (valeur 0). Cela se vérifie en affichant la variable $y$.
  105.  
  106.  
  107. ```{r}
  108. imbd$train$y[13]
  109. ```
  110.  
  111. Pour la suite, c'est à vous de jouer.
  112.  
  113.  
  114. ## Exercice : Défi "analyse de sentiments"
  115.  
  116. #### Lecture des données
  117.  
  118. * Ecrire une ligne de commande R permettant convertir le document 13 en un vecteur de longueur 2000, indiquant le nombre d'apparition de chacun des indices allant de 49 à 2048 dans ce document.
  119.  
  120.  
  121. ```{r}
  122. # comment 1
  123. help(sapply)
  124. lama<-sapply(49:2048, FUN = function(ind) sum(document13 == ind), simplify = TRUE, USE.NAMES = TRUE)
  125. sum(lama)
  126. ```
  127.  
  128.  
  129.  
  130. * Constituer un jeu de données comportant 10000 documents choisis pour moitié dans l'ensemble "train" et pour moitié dans l'ensemble "test" de l'IMBD. Techniquement nous le constituerons en 20 étapes, pour limiter l'impact sur la mémoire. Commenter et exécuter le code suivant
  131.  
  132.  
  133. ```{r}
  134. x_imbd <- NULL
  135.  
  136. for (i in 1:10){
  137.  
  138. x_imbd_500 <- NULL
  139.  
  140. for (j in (500*(i-1)+1):(500*i)){
  141.  
  142. # on ajoute le document que l'on veut de train
  143.  
  144. doc_temp <- imbd$train$x[[j]]
  145. x_imbd_500 <- rbind(x_imbd_500,
  146. sapply(49:2048,
  147. FUN = function(ind) sum(doc_temp == ind)))
  148.  
  149. if (j%%500 == 0) print(j) # ca rassure de voir un avancement ;)
  150. }
  151. x_imbd <- rbind(x_imbd, x_imbd_500)
  152. }
  153.  
  154. for (i in 1:10){
  155.  
  156. x_imbd_500 <- NULL
  157.  
  158. for (j in (500*(i-1)+1):(500*i)){
  159.  
  160. # on ajoute celui que l'on desire de test
  161.  
  162. doc_temp <- imbd$test$x[[j]]
  163. x_imbd_500 <- rbind(x_imbd_500,
  164. sapply(49:2048,
  165. FUN = function(ind) sum(doc_temp == ind)))
  166.  
  167. if (j%%500 == 0) print(j) # ca rassure
  168. }
  169. x_imbd <- rbind(x_imbd, x_imbd_500)
  170. }
  171.  
  172. ```
  173.  
  174. * Que contient l'objet `x_imbd` ?
  175. Il contient des lignes associées aux données des documents
  176. * Pour représenter les classes 0 et 1 en format matriciel, on peut utiliser la fonction `to_categoretical()` de `keras`. C'est plus simple.
  177.  
  178. ```{r}
  179. y_imbd <- to_categorical(imbd$train$y[1:5000], 2)
  180. y_imbd <- rbind(y_imbd, to_categorical(imbd$test$y[1:5000], 2))
  181.  
  182. ```
  183.  
  184. Et voilà. On est en pleine forme et on dispose d'une base d'apprentissage comportant les fréquences d'apparition des mots de l'index pour 10000 documents (`x_train`) et les opinions des utilisateurs `y_train`. Le TP peut vraiment commencer.
  185.  
  186.  
  187. #### Etude d'association
  188.  
  189. Le but d'une étude d'association est d'identifier les termes les plus associés aux opinions positives ou négatives des utilisateurs. Pour cela, nous evaluons la correlation au carré entre l'occurrence de chaque terme et l'opinion de l'utilisateur (présence d'un 1). Il se peut que certaines valeurs de corrélation ne soient pas calculables à cause d'un écart-type nul. Cela arrive pour la 2000e valeur. Nous l'écarterons donc (il en restera 1999).
  190.  
  191. * Calculer le coefficient de corrélation au carré entre les fréquences d'apparition des termes de l'index et opinion des utilsateurs (1999 valeurs).
  192.  
  193. ```{r}
  194. # comment
  195. x <- x_imbd[,-2000]
  196. # x_imbd[les occurences, les mots]
  197. # comment
  198. y <- y_imbd[,1]
  199. length(y)
  200. # comment
  201. r2 <- cor(x,y)^2
  202.  
  203. ```
  204.  
  205.  
  206. * Montrer les termes dont la valeur d'association $r^2$ est supérieure à trois pourcent (0.03), puis supérieure à 0.02, et à 0.005. _Note_ : Il faut effectuer un décalage de 45 indices dans l'index pour trouver le codage correct (c'est un bug de keras).
  207.  
  208.  
  209. ```{r}
  210. # quelque chose à changer
  211. index[o[ which(r2 > 0.03) + 45 ]] %>% names()
  212. index[o[ which(r2 > 0.02) + 45 ]] %>% names()
  213. index[o[ which(r2 > 0.005) + 45 ]] %>% names()
  214. ```
  215.  
  216. * Dans quelles proportions les termes de valeur d'association $r^2$ supérieure à 0.02 apparaissent-ils dans les documents ? Représenter graphiquement ces proportions à l'aide d'un diagramme en barre.
  217.  
  218.  
  219. ```{r}
  220. # Calculer la frequence des termes realisant la condition
  221. freq <- x[, r2>0.02] %>% apply(2, mean)
  222.  
  223. # mots dans l'index et barplot
  224. names(freq) <- index[o[which(r2 > 0.02) + 45]] %>% names()
  225. barplot(freq, col = "lightblue", las = 2)
  226. ```
  227.  
  228.  
  229.  
  230. * Dans quelles proportions les termes de valeur d'association $r^2$ supérieure à 0.02 apparaissent-ils dans les documents **à connotation positive** ? Représenter graphiquement ces proportions à l'aide d'un diagramme en barre.
  231.  
  232.  
  233. ```{r}
  234. help(apply)
  235. # Calculer la frequence des termes realisant la condition
  236. freq <- x[y==0, r2>0.02] %>% apply(2, mean)
  237.  
  238. # mots dans l'index et barplot
  239. names(freq) <- index[o[which(r2 > 0.02) + 45]] %>% names()
  240. barplot(freq, col = "lightblue", las = 2)
  241. ```
  242.  
  243.  
  244. * Dans quelles proportions les termes de valeur d'association $r^2$ supérieure à 0.02 apparaissent-ils dans les documents **à connotation négative** ? Représenter graphiquement ces proportions à l'aide d'un diagramme en barre.
  245.  
  246.  
  247. ```{r}
  248. help(apply)
  249. # Calculer la frequence des termes realisant la condition
  250. freq <- x[y==1, r2>0.02] %>% apply(2, mean)
  251.  
  252. # mots dans l'index et barplot
  253. names(freq) <- index[o[which(r2 > 0.02) + 45]] %>% names()
  254. barplot(freq, col = "lightblue", las = 2)
  255. ```
  256.  
  257.  
  258.  
  259.  
  260. #### Modèles d'apprentissage
  261.  
  262.  
  263. * \`A l'aide des outils vus dans les séances précédentes, tels que _keras_, _lda_, _nnet_, ou d'autres bibliothèques de programmes que vous pourriez trouver dans R, ajuster des modèles d'apprentissage aux données contenues dans le TP : "x_imbd" et "y_imbd".
  264.  
  265. * Dans un tableau, décrire les performances des méthodes choisies pour des échantillons d'apprentissage et de test que vous aurez créés vous-mêmes. Les performances seront mesurées par les erreurs de classification et d'entropie (log loss).
  266. ```{r}
  267. accu <- NULL
  268. logloss <- NULL
  269. length(x)/2000
  270. ```
  271. * Sauver votre modèle dans un format compressé (RDS ou HDF5 pour `keras`). Remplacer la chaîne de caractère "my_login" par votre propre login ensimag.
  272.  
  273.  
  274. ```{r}
  275. # standard r packages:
  276. # saveRDS(model, file = "perutor_model.RDS")
  277.  
  278. #keras
  279. # save_model_hdf5(object = model, filepath = "perutor_model_keras.hdf5")
  280. ```
  281.  
  282.  
  283.  
  284. * Ecrire et appliquer une fonction appelée "prediction_finale" pouvant prendre par défaut en entrée une matrice appelé "x_ultime" de taille 5000 lignes et 2000 colonnes contenant des valeurs binaires et une matrice "y_ultime" de taille 5000 lignes et 2 colonnes contenant des valeurs binaires. Cette fonction devra prédire les classes contenues dans "y_ultime" à partir des données "x_ultime" en chargeant le modèle que vous aurez choisi pour le défi. Des exemples de fonctions sont décrits ci-dessous
  285.  
  286.  
  287. ```{r, include = FALSE}
  288. prediction_finale <- function(x_ultime = "x_ultime",
  289. y_ultime = "y_ultime",
  290. file_path = "perutor_model_keras.hdf5"){
  291. #Remplacer "my_login" par votre propre login ensimag.
  292.  
  293. require(magrittr)
  294.  
  295. #tests
  296. if (nrow(x_ultime) != 5000 | ncol(x_ultime) != 2000)
  297. stop("Dimensions de x incorrectes.")
  298.  
  299. if (nrow(y_ultime) != 5000 | ncol(xy_ultime) != 2)
  300. stop("Dimensions de y incorrectes.")
  301.  
  302. #if keras
  303. require(keras)
  304.  
  305. load_model_hdf5(filepath = file_path)
  306. model %>% evaluate(x_ultime, y_ultime)
  307. }
  308. ```
  309.  
  310. ```{r}
  311. # prediction_finale(x_test_imbd, y_test)
  312. ```
  313.  
  314. * *Note* : pour d'autres modèles que ceux _keras()_, on sauvera l'objet correspondant au modèle ajusté avec la fonction _save()_ ou _saveRDS()_. On écrira une fonction permettant de charger l'objet créé (_load()_) et lui appliquant la fonction _predict()_ dans le format spécifique à la classe du modèle choisi (_knn_, _nnet_, _lda_, etc).
  315.  
  316. Par exemple, si l'objet est de classe "nnet", on pourra s'inspirer des commandes suivantes pour sauver l'objet créé et écrire la fonction demandée.
  317.  
  318.  
  319. ```{r, include = FALSE}
  320. # Remplacer "my_login" par votre propre login ensimag.
  321. # saveRDS(mod_nnet, file = "perutor_bestmodel.RDS")
  322.  
  323. prediction_finale <- function(x_ultime = "x_ultime",
  324. y_ultime = "y_ultime",
  325. file_path = "perutor_bestmodel.RDS"){
  326. require(magrittr)
  327. #tests
  328. if (nrow(x_ultime) != 5000 | ncol(x_ultime) != 2000)
  329. stop("Dimensions de x incorrectes.")
  330.  
  331. if (nrow(y_ultime) != 5000 | ncol(xy_ultime) != 2)
  332. stop("Dimensions de y incorrectes.")
  333.  
  334. #if nnet
  335. require(nnet)
  336. mod_nnet <- readRDS(file = file_path)
  337. proba <- mod_nnet %>% predict(x_ultime)
  338. acc <- mean(y_ultime[,1] == (proba < 0.5))
  339. #logloss <- completer
  340. return(acc,logloss)
  341. }
  342. ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement