Oracle Text et Data Mining (Partie 2)

Vous le savez, Oracle Data Mining (ODM) est un de mes sujets de prédilection. C’est notamment parce que le type d’informations qu’on arrive à extraire des données à partir des algorithmes spécialisés sont d’un intérêt extrême. Le décisionnel n’a alors plus rien à voir avec les explorations, même adhoc, des données réalisées par les utilisateurs. Dans les 2 parties de cet article, je montre comment utiliser Oracle Data Mining avec des documents non structurés. Pour cela, j’utilise le contenu de ce blog. L’article est découpé comme ceci :

  • La première partie de cet article publiée précédemment explique comment extraire les données depuis Internet et les charger en base de données ; c’est la plomberie !
  • Dans cette seconde partie, j’applique un algorithme de classification sans apprentissage (KMean) sur le texte de mes articles et je découvre avec stupéfaction la classification réalisée par ODM.

Vous noterez que la magie de cet exemple réside, entre autre, sur le fait que l’algorithme utilisé n’utilise aucune phase d’apprentissage. Si vous voulez aller plus loin dans la classification et influencer le moteur avec des classements déjà réalisées, vous utiliserez des algorithmes à apprentissage comme les arbres de décision ou les support vector machine (réseaux de neurones). Mais, sans allez jusque là, vous allez découvrir un résultat qui, j’en suis, sur vous étonnera…

Etape 1 : préparer les structures pour appliquer l’algorithme de clustering

Maintenant que nous avons les données dans la base de données, appliquer l’algorithme de classification est une formalité ! Il s’agit de créer un index Oracle Text; comme nous savons que nos articles sont en français, nous allons créer la structure d’index en français sans, toutefois, alimenter l’index :

exec ctx_ddl.create_preference('french_lexer','basic_lexer');
exec ctx_ddl.set_attribute('french_lexer','index_stems','french');
exec ctx_ddl.set_attribute('french_lexer','index_themes','yes');
exec ctx_ddl.set_attribute('french_lexer','theme_language','french');

create index article_idx
on article(TXT_CONTENT)
indextype is ctxsys.context
parameters('nopopulate lexer french_lexer');

Une fois l’index prêt, nous allons créer les tables qui stockerons les résultats de la classification et la description des clusters de données constitués :

create table restab (       
docid NUMBER,
clusterid NUMBER,
score NUMBER);

create table clusters (
clusterid NUMBER,
descript varchar2(4000),
label varchar2(200),
sze number,
quality_score number,
parent number);

Etape 2 : Exécuter l’algorithme

Une fois les structures préparée, il suffit de créer une préférence avec l’algorithme et ses paramètres; ici on utilise l’algorithme KMean et on créer 5 cluster de classifications :

exec ctx_ddl.create_preference('my_cluster','KMEAN_CLUSTERING');
exec ctx_ddl.set_attribute('my_cluster','CLUSTER_NUM','5')

Puis on exécute l’algorithme :

set timing on 
exec ctx_output.start_log('my_log');
exec ctx_cls.clustering('article_idx','id','restab','clusters','my_cluster');
exec ctx_output.end_log;

Après 6 secondes sont mon ordinateur portable, le résultat est constitué

Etape 3: Analyse de la classification

On peut désormais revoir le classement réalisé; les informations relatives au modèles sont dans la table clusters mais nous allons simplement visualiser le résultat dans la table restab comme si-dessous :

select CLUSTERID clu#, count(*) 
from restab
group by CLUSTERID;

CLU# COUNT(*)
---- --------
6 90
4 123
8 261
7 53
9 271

Regardons maintenant les articles les mieux classés dans le modèle généré à l’aide de la requête suivante qui ramène les articles dont le score est supérieur à 80% dans le classement :

col clusterid format 99 heading "CLU#"
col docid format 999 heading "ID"
col title format a90
col score format 9.99
set pages 1000
set lines 110
select r.CLUSTERID, r.DOCID, r.score, m.TITLE
from restab r, metadata m
where r.score>=0.8
and m.id=r.DOCID
order by r.CLUSTERID, m.PDATE

Le résultat est juste sidérant ; pour rappel, la base de données ne sait pas de quoi mon blog parle et je ne lui ai absolument rien appris comme j’aurais pu le faire avec un algorithme de réseau de neurones :

