[JAVA] Comment réaliser une recherche hybride en utilisant l'analyse morphologique et Ngram avec Solr

Cet article est également publié sur le BLOG VASILY DEVELOPERS avec le même contenu. S'il vous plaît voir d'autres articles si vous le souhaitez.

Bonjour, c'est Shiozaki des ingénieurs back-end. Jusqu'à présent, l'index d'iQON pour la recherche en texte intégral n'utilisait que l'analyse morphologique, mais l'autre jour, nous avons amélioré la recherche en utilisant également Ngram. En conséquence, le nombre de résultats dans les résultats de la recherche s'est amélioré et l'augmentation du bruit de recherche a été réduite à un niveau mineur.

Dans cet article, je présenterai les avantages de l'utilisation conjointe de Ngram et comment l'utiliser avec Apache Solr.

Je ne trouve pas les informations que je veux

En premier lieu, quel est l'état de «rechercher mais ne pas trouver les informations que vous souhaitez»? Ici, décomposons cet état en deux états suivants.

La quantité d'informations que je veux est petite

Le premier état est "les informations que vous voulez sont moins dans les résultats de la recherche". Par exemple, lorsque vous recherchez «Tokyo» sur un site d'informations touristiques, il y a des milliers de données dans la base de données, mais il n'y a que quelques résultats de recherche.

スクリーンショット 2017-02-15 20.26.09.png

Beaucoup d'informations dont vous ne voulez pas

Le deuxième état est "il y a beaucoup d'informations indésirables dans les résultats de la recherche". Lorsque vous recherchez "Tokyo", les résultats de la recherche incluent des informations sur d'autres régions telles que Kyoto et Osaka en plus des informations sur Tokyo.

スクリーンショット 2017-02-15 20.26.46.png

En fait, deux états se produisent en même temps

Dans de nombreux cas, les deux états ci-dessus se produisent en même temps lorsque vous ne trouvez pas ce que vous voulez vraiment. En d'autres termes, toutes les informations souhaitées par l'utilisateur ne sont pas renvoyées en tant que résultat de la recherche, et les informations que l'utilisateur ne souhaite pas sont également renvoyées en tant que résultat de la recherche.

Le diagramme de Ben est le suivant. Toutes les informations stockées dans la base de données sont classées selon les deux axes de savoir si elles ont été renvoyées comme résultat de la recherche et si elles étaient les informations que vous vouliez.

スクリーンショット 2017-02-15 18.26.25.png

Donnez ensuite un nom à chaque ensemble pour plus d'explications. "Résultat correct" est retourné comme résultat de la recherche et les informations demandées par l'utilisateur sont renvoyées comme résultat de la recherche, mais "bruit de recherche" est renvoyé comme information non demandée par l'utilisateur. Les informations qui ne sont pas incluses dans les résultats sont appelées «recherche manquante».

Par ailleurs, dans le domaine de la recherche d'informations, ils sont appelés respectivement "True Positive", "Flase Positive" et "False Negative".

Sur cette figure, l'état avec beaucoup d'omissions de recherche correspond au premier état expliqué ci-dessus, et l'état avec beaucoup de bruit de recherche correspond au deuxième état. Améliorer les résultats de la recherche n'est rien de plus que de réduire le nombre de bruits de recherche et d'omissions et de faire correspondre les résultats de la recherche avec les informations souhaitées.

Cependant, réduire ces deux éléments est un compromis. Souvent, améliorer l'un aggravera l'autre.

Types d'index de recherche et leurs avantages / inconvénients

Cette section décrit le traitement d'index effectué dans le moteur de recherche de texte intégral et la décomposition de mot effectuée avant cela. Le moteur de recherche en texte intégral crée un index appelé index transposé pour accélérer le processus de recherche. L'indice de translocation est un tableau associatif dans lequel un mot dans une phrase est utilisé comme clé et la séquence de documents dans laquelle le mot apparaît est utilisée comme valeur.

Ceci est expliqué en détail dans la première moitié de l'article TECH BLOG publié l'autre jour, alors jetez un œil. http://tech.vasily.jp/entry/solr6-neologd

Afin de générer un index transposé, le document doit être décomposé en mots. Il existe deux méthodes de décomposition des mots, comme le japonais, dans lequel les mots ne sont pas séparés par des espaces, le Ngram et l'analyse morphologique.

Je vais expliquer chaque fonctionnalité.

Ngram Ngram est une méthode de division mécanique des phrases en N caractères et de les décomposer en mots. La partie N change en fonction du nombre de caractères séparés, et elle est également appelée bigramme lorsque N = 2 et trigramme lorsque N = 3. Désormais, N = 2 (bigramme) sera utilisé pour l'explication.

bigram sépare le document de deux caractères et considère le résultat comme un mot. Par exemple, le document "Tokyo Metropolitan Museum of Art" se décompose en cinq mots.

"Tokyo" "Kyoto" "Tomi" "Art" "Art Museum"

