Ruby Best Practices

Just a quick word on a book I discovered recently and which every serious (and not so serious !) Ruby programmer should definitely purchase : Ruby Best Practices. Actually you don’t have to get your credit card, it is available for free download !

It is especially very useful when you are writing your Ruby libraries and you want to do stuff well.  The book tackles almost every step of the library building process, namely : tests, APIs design, Ruby basements understanding, and so on…

See ya space hackers !

Edit : the link is currently broken. I don’t know what is the author’s policy, so send me an e-mail if you want the pdf.

Étiquettes: , ,

Correction de césures et enrichissement de requêtes

Voilà un petit billet pour faire un point rapide sur mon premier mois de thèse.

J’ai travaillé sur de la recherche d’information dans des livres et plus précisément sur de l’enrichissement de requêtes en utilisant Wikipedia comme base de connaissance. Cette approche diffère du traditionnel blind relevance feedback par le fait qu’on ne va pas sélectionner des termes pour l’expansion à partir des documents cibles mais à partir de documents externes, et dans notre cas dans un unique document relatif à une requête.

J’ai eu la chance d’avoir accès à un corpus conséquent de 50,239 livres numérisés (~603 millions de lignes / ~6 milliards de mots) dans le cadre de ma participation à INEX 2010 et plus précisément à la Book Track. Un problème s’est néanmoins posé : les césures. En effet les livres sont numérisés grâce à une technique de reconnaissance optique des caractères (Optical Character Recognition) qui va conserver la structure physique, à savoir la segmentation en pages, lignes… Les césures sont donc elles-aussi interprétées comme telles !

...
than California, the credit will rather be in ex-
cess than too small ; but still we propose to add
...

Dans l’exemple ci-dessus, le mot « excess » ne sera pas indexé, mais les termes « ex- » et « cess » le seront. De l’information est donc perdue, c’est pourquoi j’ai développé un système permettant de corriger ces erreurs à l’aide d’un lexique de 118,221 mots uniques issus de l’English Gigaword. Le faible nombre de requêtes (16) ne nous a pas permis de montrer une amélioration significative des résultats entre le corpus corrigé et le corpus non-corrigé, néanmoins les méthodes d’enrichissement de requêtes ont prouvé leur efficacité.

Je vais également présenter ce travail dans un séminaire la semaine prochaine, j’ai donc fais une présentation pour l’occasion, n’hésitez pas à y jeter un oeil !

Étiquettes: , , , ,

Google rachète Metaweb

Cette « news » commence à dater un petit peu mais comme vous avez pu le voir je n’ai pas eu beaucoup de temps pour écrire cet été.

Google continue donc sa moisson d’entreprises en rachetant Metaweb, une entreprise spécialisée dans le développement de bases de connaissances structurées et d’ontologies ; son produit phare est Freebase, une base de connaissances à vocation encyclopédique, traitant d’un peu tout, organisée en fonction des différents sujets. L’idée derrière ce projet est de pouvoir représenter des entités typées (un lieu, une personne…), éventuellement d’y rattacher des concepts et surtout de pouvoir relier les entités entre elles. Et toi, ami lecteur féru de nouvelles technologies, ça ne te dit rien Freebase? Mais oui, c’est l’outil encyclopédique utilisé par Powerset ! Un petit résumé s’impose.

En septembre 2008, Microsoft rachète une entreprise nommée Powerset, spécialisée dans la recherche d’informations et principalement dans les systèmes de questions-réponses. Le moteur de recherche en ligne que propose Powerset est assez performant par rapport à ce qu’on peut trouver à côté à l’époque (c’est à dire rien…) et il utilise une base de connaissances libre et enrichie par des contributeurs : Freebase. Dans la foulée la technologie Powerset est intégrée à MSN Live Search (ici c’est assez flou, on ne sait pas précisément quel a été l’apport de Powerset) qui deviendra très vite Bing.

Dans le même temps Google commence à intégrer la gestion des questions factuelles et arrive à renvoyer des réponses correctes avec une approche très basique : certains articles de Wikipédia sont suffisamment structurés pour permettre une extraction très facile de la réponse à l’aide règles simples, en utilisant par exemple les Infobox et en pariant sur un formatage correct.

