2017-04-11 7 views
6

मैं युक्त PostgreSQL में एक टेबल कुछ कारों 1,000,000 रिकॉर्ड:postgresql में बहु-कॉलम अनुशंसा इंजन कैसे बनाएं?

+----+--------+------+---------+-----------+-------------+------------+------------+ 
| id | price | year | mileage | fuel_type | body_type | brand | model | 
+----+--------+------+---------+-----------+-------------+------------+------------+ 
| 1 | 4894 | 2011 | 121842 | "Benzin" | "Sedan"  | "Toyota" | "Yaris" | 
| 2 | 4989 | 2012 | 33901 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 3 | 4990 | 2013 | 55105 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 3 | 5290 | 2013 | 20967 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 5 | 5594 | 2008 | 121281 | "Benzin" | "Hatchback" | "Mercedes" | "A170"  | 
| 6 | 4690 | 2012 | 71303 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 7 | 5290 | 2013 | 58300 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 8 | 5890 | 2013 | 35732 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 9 | 5990 | 2013 | 38777 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
| 10 | 6180 | 2013 | 69491 | "Benzin" | "Hatchback" | "VW"  | "up!"  | 
| 11 | 6490 | 2012 | 72900 | "Benzin" | "Sedan"  | "Renault" | "Clio III" | 
| 12 | 6790 | 2012 | 49541 | "Benzin" | "Hatchback" | "Renault" | "Clio III" | 
| 13 | 6790 | 2012 | 46377 | "Benzin" | "Hatchback" | "Renault" | "Clio III" | 
| 14 | 6790 | 2012 | 45200 | "Benzin" | "Hatchback" | "Renault" | "Clio III" | 
| 15 | 6894 | 2007 | 108840 | "Benzin" | "Sedan"  | "VW"  | "Golf V" | 
| 16 | 6990 | 2009 | 54200 | "Benzin" | "Sedan"  | "Renault" | "Mégane" | 
| 17 | 6990 | 2012 | 40652 | "Benzin" | "Hatchback" | "Renault" | "Clio III" | 
| 18 | 6990 | 2012 | 38080 | "Benzin" | "Sedan"  | "Renault" | "Clio III" | 
| 19 | 7290 | 2012 | 28600 | "Benzin" | "Hatchback" | "Renault" | "Clio III" | 
| 20 | 7290 | 2013 | 52800 | "Benzin" | "Hatchback" | "Renault" | "Twingo" | 
+----+--------+------+---------+-----------+-------------+------------+------------+ 

मैं एक सिफारिश इंजन बनाने के लिए चाहते हैं, कि 20 सबसे "समान" कुछ अलग मापदंड पर जैसे आधारित मैचों लौट सकते हैं जब कोई उपयोगकर्ता खोज करता है: brand = 'Renault' AND price < 60000 AND year > 2010, मैं खोज परिणाम के बाहर कुछ अन्य, अन्य कारों के साथ अधिक ढीले परिणाम प्रस्तुत करना चाहता हूं, जो समान है, लेकिन सभी खोज मानदंडों को सटीक रूप से मेल नहीं खाता है।

मैं रूबी में कुछ नियम आधारित कोड बनाने की कोशिश की है, ऐसा ही कुछ करता है:

  • आप एक 'रेनॉल्ट क्लियो' के आधार पर खोज अगर हम तो'Renault Twingo' एक करीबी मैच भी
  • तो है आप अधिकतम कि
  • आदि आदि

इस कोड के आधार पर करने के लिए उन निकटतम से तो आदेश 8000 की कीमत है, मैं के साथ एक SQL क्वेरी उत्पन्न जहां और खंड द्वारा आदेश।

हालांकि समस्या यह है कि चीजें बहुत बड़ी हैं, क्योंकि मेरे पास 20 अलग-अलग कॉलम हैं जिन्हें मैं वैकल्पिक रूप से विचार करना चाहता हूं, प्रारंभिक मानदंडों पर आधार। इसके अलावा, मैं इस अर्थ में पिछड़ा संगत होने की सिफारिश चाहता हूं कि मैं केवल एक साधारण फ़िल्टरिंग (WHERE) क्वेरी नहीं करना चाहता, कि मामले में शून्य मिलान लौट सकते हैं। इसके बजाय मैं चाहता हूं कि जब आप पाठ समानता एल्गोरिदम का उपयोग करते हैं, तो आप ऐसा कुछ भी करते हैं, जहां आप एक वाक्यांश की तुलना कर सकते हैं और उन सभी के लिए तुलना स्कोर प्राप्त कर सकते हैं जिन्हें आप क्रमबद्ध कर सकते हैं।

मैं इस बारे में बहुत परेशान हूं कि मैं इसे कैसे कार्यान्वित कर सकता हूं, एक दृष्टिकोण में यह 1000 नियमों को परिभाषित नहीं कर रहा है और यदि/तो SQL क्वेरी उत्पन्न करने के लिए कथन। क्या कोई अन्य तकनीक है जिसका उपयोग मैं कर सकता हूं, या शायद पोस्टग्रेस्क्ल की तुलना में एक और तकनीक?

