About Me

My photo
Just wasting time sharing knowledge about, Big Data and Analytics

Sep 26, 2013

Construire un moteur de reco simple avec R (1/2)

Construire un moteur de recherche

On va montrer comment on peut construire un moteur de recommandation simple en utilisant les outils de Textmining.
Cette construction se fera en deux temps :
  • On construit un moteur de recherche pour identifier par exemple, dans la base de données les éléments les plus proches de sa requête
  • On applique un modèle naïf de probabilité pour faire des recommandations.
J'ai aucune vraie formation sur la question et l'aide d'un linguiste et d'un vrai développeur me serait utile pour développer une vraie appli qui réponde à cette problématique.
On peut donc considérer qu'il s'agit ici de bases théoriques et de grands principes pouvant y aider.
Considérer les données suivantes :
rm(list = ls())
setwd("./Tutoriels/MoteurRecherche/")
## Error: impossible de changer de répertoire de travail
achat1 <- "Livres : Milan Kundera (la vie est ailleurs), Musique : Leonard Cohen"
achat2 <- "Livres : La liste de mes envies, Guide touristique Brno, Milan, Vienne, Prague"
achat3 <- "Musique: Gainsbourg, Trenet, Aznavour, vivaldi, Mozart, Vienne"
achat4 <- "Les oraux de Littérature et mathématique en clase prépa."
achat5 <- "Livres : Milan Kundera (l'immortalité), Musique : Nina Simone, Théâtre : Jacques et son maître"
Que l'on agrége dans une liste fourre-tout. On peut imaginer ici qu'il s'agit d'une base de données (non structurée) qui contienne à peu près tous les commentaires faits par des clients.
fourre_tout <- list(achat1, achat2, achat3, achat4, achat5)
N <- length(fourre_tout)
names(fourre_tout) <- paste0("achat", c(1:N))
Pour l'exercice, disons qu'un client vient sur le site et recherche
req <- "Milan Kundera"
Tout l'exercice consiste donc à pouvoir faire correspondre cette recherche avec les éléments qu'il y a déjà dans la base de données et de faire resortir les éléments qui s'en rapprochent le plus pour faire des recommandations.

Construction d'un corpus

library(tm)
library(Snowball)

Corpus <- VectorSource(c(fourre_tout, req))
Corpus$Names <- c(names(fourre_tout), "recherche")
monCorpus <- Corpus(Corpus)
monCorpus
## A corpus with 6 text documents
Le corpus constitué, on applique tous les traitements de standardisation de text mining afin de favoriser les recherches de corrélation.
Traitement
monCorpus <- tm_map(monCorpus, removePunctuation)
monCorpus <- tm_map(monCorpus, stemDocument)
monCorpus <- tm_map(monCorpus, tolower)
monCorpus <- tm_map(monCorpus, stripWhitespace)
monCorpus$achat1
## livr milan kundera la vie est ailleur musiqu leonard cohen

Modélisation