{{Infobox Communes de France
...
cp    = 84000
...
}}

Néanmoins en deux ans Google a beaucoup avancé dans ce domaine et s’est également dirigé vers des représentations d’entités notamment en développant Google Squared, qui permet notamment de trouver des réponses courtes à des questions factuelles, ou des propriétés se rapportant à l’entité en question, ce qui revient plus ou moins au même. Un billet très intéressant à ce sujet est disponible sur le blog de Google.

On peut voir dans le rachat de Metaweb une opportunité pour Google d’améliorer et de renforcer son service Squared, lui-même directement lié au moteur de recherche, notamment grâce à la quantité faramineuse d’informations à leur disposition. Néanmoins, en l’état, le travail de Google sur Freebase risque d’impacter directement les résultats et le fonctionnement de Powerset. Coup stratégique, marketing, autre? Peut-être un peu de tout, il faut néanmoins noter que malgré ce rachat Google compte laisser Freebase en accès libre à la communauté !

Étiquettes: , , , ,

How to avoid memory leaks with Doctrine?

Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes)...

I hate this message, in fact it says « You suck, you don’t even know what you’re doing with your objects ». It happened recently when I was writing a script which retrieves old data from an old database, computes it and inserts new values in an other database. I used Doctrine because it was a part of a Symfony project, and I discovered many things :

  • Doctrine objects take a LOT of memory space
  • PHP 5.2.11 does not garbage collects Doctrine (or any other ORM) objects at the end of the scope

Why? Because before PHP 5.3 the garbage collector can’t collect objects that have circular references, and that is the case of Doctrine objects. So they aren’t freed at the end of the scope, resulting in memory leakage.

So in order to process thousands/millions records with a database ORM, you need to handle memory freeing. Doctrine hopefully provides a free() method which, combined with unset(), can solve your problem.

// ...
$my_object = new MyDoctrineClass() ;

// your data processing...

$my_object->free() ;
unset($my_object) ;
// ...

Étiquettes: , , , ,

IronRuby, un autre pas de Microsoft vers l’Open Source

Le fait ne peut pas être nié, Microsoft a changé de politique. L’entreprise ultra proprio-conservatrice veut redorer son image auprès des développeurs adeptes du libre depuis déjà un moment, le comble étant leur contribution au noyau Linux (dans le cas d’une virtualisation de Linux sur Windows, mais tout de même) !

Depuis maintenant 3 ans Microsoft s’est lancé dans le développement de son implémentation de Ruby : IronRuby. Son premier gros avantage est sa grande portabilité, en effet elle tourne sur le framework .NET et sur Mono, et utilise le .NET Common Language Runtime qui lui permet notamment de bénifier d’un garbage collector bien plus évolué que MRI.

Mais surtout IronRuby peut tourner sur le moteur Silverlight (respectivement Moonlight pour Linux) et ainsi être utilisé pour développer des applications web utilisant du son, de la vidéo etc… Comme pour Flash, tout se passe côté client : un plugin Silverlight doit être installé pour pouvoir faire tourner les applications, et le code Ruby est écrit directement dans des balises HTML (oui oui !) et exécuté à la volée par la machine Silverlight.

<script type="text/ruby" >
document.message.html = "Hi IronRuby !"
</script>

Voilà un petit aperçu des possibilités d’animation proposées par IronRuby : http://vimeo.com/8602586.

Mais pour moi l’intérêt ne se situe pas dans l’arrivée d’une nouvelle technologie mais bien dans le fait que Microsoft veut s’affirmer dans le monde de l’Open Source et faire oublier sa politique précédente. Le fait qu’ils passent (entre autres) par Ruby est également très intéressant, et c’est une très bonne chose pour ce langage d’avoir un support aussi important que celui de Microsoft. Malgrès ses nombreux défauts je suis persuadé que Ruby aura un rôle important à jouer (quand les threads seront enfin implantés nativement peut-être…) surtout auprès des entreprises utilisant des méthodes de développement agiles.

Étiquettes: , , ,

Bing, Street view et la réalité augmentée

