Оптимизируйте функцию python с помощью numpy без использования цикла for - PullRequest
1 голос
/ 27 октября 2019

У меня есть следующая функция python:

def npnearest(u: np.ndarray, X: np.ndarray, Y: np.ndarray, distance: 'callbale'=npdistance):
    '''
    Finds x1 so that x1 is in X and u and x1 have a minimal distance (according to the 
    provided distance function) compared to all other data points in X. Returns the label of x1

    Args:
        u (np.ndarray): The vector (ndim=1) we want to classify
        X (np.ndarray): A matrix (ndim=2) with training data points (vectors)
        Y (np.ndarray): A vector containing the label of each data point in X
        distance (callable): A function that receives two inputs and defines the distance function used

    Returns:
        int: The label of the data point which is closest to `u`
    '''

    xbest = None
    ybest = None
    dbest = float('inf')

    for x, y in zip(X, Y):
        d = distance(u, x)
        if d < dbest:
            ybest = y
            xbest = x
            dbest = d

    return ybest

Где, npdistance просто дает расстояние между двумя точками, т.е.

def npdistance(x1, x2):
    return(np.sum((x1-x2)**2))

Я хочу оптимизировать npnearest, выполняя ближайшеепоиск соседей прямо в numpy. Это означает, что функция не может использовать циклы for/while.

Спасибо

Ответы [ 2 ]

1 голос
/ 27 октября 2019

Numpy поддерживает векторизованные операции ( широковещание )

Это означает, что вы можете передавать массивы, и операции будут применяться ко всем массивам оптимизированным способом (SIMD - одна инструкция, несколько данных)

Затем вы можете получить адрес минимального массива, используя .argmin()

Надеюсь, это поможет

In [9]: numbers = np.arange(10); numbers                                                                                                        
Out[9]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [10]: numbers -= 5; numbers                                                                                                                  
Out[10]: array([-5, -4, -3, -2, -1,  0,  1,  2,  3,  4])

In [11]: numbers = np.power(numbers, 2); numbers                                                                                                
Out[11]: array([25, 16,  9,  4,  1,  0,  1,  4,  9, 16])

In [12]: numbers.argmin()                                                                                                                       
Out[12]: 5
1 голос
/ 27 октября 2019

Поскольку вам не нужно использовать эту точную функцию, вы можете просто изменить сумму, чтобы работать над определенной осью. Это вернет новый список с вычислениями, и вы можете вызвать argmin, чтобы получить индекс минимального значения. Используйте это и найдите ваш ярлык:

import numpy as np

def npdistance_idx(x1, x2):
    return np.argmin(np.sum((x1-x2)**2, axis=1))

Y = ["label 0", "label 1", "label 2", "label 3"]
u = np.array([[1, 5.5]])
X = np.array([[1,2], [1, 5], [0, 0], [7, 7]])

idx = npdistance_idx(X,  u)
print(Y[idx])  # label 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...