+0

मुझे डर है कि यह एक स्टैक ओवरफ्लो प्रश्न में हल करने के लिए बहुत मुश्किल (और अस्पष्ट) है। एसक्यूएल सटीक मिलान करने में आम तौर पर अच्छा होता है, लेकिन एक विशिष्ट कार मॉडल की तरह "कुछ" खोजना इसकी मूल क्षमताओं से परे है। मुझे एक (अपेक्षाकृत) सरल "अनुमानित" नाम मिलान लागू करना पड़ा और मैंने कुछ हद तक * अनुमानित क्वेरी परिणाम (और गति) प्राप्त करने में सक्षम होने के लिए एक ट्रिगर में एक विशेष उद्देश्य सूचकांक तैयार करना समाप्त कर दिया। मुझे डर है कि आपको छोटे से शुरू करना होगा और वहां से बढ़ना होगा। – Patru

उत्तर

1

मशीन लर्निंग तकनीक लागू करें: उदाहरण के लिए, यदि क्वेरी एक ब्रांड वांछित एक अन्य की तुलना में वापस नहीं लौट सकते तो यह कोई मतलब नहीं इस संपत्ति का विचलन की गणना करने के लिए बनाता है।

MADlib http://madlib.incubator.apache.org/ पोस्टग्रेज़ का एक विस्तार है जो आपको डेटाबेस के अंदर विभिन्न मशीन लर्निंग एल्गोरिदम के साथ काम करने की क्षमता देता है। सीखना और कोशिश करना उचित है।

अपने वैक्टरों के लिए रैखिक प्रतिगमन के साथ शुरू करें और फिर यादृच्छिक जंगलों और अन्य एल्गोरिदम का भी प्रयास करें और तुलना करें कि आपके मामले में बेहतर क्या काम करता है (एल्गोरिदम की गुणवत्ता का मूल्यांकन करने की चाल सरल है: आप अपने सभी डेटा लेते हैं, 70 का उपयोग करते हैं प्रशिक्षित करने के लिए -80% प्रशिक्षित करने के लिए, और फिर प्रशिक्षित इंजन से अनुमान प्राप्त करने के लिए शेष का उपयोग करें - और फिर विचलन त्रुटि की गणना करने के लिए कुछ फ़ंक्शन का उपयोग करें, आमतौर पर लोग माध्य वर्ग त्रुटि दृष्टिकोण का उपयोग करते हैं)।

इसके अलावा, मैं यूट्यूब (सभी मुफ्त!) पर प्रकाशित ऑनलाइन पुस्तक और व्याख्यान के साथ एक भयानक स्टैनफोर्ड ऑनलाइन पाठ्यक्रम की सिफारिश कर सकता हूं: http://mmds.org/। सिफारिश इंजन बनाने के लिए विभिन्न आधुनिक दृष्टिकोणों में इसका वर्णन बहुत अच्छा है।

0

आदर्श रूप से, आप tsvector टाइप वाले कॉलम में "टेक्स्ट भाग" (पंक्ति से संबंधित प्रत्येक पाठ) को कैश कर सकते हैं, इससे आपको पूर्ण टेक्स्ट खोज करने की क्षमता मिल जाएगी और यहां तक ​​कि प्रत्येक शब्द को "वज़न" ताकि खोज करने पर यह अधिक महत्वपूर्ण हो।

उदाहरण के लिए, आप ब्रांड नाम पर अधिक वजन दे सकते हैं ताकि परिणामों को उसी ब्रांड के सभी दिखाए हुए दिमाग में हल किया जा सके। आइए मान लीजिए कि आपके पास "फुलटेक्स्ट" नामक एक सर्वेक्षक कॉलम है: 'Clio:1A Renault:2B,4C Benzin:5D'::tsvector;, आप इसे tsquery के साथ 'Renault & Clio'::tsquery; जैसे खोज सकते हैं और यह प्रत्येक रेनॉल्ट और प्रत्येक क्लियो के लिए परिणाम देगा, लेकिन यह शीर्ष Clio पहले और Renault पर अगला होगा। ध्यान रखें कि अगर किसी भी मौके से Mercedes Clio मौजूद है, तो यह भी दिखाएगा।

दस्तावेज़ीकरण बहुत स्पष्ट है और कुछ उदाहरणों के साथ, मैं इसमें खुदाई करने की सलाह देता हूं।

कहा जा रहा है कि डेटाबेस इस मामले में आपके लिए काम नहीं करेगा। यदि क्लियो केवल एक करीबी मैच है क्योंकि उनके पास एक ही ब्रांड (रेनॉल्ट) है, तो यह चाल चल जाएगा। हालांकि यदि आप कार के आकार की तरह अन्य तर्कों (मानसिक रूप से) का उपयोग करते हैं, यदि यह शहर की कार और ऐसी चीजें हैं, तो आप अकेले हैं जो उस एल्गोरिदम को डिज़ाइन कर सकते हैं। उदाहरण के लिए मूल्य सीमा भाग ऐसा कुछ नहीं है जो आपके लिए कोई भी पूर्ण पाठ खोज करेगा, आपको सक्रिय रूप से यह जांचना होगा कि कोई संख्या शामिल है या अंततः सॉर्ट करें (जब तक कि कोई सटीक मिलान न हो)।

