Professional Documents
Culture Documents
Μάθημα 6ο
import numpy as np
from scipy.optimize import fmin_bfgs
import matplotlib.pyplot as plt
Στο προηγούμενο μάθημα είδαμε πώς ορίζουμε συναρτήσεις, και πώς χρησιμοποιούμε την fmin_bfgs (από το
scipy), για την ελαχιστοποίησή της.
Έστω η συνάρτηση: $$f(x)=x^2$$ που είναι, στην ουσία, η συνάρτηση σφαίρας σε μια διάσταση.
In [3]:
x = np.arange(-100,100)
plt.plot(x,f(x));
Στο προηγούμενο μάθημα είδαμε πώς χρησιμοποιούμε την fmin_bfgs για να βρούμε το ελάχιστο σημείο της
συνάρτησης.
http://localhost:8888/lab 1/18
23/5/2022 6_Non-linear_metaheuristics
In [6]:
fmin_bfgs(f,
x0=np.array([-1.2]))
Out[6]:
array([-8.07760955e-09])
Η fmin_bfgs απαιτεί να δώσουμε ώς όρισμα μια αρχική "μαντεψιά" για το πού περίπου βρίσκεται το ελάχιστο
της συνάρτησης.
Ας σχεδιάσουμε ξανά την συνάρτηση, δείχνοντας με πράσινη βούλα το x0, η αρχική τιμή που δίνουμε για να
ξεκινήσει η αναζήτηση, και με κόκκινο αστέρι την λύση που βρήκε η fmin_bfgs.
In [33]:
x0 = -6.2
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [6.4000544e-08]
http://localhost:8888/lab 2/18
23/5/2022 6_Non-linear_metaheuristics
In [34]:
x0 = -20
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [4.78360347e-08]
http://localhost:8888/lab 3/18
23/5/2022 6_Non-linear_metaheuristics
In [36]:
x0 = -80
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [9.42292193e-07]
http://localhost:8888/lab 4/18
23/5/2022 6_Non-linear_metaheuristics
In [29]:
x0 = 89
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [1.80888756e-06]
Βλέπουμε πως ότι x0 και να δώσουμε, η fmin_bfgs βρίσκει πάντα το ολικό βέλτιστο.
http://localhost:8888/lab 5/18
23/5/2022 6_Non-linear_metaheuristics
In [178]:
x = np.arange(0,100)
plt.plot(x,f(x));
Τρέχουμε τώρα, για την καινούργια συνάρτηση, τρέχοντας την fmin_bfgs για διάφορες τιμές x0 και
σχεδιάζοντας τα αποτελέσματα.
http://localhost:8888/lab 6/18
23/5/2022 6_Non-linear_metaheuristics
In [179]:
x0 = 20
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [11.05084033]
http://localhost:8888/lab 7/18
23/5/2022 6_Non-linear_metaheuristics
In [180]:
x0 = 60
fmin = fmin_bfgs(f,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,f(x));
plt.plot(x0,f(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,f(fmin),marker='*',markersize=12,color='r');
solution x = [65.81860792]
Βλέπουμε ότι η αρχική τιμή που δώσαμε επηρέασε το τελικό αποτέλεσμα, το οποίο δεν ήταν πάντα βέλτιστο.
Ας το δούμε αυτό ξανά σε μια καινούργια, διαφορετική συνάρτηση. Με πράσινη βούλα συμβολίζονται οι
αρχικές τιμές που δίνουμε, και με κόκκινο σταυρό οι λύσεις που βρίσκει η fmin_bfgs.
http://localhost:8888/lab 8/18
23/5/2022 6_Non-linear_metaheuristics
In [78]:
plt.plot(x,func(x));
plt.plot(x0,func(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,func(fmin),marker='*',markersize=12,color='r');
solution x = [-1.22144316]
http://localhost:8888/lab 9/18
23/5/2022 6_Non-linear_metaheuristics
In [74]:
fmin = fmin_bfgs(func,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,func(x));
plt.plot(x0,func(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,func(fmin),marker='*',markersize=12,color='r');
solution x = [9.91202952]
http://localhost:8888/lab 10/18
23/5/2022 6_Non-linear_metaheuristics
In [76]:
fmin = fmin_bfgs(func,
x0=np.array([x0]))
print('')
print('solution x =',fmin)
print('')
plt.plot(x,func(x));
plt.plot(x0,func(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,func(fmin),marker='*',markersize=12,color='r');
solution x = [4.10148757]
http://localhost:8888/lab 11/18
23/5/2022 6_Non-linear_metaheuristics
In [140]:
plt.plot(x,func(x));
plt.plot(x0,func(x0),marker='o',markersize=8,color='g');
plt.plot(fmin,func(fmin),marker='*',markersize=12,color='r');
solution x = [4.10146311]
Βλέπουμε ότι σε συναρτήσεις με διάφορα τοπικά ελάχιστα, η fmin_bfgs παίρνει την αρχική τιμή που δίνουμε,
"κατηφορίζει" προς όποια κατεύθυνση είναι κατηφορική, και σταματάει σε οποιοδήποτε ελάχιστο συναντήσει.
Το αν αυτό το ελάχιστο θα είναι τοπικό ή ολικό, είναι καθαρά θέμα τύχης, που εξαρτάται από το αν το x0
τυχαίνει να είναι κοντά στο ολικό βέλτιστο.
Για μια συνάρτηση σαν την παρκάτω είναι προφανές πως δεν υπάρχει καν λόγος να τρέξουμε την fmin_bfgs.
http://localhost:8888/lab 12/18
23/5/2022 6_Non-linear_metaheuristics
In [112]:
x = np.arange(0,100)
f= lambda x:(-3*x**2 + 75*x*np.sin(x) + 3) * np.cos(x/7)
plt.plot(x,f(x));
Είναι προφανές ότι για τέτοιες περιπτώσεις θα χρειαστούμε ένα διαφορετικό είδος αλγορίθμου.
In [136]:
Θα δοκιμάσουμε πρώτα σε μια συνάρτηση που χρησιμοποιήσαμε παραπάνω, που την ορίσαμε ως εξής
http://localhost:8888/lab 13/18
23/5/2022 6_Non-linear_metaheuristics
In [181]:
plt.plot(x,func(x));
Πριν τρέξουμε τους μεταευριστικούς αλγόριθμους, θα βρόυμε την βέλτιστη λύση, για να επαληθεύσουμε τα
αποτελέσματα των αλγορίθμων.
In [183]:
np.min(func(x))
Out[183]:
-0.6740974948332839
In [184]:
x[np.argmin(func(x))]
Out[184]:
-1.2000000000000313
http://localhost:8888/lab 14/18
23/5/2022 6_Non-linear_metaheuristics
Οι τρεις μεταευριστικοί αλγόριθμοι που θα δούμε έχουν όλοι τους την εξής σύνταξη:
$$algorithm(function,bounds)$$
όπου algorithm το όνομα του αλγόριθμου, function το όνομα της συνάρτησης που θέλουμε να
ελαχιστοποιήσουμε, και bounds το διάστημα που επιτρέπεται να πάρουν οι τιμές x. Αν, για παράδειγμα,
θέλουμε το x να παίρνει τιμές από μείον δέκα έως δέκα, γράφουμε bounds=[(-10,10)]
Δοκιμάζουμε τώρα τους τρεις αλγόριθμους. Θυμηθείται ότι θέλουμε να μας βρουν μια λύση γύρω στο -1.2
In [146]:
dual_annealing(func,
bounds=[(-10,10)])
Out[146]:
fun: array([-0.6743051])
message: ['Maximum number of iteration reached']
nfev: 2013
nhev: 0
nit: 1000
njev: 0
x: array([-1.22144842])
In [147]:
differential_evolution(func,
bounds=[(-10,10)])
Out[147]:
fun: array([-0.6743051])
jac: array([1.11022302e-08])
message: 'Optimization terminated successfully.'
nfev: 111
nit: 6
success: True
x: array([-1.22144843])
In [182]:
shgo(func,
bounds=[(-10,10)])
Out[182]:
fun: -8.026429359839729e-05
funl: array([-8.02642936e-05])
message: 'Optimization terminated successfully.'
nfev: 30
nit: 2
nlfev: 27
nlhev: 0
nljev: 9
success: True
x: array([9.91730485])
xl: array([[9.91730485]])
http://localhost:8888/lab 15/18
23/5/2022 6_Non-linear_metaheuristics
Βλέπουμε ότι ενώ τα dual_annealing και differential_evolution είχαν άριστη απόδοση, η shgo δεν μας έδωσε
την σωστή λύση. Αυτό δεν σημαίνει ότι δεν δουλεύει.
Την ξανατρέχω, και αυτή την φορά χρησιμοποιώ την παράμετρο iters. Αυτός είναι ο αριθμός επαναλήψεων
που τρέχει η εντολή, και ενώ η προεπιλογή είναι μία επανάληψη, εμείς θα τις αυξήσουμε σε 5.
In [158]:
shgo(func,
iters=5,
bounds=[(-10,10)])
Out[158]:
fun: -0.6743051024666705
funl: array([-6.74305102e-01, -2.40375639e-01, -2.08875401e-03, -8.026
42936e-05])
message: 'Optimization terminated successfully.'
nfev: 106
nit: 5
nlfev: 89
nlhev: 0
nljev: 29
success: True
x: array([-1.22144846])
xl: array([[-1.22144846],
[ 4.10146617],
[-6.87286227],
[ 9.91730485]])
In [160]:
x = np.arange(0,100)
f= lambda x:(-3*x**2 + 75*x*np.sin(x) + 3) * np.cos(x/7)
plt.plot(x,f(x));
http://localhost:8888/lab 16/18
23/5/2022 6_Non-linear_metaheuristics
Η βέλτιστη τιμή που ελαχιστοποιεί την συνάρτηση, καθώς και η τιμή που παίρνει η συνάρτηση, υπολογίζονται
παρακάτω.
In [162]:
x[np.argmin(f(x))], np.min(f(x))
Out[162]:
(87, -27800.31210245675)
Ας δοκιμάσουμε τώρα τους τρεις μεταευριστικούς αλγορίθμους του scipy, και ας συγκρίνουμε τις λύσεις που
υπολογίζουν με τις πραγματικές.
In [164]:
dual_annealing(f,bounds=[(0,100)])
Out[164]:
fun: array([-28306.9934827])
message: ['Maximum number of iteration reached']
nfev: 2035
nhev: 0
nit: 1000
njev: 0
x: array([86.61099446])
In [165]:
differential_evolution(f,bounds=[(0,100)])
Out[165]:
fun: array([-28306.9934827])
jac: array([0.0007276])
message: 'Optimization terminated successfully.'
nfev: 132
nit: 7
success: True
x: array([86.61099454])
In [166]:
shgo(f,bounds=[(0,100)])
Out[166]:
fun: -8486.550386356275
funl: array([-8486.55038636])
message: 'Optimization terminated successfully.'
nfev: 25
nit: 2
nlfev: 22
nlhev: 0
nljev: 6
success: True
x: array([48.48133589])
xl: array([[48.48133589]])
http://localhost:8888/lab 17/18
23/5/2022 6_Non-linear_metaheuristics
H shgo βλέπουμε για άλλη μια φορά πως μας έδωσε υποβέλτιστο αποτέλεσμα. Αν αυξήσουμε κατά ελάχιστα
τον αριθμό των επαναλήψεων, όμως, και από 1 τον κάνουμε 3, μας δίνει το βέλτιστο αποτέλεσμα.
In [177]:
shgo(f,iters=3,bounds=[(0,100)])
Out[177]:
fun: -28306.99348270172
funl: array([-2.83069935e+04, -8.48655039e+03, 3.00000000e+00])
message: 'Optimization terminated successfully.'
nfev: 88
nit: 3
nlfev: 83
nlhev: 0
nljev: 16
success: True
x: array([86.61099448])
xl: array([[86.61099448],
[48.48133588],
[ 0. ]])
http://localhost:8888/lab 18/18