Ensuite, lors d'une recherche, la requête de recherche est de même divisée en mots et combinée avec leur ET. Par exemple, pour la requête de recherche "Musée", recherchez sous la condition "Art AND Art Museum".

L'avantage de Ngram est que cela garantit qu'il n'y a aucune recherche manquante pour une sous-chaîne de N caractères ou plus. D'autre part, l'inconvénient de Ngram est que ce "Tokyo Metropolitan Museum of Art" est touché même pour la requête de recherche "Kyoto".

Avantages: recherche de correspondance partielle garantie Inconvénients: bruit de recherche élevé

Analyse morphologique

Pour la division des mots par analyse morphologique, la division des mots est effectuée en unités grammaticalement significatives à l'aide d'un dictionnaire préparé à l'avance. Par conséquent, l'avantage est que les problèmes lors de l'utilisation de Ngram sont peu susceptibles de se produire.

D'autre part, il est nécessaire de préparer un dictionnaire à l'avance, et si les performances du dictionnaire sont faibles, les performances de recherche se détérioreront. Par exemple, si vous décomposez «gouvernement étranger» en «étranger», «carotte» et «gouvernement», le document n'atteindra pas la requête de recherche «gouvernement».

De plus, kuromoji, qui est un analyseur morphologique installé en standard dans Solr et Elastic Search, utilise un dictionnaire IPA, mais ce dictionnaire a une faiblesse qu'il n'est pas si fort par rapport à la nomenclature appropriée dans un domaine spécifique. En conséquence, une nomenclature appropriée qui devrait à l'origine être un mot est souvent décomposée en plusieurs mots. Exemple: "Rokushitan" → "Roku" "Shitan"

D'autre part, il y a un autre problème à utiliser une nomenclature appropriée comme un mot. Par exemple, si vous indexez la nomenclature appropriée «Aéroport international du Kansai» en un seul mot, les documents contenant «Aéroport international du Kansai» ne seront pas consultés dans les requêtes de recherche telles que «Aéroport international» et «Aéroport». Pour résoudre ce problème, kuromoji a pour fonction de diviser davantage le mot "Kansai International Airport" et d'indexer un total de 4 mots dont les 3 mots "Kansai", "International" et "Airport". Cependant, un tel comportement dépend également du dictionnaire et de l'analyseur morphologique, et il n'y a aucune garantie que la recherche de correspondance partielle sera possible.

Avantages: faible bruit de recherche Inconvénient: il existe de nombreuses omissions de recherche en fonction des performances du dictionnaire

Analyse morphologique combinée et Ngram

Les avantages et inconvénients de Ngram et de l'analyse morphologique sont résumés dans le tableau ci-dessous en termes de nombre de bruits de recherche et de nombre d'omissions de recherche.

Bruit de recherche Omission de recherche
Ngram Beaucoup Peu
Analyse morphologique Peu Beaucoup

Cette figure montre également qu'il existe un compromis entre la réduction du bruit de recherche et la réduction des omissions de recherche.

Cependant, en utilisant ces deux ensemble, il est possible de réduire le nombre d'omissions de recherche et le nombre de bruits de recherche sensiblement par rapport au cas où chacun est utilisé seul.

La méthode spécifique pour les utiliser ensemble est la suivante.

** Processus de génération d'index **

  1. Générez un index Ngram pour votre document
  2. Générer un index par analyse morphologique

** Processus de recherche **

  1. Rechercher Ngram et indexer par analyse morphologique en même temps
  2. Fusionner les résultats de la recherche avec les poids afin que les résultats d'index de l'analyse morphologique soient susceptibles d'être en haut.

スクリーンショット 2017-02-15 20.49.32.png

Réduisez les omissions de recherche en fusionnant deux résultats de recherche. Cependant, la simple fusion augmentera le bruit de recherche. La clé de ce traitement combiné est de fusionner les résultats de l'analyse morphologique afin qu'ils soient susceptibles d'être au début. Lorsque les utilisateurs regardent les résultats de la recherche, ils commencent par le début, donc s'il y a des informations qu'ils veulent au début, ils peuvent être satisfaits et arrêter de regarder les résultats suivants. Dans de tels cas, on peut considérer que le bruit de recherche n'a pas augmenté sensiblement.

Comment faire une requête avec Solr qui utilise l'analyse morphologique et Ngram ensemble

Explique comment écrire un fichier de paramètres Solr spécifique et comment écrire une requête.

J'ai confirmé ces comportements dans Solr 6.2.1, mais je n'écris pas dans une version spécifique, donc je pense que cela fonctionnera dans d'autres versions de Solr.

Méthode de génération d'index

Le premier est la partie de génération d'index. Écrivez les trois informations suivantes dans le schéma géré.

Définition du type de champ

Il définit text_ja_ngram, qui est un fieldType pour la génération d'index dans Ngram, et text_ja, qui est un champ pour la génération d'index dans l'analyse morphologique.

