используйте numpy random для быстрого случайного выбора

#python-2.7 #numpy #random

#python-2.7 #numpy #Случайный

Вопрос:

РЕДАКТИРОВАТЬ: я ввел реальные значения, чтобы код теперь работал:

У меня есть 4 массива numpy одинаковой длины:

 R = np.array[ 0.39374042  0.55270474  0.50848503  0.63725071  0.0350963   0.67203288
  0.03419264  0.60936204  0.3819783   0.17653394  0.76278053  0.85589961
  0.91961392  0.85265048  0.6108294   0.15980841  0.76017363  0.21771499
  0.25927199  0.39172983  0.36364338  0.77375089  0.92969549  0.01237327
  0.12195605  0.5587532   0.70229425  0.82809111  0.06700928  0.64284712
  0.15944779  0.76857694  0.35924588  0.75636962  0.25039875  0.60632514
  0.49124143  0.73741699  0.2178207   0.15998988  0.79652839  0.73693122]
 

R содержит np.random.uniform значения от 0 до 1

 RGB = np.array[[[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[  0 110 105]
  [174  40 109]
  [  5  59 158]
  [  0 181 107]]

 [[  0 161  73]
  [182  48  57]
  [174  40 109]
  [ 32 134  39]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[174  40 109]
  [  5  59 158]
  [  0 181 107]
  [193  93 160]]

 [[219  99 109]
  [174  40 109]
  [  0 181 107]
  [104 162  26]]

 [[ 63 114 221]
  [  0 172 192]
  [ 32  77 211]
  [187  77 195]]

 [[219  99 109]
  [238  67  47]
  [ 87 194  65]
  [176 187   0]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[110 213 158]
  [235 154 164]
  [  0 190 211]
  [187  77 195]]

 [[219  99 109]
  [110 213 158]
  [235 154 164]
  [193  93 160]]

 [[219  99 109]
  [110 213 158]
  [ 87 194  65]
  [  0 181 107]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[219 162 208]
  [110 213 158]
  [235 154 164]
  [167 233 196]]

 [[110 213 158]
  [235 154 164]
  [255 226 130]
  [167 233 196]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[239 212 240]
  [136 220 234]
  [208 242 247]
  [167 233 196]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]

 [[118 187 239]
  [219 162 208]
  [136 220 234]
  [  0 190 211]]]
 

RGB содержит наборы из 4 значений цвета RGB

 A = np.array[ -1  -1  -1  -1  -1  -1 159 148  -1  -1  -1  -1  45  97  57  80  -1  -1
  60  84  86  -1  -1  -1 112  72  -1  -1  -1  -1 133  -1  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1]
 

A содержит либо -1 , либо индексы наборов из 4 значений в B

 B = np.array[[-1.54525517  1.09915125 -1.74258272  3.18868664]
 [-1.04522579  1.04443564 -1.83606995  2.8368601 ]
 [-2.51080789  1.4980096  -1.62047649  3.63327478]
 [-0.75381136  0.38494135 -1.76551145  3.13438146]
 [-0.42398121  1.45934623 -2.04842952  2.0130645 ]
 [-3.58516396  1.51736923 -1.40004578  4.46784052]
 [ 0.46980945  0.23242436  0.15812529  0.1396409 ]
 [ 0.02950557  0.43429909  0.34304701  0.19314833]
 [-2.44568468  0.98038089 -1.01581931  3.4811231 ]
 [ 1.38051381  0.11766208 -1.64270991  1.14453402]
 [-2.90620565  2.2622749  -1.17507929  2.81901003]
 [-2.11827269  0.28090219 -0.94480948  3.78217997]
 [ 0.07434589  0.03948412  0.45858244  0.42758754]
 [ 0.10902808  0.29206381  0.50180905  0.09709906]
 [ 0.02106152  0.62921187  0.12285574  0.22687087]
 [ 0.25688419  0.62417539  0.01976311  0.09917731]
 [-2.56431038  0.58433235 -0.32521341  3.30519143]
 [ 3.34007944 -0.24491683 -1.39262584 -0.70253677]
 [ 0.43784474  0.09927102  0.12535527  0.33752897]
 [ 0.18369437  0.15869915  0.55640207  0.10120441]
 [ 0.13323323  0.23276694  0.33810426  0.29589556]
 [ 2.31472564 -0.25736362 -0.51265688 -0.54470514]
 [-3.13602078  2.46578654  0.08271576  1.58751849]
 [-2.08295869 -0.0948967   0.37305594  2.80479945]
 [ 0.39357387  0.12289595  0.12890858  0.3546216 ]
 [ 0.3637729   0.35308756  0.03283074  0.25030881]
 [ 0.91809484  0.00616419  0.47102103 -0.39528007]
 [-2.10633552  1.9717707   0.71079464  0.42377018]
 [-2.63786465  0.31323965  1.15219987  2.17242513]
 [ 4.66105371 -0.67514766 -0.17463501 -2.81127104]
 [ 0.4466582   0.12232826  0.19249585  0.2385177 ]
 [-1.1656546   1.27760641  1.48320113 -0.59515294]
 [-2.54309788  0.61607798  1.90256384  1.02445605]
 [ 3.38699312 -0.695849    0.92595314 -2.61709726]
 [-3.3691958   2.67546554  1.66471811  0.02901215]
 [-2.01283737 -0.53906846  2.02201185  1.52989397]
 [-0.7635726   0.59671731  2.45595894 -1.28910365]
 [-1.6913111   0.68635463  2.63177913 -0.62682267]
 [ 1.67630612 -0.3755707   2.14031351 -2.44104893]
 [-2.03409447  2.03385782  2.43486791 -1.43463126]
 [-2.68827085 -0.01102552  2.97885322  0.72044315]
 [ 6.15409418 -1.17188198  1.36416304 -5.34637524]]
 

B содержит 4 значения, которые добавляют к 1

Что я хочу сделать, так это создать новый массив N , который будет содержать значения RGB, выбранные с помощью метода, аналогичного этому, но с использованием nympy, чтобы избежать трудоемкого цикла.

Пример кода с циклом:

 new_array = []

for i in range(len(A)):
    if A[i] != -1:
        a = B[i][0]
        b = B[i][0]   a
        c = B[i][0]   b

        u = RGB[i][0]
        v = RGB[i][0]
        w = RGB[i][0]
        x = RGB[i][0]

        random = R[i]

        if a <= random:
             new_array = new_array   [u]
        elif b <= random:
             new_array = new_array   [v]
        elif c <= random:
             new_array = new_array   [w]
        else:
             new_array = new_array   [x]

    else:
        new_array = new_array   [0 0 0]
 

Есть ли способ полностью переписать эту функцию в numpy?
Спасибо

Комментарии:

1. Ваш код не работает, можете ли вы опубликовать какой-нибудь рабочий код и пример данных. new_array это список, который вы можете использовать append() для добавления элементов.

Ответ №1:

Я попытаюсь перефразировать проблему.

  • входной массив A (N целых чисел со значением 0 ..M-1 или -1), указывающий на векторы вероятности B
  • входной массив B (M x 4), дающий вероятности (каждая строка суммируется до 1)
  • таблица цветов RGB (N x 4 x 3), предоставляющая триплеты RGB на выбор
  • входной вектор R (N), содержащий равномерно распределенные случайные значения [0,1]

Итак, для каждого значения:

  • вектор вероятности выбирается из B
  • случайное значение используется для выбора того, какая из четырех альтернатив будет выбрана из одной и той же строки в RGB

Кроме того, есть два дополнительных правила:

  • если A[n]==-1, то соответствующий выходной цвет будет черным
  • если в B [n] есть отрицательные вероятности, то соответствующий выходной цвет будет черным

Результатом будет цветовой массив Nx3.


Итак, давайте сначала построим чистый вектор вероятности, чтобы невозможные комбинации были представлены [-1,0,0,0] .

 # get the number of rows:
N = len(A)

# create a boolean array to show which indices in A are valid
A_valid = (A != -1)

# get B vectors for all valid points in A
B_vectors = B[A[A_valid]]

# clean the B_vectors so that if there are <0 vectors, they are replaced by -1,0,0,0
B_vectors[numpy.amin(B_vectors, axis=1) < 0] = [-1.0, 0.0, 0.0, 0.0]

# create a clean probability table (N x 4)
probs = numpy.empty((N, 4))
# fill in the probabilities where they can be picked form B
probs[A_valid] = B_vectors
# fill the rest with -1,0,0,0
probs[-A_valid] = [-1, 0, 0, 0]
 

Теперь у нас есть таблица либо с реальными вероятностями (положительные числа суммируются до 1), либо (-1,0,0,0) в случае, если в A есть -1 или невозможный вектор вероятности в B в конкретной строке.

Векторы вероятности проще использовать, если формируется кумулятивная вероятность. Например, вектор вероятности (.2, .3, .4, .1) преобразуется в (.2, .5, .9, 1.0). В этой форме случайное число r можно сравнить напрямую, чтобы увидеть, какую ячейку следует выбрать.

Следующий шаг — получить ячейки цвета (0,1,2,3), используя этот подход:

 # cumulative probabilities
cumprobs = numpy.cumsum(probs, axis=1)

# color indices
cidx = numpy.zeros(N)

# compare the colour indices to the random vector r
cidx[r > cumprobs[:,0]] = 1
cidx[r > cumprobs[:,1]] = 2
cidx[r > cumprobs[:,2]] = 3
 

(По какой-то странной причине в numpy нет функции для выполнения этого. numpy.digitize работает только с одномерными векторами.)

Следует отметить, что если для некоторой строки совокупные вероятности равны (.2, .5, .9, 1.0), а r для той же строки равно 0.95, cidx сначала 0 (после создания массива), затем устанавливается в 1 (потому что r> .2), затем в 2 (потому что r> .5) и, наконец, до 3 (потому что r> .9).

Затем мы можем создать таблицу выходных цветов, используя cidx и RGB :

 # pick the item defined by cidx for each row
rainbow = RGB[arange(N), cidx]
 

При этом выбирается цвет, указанный соответствующими cidx RGB значениями и в этой строке.

Наконец, мы должны затемнить все недопустимые цвета:

 # if the probability starts with -1, then we'll blacken the color out
rainbow[probs[:,0] < 0.] = [0,0,0]
 

Теперь результат должен быть rainbow .

Комментарии:

1. на самом деле я ошибался в структуре A, теперь она должна быть проще с A, содержащим индексы значений в B. Тем не менее, я не понимаю, как вы используете cumsum() here и что именно он делает…

2. можете ли вы объяснить, как «Вычислить совокупные вероятности из массива A (cumsum(A, axis = 1)), потому что тогда вы можете сравнить R напрямую».?

3. Теперь, когда показан массив B, есть что-то странное. Я думал, что значения в B дадут вероятности, при которых выбирается одно из соответствующих значений RGB. Однако, поскольку B наполовину заполнен отрицательными числами, это невозможно. Кроме того, по той же причине ваш собственный код не имеет смысла. Не могли бы вы привести числовой пример для одной строки, код не требуется, только объяснение.

4. нет, нет, нет … ваше предположение верно: значения B дают вероятности для RGBs, просто в любое время, когда A содержит -1, вероятности не имеют смысла: могут быть ниже 0 или выше 1 (т. Е. Реального решения проблемы нет)

5. Я сильно отредактировал ответ, чтобы включить код и дополнительные пояснения. Это то, что вы хотите иметь сейчас?