2015-06-07 2 views
5

Есть ли способ избежать этого цикла, чтобы оптимизировать код?NumPy: Как избежать этого цикла?

import numpy as np 

cLoss = 0 
dist_ = np.array([0,1,0,1,1,0,0,1,1,0]) # just an example, longer in reality 
TLabels = np.array([-1,1,1,1,1,-1,-1,1,-1,-1]) # just an example, longer in reality 
t = float(dist_.size) 
for i in range(len(dist_)): 
    labels = TLabels[dist_ == dist_[i]] 
    cLoss+= 1 - TLabels[i]*(1. * np.sum(labels)/t) 
print cLoss 

Примечание:dist_ и TLabels оба Numpy массивов одинаковой формы (t,1)

+3

Что вы пытаетесь достичь? –

+0

Ну, я считаю, что это правильно: 'TLabels [dist_ == dist_ [i]]' будет возвращать значения из 'TLabels', которые имеют индексы, где' dist_ == dist_ [i] '. Например, пусть 'dist_ = array ([2,1,2])' и 'TLabels = array ([1,2,3])' so 'dist_ == dist_ [0]' будет возвращать 'array ([True, False, True]) 'чем' TLabels [dist_ == dist_ [0]] = array ([1,3]) ' – farhawa

+0

Просто, чтобы быть ясным, массивы' (t, 1) 'или' (t,) '? Где инициализируется 'cLoss'? – hpaulj

ответ

2

Я не уверен, что вы точно хотите сделать, но знаете ли вы о scipy.ndimage.measurements для вычисления на массивах с надписями? Похоже, вы хотите что-то вроде:

cLoss = len(dist_) - sum(TLabels * scipy.ndimage.measurements.sum(TLabels,dist_,dist_)/len(dist_)) 
1

Я не уверен, если это лучше, так как я не совсем понимаю, почему вы можете захотеть сделать это. Многие переменные в вашем цикле являются двунаправленными, поэтому их можно заранее вычислить.

Также записи dist_ могут использоваться в качестве логического переключателя, но я все равно использовал явный экземпляр.

dist_  = np.array([0,1,0,1,1,0,0,1,1,0]) 
TLabels  = np.array([-1,1,1,1,1,-1,-1,1,-1,-1]) 
t   = len(dist) 
dist_zeros = dist_== 0 
one_zero_sum = [sum(TLabels[dist_zeros])/t , sum(TLabels[~dist_zeros])/t] 

cLoss  = sum([1-x*one_zero_sum[dist_[y]] for y,x in enumerate(TLabels)]) 

который приводит к cLoss = 8.2. Я использую Python3, поэтому не проверял, является ли это истинным делением или нет в Python2.

2

Я сначала задаюсь вопросом, что такое labels на каждом шагу в цикле?

С dist_ = array([2,1,2]) и TLabels=array([1,2,3])

я

[-1 1] 
[1] 
[-1 1] 

Различная длина немедленно поднять флаг предупреждения - это может быть трудно векторизации это.

С более длинными массивами в отредактированном примере

[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 
[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 

В labels векторах являются все же длиной. Это нормально или просто совпадение ценностей?

Капля пару элементов прочь dist_ и labels являются:

In [375]: for i in range(len(dist_)): 
     labels = TLabels[dist_ == dist_[i]] 
     v = (1.*np.sum(labels)/t); v1 = 1-TLabels[i]*v 
     print(labels, v, TLabels[i], v1) 
     cLoss += v1 
    .....:  
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([-1, 1, -1, -1]), -0.25, 1, 1.25) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 

Снова разные длины этикетки, но на самом деле лишь несколько расчетов. Значение 1 v для каждого значения dist_.

Без уточнения всех деталей, похоже, вы просто вычисляете labels*labels для каждого отдельного значения dist_, а затем суммируете его.

Это выглядит как проблема groupBy. Вы хотите разделить dist_ на группы с общим значением и суммировать некоторую функцию их соответствующих значений TLabels. Python itertools имеет функцию groupBy, поэтому pandas. Я думаю, что оба требуют от вас сортировать dist_.

Попробуйте отсортировать dist_ и посмотреть, добавляет ли это ясность в проблему.

Смежные вопросы