CLU#   ID SCORE TITLE
---- ---- ----- -----------------------------------------------------------------
4 12 .91 /*+ oracle no:comments */ Colonnes corrélées et dynamic sampling
4 94 .92 Exemple d'ordre SQL #1 /*+Anti-pattern*/
4 101 .97 Exemple d'ordre SQL #2 /*+Anti-Pattern*/
4 96 .99 Exemple d'ordre SQL #3 /*+Anti-Pattern*/
4 105 .95 SQL #4 et SQL profile /*+Anti-Pattern*/
4 104 .92 Exemple d'ordre SQL #5 et #6 /*+Anti-Pattern*/
4 98 .91 Segment Advisor et SQL #7 /*+Premiers Pas*/
4 97 .85 Surveiller l'utilisation des index et SQL #8
4 115 .92 Statistiques d'un plan /*+ Need 4 Speed */
4 111 .83 Créer un SQL Tuning Set (STS) /*+ Fast and Furious */
4 106 .93 Index (ou presque)
4 206 .96 Des temps de réponses plus rapides sans changer de plan !
4 210 .98 Statistiques Multi-Colonnes en 11g
4 195 .93 Statistiques et colonnes virtuelles en 11g
4 208 .99 Bind Peeking et Variables Bind en 11g
4 209 .87 Real Time SQL monitoring /*+ 11g Tuning Pack */
4 175 .98 SQL Plan Management, la "killer app" de 11g
4 194 .85 Real Application Testing (It's not RAC !) /*+ Part 2 */
4 207 .89 Balade dans les "colonnes virtuelles" d'Oracle 11g
4 202 .95 Les index invisibles de la 11g
4 304 .97 "cursor_sharing=similar" et "method_opt=>'FOR ALL COLUMNS SIZE AUTO'"
4 328 .93 Quand Consistent Gets n'est pas la meilleure façon de comparer des ordres SQL
4 326 .87 Partitionner un index différemment de sa table
4 334 .83 Pas plus de 2 lignes par bloc !
4 339 .83 Estimer à quel point vos requêtes seront plus rapides avec Exadata Storage Server
4 347 .95 11g et Correlations Multi-Colonnes sans statistiques étendues
4 353 .91 Un Hint pour ignorer les Hints
4 357 .98 Entre SQL Plan Management et SQL Profile (1/3)
4 350 .98 Entre SQL Plan Management et SQL Profile (2/3)
4 354 .97 Entre SQL Plan Management et SQL Profile (3/3)
4 372 .97 L'Inquiétante ÿtrangeté d'Oracle Cost Based Optimizer
4 375 .85 Afficher le résultat d'un "SELECT" verticalement.
4 394 .85 Un UPDATE pas si bête...
4 413 .96 V$SQL_BIND_CAPTURE, SQL Tuning Set (STS) et SQL Performance Analyzer (SPA)
4 425 .82 Mon petit Data Mart (Partie 1) : Dimensions, Partitions et Données
4 424 .81 Mon petit Data Mart (Partie 2) : Vues Matérialisées et Query Rewrite
4 414 .84 Mon petit Data Mart (Partie 4) : Clés étrangÿres et Query Rewrite
4 421 .87 Mon petit Data Mart (Partie 5) : Star Transformation et Bitmap Join Index
4 420 .87 Oracle 11gR2 et un cas non documenté d'"Adaptive Cursor Sharing"
4 435 .98 Changer un plan d'exécution avec Oracle 11g et DBMS_SPM
4 450 .87 optimizer_dynamic_sampling=3+
4 453 .95 Index B*Tree, INDEX FULL SCAN et fonctions dans une clause WHERE
4 464 .95 Comparer le contenu de 2 SQL Tuning Set avec Oracle 11g R2
6 227 .95 RMAN et Data Guard 11g (Part 1) : Active Database Duplication
6 214 .87 RMAN et Data Guard 11g (Part 2) : Sauvegardes Multi-Sections
6 259 .87 Installer/désinstaller 10g en ligne de commande
6 257 .84 Installer/Désinstaller 11g en ligne de commande
6 277 .86 Utiliser oraenv dans vos scripts
6 287 .84 Cloner une base de données sans sauvegarde en 11g
6 292 .84 Oracle 10.2.0.4, DBUA et Capture d'Activité sur 10g pour Database Replay
6 285 .90 RMAN DUPLICATE à partir d'un BEGIN/END BACKUP
6 306 .88 Database PITR et création/suppression de fichiers
6 331 .92 Installer 11.1.0.7 (et les Patchs Set Suivants ?) en Silence
6 343 .85 Cloner un ORACLE_HOME d'une base de données RAC 10g
6 358 .83 Block Media Recovery et Data Recovery Advisor
6 368 .91 La subtilité de RMAN contre la conviction de SQL*Plus
7 199 1.00 Quand allez-vous mettre Oracle 11g en production ?
7 249 .82 Une idée doit être exprimée de la maniÿre la plus simple possible
7 317 .97 Séminaire Web : RAC 10g Tuning
7 364 1.00 Pourquoi chanter réduit les perfomances des IO?
7 402 1.00 APEX ou Excel ?
7 410 1.00 Une pub Laposte.fr... ou est-ce une pub MacBook ou Starwars?
7 462 1.00 Video "Exadata Flash Smart Cache" ou "Exadata & OLTP"

Maintenant considérez les thèmes suivants :

  • 4 -> Tuning SQL
  • 6 -> Installation et Sauvegardes
  • 7 -> Small Talk et Fun

Etape 4: Conclusion

Vous aurez, à n’en pas douter, compris l’intérêt d’utiliser Oracle Data Mining avec vos systèmes décisionnels ou simplement dans vos systèmes opérationnels. N’hésitez pas à partager vos remarques, vos expériences ou vos questions. Pour finir, supprimez les structures créées par ODM :

exec ctx_ddl.drop_preference('my_cluster');
drop index article_idx ;
drop table restab purge;
drop table clusters purge;
exec ctx_ddl.drop_preference('french_lexer');