अंत में, आपका काम ठीक उसी तरह होगा, उपयोगकर्ता इनपुट के आधार पर "स्मार्ट" एक फ़ंक्शन बनाएं और एक जटिल क्वेरी को परिभाषित करेगा जिसे आप डेटाबेस के विरुद्ध चला सकते हैं। यह एक लंबी प्रक्रिया है लेकिन निश्चित रूप से करने योग्य है। स्मार्ट होने की कोशिश करें लेकिन बहुत अधिक नहीं है और किसी भी मामले में tsvector आपको सभी टेक्स्ट कॉलम के लिए कवर करेगा, जो आपके पास कितने कॉलम कम करेगा।

6

की गणना प्रत्येक संख्यात्मक संपत्ति के लिए भारित विचलन:

deviation = abs(actual_value- expected_value)* property_weight 

शाब्दिक संपत्तियों के लिए एक सरल गणना लागू करें:

deviation = (actual_value <> expected_value)::int* property_weight 

सिफारिश विचलन का योग के आरोही क्रम में पदों।

उदाहरण। हम लाभ 50000 और कीमत 6000 के साथ 2012 से रेनॉल्ट Twingo हैचबैक के लिए देख रहे हैं:

select *, 
    abs(price- 6000)* 100+ 
    abs(year- 2012)* 10000+ 
    abs(mileage- 50000)* 1+ 
    (body_type <> 'Hatchback')::int* 40000+ 
    (brand <> 'Renault')::int* 100000+ 
    (model <> 'Twingo')::int* 50000 
    as recommendation 
from cars 
order by recommendation 
limit 10; 

id | price | year | mileage | fuel_type | body_type | brand | model | recommendation 
----+-------+------+---------+-----------+-----------+---------+----------+---------------- 
    9 | 5990 | 2013 | 38777 | Benzin | Hatchback | Renault | Twingo |   22223 
    8 | 5890 | 2013 | 35732 | Benzin | Hatchback | Renault | Twingo |   35268 
    7 | 5290 | 2013 | 58300 | Benzin | Hatchback | Renault | Twingo |   89300 
    4 | 5290 | 2013 | 20967 | Benzin | Hatchback | Renault | Twingo |   110033 
    3 | 4990 | 2013 | 55105 | Benzin | Hatchback | Renault | Twingo |   116105 
    2 | 4989 | 2012 | 33901 | Benzin | Hatchback | Renault | Twingo |   117199 
12 | 6790 | 2012 | 49541 | Benzin | Hatchback | Renault | Clio III |   129459 
13 | 6790 | 2012 | 46377 | Benzin | Hatchback | Renault | Clio III |   132623 
14 | 6790 | 2012 | 45200 | Benzin | Hatchback | Renault | Clio III |   133800 
20 | 7290 | 2013 | 52800 | Benzin | Hatchback | Renault | Twingo |   141800 
(10 rows) 

आप आसानी से गुणों का वजन बदलकर एल्गोरिथ्म जांच कर सकते हैं।

प्राप्त करने के लिए शाब्दिक संपत्तियों की अधिक sophistcated अनुमान आप इस तरह सहायक तालिकाओं में प्रॉपर्टीज़ के लिए संख्यात्मक मान असाइन कर सकते हैं:

create table models(id serial primary key, model text, value integer); 
insert into models (model, value) values 
('Twingo', 10), 
('Clio III', 11), -- Clio is more similar to Twingo than to Laguna 
('Laguna', 18) 
--- etc 

और मुख्य क्वेरी में संख्यात्मक गुण के रूप में मूल्यों का उपयोग, जैसे:

select cars.*, 
    abs(price- 6000)* 100+ 
    abs(year- 2012)* 10000+ 
    abs(mileage- 50000)* 1+ 
    (body_type <> 'Hatchback')::int* 40000+ 
    (brand <> 'Renault')::int* 100000+ 
    abs(models.value- 10)* 50000 -- 10 is a numeric value for Twingo 
    as recommendation 
from cars 
join models using(model) 
order by recommendation 
limit 10; 

अनुकूलन पर एक नोट। यदि आप किसी भी संपत्ति के दायरे को कठोर रूप से परिभाषित कर सकते हैं, तो इसे बेहतर प्रदर्शन के लिए WHERE खंड में रखें।

select *, 
    abs(price- 6000)* 100+ 
    abs(year- 2012)* 10000+ 
    abs(mileage- 50000)* 1+ 
    (body_type <> 'Hatchback')::int* 40000+ 
    (model <> 'Twingo')::int* 50000 
    as recommendation 
from cars 
where brand = 'Renault' -- ! 
order by recommendation 
limit 10; 
संबंधित मुद्दे