векторизация для цикла в Numpy / Scipy? - PullRequest
4 голосов
/ 19 апреля 2010

Я пытаюсь векторизовать цикл for, который есть внутри метода класса. Цикл for имеет следующую форму: он выполняет итерацию по множеству точек и в зависимости от того, является ли истинной определенная переменная (называемая «self.condition_met» ниже), вызывает пару функций для точки и добавляет результат в список , Каждая точка здесь представляет собой элемент в векторе списков, то есть структуру данных, которая выглядит как массив ([[1,2,3], [4,5,6], ...]). Вот проблемная функция:

def myClass:
   def my_inefficient_method(self):
       final_vector = []
       # Assume 'my_vector' and 'my_other_vector' are defined numpy arrays
       for point in all_points:
         if not self.condition_met:
             a = self.my_func1(point, my_vector)
             b = self.my_func2(point, my_other_vector)
         else:
             a = self.my_func3(point, my_vector)
             b = self.my_func4(point, my_other_vector)
         c = a + b
         final_vector.append(c)
       # Choose random element from resulting vector 'final_vector'

self.condition_met устанавливается перед вызовом my_inefficient_method, поэтому, кажется, нет необходимости проверять его каждый раз, но я не уверен, как лучше написать это. Поскольку здесь нет деструктивных операций, похоже, я мог бы переписать всю эту вещь как векторизованную операцию - возможно ли это? есть идеи как это сделать?

Ответы [ 3 ]

2 голосов
/ 19 апреля 2010

Это займет всего пару строк кода в NumPy (остальное - просто создание набора данных, пара функций и настройка).

import numpy as NP

# create two functions 
fnx1 = lambda x : x**2
fnx2 = lambda x : NP.sum(fnx1(x))

# create some data
M = NP.random.randint(10, 99, 40).reshape(8, 5)

# creates index array based on condition satisfaction
# (is the sum (of that row/data point) even or odd)
ndx = NP.where( NP.sum(M, 0) % 2 == 0 )

# only those data points that satisfy the condition (are even) 
# are passed to one function then another and the result off applying both 
# functions to each data point is stored in an array
res = NP.apply_along_axis( fnx2, 1, M[ndx,] )

print(res)
# returns: [[11609 15309 15742 12406  4781]]

Из вашего описания я абстрагировал этот поток:

  • проверка состояния (логическое) 'если True '
  • вызывает парные функции для этих данных точки (строки), которые удовлетворяют состояние
  • добавляет результат из каждого набора вызовов в список ('res' ниже)
2 голосов
/ 19 апреля 2010

Можете ли вы переписать my_funcx для векторизации?Если это так, вы можете сделать

def myClass:
   def my_efficient_method(self):
       # Assume 'all_points', 'my_vector' and 'my_other_vector' are defined numpy arrays
       if not self.condition_met:
           a = self.my_func1(all_points, my_vector)
           b = self.my_func2(all_points, my_other_vector)
       else:
           a = self.my_func3(all_points, my_vector)
           b = self.my_func4(all_points, my_other_vector)
       final_vector = a + b
       # Choose random element from resulting vector 'final_vector'
0 голосов
/ 19 апреля 2010

Вероятно, лучше сделать то, что mtrw, но если вы не уверены в векторизации, вы можете попробовать numpy.vectorize на my_func s

http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

...