Улучшение производительности маскировки с последующим средневзвешенным - PullRequest
0 голосов
/ 12 декабря 2018

Функция func(), определенная ниже, находится глубоко внутри процесса Марковской цепочки Монте-Карло, что означает, что она вызывается миллионы раз.Мне нужно максимально улучшить его производительность, но я не нашел способа сделать это.

Определение маски (msk) и средневзвешенное значение занимают примерно одинаковую частьвремя.Возможно, нет способа получить средневзвешенное значение быстрее, чем это делает numpy, но можно ли хотя бы улучшить определение маски?

def func(weights, x1, x2, x3, x4):
    for x in (x2, x3, x4):
        # Mask of the distance between the column '-6' of x1 versus arrays
        # x2,x3,x4
        msk = abs(x1[-6] - x[-6]) > 0.01
        # If the distance in this array is larger than the maximum allowed,
        # mask with the values taken from 'x1'.
        x[:, msk] = x1[:, msk]

    # Weighted average for all the arrays.
    avrg_data = np.average(np.array([x1, x2, x3, x4]), weights=weights, axis=0)

    return avrg_data


# Random data with proper shape
x1, x2, x3, x4 = np.random.uniform(1., 10., (4, 10, 1000))
weights = np.random.uniform(0.01, .5, 4)

# Call many times and time it
s = t.time()
for _ in range(10000):
    func(weights, x1, x2, x3, x4)
print(t.time() - s)

1 Ответ

0 голосов
/ 12 декабря 2018

Я поэкспериментировал с вашим кодом и попытался, если бы средневзвешенное значение напрямую без использования np.average было бы быстрее, и похоже, что так оно и есть.На моей платформе это примерно на 40% быстрее.

import time as t
import numpy as np

def func(weights, x1, x2, x3, x4):
    for x in (x2, x3, x4):
        # Mask of the distance between the column '-6' of x1 versus arrays
        # x2,x3,x4
        msk = abs(x1[-6] - x[-6]) > 0.01

        # If the distance in this array is larger than the maximum allowed,
        # mask with the values taken from 'x1'.
        x[:, msk] = x1[:, msk]

    # Weighted average for all the arrays.
    avrg_data = np.average(np.array([x1, x2, x3, x4]), weights=weights, axis=0)

    return avrg_data

def faster_func(weights, x1, x2, x3, x4):
    for x in (x2, x3, x4):
        # Mask of the distance between the column '-6' of x1 versus arrays
        # x2,x3,x4
        msk = abs(x1[-6] - x[-6]) > 0.01

        # If the distance in this array is larger than the maximum allowed,
        # mask with the values taken from 'x1'.
        x[:, msk] = x1[:, msk]

    # Scale weights so they add up to 1, then add based on them
    weights = weights / np.mean(weights) / 4    
    avrg_data = x1*weights[0] + x2*weights[1] + x3*weights[2] + x4*weights[3]

    return avrg_data

# Random data with proper shape
x1, x2, x3, x4 = np.random.uniform(1., 10., (4, 10, 1000))
weights = np.random.uniform(0.01, .5, 4)

# Call many times and time it
for method in (func, faster_func):
    s = t.time()
    for _ in range(10000):
        method(weights, x1, x2, x3, x4)
    print(method, t.time() - s)

# Test that the results are still the same
result1 = func(weights, x1, x2, x3, x4)
result2 = faster_func(weights, x1, x2, x3, x4)
biggest_difference = np.max(abs(result1-result2))
print("Biggest difference between two methods was %.8f" % biggest_difference)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...