La réalité augmentée a toujours été un truc qui m’a impressionné, c’est parfois tellement bluffant qu’on se demande si en fait ce ne sont pas des effets spéciaux ajoutés spécialement pour l’occasion, un peu comme ce film : Augmented (hyper)Reality.

Sauf que maintenant cette technologie n’est plus seulement un objet de fantasme mais est en passe d’être accessible au grand public, en témoigne cette présentation du créateur de Bing Maps au TED2010 : augmented-reality maps.

Pour résumer rapidement, Microsoft a développé depuis un moment déjà une alternative à Google Maps : Bing Maps. Ils reprennent exactement le même concept, quasimment la même interface, poussant le vice jusqu’à créer leur propre service « Street View », qui vous permet de vous balader dans la rue comme si vous y étiez en prennant en compte la géométrie de l’environnement et des bâtiments.

L’innovation principale présentée dans la vidéo est l’apparition de réalité augmentée, notamment par la superposition d’images. Des utilisateurs possédant une application pour téléphone spéciale développée par Microsoft et Flickr peuvent prendre des photos qui seront géolocalisées et stockées dans une base de données Flickr spéciale, partagée avec Bing Maps’ Street View, qui va afficher ces photos superposées à la « réalité » de Microsoft.

bing_maps_ar

Encore plus fort, Blaise Aguera appelle – en plein milieu de sa présentation – des collègues qui se trouve exactement à l’endroit qu’il visite avec Street View ; ces personnes commencent alors à se filmer et la vidéo s’incruste en temps réel dans la vue de Street View !

bing_maps_ar2

Au delà de cette démonstration incroyable, plusieurs questions se posent, autant au niveau de la technique qu’au niveau de l’éthique. La chose la plus impressionante pour moi actuellement est la superposition quasi-parfaite d’une vidéo sur une image fixe le tout en temps réel sans ralentissement notable ; je pense d’ailleurs que pour cette démonstration il n’y a aucun calcul de superposition effectué et que pour obtenir un résultat aussi satisfaisant il faut que le visionneur se trouve exactement aux mêmes coordonnées GPS que le filmeur (à quelques centimètres près). Néanmoins cela n’enlève rien à la performance de Microsoft qui nous propose ici une application ludique et utile de la réalité augmentée.

Mais au niveau de l’éthique maintenant ; on peut voir que sur les photos prises par Bing Maps’ Street View les visages sont floutés (pour des questions de respect de la vie privée, cette pratique avait bien sûr été initiée par Google) mais qu’en sera-t-il des personnes prises en vidéo? Les passants au second plan, les erreurs de cadrage, les filmeurs volontairement mal intentionnés… Les scénarios sont sans limites, on peut déjà imaginer les Experts utilisant Street View pour reconnaître un passant se promenant avec sa maîtresse deux heures avant le meurtre de sa femme… :)

Pour rester sérieux et conclure sur cette nouvelle technologie très intéressante mais surtout impressionante, il faut espérer que Microsoft résoudra ces petits problèmes éthiques avant que nous puissions à notre tour jouer à enrichir numériquement la réalité… virtuelle.

Étiquettes: , , , ,

Symfony 1.2 sur une Debian Etch

Symfony 1.2 (et versions supérieures) nécessitent au minimum PHP 5.2.4, version qui n’est notamment pas disponible dans les dépôts de Debian Etch. Ce petit tuto montre comment compiler une version de PHP compatible avec les versions actuelles de Symfony (jusqu’à 1.4) tout en gardant une précédente version de PHP déjà installée.

Compilation de PHP

Il faut commencer par installer certaines librairies nécessaires pour la compilation de PHP :

apt-get install libgd-dev libpng12-dev libxml2-dev libmysql++-dev libxslt1-dev zlib1g-dev libldap2-dev libcurl3-dev libpq-dev

Ensuite on va récupérer les sources de la version de PHP qui nous intéresse (ici 5.2.11) et les mettre dans un répertoire temporaire :

mkdir /usr/local/tmp
cd /usr/local/tmp
wget http://fr2.php.net/get/php-5.2.11.tar.gz/from/this/mirror
tar xzf php-5.2.11.tar.gz
cd php-5.2.11

Vient ensuite la compilation. Ici le chemin d’installation choisit pour tout le tuto est /usr/local/php5211, il faudra modifier toutes ses occurences si on veut l’installer ailleurs :

