Как оптимизировать этот код, имеющий несколько циклов? - PullRequest
1 голос
/ 29 апреля 2020

Так что я пробовал это, и я считаю, что это действительно невозможно. Я не очень осведомлен об умных способах сделать следующее. Может кто-нибудь помочь? Также входы списков довольно велики.

Эта задача состояла в том, чтобы создать изображение из значений, сгенерированных мной. center_star содержит список пар [x, y], которые являются центрами различных точек, подобных объектам. Значение

1800 означает, что генерируемое изображение имеет размер 1800x1800 пикселей.

Сигма-переменная имеет значение 2 от по умолчанию.

final=[[0]*1800]*1800
for i in range(len(center_stars)):
    xi=center_stars[i][0]
    yi=center_stars[i][1]
    print(i)
    for j in range(1800):
        for k in range(1800):
            final[j][k]+=gauss_amplitude[i]*(math.e**((-1*((xi-j)**2+(yi-k)**2))/2*sigma*sigma))

Есть ли более разумный способ сэкономить время, используя некоторые операции numpy, и выполнить этот фрагмент кода за меньшее время?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2020

вы можете попробовать сжать код следующим образом:

Gauss=lambda i,j,k,xi,yi:gauss_amplitude[i]*(math.e**((-((xi-j)**2+(yi-k)**2))/(2*sigma*sigma)))
final=[[Gauss(i,j,k,x[0],x[1]) for j in range(1800) for k in range(1800)] for i,x in enumerate(center_starts)]

0 голосов
/ 30 апреля 2020

Если ваши сигмы все одинаковые, вы можете достичь этого без любого l oop, используя scipy.signal.convolve2d.

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve2d
from scipy.stats import multivariate_normal

sigma = 3
width = 200   # smaller than yours so you can see the single pixels
n_stars = 50

# draw some random stars
star_row = np.random.randint(0, width, n_stars)
star_col = np.random.randint(0, width, n_stars)
star_amplitude = np.random.normal(50, 10, n_stars)

# assign amplitudes to center pixel of stars
amplitudes = np.zeros((width, width))
amplitudes[star_row, star_col] = star_amplitude


# create 2d gaussian kernel
row = col = np.arange(-4 * sigma, 4 * sigma + 1)
grid = np.stack(np.meshgrid(row, col)).T
kernel = multivariate_normal(
    [0, 0],
    [[sigma**2, 0], [0, sigma**2]]
).pdf(grid)
kernel /= kernel.sum()


# convolve with 2d gaussian
final = convolve2d(amplitudes, kernel, mode='same')


fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(9, 3))

img = ax1.imshow(amplitudes)
fig.colorbar(img, ax=ax1)
ax1.set_label('Before Convolution')

img = ax2.imshow(kernel)
fig.colorbar(img, ax=ax2)
ax2.set_label('Convolution Kernel')

img = ax3.imshow(final)
fig.colorbar(img, ax=ax3)
ax3.set_label('After Convolution')

fig.tight_layout()
fig.savefig('conv2d.png', dpi=300)

Результат:

result

Если сигмы различаются, вы получаете способ с одним l oop над возможными сигмами.

0 голосов
/ 29 апреля 2020

Примерно так:

import math
import numpy as np
N = 1800
final = np.empty((N, N))
final1 = np.empty((N, N))
j = np.arange(N)
k = np.arange(N)
jj, kk = np.meshgrid(j, k)
sigma = 2.
s = 0.5 / (sigma * sigma)
for i in range(len(center_stars)):
    xi = center_stars[i][0]
    yi = center_stars[i][1]
    final += gauss_amplitude[i] * np.exp(- ((xi - jj.T)**2 + (yi - kk.T)**2) * s)
# Code below is for comparison:
    for j in range(N):
        for k in range(N):
            final1[j][k]+=gauss_amplitude[i] * (math.e** (-((xi-j)**2+(yi-k)**2)/(2*sigma*sigma)))

Кроме того, я предполагаю, что вы пропустили скобки вокруг 2*sigma*sigma

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...