SQLIte et lemmatisation du pauvre
Analyser le contenu et la structure de la base lexique.sqlite ci-dessous avec un client d'administration à télécharger comme une extension FireFox : https://addons.mozilla.org/en-us/firefox/addon/sqlite-manager/
Le lemmatiseur du pauvre donne "avion" comme lemme pour la forme "avions". Êtes vous satisfaits ? En modifiant la requête préparée (ORDER BY freq DESC), vous devriez obtenir le lemme le plus fréquent qui correspond à une forme.
/*
ATTENTION, cette classe est incomplète
Éléments de code permettant d'utiliser la base lexique.sqlite en lien ci-dessous
dans un parseur SAX établissant des listes de mots en ordre de fréquence
selon les balises
*/
public class SAXFrequence extends DefaultHandler{
/** Connexion paratagée */
static Connection connex;
/** Requête préparée pour la recherche d'un lemme */
static PreparedStatement reqLemma;
/** Factorisation d'une méthode qui renvoit un lemme contre une forme fléchie */
public static String lemma (String orth) {
// le code SQL peut lancer des exceptions, elles sont retenues ici
try {
// passer la forme recherchée à la requête préparée
reqLemma.setString(1, orth);
// exécuter la requête
ResultSet rs = reqLemma.executeQuery();
// si pas de résultat, renvoyer la forme initiale
if (!rs.next()) return orth;
// sinon renvoyer le premier lemme rencontré
else return rs.getString("lemma");
} catch (SQLException e) {
e.printStackTrace();
}
// pas de raison que cela arrive, mais sert au compilateur
return orth;
}
/**
La signature de cette méthode à laquelle on passe n'importe quel dictionnaire
permet de factoriser les traitements apportés aux mots avant de les compter
*/
private void traiteTexte(String texte, Map<String,Integer> dico) {
String[] mots = frenchTokenizer.tokenize(texte);
// Remplissage de la table de fréquence
for (String mot : mots) {
mot=mot.toLowerCase();
if(mot.isEmpty()) continue;
// traitement optionnel des mots vides
if (lesMotsVides.contains(mot)) continue;
// filtrage des lemmes
mot=lemma(mot);
if (dico.containsKey(mot)) {
dico.put(mot, dico.get(mot) + 1);
} else {
dico.put(mot, 1);
}
}
}
/** Trier et afficher les tableaux de mots sur deux colonnes */
public void tetes(int n) throws SAXException{
// pour trier les dictionnaires, on se propose de renter les couples <Klé,Valeur>
// dans une collection nativement triées
// Afin que le tri se fasse selon ce que l'on souhaite, on créé un comparateur
SortedSet<Map.Entry<String, Integer>> trieur1 =
new TreeSet<Map.Entry<String, Integer>>(new Comparateur());
trieur1.addAll(dicoP.entrySet());
// un itérateur sur lequel boucler dans l'ordre de tri
Iterator<Entry<String, Integer>> it1=trieur1.iterator();
SortedSet<Map.Entry<String, Integer>> trieur2 =
new TreeSet<Map.Entry<String, Integer>>(new Comparateur());
trieur2.addAll(dicoSaid.entrySet());
// un itérateur sur lequel boucler dans l'ordre de tri
Iterator<Entry<String, Integer>> it2=trieur2.iterator();
// têtes de liste
String wrap=" ";
System.out.println("<p>"+wrap.substring(0, wrap.length()-3)+"<said>");
String s1,s2;
for(int i=0;i<n;i++) {
s1=s2=""; // inialiser à rien si les listes sont inégales
if(it1.hasNext()) s1=""+it1.next().toString();
if(it2.hasNext()) s2=it2.next().toString();
System.out.println(s1+wrap.substring(0, wrap.length()-s1.length())+s2);
}
}
/**
* Un objet qui compare des couple <Klé,Valeur> dans un SortedSet
*/
public class Comparateur implements Comparator<Map.Entry<String, Integer>> {
@Override
/**
* Comparateur pour trier les couple clé valeur pour le TreeMap (trieur)
* On compare d'abord sur la valeur (effectif entier)
* Attention, si deux valeurs sont égales selon le comparateur,
* alors elles sont considérées identiques.
* Si on veut plus d'un mot par effectif (ex: atelier=1, duchesse=1)
* il faut que le comparateur les distingue aussi sur le mot (la clé)
*/
public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
// on classe dans l'ordre de valeur inverse des Integer
int dif=e2.getValue().compareTo(e1.getValue());
if (dif!=0) return dif;
return e1.getKey().compareTo(e2.getKey());
}
}
public static void main(String[] args) throws Exception{
// la date en ms depuis le 1er janvier 1970 à l'instant t
long start=System.currentTimeMillis();
// charger le contrôleur SQLite
Class.forName("org.sqlite.JDBC");
// créer la connexion à la base lexique
connex = DriverManager.getConnection("jdbc:sqlite:rsc/lexique.sqlite");
reqLemma = connection.prepareStatement("SELECT lemma FROM lexique WHERE orth = ?");
// comment bien utiliser l'affichage des têtes
SAXFrequence parseur=new SAXFrequence();
xmlReader.setContentHandler(parseur);
xmlReader.parse("rsc/celine_voyage.xml");
// ici on pourrait ajouter d'autres fichiers
parseur.tetes(20);
//…
// contrôlez vos performances
System.out.println(System.currentTimeMillis() - start + "ms");
}
}
Afficher les verbes et les substantifs les plus fréquents selon les deux types de texte (description <p>, dialogue <said>).
Pour obtenir ce résultat il vous faut une base similaire à lexique.sqlite, mais avec une colonne en plus, qui donne la nature du mot. L'information est toute entière tirée de la table téléchargeable ici http://www.lexique.org/telLexique.php . Remarquez la colonne 4_cgram.
Pour produire votre propre base, commencez une classe à part Lexique, qui contiendra vos outils qui concernent le maniement de cette table venant de lexique.org, ainsi que la méthode lemma. Reprenez le tutoriel Sample.java https://bitbucket.org/xerial/sqlite-jdbc et de la documentation sur SQLite pour créer une table à 4 colonnes (CREATE TABLE). Pour alimenter la base, pensez aux requêtes préparées
PreparedStatement stmt = con.prepareStatement("INSERT INTO data('champ1', 'champ2') VALUES (?, ?)");
Vous trouverez beaucoup d'exemples sur Internet.
Conseil: Tester votre base pour lemmatiser sur un chapitre d'abord. Ensuite faîtes une recherche sur la notion d'index dans une base de données. Une ligne en plus permet parfois de multiplier les performances d'un programme.
En même temps que votre code Lexique et SAXFrequence, vous enverrez vos résultats aux adresses personnelles de vos professeurs JAVA.
Anonymous
Un lexique en base SQLite