Saya sedang mengerjakan beberapa kode yang harus dapat membentuk fitting gaussian 2d. Saya kebanyakan mendasarkan kode saya pada pertanyaan berikut: Menyesuaikan fungsi Gaussian 2D menggunakan scipy.optimize.curve_fit - ValueError dan minpack.error. Sekarang adalah masalah bahwa saya tidak benar-benar memiliki tebakan awal tentang berbagai parameter yang perlu digunakan.

Saya sudah mencoba ini:

def twoD_Gaussian(x_data_tuple, amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
    (x,y) = x_data_tuple
    xo = float(xo)
    yo = float(yo)    
    a = (np.cos(theta)**2)/(2*sigma_x**2) + (np.sin(theta)**2)/(2*sigma_y**2)
    b = -(np.sin(2*theta))/(4*sigma_x**2) + (np.sin(2*theta))/(4*sigma_y**2)
    c = (np.sin(theta)**2)/(2*sigma_x**2) + (np.cos(theta)**2)/(2*sigma_y**2)
    g = offset + amplitude*np.exp( - (a*((x-xo)**2) + 2*b*(x-xo)*(y-yo) 
                            + c*((y-yo)**2)))
    return g.ravel()

Data.reshape (201.201) hanyalah sesuatu yang saya ambil dari pertanyaan yang disebutkan di atas.

mean_gauss_x = sum(x * data.reshape(201,201)) / sum(data.reshape(201,201))
sigma_gauss_x = np.sqrt(sum(data.reshape(201,201) * (x - mean_gauss_x)**2) / sum(data.reshape(201,201)))

mean_gauss_y = sum(y * data.reshape(201,201)) / sum(data.reshape(201,201))
sigma_gauss_y = np.sqrt(sum(data.reshape(201,201) * (y - mean_gauss_y)**2) / sum(data.reshape(201,201)))


initial_guess = (np.max(data), mean_gauss_x, mean_gauss_y, sigma_gauss_x, sigma_gauss_y,0,10)


popt, pcov = curve_fit(twoD_Gaussian, (x, y), data, p0=initial_guess)

data_fitted = twoD_Gaussian((x, y), *popt)

Jika saya mencoba ini, saya mendapatkan pesan kesalahan berikut: ValueError: mengatur elemen array dengan urutan.

Apakah alasan tentang parameter awal benar? Dan mengapa saya mendapatkan kesalahan ini?

0
Wouter Blokland 13 Agustus 2019, 14:34

1 menjawab

Jawaban Terbaik

Jika saya menggunakan kode runnable dari pertanyaan tertaut dan ganti definisi Anda tentang initial_guess:

mean_gauss_x = sum(x * data.reshape(201,201)) / sum(data.reshape(201,201))
sigma_gauss_x = np.sqrt(sum(data.reshape(201,201) * (x - mean_gauss_x)**2) / sum(data.reshape(201,201)))

mean_gauss_y = sum(y * data.reshape(201,201)) / sum(data.reshape(201,201))
sigma_gauss_y = np.sqrt(sum(data.reshape(201,201) * (y - mean_gauss_y)**2) / sum(data.reshape(201,201)))

initial_guess = (np.max(data), mean_gauss_x, mean_gauss_y, sigma_gauss_x, sigma_gauss_y,0,10)

Kemudian

print(inital_guess)

Hasil

(13.0, array([...]), array([...]), array([...]), array([...]), 0, 10)

Perhatikan bahwa beberapa nilai dalam initial_guess adalah array. Fungsi optimize.curve_fit mengharapkan initial_guess menjadi tupel skalar. Ini adalah sumber masalahnya.


Pesan kesalahan

ValueError: setting an array element with a sequence

Sering muncul ketika array seperti diberikan ketika nilai skalar diharapkan. Ini adalah petunjuk bahwa sumber masalahnya mungkin ada hubungannya dengan array yang memiliki jumlah dimensi yang salah. Misalnya, mungkin muncul jika Anda meneruskan larik 1D ke fungsi yang mengharapkan skalar.


Mari kita lihat potongan kode ini yang diambil dari pertanyaan tertaut:

x = np.linspace(0, 200, 201)
y = np.linspace(0, 200, 201)
X, Y = np.meshgrid(x, y)

x dan y adalah larik 1D, sedangkan X dan Y adalah larik 2D. (Saya telah menggunakan huruf kapital pada semua array 2D untuk membantu membedakannya dari array 1D).

Sekarang perhatikan bahwa Python sum dan metode sum NumPy berperilaku berbeda ketika diterapkan ke array 2D:

In [146]: sum(X)
Out[146]: 
array([    0.,   201.,   402.,   603.,   804.,  1005.,  1206.,  1407.,
        1608.,  1809.,  2010.,  2211.,  2412.,  2613.,  2814.,  3015.,
        ...
       38592., 38793., 38994., 39195., 39396., 39597., 39798., 39999.,
       40200.])

In [147]: X.sum()
Out[147]: 4040100.0

Fungsi Python sum setara dengan

total = 0
for item in X:
    total += item

Karena X adalah larik 2D, loop for item in X berulang pada baris X. Oleh karena itu, setiap item adalah larik 1D yang mewakili baris X. Jadi, total akhirnya menjadi array 1D.

Sebaliknya, X.sum() menjumlahkan semua elemen dalam X dan mengembalikan skalar.

Karena initial_guess harus berupa tupel skalar, di mana pun Anda menggunakan sum Anda harus menggunakan metode NumPy sum. Misalnya, ganti

mean_gauss_x = sum(x * data) / sum(data)

Dengan

mean_gauss_x = (X * DATA).sum() / (DATA.sum())

import numpy as np
import scipy.optimize as optimize
import matplotlib.pyplot as plt

# define model function and pass independant variables x and y as a list
def twoD_Gaussian(data, amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
    X, Y = data
    xo = float(xo)
    yo = float(yo)
    a = (np.cos(theta) ** 2) / (2 * sigma_x ** 2) + (np.sin(theta) ** 2) / (
        2 * sigma_y ** 2
    )
    b = -(np.sin(2 * theta)) / (4 * sigma_x ** 2) + (np.sin(2 * theta)) / (
        4 * sigma_y ** 2
    )
    c = (np.sin(theta) ** 2) / (2 * sigma_x ** 2) + (np.cos(theta) ** 2) / (
        2 * sigma_y ** 2
    )
    g = offset + amplitude * np.exp(
        -(a * ((X - xo) ** 2) + 2 * b * (X - xo) * (Y - yo) + c * ((Y - yo) ** 2))
    )
    return g.ravel()


# Create x and y indices
x = np.linspace(0, 200, 201)
y = np.linspace(0, 200, 201)
X, Y = np.meshgrid(x, y)

# create data
data = twoD_Gaussian((X, Y), 3, 100, 100, 20, 40, 0, 10)
data_noisy = data + 0.2 * np.random.normal(size=data.shape)
DATA = data.reshape(201, 201)


# add some noise to the data and try to fit the data generated beforehand
mean_gauss_x = (X * DATA).sum() / (DATA.sum())
sigma_gauss_x = np.sqrt((DATA * (X - mean_gauss_x) ** 2).sum() / (DATA.sum()))

mean_gauss_y = (Y * DATA).sum() / (DATA.sum())
sigma_gauss_y = np.sqrt((DATA * (Y - mean_gauss_y) ** 2).sum() / (DATA.sum()))


initial_guess = (
    np.max(data),
    mean_gauss_x,
    mean_gauss_y,
    sigma_gauss_x,
    sigma_gauss_y,
    0,
    10,
)
print(initial_guess)
# (13.0, 100.00000000000001, 100.00000000000001, 57.106515650488404, 57.43620227324201, 0, 10)
# initial_guess = (3,100,100,20,40,0,10)

popt, pcov = optimize.curve_fit(twoD_Gaussian, (X, Y), data_noisy, p0=initial_guess)

data_fitted = twoD_Gaussian((X, Y), *popt)

fig, ax = plt.subplots(1, 1)
ax.imshow(
    data_noisy.reshape(201, 201),
    cmap=plt.cm.jet,
    origin="bottom",
    extent=(X.min(), X.max(), Y.min(), Y.max()),
)
ax.contour(X, Y, data_fitted.reshape(201, 201), 8, colors="w")
plt.show()
1
unutbu 13 Agustus 2019, 15:19