./configure --enable-fastcgi --with-gd --with-mysql --prefix=/usr/local/php5211 --with-xsl --enable-soap --with-zlib --with-config-file-path=/usr/local/php5211 --with-curl --with-pdo-mysql --with-pgsql --with-pdo-pgsql --with-ldap
make
make install

Il faut enfin mettre le fichier php.ini-recommended là où on a dit qu’on le trouverait (avec l’option –with-config-file-path) :

mv php.ini-recommended ../../php5211/lib/php.ini

Définition du VirtualHost

Il faut maintenant modifier le httpd.conf pour ajouter la prise en charge des applications Symfony par la nouvelle installation PHP. Si on garde le même répertoire d’installation qu’au dessus (/usr/local/php5211) ça donne :

# httpd.conf
LoadModule actions_module /usr/lib/apache2/modules/mod_actions.so # important, à ne pas oublier

NameVirtualHost 127.0.0.1:8080
Listen 127.0.0.1:8080

<VirtualHost 127.0.0.1:8080>
DocumentRoot "/var/www/mon_appli_symfo"
DirectoryIndex index.php

<Directory "/var/www/mon_appli_symfo">
AllowOverride All
Allow from All
</Directory>

ScriptAlias /php5211-cgi /usr/local/php5211/bin/php-cgi
Action php5211-cgi /php5211-cgi
AddHandler php5211-cgi .php

</VirtualHost>

Il reste plus qu’à activer le module apache rewrite (c’est probablement déjà fait) :

a2enmod rewrite

Normalement tout marche ; il vaut mieux ne pas supprimer les sources de PHP au cas où il manque une option et qu’il faille un jour le recompiler.

Étiquettes: , , , ,

Interrogations de moteurs de recherche par des requêtes formulées en langage naturel

Quel titre ! Je vous en parlais déjà il y a quelques mois mais il y a encore beaucoup à dire sur ce sujet.

Tout d’abord nous avons écrit un article scientifique (dont le titre est le titre de ce billet) décrivant les innovations apportées par notre travail, qui a été accepté pour la convention MajecStic qui se tient à Avignon les 16, 17 et Novembre. Nous y expliquons les points principaux de notre démarche, à savoir la combinaison d’une base de connaissances classifiée avec des règles portant sur les mots importants présents dans les questions. Néanmoins nous n’avons pas eu le temps d’implémenter entièrement l’idée exprimée dans mon précédent billet sur ce sujet car elle ne fonctionnait que dans des cas très restreints, mais nous ne l’avons pas abandonnée et nous y pensons pour en faire le sujet d’une nouvelle publication.

Cette expérience nous a et va encore énormément nous apprendre, étant donné que Ludovic va (très certainement) faire une thèse dans le domaine du Traitement Automatique du Langage Naturel Ecrit (TALNE) et que j’en prends également doucement le chemin.

Une version en ligne est disponible à cette adresse : http://vickev.fr/~sit/semantic-ruby/www .
Soyez indulgents, il s’agit d’une version très expérimentale qui ne fonctionne correctement qu’avec des questions simples (pour le moment… !) ; vous pouvez tester avec des questions complexes mais les résultats ne sont pas garantis. La recherche d’information en elle-même est produite par NLGbAse uniquement.

Voilà un billet un peu moins technique mais sur un sujet qui me passionne tout autant, en espérant qu’il vous aura également intéressé ! A bientôt !

Edit : comme prévu je mets l’article en ligne : http://majecstic2009.univ-avignon.fr/Actes_MajecSTIC_RJCP/MajecSTIC/articles/1292.pdf. A noter que nous avons été nominés pour le Best Paper, nous ne l’avons pas reçu mais nous avons eu droit à un « Prix spécial du meilleur espoir » ! :]

Étiquettes: , , , ,

Des nouvelles !

Nouvel hébergement, nouveau design, nouveau blog. Après plus de 6 mois sans ticket je dépoussière la place et essaye d’écrire au moins 2 articles par mois (gloups…), avec une approche probablement plus scientifique mais toujours profondément Ruby !

