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