<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BM25 &#8211; Solr.pl</title>
	<atom:link href="https://solr.pl/tag/bm25/feed/" rel="self" type="application/rss+xml" />
	<link>https://solr.pl</link>
	<description>All things to be found - Blog related to Apache Solr &#38; Lucene projects - https://solr.apache.org</description>
	<lastBuildDate>Sat, 14 Nov 2020 11:52:45 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
	<item>
		<title>Rozproszone obliczanie IDF</title>
		<link>https://solr.pl/2019/05/20/rozproszone-obliczanie-idf/</link>
					<comments>https://solr.pl/2019/05/20/rozproszone-obliczanie-idf/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Mon, 20 May 2019 10:52:15 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[BM25]]></category>
		<category><![CDATA[idf]]></category>
		<category><![CDATA[relevancy]]></category>
		<category><![CDATA[tf]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=786</guid>

					<description><![CDATA[Korzystając z SolrCloud, kiedy nasza kolekcja rozproszona jest pomiędzy wiele instancji Solr dotyka nas problem związany z obliczaniem tzw. odwrotnej częstotliwości dokumentu, czyli zmiennej określającej w jak dużej liczbie dokumentów występuje dany term. Problem w tym, iż domyślnie każda instanacja]]></description>
										<content:encoded><![CDATA[
<p>Korzystając z SolrCloud, kiedy nasza kolekcja rozproszona jest pomiędzy wiele instancji Solr dotyka nas problem związany z obliczaniem tzw. odwrotnej częstotliwości dokumentu, czyli zmiennej określającej w jak dużej liczbie dokumentów występuje dany term. Problem w tym, iż domyślnie każda instanacja Solr trzyma dane na temat tej częstotliwości tylko sobie i nie dzieli się z innymi <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> A co za tym idzie, im bardziej rozproszona jest nasza kolekcja, tym mniejsza jest precyzja naszego wyszukiwania. Zobaczmy zatem co możemy na to poradzić. </p>



<span id="more-786"></span>



<h2 class="wp-block-heading">IDF i Solr</h2>



<p>Wraz z premierą <a href="https://solr.pl/2016/04/08/lucene-i-solr-6-0/">Lucene i Solr 6.0</a> domyślny algortym odpowiadający za score TF/IDF został zastąpiony algorytmem BM25, który powinien spisywać się lepiej ze względu na ograniczenia związane z maksymalnym wpływem częstotliwości termu. </p>



<p>W algorytmie BM25 współczynnik IDF obliczany jest w następujący sposób:</p>



<pre class="wp-block-preformatted">log(1 + (docCount - docFreq + 0.5)/(docFreq + 0.5))</pre>



<p>Oznacza to, iż wartość IDF jest dużo szybciej i mocniej ograniczana w przypadku często występujących termów porównując to algorytmu TF/IDF obecnego przez we wcześniejszych wersjach Lucene i Solr. </p>



<p>Problemem jest to, iż informacja ja, domyślnie nie jest rozproszona. Oznacza to, że każdy shard przechowuje te informacje powodując, iż im bardziej kolekcja jest rozproszona, tym mniejsza dokładność. W większości przypadków nie jest to problem, jednak są takie gdzie jest to jednak coś, czym zaczynamy się przejmować. Dodatkowo, zmiany w architekturze kolekcji powodują zmiany w wyliczanym współczynniku score, nawet przy tych samych dokumentach. Jest to czasem niedopuszczalne. </p>



<h2 class="wp-block-heading">Rozproszone IDF</h2>



<p>Wraz z Solr 5.0 wprowadzona została możliwość skonfigurowania Solr do korzystania z rozproszonego obliczania IDF. Wystarczy do pliku <em>solrconfig.xml</em> dodać definicję <em>statsCache</em> i to wszystko. Na przykład:</p>



<pre class="wp-block-preformatted">&lt;statsCache class="org.apache.solr.search.stats.ExactStatsCache" /&gt;</pre>



<p>Proste prawda? Spójrzmy zatem jakie mamy opcje jeżeli chodzi o implementację:</p>



<p><em><strong>LocalStatsCache</strong></em> &#8211; domyślna implementacja, kiedy nie mamy zdefiniowanego elementu <em>statsCache</em> w pliku <em>solrconfig.xml</em>. W tym wypadku sytuacja jest bardzo prosta &#8211; brak rozproszonego obliczania współczynnika IDF.</p>



<p><strong><em>ExactStatsCache</em></strong> &#8211; implementacja cacheująca statystyki dotyczące termów wymagająca dodatkowego kroku podczas przetwarzania zapytania, tak aby zapytanie było analizowane na każdym shardzie wchodzącym w skład kolekcji. Może skutkować spadkiem wydajności zapytań ze względu na dodatkowe operacje.</p>



<p><strong><em>ExactSharedStatsCache</em></strong> &#8211;  implementacja podobna do opisywanej powyżej z tą różnicą, iż statystki są współdzielone pomiędzy żądaniami. Może skutkować większą wydajnością, niż <em><strong>ExactStatsCa</strong></em><em style="font-weight: bold;">che</em>, ale cechować go będzie większe wykorzystanie pamięci.</p>



<p><strong><em>LRUStatsCache</em></strong> &#8211; w odróżnieniu do <em><strong>ExactStatsCache</strong></em> implementacja przechowująca statystyki dotyczące termów w <a href="https://pl.wikipedia.org/wiki/Least_Recently_Used">LRU cache</a>. Bazując na informacjach w cache&#8217;u Solr jest w stanie określić, czy dodatkowe zapytania są potrzebne tym samym zmniejszając ich częstotliwość, a tym samym zwiększając wydajność zapytań. Termy przechowywane są w mapach &#8211; liczba map determinowana jest liczbą shardów z których składa się kolekcja &#8211; map będzie tyle, ile jest shardów, a każdy shard trzyma jedną mapę ze statystykami termów.</p>



<h2 class="wp-block-heading">Czy to działa?</h2>



<p>Na tak postawione pytanie możemy odpowiedzieć tylko &#8211; trzeba to po prostu sprawdzić. W tym celu stworzymy dwie kolekcje <em>distrib_idf</em> oraz <em>non_distrib_idf</em> oraz zaindeksujemy przykładowe dane (konfigurację i dane można znaleźć na naszym Githubie &#8211; <a href="https://github.com/solrpl/blog">https://github.com/solrpl/blog</a>). Każda z kolekcji będzie miała dwa shardy, jedną replikę, a sam klaster SolrCloud będzie składał się z dwóch instancji Solr.</p>



<p>Po zaindeksowaniu kilku przykładowych dokumentów możemy sprawdzić różnicę w wyliczaniu score zadając następujące zapytanie do każdej z kolekcji:</p>



<pre class="wp-block-preformatted">.../select?q=title:solr&amp;fl=*,score</pre>



<p>W przypadku kolekcji, która została skonfigurowana bez <em><strong>statsCache</strong></em> wyniki wyglądają następująco:</p>



<pre class="wp-block-preformatted">{
   "responseHeader":{
     "zkConnected":true,
     "status":0,
     "QTime":7,
     "params":{
       "q":"title:solr",
       "fl":"*,score"}},
   "response":{"numFound":4,"start":0,"maxScore":0.082873434,"docs":[
       {
         "id":"2",
         "title":["Solr document two"],
         "<em>version</em>":1633875263859195904,
         "score":0.082873434},
       {
         "id":"3",
         "title":["Solr document three"],
         "<em>version</em>":1633875263924207616,
         "score":0.082873434},
       {
         "id":"1",
         "title":["Solr document one"],
         "<em>version</em>":1633875263562448896,
         "score":0.082873434},
       {
         "id":"4",
         "title":["Solr document four"],
         "<em>version</em>":1633875263679889408,
         "score":0.082873434}]
   }}</pre>



<p>W przypadku kolekcji w której <em><strong>statsCache</strong></em> jest skonfigurowany wyniki wyglądają następująco:</p>



<pre class="wp-block-preformatted">{
   "responseHeader":{
     "zkConnected":true,
     "status":0,
     "QTime":12,
     "params":{
       "q":"title:solr",
       "fl":"*,score"}},
   "response":{"numFound":4,"start":0,"maxScore":0.04789114,"docs":[
       {
         "id":"2",
         "title":["Solr document two"],
         "<em>version</em>":1633875264251363328,
         "score":0.04789114},
       {
         "id":"3",
         "title":["Solr document three"],
         "<em>version</em>":1633875264254509056,
         "score":0.04789114},
       {
         "id":"1",
         "title":["Solr document one"],
         "<em>version</em>":1633875264186351616,
         "score":0.04789114},
       {
         "id":"4",
         "title":["Solr document four"],
         "<em>version</em>":1633875264189497344,
         "score":0.04789114}]
   }}</pre>



<p>Jest to oczywiście bardzo prosty przykład, jednak jak widać w przypadku kolekcji w której nie mamy skonfigurowanego <em><strong>statsCache</strong></em> score dokumentów jest prawie dwa razy wyższy. Ma to sens biorąc pod uwagę, iż term <strong><em>solr</em></strong> występuje w polu <strong><em>title</em></strong> cztery razy, po dwa razy w każdym shardzie. Oznacza to, iż kolekcja bez skonfigurowanego rozproszonego wyliczania IDF nie widzi pełnych danych.</p>



<h2 class="wp-block-heading">Podsumowanie</h2>



<p>Brak rozproszonego obliczania współczynnika IDF może powodować problemy &#8211; wtedy, kiedy jakość wyników wyszukiwania jest dla nas szczególnie ważna. Na szczęście, od wersji 5 silnika wyszukiwania Solr jesteśmy w stanie w bardzo prosty sposób włączyć rozproszony cache statystyk termów, a tym samym całkowicie rozprawić się z problemem. Oczywiście należy pamiętać, iż włączenie mechanizmu <strong><em>statsCache</em></strong> niesie za sobą obniżenie wydajności zapytań ze względu na konieczność dodatkowych operacji. Powodzenia <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2019/05/20/rozproszone-obliczanie-idf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