J’espère que la nouvelle interface plus chaleureuse vous incitera à commenter, réagir et débattre. A bientôt pour de nouvelles bloguesques aventures !

Étiquettes:

Les casts en C++

Pour varier un peu le contenu de mon blog (et aussi parcequ’on m’a fait des réflexions désobligeantes sur Ruby ! ;p) je ressors aujourd’hui un petit tutorial C++ que j’avais écris pour les autres membres d’un projet effectué l’année dernière (un Tamagotchi pour la petite histoire).

Alors bien sûr, vous connaissez les casts en C, ça donne quelque chose comme ça :

int a = 10 ;
unsigned b = (unsigned)a ;

Seulement c’est la méthode C, et dans son immense mansuétude, Mr. Bjarne Stroustrup nous a donné 4 opérateurs standards permettant de faire tous les casts possible.

  • Le static_cast<>C’est l’opérateur de cast classique, il fait une conversion statique, comme celle que j’ai écrite 3 lignes plus haut. L’équivalent en C++ est donc :
    int a = 10 ;
    unsigned b = static_cast<unsigned>(a) ;

    Rien de spécial à savoir, les conversions illégales passeront pas à la compilation, enfin la routine quoi.

  • Le reinterpret_cast<>Ca c’est un cast un peu spécial mais très pratique ; il s’emploie quand vous voulez dire au compilateur de prendre un objet de type A pour un objet de type B. Il ne fait aucune conversion physique, il s’agit juste d’une indication que donne le développeur au compilateur, du genre « Je sais bien que ta fonction prend en paramètre un objet B, mais moi j’te file un objet A, et ça marche. Tu veux pas compiler, alors je réinterprète le type de mon objet pour que ça devienne un B. »
    void Fun (B *Obj)
    {
    // Une fonction lambda, prenant un B* en paramètre...
    }
    // ...
    A* Bla = new A() ;
    Fun (reinterpret_cast<B*> (A)) ;

    A noter, les familles A et B doivent être liées (du genre A dérive de B…) sinon la compilation de marchera quand même pas.

  • Le const_cast<>Super pratique le const_cast ! Il y a toujours des problèmes de conversion entre des variables normales et des variables const, c’est lourd, on se prend la tête, on essaye de mettre des variables intermédiaires, ça foire… Quand on passe d’une variable normale à une variable const, la conversion est explicite et il n’y a aucun problème, mais quand on passe d’un const à une normale, là ça craint, et ça compile pas.Enfin bref, le const_cast<> permet de s’affranchir tout simplement de ce problème.
    const X* Bla = new X() ;
    X* Bla2 = const_cast<X*> (Bla) ;
  • Le dynamic_cast<>Celui-là c’est le plus complexe, à utiliser dans des cas très précis, des problèmes insolubles autrement. Et c’est pas facile à expliquer aussi.
    Je vais commencer par introduire la notion de cross_casting. Imaginez que vous avez trois classes, Bla, Prout, et la classe BlaProut qui dérive des deux autres en mêmes temps.

    Soit :
    Bla      Prout
    \       /
    \   /
    BlaProut

    Ou encore :

    class Bla ;
    class Prout ;
    class BlaProut : public Bla, public Prout ;

    Maintenant regardez bien ça va aller très vite, c’est pas de la magie mais presque. Avec un petit dynamic_cast<> je vais pouvoir obtenir un objet de Prout à partir d’un objet de Bla…

    Bla *B = new BlaProut() ; // je peux le faire parceque BlaProut dérive de Bla !
    Prout *P = dynamic_cast<Prout*> (B) ;

    Impressionnant n’est-ce pas? Et pourquoi ça marche? Parceque c’est exactement équivalent à ceci :

    Bla *B = new BlaProut() ;
    BlaProut *BP = dynamic_cast<BlaProut*> (B) ; // on cast un Bla* en BlaProut*
    Prout *P = static_cast<Prout*> (BP) ; // eh oui, ça marche ! 

    Mais comme vous vous en doutez bien, ce genre de conversions va forcément induire des problèmes à terme. De mon côté je n’ai jamais eu à utiliser le dynamic_cast<>, et j’espère vraiment que ça n’arrivera pas de sitôt…

Étiquettes: ,