2012-08-29 6 views
13

कम करें मेरे पास एक कंप्यूटर दृष्टि एल्गोरिदम है जिसे मैं scipy.optimize.minimize का उपयोग करके ट्यून करना चाहता हूं। अभी मैं केवल दो मानकों को ट्यून करना चाहता हूं लेकिन पैरामीटर की संख्या अंततः बढ़ सकती है इसलिए मैं ऐसी तकनीक का उपयोग करना चाहूंगा जो उच्च-आयामी ढाल खोजों को कर सके। SciPy में नेल्डर-मीड कार्यान्वयन एक अच्छा फिट लग रहा था।scipy अनुकूलन में पूर्ण चरण आकार

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

इसके लायक होने के लिए मैं गिट रेपो से एक नए निर्माण का उपयोग कर रहा हूं। क्या किसी को पता है कि प्रत्येक पैरामीटर के लिए एक विशिष्ट चरण आकार का उपयोग करने के लिए कैसे कहा जाए? क्या कोई तरीका है कि मैं अपना खुद का ढाल कार्य कर सकता हूं? क्या कोई झुका हुआ ध्वज है जो मेरी मदद कर सकता है? मुझे पता है कि यह एक साधारण पैरामीटर स्वीप के साथ किया जा सकता है, लेकिन अंततः मैं इस कोड को पैरामीटर के बहुत बड़े सेट पर लागू करना चाहता हूं।

import numpy as np 
from scipy.optimize import minimize 
from ScannerUtil import straightenImg 
import bson 

def doSingleIteration(parameters): 
    # do some machine vision magic 
    # return the difference between my value and the truth value 

parameters = np.array([11,10]) 
res = minimize(doSingleIteration, parameters, method='Nelder-Mead',options={'xtol': 1e-2, 'disp': True,'ftol':1.0,}) #not sure if these params do anything 
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
print res 

यह मेरी उत्पादन कैसा दिखता है:

कोड में ही मृत सरल है। जैसा कि आप देख सकते हैं कि हम बहुत सारे रन दोहरा रहे हैं और कम से कम नहीं हो रहे हैं।

*+++++++++++++++++++++++++++++++++++++++++ 
[ 11. 10.] <-- Output from scipy minimize 
{'block_size': 11, 'degree': 10} <-- input to my algorithm rounded and made int 
+++++++++++++++++++++++++++++++++++++++++ 
120 <-- output of the function I am trying to minimize 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.55 10. ] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11. 10.5] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.55 9.5 ] 
{'block_size': 11, 'degree': 9} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.1375 10.25 ] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.275 10. ] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11. 10.25] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.275 9.75 ] 
{'block_size': 11, 'degree': 9} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
+++++++++++++++++++++++++++++++++++++++++ 
~~~ 
SNIP 
~~~ 
+++++++++++++++++++++++++++++++++++++++++ 
[ 11.   10.0078125] 
{'block_size': 11, 'degree': 10} 
+++++++++++++++++++++++++++++++++++++++++ 
120 
Optimization terminated successfully. 
     Current function value: 120.000000 
     Iterations: 7 
     Function evaluations: 27 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    status: 0 
    nfev: 27 
success: True 
    fun: 120.0 
     x: array([ 11., 10.]) 
message: 'Optimization terminated successfully.' 
    nit: 7* 
+2

