I have a function with multi unknown parameters (m, n, u, v, w, a)
:
z=m * (x + 273.15) -n + u * y - v * (x + 273.15)^2 - w * y^2 + a * y * (x + 273.15)
and i known some points of (x, y, z)
, my question is how i can use this to get the best-fit parameters (m, n, u, v, w, a)
by Python? Thanks!
x y z
400 5 -356383.4277 405 5.2 -355202.4426 410 5.4 -354021.3507 415 5.6 -352840.1520 420 5.8 -351658.8464 425 6 -350477.4341 430 6.2 -349295.9149 435 6.4 -348114.2890 440 6.6 -346932.5562 445 6.8 -345750.7167 450 7 -344568.7703 455 7.2 -343386.7171 460 7.4 -342204.5571 465 7.6 -341022.2904 470 7.8 -339839.9168 475 8 -338657.4364 480 8.2 -337474.8492 485 8.4 -336292.1552 490 8.6 -335109.3543 495 8.8 -333926.4467 500 9 -332743.4323 505 9.2 -331560.3111 510 9.4 -330377.0830 515 9.6 -329193.7482 520 9.8 -328010.3065 525 10 -326826.7581 530 10.2 -325643.1028 535 10.4 -324459.3407 540 10.6 -323275.4719 545 10.8 -322091.4962 550 11 -320907.4137 555 11.2 -319723.2244 560 11.4 -318538.9283 565 11.6 -317354.5254 570 11.8 -316170.0157 575 12 -314985.3991 580 12.2 -313800.6758 585 12.4 -312615.8457 590 12.6 -311430.9088 595 12.8 -310245.8650 600 13 -309060.7145 605 13.2 -307875.4571 610 13.4 -306690.0930 615 13.6 -305504.6220 620 13.8 -304319.0442 625 14 -303133.3596 630 14.2 -301947.5683 635 14.4 -300761.6701 640 14.6 -299575.6651 645 14.8 -298389.5533 650 15 -297203.3347 655 15.2 -296017.0092 660 15.4 -294830.5770 665 15.6 -293644.0380 670 15.8 -292457.3922 675 16 -291270.6395 680 16.2 -290083.7801 685 16.4 -288896.8138 690 16.6 -287709.7408 695 16.8 -286522.5609 700 17 -285335.2742 705 17.2 -284147.8808 710 17.4 -282960.3805 715 17.6 -281772.7734 720 17.8 -280585.0595 725 18 -279397.2388 730 18.2 -278209.3113 735 18.4 -277021.2770 740 18.6 -275833.1359 745 18.8 -274644.8880 750 19 -273456.5332 755 19.2 -272268.0717 760 19.4 -271079.5034 765 19.6 -269890.8282 770 19.8 -268702.0463 775 20 -267513.1575 780 20.2 -266324.1619 785 20.4 -265135.0596 790 20.6 -263945.8504 795 20.8 -262756.5344 800 21 -261567.1116
Do these values look reasonable?
[1195.654050550027, 1018.6061701876612, 0.16848387190088943, 3.4621025949581963, 1067.8784835891688, 129.32110722461852]
You can play around with different scipy optimizers, or give a better initial value instead of all zeros. There's a small example below.
#!/usr/bin/env python3
from scipy.optimize import differential_evolution
data = """5 400 -356383.4277
5.2 405 -355202.4426
5.4 410 -354021.3507
5.6 415 -352840.152
5.8 420 -351658.8464
..... paste in the full data ...
20.6 790 -263945.8504
20.8 795 -262756.5344
21 800 -261567.1116"""
# Parse data
data = data.split("\n")
data = list(map(lambda x: filter(None, x.split(" ")), data))
data = map(lambda x: list(map(float, x)), data)
data = list(data)
def fn(x, y, m, n, u, v, w, a):
return m * (x + 273.15) -n + u * y - v * ((x + 273.15) ** 2) - w * (y ** 2) + a * y * (x + 273.15)
def fitness(parameters):
error = 0
for y, x, z in data:
res = fn(x, y, *parameters)
error += abs(res - z) ** 2
return error
from scipy.optimize import differential_evolution
# 6 parameters between 0 and 1200
bounds = [(0, 1200)] * 6
x = differential_evolution(fitness, bounds, disp=True).x
print(list(x))
print(fn(795, 20.8, *x))