Construire un modèle de recommandation suppose de pouvoir associer chaque mot de chaque corpus à un autre mot d'un autre corpus. La matrice de documents est faite pour çà.
doc.tdm <- TermDocumentMatrix(monCorpus)
inspect(doc.tdm)
## A term-document matrix (35 terms, 6 documents)
## 
## Non-/sparse entries: 45/165
## Sparsity           : 79%
## Maximal term length: 12 
## Weighting          : term frequency (tf)
## 
##               Docs
## Terms          achat1 achat2 achat3 achat4 achat5 recherche
##   ailleur           1      0      0      0      0         0
##   aznavour          0      0      1      0      0         0
##   brno              0      1      0      0      0         0
##   clase             0      0      0      1      0         0
##   cohen             1      0      0      0      0         0
##   envi              0      1      0      0      0         0
##   est               1      0      0      0      0         0
##   gainsbourg        0      0      1      0      0         0
##   guid              0      1      0      0      0         0
##   jacqu             0      0      0      0      1         0
##   kundera           1      0      0      0      1         1
##   leonard           1      0      0      0      0         0
##   les               0      0      0      1      0         0
##   limmortalité      0      0      0      0      1         0
##   list              0      1      0      0      0         0
##   littératur        0      0      0      1      0         0
##   livr              1      1      0      0      1         0
##   maîtr             0      0      0      0      1         0
##   mathématiqu       0      0      0      1      0         0
##   mes               0      1      0      0      0         0
##   milan             1      1      0      0      1         1
##   mozart            0      0      1      0      0         0
##   musiqu            1      0      1      0      1         0
##   nina              0      0      0      0      1         0
##   oraux             0      0      0      1      0         0
##   pragu             0      1      0      0      0         0
##   prépa             0      0      0      1      0         0
##   simon             0      0      0      0      1         0
##   son               0      0      0      0      1         0
##   théâtre           0      0      0      0      1         0
##   touristiqu        0      1      0      0      0         0
##   trenet            0      0      1      0      0         0
##   vie               1      0      0      0      0         0
##   vienn             0      1      1      0      0         0
##   vivaldi           0      0      1      0      0         0
Cette matrice montre bien ce qu'elle fait. Et en toute rigueur, on devrait pouvoir la calculer manuellement avec des coefficients de probabilité. C'est l'objet de notre deuxième partie.
Techniquement, il faudrait que ma recherche attribue un poids au mot ailleurs.
Mais poursuivons. L'élément central de la recherche de similarité est sans doute de pouvoir calculer un tf-id; Cette mesure statistique permet d'évaluer l'importance d'un terme contenu dans un document (Cf Wikipédia - ?tf-idf), relativement à une collection ou un corpus. Le poids augmente proportionnellement au nombre d'occurrences du mot dans le document. Il varie également en fonction de la fréquence du mot dans le corpus.
Une autre façon naïve de le faire serait d'attribuer des probabilités à priori à chaque mot, basées par exemple sur un historique de requête.
A suivre

Sep 9, 2013

Ce que je sais sur les séries temporelles (1/5)

Ce que je sais sur les séries temporelles (1/5)

En lisant la préface de Flore Vasseur à l'essai “le monde en 2030 vu par la CIA”, j'ai été très frappé par mon manque de culture macroéconomique. En effet, un essaiqui parle de 2030, regorge presqu'essentiellement de prévisions macroéconomiques basées sur des scenarii plus ou moins long terme. Derrière les analyses, il y a souvent recours à l'économétrie des séries temporelles, pour par exemple estimer que “le monde aura largement engagé sa mutation écologique en raison de la rareté du pétrôle et de l'élévation des prix des matières premières”, il faut sans doute avoir un modèle de prévision des prix et pouvoir projeter ce modèle dans le cadre des modèles d'équilibres généraux.

En bref, j'ai l'impression d'une vraie inculture en prévision macroécronomique.

Alors je lance un fil d'articles autour des séries temporelles.

Définition

Séries temporelles : Analyse statistique d'observations régulièrement espacées dans le temps. Historique : Astronomie, voir (“On the periodicity of sunspots”, 1906). On peut même aller plus loin. Un manuscrit du Xeme siècle essayait déjà de représenter l'inclinaison des orbites des planètes en fonction du temps et on doit plusieurs siècles plus tard à Kepler d'avoir pu énoncer les lois sur les mouvements des planètes.

Aller plus loin :

A quoi ça sert

Prévoir : Très utile dans un monde qui change d'imaginer demain. Exemple : la consommation d'électricité en France.

Théorie

Les ramifications théoriques des séries temporelles se trouvent un peu partout en analyse mathématique. Les processus stochastiques, les chaines de markov, l'analyse spectrale, bref, selon que l'on suit ce cours pour la première fois dans une faculté d'économie ou de mathématiques, l'approche peut être très différente et les degrés de compréhension aussi. Une bonne façon d'introduire à la théorie mathématique derrière les séries temporelles reste pour moi l'étude des chaines de markov. On peut consulter ici.

Modélisation

4.1. Première approche : Le lissage

