फजी खोज कार्यान्वयन



यदि आपका वेब प्रोजेक्ट किसी तरह से उपयोगकर्ताओं के लिए कुछ डेटा की खोज और प्रावधान से जुड़ा हुआ है, तो आपको संभवतः खोज स्ट्रिंग को लागू करने के कार्य के साथ सामना करना होगा। उसी समय, यदि किसी कारण से परियोजना में Google या यांडेक्स जैसी स्मार्ट सेवाओं की तकनीकों का उपयोग करना संभव नहीं है, तो खोज को आंशिक रूप से या पूरी तरह से स्वतंत्र रूप से लागू करना होगा। उप-कार्यों में से एक संभवतः फजी खोज का कार्यान्वयन होगा, क्योंकि उपयोगकर्ताओं को अक्सर गलत किया जाता है और कभी-कभी सटीक शब्द, नाम या नाम नहीं पता होता है।

यह आलेख फ़ज़ी खोज के संभावित कार्यान्वयन का वर्णन करता है, जिसका उपयोग साइट edatuda.ru पर खोज करने के लिए किया गया था।

कार्य
हमारे रेस्तरां, कैफे और बार खोज सेवा के निर्माण के हिस्से के रूप में, एक कार्य एक खोज पट्टी को लागू करने के लिए उत्पन्न हुआ जिसमें उपयोगकर्ता अपने संस्थानों के नामों का संकेत दे सकते हैं।
कार्य निम्नानुसार निर्धारित किया गया था:
  1. ड्रॉप-डाउन सूची में चयन प्रक्रिया में खोज परिणाम प्रदर्शित किए जाने चाहिए।
  2. खोज को उपयोगकर्ताओं की संभावित त्रुटियों और टाइपो को ध्यान में रखना चाहिए (उदाहरण के लिए, mcdonalds सिर्फ macdonalds टाइप करना चाहते हैं)।
  3. प्रत्येक संस्थान के लिए बहुत सारे समानार्थी शब्द सेट करने में सक्षम होना चाहिए (उदाहरण के लिए mcdonalds => makdak)।

आइटम 1-3 की दृश्य प्रस्तुति:



