Daha az ayrıntılı python'da 2 boyutlu bir numpy dizisi nasıl normalleştirilir?


89

3 kere 3 uyuşmuş bir dizi verildiğinde

a = numpy.arange(0,27,3).reshape(3,3)

# array([[ 0,  3,  6],
#        [ 9, 12, 15],
#        [18, 21, 24]])

2 boyutlu dizinin satırlarını normalleştirmek için

row_sums = a.sum(axis=1) # array([ 9, 36, 63])
new_matrix = numpy.zeros((3,3))
for i, (row, row_sum) in enumerate(zip(a, row_sums)):
    new_matrix[i,:] = row / row_sum

Daha iyi bir yolu olmalı, değil mi?

Belki açıklığa kavuşturmak için: Normalleştirme derken, satır başına girişlerin toplamı bir olmalıdır. Ancak bunun çoğu insan için net olacağını düşünüyorum.


17
Dikkatli olun, "normalleştir" genellikle bileşenlerin kare toplamının bir olduğu anlamına gelir .
Tanımınız

Yanıtlar:


139

Yayıncılık bunun için gerçekten iyidir:

row_sums = a.sum(axis=1)
new_matrix = a / row_sums[:, numpy.newaxis]

row_sums[:, numpy.newaxis]olmaktan row_sums yeniden şekillendirir (3,)olmasının (3, 1). Bunu yaptığınızda a / b, ave bbirbirlerine karşı yayınlanır.

Burada yayın hakkında daha fazla bilgi edinebilir veya daha da iyisi burada öğrenebilirsiniz .


29
Bu, daha a.sum(axis=1, keepdims=True)sonra kullanmak zorunda kalmadan yayınlayabileceğiniz tekli sütun boyutunu korumak için kullanılarak daha da basitleştirilebilir np.newaxis.
ali_m

6
ya row_sum'lardan herhangi biri sıfırsa?
asdf

8
Bu, yukarıda belirtildiği gibi soru için doğru cevaptır - ancak olağan anlamda bir normalleştirme isteniyorsa, np.linalg.normyerine kullanın a.sum!
coldfix

2
bu tercih edilir row_sums.reshape(3,1)mi?
Paul,

1
Satır toplamı 0 olabileceği için o kadar sağlam değil.
no.

105

Scikit-learn, normalize()çeşitli normalleştirmeleri uygulamanıza izin veren bir işlev sunar . "Toplamı 1 yap" ifadesine L1-norm denir. Bu nedenle:

from sklearn.preprocessing import normalize

matrix = numpy.arange(0,27,3).reshape(3,3).astype(numpy.float64)
# array([[  0.,   3.,   6.],
#        [  9.,  12.,  15.],
#        [ 18.,  21.,  24.]])

normed_matrix = normalize(matrix, axis=1, norm='l1')
# [[ 0.          0.33333333  0.66666667]
#  [ 0.25        0.33333333  0.41666667]
#  [ 0.28571429  0.33333333  0.38095238]]

Şimdi satırlarınızın toplamı 1 olacak.


3
Bu aynı zamanda, yoğun diziler olarak belleğe sığmayan seyrek diziler üzerinde çalışması avantajına da sahiptir.
JEM_Mosig

10

Bence bu çalışmalı

a = numpy.arange(0,27.,3).reshape(3,3)

a /=  a.sum(axis=1)[:,numpy.newaxis]

2
iyi. 27'e ondalık noktasını ekleyerek arange için d_type değişimini dikkat
wim

4

Her satırı, büyüklüğü bir olacak şekilde normalleştirmeye çalışıyorsanız (yani, bir satırın birim uzunluğu bir veya bir satırdaki her öğenin karesinin toplamı birdir):

import numpy as np

a = np.arange(0,27,3).reshape(3,3)

result = a / np.linalg.norm(a, axis=-1)[:, np.newaxis]
# array([[ 0.        ,  0.4472136 ,  0.89442719],
#        [ 0.42426407,  0.56568542,  0.70710678],
#        [ 0.49153915,  0.57346234,  0.65538554]])

Doğrulanıyor:

np.sum( result**2, axis=-1 )
# array([ 1.,  1.,  1.]) 

Eksen np.linalg.norm (artık?) İçin bir parametre gibi görünmüyor.
Ztyx

özellikle bu l2 normuna karşılık gelir (burada 1'e toplamı olan satırlar l1 normuna karşılık gelir)
dpb

3

Bunu tarafından 1 satır elemanları toplamı normale olabilir düşünüyorum: new_matrix = a / a.sum(axis=1, keepdims=1). Ve sütun normalizasyonu ile yapılabilir new_matrix = a / a.sum(axis=0, keepdims=1). Umarım bu hep olabilir.


2

Yerleşik numpy işlevini kullanabilirsiniz: np.linalg.norm(a, axis = 1, keepdims = True)


1

Görünüşe göre bu da işe yarıyor

def normalizeRows(M):
    row_sums = M.sum(axis=1)
    return M / row_sums

1

Ayrıca matris transpozisyonunu da kullanabilirsiniz:

(a.T / row_sums).T

0

Veya lambda işlevini kullanarak

>>> vec = np.arange(0,27,3).reshape(3,3)
>>> import numpy as np
>>> norm_vec = map(lambda row: row/np.linalg.norm(row), vec)

her vec vektörünün bir birim normu olacaktır.


0

İşte kullanmanın olası bir yolu daha reshape:

a_norm = (a/a.sum(axis=1).reshape(-1,1)).round(3)
print(a_norm)

Veya Noneeserleri kullanmak da:

a_norm = (a/a.sum(axis=1)[:,None]).round(3)
print(a_norm)

Çıktı :

array([[0.   , 0.333, 0.667],
       [0.25 , 0.333, 0.417],
       [0.286, 0.333, 0.381]])

-2
normed_matrix = normalize(input_data, axis=1, norm='l1')
print(normed_matrix)

input_data, 2D dizinizin adıdır

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.