<fieldType name="text_ja_ngram" class="solr.TextField" autoGeneratePhraseQueries="true" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.ICUNormalizer2CharFilterFactory" name="nfkc"/>
    <tokenizer class="solr.NGramTokenizerFactory" minGramSize="2" maxGramSize="2"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

<fieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.ICUNormalizer2CharFilterFactory" name="nfkc"/>
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.StopFilterFactory" words="lang/stopwords_ja.txt" ignoreCase="true"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

Définition du champ

Définissez ensuite les champs pour ces fieldTypes.

<field name="search_ngram" type="text_ja_ngram" multiValued="true" indexed="true" required="false" stored="true"/>
<field name="search" type="text_ja" multiValued="true" indexed="true" required="false" stored="true"/>

Copie de données à partir d'autres champs

Enfin, utilisez copyField pour copier le champ que vous souhaitez rechercher dans les deux champs ci-dessus.

<copyField source="title" dest="search_ngram" />
<copyField source="title" dest="search" />
<copyField source="description" dest="search_ngram" />
<copyField source="description" dest="search" />
...

Ceci termine le paramétrage de la partie de génération d'index. Essayons de confirmer que ceux-ci fonctionnent correctement avec la fonction d'analyse.

スクリーンショット 2017-02-13 20.30.23.png

Comment lancer une requête

Voici une requête à lancer sur ces champs.

Utilisez la requête eDisMax pour rechercher dans plusieurs champs. Vous pouvez effectuer une recherche à l'aide des deux champs en effectuant une requête avec les paramètres suivants.

Les 100 et 50 spécifiés par qf sont les poids des champs respectifs. Plus le poids est élevé, plus il est facile pour le document qui touche le champ d'apparaître en premier. Pour régler ici, il est nécessaire de changer la valeur tout en regardant les résultats de la recherche.

Résumé

En utilisant l'analyse morphologique et Ngram ensemble, nous avons pu réduire les omissions de recherche et supprimer l'augmentation du bruit de recherche. En conséquence, iQON a permis de rechercher des produits par l'abréviation de la marque. Par exemple, vous pouvez maintenant frapper le produit "JIMMY CHOO" avec la requête de recherche "JIMMY".

Recommended Posts

Comment réaliser une recherche hybride en utilisant l'analyse morphologique et Ngram avec Solr
Comment déployer sur AWS à l'aide de NUXTJS S3 et CloudFront officiels? Avec docker-compose
Comment sortir Excel et PDF avec Excella
Comment exécuter une méthode et simuler avec JUnit
Comment jouer de la voix ou de la musique en utilisant javascript
Comment créer une API avec GraphQL et Rails
[Docker] Comment mettre à jour à l'aide d'un conteneur dans Heroku et comment gérer l'erreur de migration
Comment faire un test unitaire avec JVM sur une source à l'aide de RxAndroid
Comment sérialiser et désérialiser le type LocalDateTime avec GSON
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Comment installer Gradle et Kotlin avec SDKMAN (Mac)
Comment tester avec des images lors de l'utilisation d'ActiveStorage et de Faker
Comment définir des variables d'environnement lors de l'utilisation de Payjp avec Rails
Comment transformer des figurines ARKit et SceneKit avec Metal Shader
Comment définir et décrire des variables d'environnement à l'aide de Rails zsh
Comment créer une application à l'aide de Tensorflow avec Android Studio
Comment joindre une table sans utiliser DBFlute et SQL
Obtenez des résultats détaillés de l'analyse morphologique avec Apache Solr 7.6 + SolrJ
Comment démarrer avec JDBC en utilisant PostgresSQL sur MacOS
Comment s'inscrire en tant que client dans Square à l'aide de Tomcat
Comment gérer différentes versions de rbenv et Ruby
Comment numéroter (nombre) avec html.erb
Comment mettre à jour avec activerecord-import
Comment autoriser à l'aide de graphql-ruby
Obtenez des résultats détaillés de l'analyse morphologique avec Apache Solr 7.6 + SolrJ (japonais)
Comment réaliser un téléchargement de fichiers volumineux avec TERASOLUNA 5.x (= Spring MVC)
Comment POST JSON dans la méthode Java en utilisant OkHttp3 et la méthode en utilisant HttpUrlConnection-
[Rails] Comment introduire le kaminari avec Slim et changer le design
À propos de TestSize préconisé par Google et comment réaliser TestSize par Java et Maven
[Astuces] Comment résoudre les problèmes avec XCode et Swift pour les débutants
[Rails] Comment télécharger des images sur AWS S3 à l'aide de Carrierwave et de fog-aws
[Rails] Comment télécharger des images sur AWS S3 à l'aide de refile et refile-s3
Comment réaliser un téléchargement de fichiers volumineux avec Rest Template of Spring
[Ruby on Rails] Comment se connecter avec seulement votre nom et mot de passe en utilisant le bijou