Considérons les cours du CAC 40 depuis le 01 janvier 2008. Dans toute la série d'articles sur les séries temporelles, nous allons travailler avec ces chroniques.

library(tseries)
library(zoo)
cac = get.hist.quote("^FCHI", start = "2008-01-01", end = "2010-01-01")
## time series starts 2008-01-02
## time series ends   2009-12-31
plot(cac, col = "lightblue", main = "CAC 40 depuis le 01 janvier 2008")

plot of chunk unnamed-chunk-1

On va analyser uniquement les cours d'ouverture;

Le lissage consiste à extrapoler une série en vue de faire une prévision. Il n y a pas de bon lissage, tout dépend du poids que l'on accorde au passé et de ce qu'on veut voir dans l'avenir à court, moyen ou long terme. Il y a toute une théorie sur le choix de la “bonne "constante de lissage, lorsque le bue est la prévision, on s'accorde plus ou moins à dire que la minimisation des moindres carrés des erreurs(Prévision vs Réalisation).

  • Lissage par moyenne glissante
Open = cac[, 1]
head(Open)
## 2008-01-02 2008-01-03 2008-01-04 2008-01-07 2008-01-08 2008-01-09 
##       5610       5538       5544       5432       5477       5459
T = time(Open)
MoyenneGlissante = filter(coredata(Open), filter = rep(1/12, 12))
MoyenneGlissante = zoo(MoyenneGlissante, T)
plot(Open, main = "Indice du CAC 40", xaxt = "n")
axis.Date(1, at = seq(T[1], T[length(T)] + 6, "month"), format = "%m/%y", cex.main = 0.6)
lines(MoyenneGlissante, lwd = 2, col = "red")

plot of chunk unnamed-chunk-2

Le lissage permet d'obtenir la tendance de la série. Plus généralement, on a parfois recours à des lissages exponentiels.

  • Lissage exponentiel Holt-Winters propose la méthode de lissage la plus généralisable au travers de trois paramètres dit de réglages. Lorsqu'on ne spécifie pas les paramètres, ils sont calculés automatiquement à partir de l'historique selon la minimisation de l'écart entre la prévision et la réalisation

Mais pour faire un lissage exponentiel en utilisant la méthode HoltWinters, il faut une régularité dans la série, ce qui n'est pas le cas des séries boursières en général.

Considérons donc pour voir le lissage exponentiel un autre type de série. Les exportatios américaines en France, puisqu'il en était question dans Alternatives économiques du mois dernier.

Un formidable package Rdatamarket met à la disposition des "chercheurs” de formidable jeux de données macroéconomiques. J'yreviendrais.

library(rdatamarket)
dminit(yourdmininit;)
exports <- dmlist("1l5r")
exports.ts <- ts(exports$Value, start = 1985, frequency = 12)
head(exports.ts)
## [1] 548.9 483.2 611.3 487.7 566.3 465.3
plot.ts(exports.ts, col = "blue4", lwd = 1)
hw = HoltWinters(exports.ts)
lines(hw$fitted[, 1], col = "red3", lwd = 1)

plot of chunk unnamed-chunk-3

Ce lissage peut permettre de réaliser des prévisions. Et c'est un premier aperçu de la manière donc on peut prolonger une série.

4.2. Décomposition d'une série chronologique Il est en général considéré qu'une série est composée d'une tendance(évolution naturelle), d'une saisonnalité( evènements récurrents aux mêmes périodes) et d'un bruit blanc (marche aléatoire)

Pour décomposer la série, on utilise en R la fonction decompose :

composantes = decompose(x = exports.ts)
plot(composantes)

plot of chunk unnamed-chunk-4

Lorsque rien n'est précisé, le modèle utilisé est un modèle additif. AUtrement dit, il est supposé que la série Exports.ts = Trend + Saison + BB

Une autre façon de voir aurait été de considérer un modèle multiplicatif Exports.ts = Trend x Saison x BB

composantes = decompose(x = exports.ts, type = "multiplicative")
plot(composantes, col = "red")

plot of chunk unnamed-chunk-5

4.3 Autocorrélations