इस प्रकार, क्वेरी वाक्यांश प्राप्त करने की संभावना है, सबसे अधिक संभावना है, आपको पूर्व-संकलित शब्दकोश से लिखित में निकटतम प्रविष्टियों का चयन करने की आवश्यकता है। वास्तव में, कार्य टाइपोस को ठीक करना था जो आधुनिक खोज इंजन कर सकते हैं। इसे हल करने के सामान्य तरीकों में से एक:
  1. एन-ग्राम सूचकांक बनाने पर आधारित एक विधि।
    अच्छी, त्वरित और आसान विधि।
  2. दूरी आधारित संपादन विधि।
    संभवतः सबसे सटीक तरीकों में से एक जो संदर्भ को ध्यान में नहीं रखता है।
  3. दावा 1 और दावा 2 का मिलन।
    बड़े शब्दकोशों में खोज को गति देने के लिए, यह पहली बार धारा 2 के आवेदन के साथ n- ग्राम सूचकांक के आधार पर शब्दों के एक समूह का चयन करने के लिए समझ में आता है ( ज़ोबेल और डार्थ के काम को देखें "बड़े अक्षरों में अनुमानित मिलान ढूँढना )

एक हब्र पर पाठ और शब्दकोश में फजी खोज के लिए समर्पित एक अच्छा लेख था। यह अच्छी तरह से पैराग्राफ 1 और 2 का वर्णन करता है, विशेष रूप से, अच्छी तस्वीरों के साथ लेवेन्सहाइटिन और डेमेराउ-लेवेन्शिन की दूरी। इसलिए, यह आलेख इन विधियों का विस्तृत विवरण प्रदान नहीं करेगा।

कार्यान्वयन खोजें
हमारे मामले में, शब्दकोश कई हजार प्रविष्टियों के क्रम के रूप में बड़ा नहीं है (उदाहरण के लिए खोज इंजन के साथ), इसलिए हमने एन-ग्राम इंडेक्स का निर्माण किए बिना संपादन दूरी के आधार पर विधि का उपयोग करने का निर्णय लिया।
संपादन दूरी की गणना के लिए पारंपरिक एल्गोरिदम अच्छी तरह से लाइनों की निकटता का मूल्यांकन करते हैं, लेकिन पात्रों के बारे में किसी भी जानकारी का उपयोग नहीं करते हैं (उनकी समानता या असमानता को छोड़कर), जैसे कि कीबोर्ड पर पात्रों के बीच की दूरी या ध्वनि के निकटता के बीच की दूरी।
खाते में कुंजियों के बीच की दूरी को ध्यान में रखते हुए उपयोगी हो सकता है क्योंकि जब जल्दी से टाइप करते हैं, तो चूक के कारण बड़ी संख्या में त्रुटियां होती हैं, जबकि उपयोगकर्ता द्वारा गलती से अगली कुंजी दबाए जाने की संभावना अधिक दूरस्थ एक से अधिक है।
ध्वन्यात्मक नियमों को ध्यान में रखना भी महत्वपूर्ण है। उदाहरण के लिए, विदेशी नामों और शीर्षकों के मामले में, उपयोगकर्ता अक्सर शब्दों की सटीक वर्तनी नहीं जानते हैं, लेकिन उनकी ध्वनि याद रखते हैं।
ज़ॉबेल और डार्थ के काम में, "फ़ोनेटिक स्ट्रिंग मिलान: सूचना पुनर्प्राप्ति से सबक" एक स्ट्रिंग तुलना विधि का वर्णन करता है जो कि ध्वन्यात्मक नियमों के एक सेट के साथ संपादन दूरी की गणना को जोड़ती है (वाक्यांश "ध्वन्यात्मक नियम" पूरी तरह से सही नहीं है)। लेखकों ने कई ध्वन्यात्मक समूहों की पहचान की जिसमें वर्ण शामिल थे जो एक समूह के पात्रों को बदलने की "लागत" जब संपादन दूरी की गणना करते थे तो एक ही समूह से संबंधित पात्रों की जगह की "लागत" से कम नहीं थी। हमने इस विचार का उपयोग किया।
बुनियादी एल्गोरिथ्म के रूप में, हमने वैगनर-फिशर एल्गोरिथ्म को कई संशोधनों के साथ दमरेउ-लेवेनशेटिन दूरी को खोजने के लिए अनुकूलित किया:
  1. बुनियादी एल्गोरिथ्म में, सभी ऑपरेशनों की "लागत" है। हम सम्मिलित करने और हटाने के ऑपरेशन की "लागत" को 2 पर सेट करते हैं, एक्सचेंज ऑपरेशन को 1, और दूसरे के साथ एक वर्ण को बदलने के संचालन की गणना निम्नानुसार की जाती है: यदि तुलना किए गए वर्णों के अनुरूप कुंजी एक दूसरे के बगल में स्थित हैं। कीबोर्ड या तुलना वर्ण एक ध्वन्यात्मक समूह के हैं, तो प्रतिस्थापन की "लागत" 1 है, अन्यथा 2।
  2. नतीजतन, उपसर्ग दूरी वापस आ गई है, अर्थात्। शब्दकोश से क्वेरी शब्द और शब्द के सभी उपसर्गों के बीच न्यूनतम दूरी। यह आवश्यक है क्योंकि क्वेरी शब्द जो हम शब्दकोश रूपों के साथ तुलना करेंगे, आमतौर पर काट दिया जाएगा। यानी हम "mcdonalds" डिक्शनरी के साथ "mcd" दर्ज किए गए उपयोगकर्ता की तुलना कर सकते हैं और एक बड़ी दूरी (7 इन्सर्ट ऑपरेशंस) प्राप्त कर सकते हैं, हालाँकि इस मामले में "mcdonalds" क्वेरी बहुत ही सटीक रूप से मेल खाता है।

हमने मामूली बदलावों के साथ उपर्युक्त कार्य से ध्वन्यात्मक समूहों को लिया:


मूल काम में, समूहों की रचना मूल अंग्रेजी शब्दों की ध्वनि के आधार पर की गई थी, इसलिए इसमें कोई गारंटी नहीं है कि वे अनुवादित रूसी पाठ में एक अच्छा परिणाम दिखाएंगे। हमने अपने स्वयं के अवलोकनों के आधार पर छोटे बदलाव किए (उदाहरण के लिए, मूल "fpv" समूह से 'p' को हटा दिया गया)।

सी ++ में परिणामी कार्यान्वयन:
{{{ class EditDistance { public: int DamerauLevenshtein(const std::string& user_str, const std::string& dict_str) { size_t user_sz = user_str.size(); size_t dict_sz = dict_str.size(); for (size_t i = 0; i <= user_sz; ++i) { trace_[i][0] = i << 1; } for (size_t j = 1; j <= dict_sz; ++j) { trace_[0][j] = j << 1; } for (size_t j = 1; j <= dict_sz; ++j) { for (size_t i = 1; i <= user_sz; ++i) { //  ,    int rcost = ReplaceCost(user_str[i - 1], dict_str[j - 1]); int dist0 = trace_[i - 1][j] + 2; int dist1 = trace_[i][j - 1] + 2; int dist2 = trace_[i - 1][j - 1] + rcost; trace_[i][j] = std::min(dist0, std::min(dist1, dist2)); //   if (i > 1 && j > 1 && user_str[i - 1] == dict_str[j - 2] && user_str[i - 2] == dict_str[j - 1]) { trace_[i][j] = std::min(trace_[i][j], trace_[i - 2][j - 2] + 1); } } } //   //   int min_dist = trace_[user_sz][0]; for (size_t i = 1; i <= dict_sz; ++i) { if (trace_[user_sz][i] < min_dist) min_dist = trace_[user_sz][i]; } return min_dist; } private: const static size_t kMaxStrLength = 255; int trace_[kMaxStrLength + 1][kMaxStrLength + 1]; private: int ReplaceCost(unsigned char first, unsigned char second); } }}} 


ध्यान दें कि संक्षिप्त शब्दों में, उपयोगकर्ता, एक नियम के रूप में, ऐसे ब्लंडर को लंबे समय तक नहीं बनाते हैं। ऐसा करने के लिए, हम क्वेरी शब्द की लंबाई के लिए आनुपातिक शब्दों के बीच अधिकतम स्वीकार्य दूरी की दहलीज बनाते हैं।
 {{{ const double kMaxDistGrad = 1 / 3.0; ... uint32_t dist = distance_.DamerauLevenshtein(word, dict_form); if (dist <= (word.size() * kMaxDistGrad)) { // ok } }}} 


सूची
बता दें कि संस्थानों के लिए स्रोत के रिकॉर्ड हैं:
<मेटा डेटा: आईडी, ...> <संस्थान का नाम> <पर्याय रूप का नाम>
फिर सूचकांक को निम्नानुसार दर्शाया जा सकता है:

Source: https://habr.com/ru/post/In123320/


All Articles