चला जाता है, वह SciPy के Nelder-मीड विधि सिंप्लेक्स रैखिक प्रोग्रामिंग एल्गोरिथ्म का उपयोग करता। यह फ़ंक्शन को अनुकूलित करने के लिए गैर-अभिन्न बिंदु/चरण आकारों का उपयोग करने पर निर्भर करता है।मैं सामान्य रूप से SciPy से परिचित नहीं हूं, इसलिए ऐसा करने के लिए कॉन्फ़िगरेशन विकल्प हो सकता है जो आप चाहते हैं। आप पूर्णांक प्रोग्रामिंग (http://en.wikipedia.org/wiki/Integer_programming) में भी देखना चाहते हैं, जैसा कि आप पूरा करने की कोशिश कर रहे हैं। –

+0

@EricG वास्तव में मुझे लगता है कि सिर्फ एक नाम मिश्रण है, Nelder-Mead "Simplex" एक Simplex की ज्यामितीय संरचना के साथ काम करता है। रैखिक प्रोग्रामिंग से सिंपलक्स एल्गोरिदम के साथ इसका कोई लेना-देना नहीं है, और यह वैसे भी nonlinear अनुकूलन है। – seberg

+1

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

उत्तर

5

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

संपादित करें: @Dougal से टिप्पणी को ध्यान में रखते हुए मैं बस यहां जोड़ूंगा: यदि आप अपने नेल्डर-मीड काम करता है (और तेजी से अभिसरण करता है) तो कोशिश कर रहा है, तो नीचे दिए गए अंक मदद ...

लेकिन शायद कुछ बिंदुओं कि मदद:

  1. को ध्यान में रखते कैसे पूरे पूर्णांक बाधा बहुत मुश्किल है, हो सकता है यह अनुकूलक मदद करने के लिए कुछ सरल प्रक्षेप करने के लिए एक विकल्प होगा। यह अभी भी एक पूर्णांक समाधान के लिए अभिसरण होना चाहिए। बेशक इसे अतिरिक्त अंक की गणना करने की आवश्यकता है, लेकिन यह कई अन्य समस्याओं को हल कर सकता है। (यहां तक ​​कि रैखिक पूर्णांक प्रोग्रामिंग में अपनी स्वेच्छापूर्ण प्रणाली पहले AFAIK हल करने के लिए आम)
  2. Nelder-मीड एन 1 अंक के साथ शुरू होता है, इन scipy में कठिन वायर्ड (कम से कम पुराने संस्करणों) (1+0.05) * x0[j] को (j के लिए सभी आयामों में कर रहे हैं, जब तक x0[j] 0 है), जो आप अपने पहले मूल्यांकन चरणों में देखेंगे। हो सकता है कि इन्हें नए संस्करणों में आपूर्ति की जा सके, अन्यथा आप बस सिसि कोड को बदल सकते हैं/कॉपी कर सकते हैं (यह शुद्ध पायथन है) और इसे और अधिक उचित पर सेट करें। या यदि आपको लगता है कि यह आसान है, तो सभी इनपुट चर को स्केल करें ताकि (1 + 0.05) * x0 समझदार आकार का हो।
  3. शायद आपको सभी फ़ंक्शन मूल्यांकन कैश करना चाहिए, क्योंकि यदि आप नेल्डर-मीड का उपयोग करते हैं तो मुझे लगता है कि आप हमेशा डुप्लिकेट मूल्यांकन (कम से कम अंत में) में चला सकते हैं।
  4. आपको यह जांचना होगा कि कैसे नेलर-मीड एक ही मूल्य को कम कर देगा और छोड़ देगा, क्योंकि यह हमेशा एक ही परिणाम पाता है।
  5. आप आम तौर पर अपने कार्य में अच्छी तरह से सब पर व्यवहार किया जाता है, तो ... यह अनुकूलन बर्बाद है की जांच करना चाहिए अगर समारोह पैरामीटर अंतरिक्ष पर चिकनी परिवर्तन नहीं होता है, और फिर भी यह आसानी से अगर आप उन लोगों में से होना चाहिए स्थानीय न्यूनतम में चला सकते हैं ।
1

स्नैप अपने तैरता एक्स, वाई (उर्फ winsize, सीमा (जब से तुम सब मूल्यांकन कैश की गई - किसी भी अतिरिक्त evluations नहीं करना पड़ता आप सकता है कम से कम भूखंड उन और त्रुटि परिदृश्य पर एक नजर है - 2. देखें)) एक पूर्णांक ग्रिड अपने समारोह के अंदर, इस तरह के:

def func(x, y): 
    x = round(x) 
    y = round((y - 1)/2) * 2 + 1 # 1 3 5 ... 
    ... 

फिर Nelder-मीड केवल ग्रिड पर समारोह मूल्यों देखेंगे, और आप के पास-पूर्णांक एक्स, वाई देना चाहिए।

(यदि आप अपने कोड किसी ऐसे स्थान पर पोस्ट करने के लिए परवाह चाहते हैं, तो मैं पुन: प्रारंभ के साथ एक Nelder-मीड के लिए परीक्षण मामलों के लिए देख रहा हूँ।)

2

दुर्भाग्य से, SciPy के अंतर्निहित अनुकूलन टूल आसानी से की अनुमति नहीं है इसके लिए। लेकिन कभी डर नहीं; ऐसा लगता है कि आपके पास उत्तल समस्या है, और इसलिए आपको एक अद्वितीय इष्टतम खोजने में सक्षम होना चाहिए, भले ही यह गणितीय रूप से सुंदर न हो।

दो विकल्प है कि मैं अलग समस्याओं के लिए क्रियान्वित किया है एक कस्टम ढाल वंश एल्गोरिथ्म बनाने, और univariate समस्याओं की एक श्रृंखला पर द्विभाजन उपयोग कर रहे हैं। यदि आप अपने ट्यूनिंग में क्रॉस-सत्यापन कर रहे हैं, तो दुर्भाग्य से आपका नुकसान कार्य आसान नहीं होगा (विभिन्न डेटासेट पर क्रॉस-सत्यापन से शोर की वजह से), लेकिन आम तौर पर उत्तल होगा।

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

एक धीमी लेकिन संभवतः अधिक मजबूत विकल्प प्रत्येक पैरामीटर आप परीक्षण कर रहे हैं के लिए द्विभाजन लागू करने के लिए है। यदि आप जानते हैं कि आपके दो पैरामीटर (या n पैरामीटर) में संयुक्त रूप से उत्तल में बात नहीं, आप n univariate अनुकूलन समस्याओं में इस अलग कर सकते हैं, और एक द्विभाजन एल्गोरिथ्म जो रिकर्सिवली इष्टतम मानकों पर hones लिखें। यह कुछ प्रकार की quasiconvexity को संभालने में मदद कर सकता है (उदाहरण के लिए यदि आपका हानि फ़ंक्शन अपने डोमेन के हिस्से के लिए पृष्ठभूमि शोर मान लेता है, और किसी अन्य क्षेत्र में उत्तल है), लेकिन प्रारंभिक पुनरावृत्ति के लिए सीमाओं के लिए एक अच्छा अनुमान होना आवश्यक है।

आप बस xtol फिक्सिंग कि gridsize को मैप करने के बिना एक पूर्णांक ग्रिड करने का अनुरोध किया x मूल्यों स्नैप हैं, तो आप एक ग्रिड कोशिका के भीतर solver अनुरोध दो अंक होने का जोखिम है, वही उत्पादन मूल्य प्राप्त करने, और यह निष्कर्ष दिया कि उस पर है कम से कम।

कोई आसान जवाब है, दुर्भाग्य से।

1

Nelder-Mead minimize विधि अब आपको प्रारंभिक सिम्प्लेक्स वर्टेक्स पॉइंट्स निर्दिष्ट करने देता है, इसलिए आप सरल मोड को अलग-अलग सेट करने में सक्षम होना चाहिए, और फिर सिम्प्लेक्स फिर से घूमता है और न्यूनतम खोजता है और सरल आकार के साथ अभिसरण करता है डॉक्स के अनुसार नीचे 1.

https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html#optimize-minimize-neldermead