Làm thế nào để chuẩn hóa mảng numpy 2 chiều trong python ít tiết hơn?


87

Cho một mảng 3 lần 3 numpy

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

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

Để chuẩn hóa các hàng của mảng 2 chiều tôi đã nghĩ đến

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

Phải có một cách tốt hơn, phải không?

Có lẽ để làm rõ: Ý tôi là bằng cách chuẩn hóa, tổng các mục nhập trên mỗi hàng phải là một. Nhưng tôi nghĩ điều đó sẽ rõ ràng với hầu hết mọi người.


17
Cẩn thận, "bình thường hóa" thường có nghĩa là vuông tổng của các thành phần là một. Định nghĩa của bạn sẽ khó rõ ràng đối với hầu hết mọi người;)
coldfix

Câu trả lời:


138

Phát sóng thực sự tốt cho điều này:

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

row_sums[:, numpy.newaxis]định hình lại row_sums từ hiện (3,)hữu (3, 1). Khi bạn làm a / b, abđược phát sóng chống lại nhau.

Bạn có thể tìm hiểu thêm về phát sóng tại đây hoặc thậm chí tốt hơn tại đây .


29
Điều này có thể được đơn giản hóa hơn nữa bằng cách sử dụng a.sum(axis=1, keepdims=True)để giữ kích thước cột singleton, sau đó bạn có thể phát sóng cùng mà không cần phải sử dụng np.newaxis.
ali_m

6
điều gì sẽ xảy ra nếu bất kỳ row_sums nào bằng 0?
asdf

7
Đây là câu trả lời chính xác cho câu hỏi như đã nêu ở trên - nhưng nếu muốn chuẩn hóa theo nghĩa thông thường, hãy sử dụng np.linalg.normthay vì a.sum!
coldfix

1
cái này có được ưu tiên row_sums.reshape(3,1)không?
Paul

1
Nó không phải là mạnh mẽ kể từ khi tổng hàng có thể bằng 0.
nos

103

Scikit-learning có chức năng chuẩn hóa cho phép bạn áp dụng nhiều cách chuẩn hóa khác nhau. "Làm cho nó tổng thành 1" là tiêu chuẩn L1 và để thực hiện điều đó:

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]]

Bây giờ các hàng của bạn sẽ tổng thành 1.


3
Điều này cũng có lợi thế là nó hoạt động trên các mảng thưa thớt sẽ không vừa với bộ nhớ như các mảng dày đặc.
JEM_Mosig

10

Tôi nghĩ rằng điều này sẽ làm việc,

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

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

2
tốt. lưu ý sự thay đổi của dtype để arange, bằng cách thêm dấu thập phân đến 27.
Wim

3

Trong trường hợp bạn đang cố gắng chuẩn hóa mỗi hàng sao cho độ lớn của nó là một (nghĩa là độ dài đơn vị của hàng là một hoặc tổng bình phương của mỗi phần tử trong hàng là một):

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]])

Đang xác minh:

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

Axis dường như không phải là một tham số cho np.linalg.norm (nữa?).
Ztyx

đặc biệt tương ứng này đến mức l2 (nơi như hàng tổng hợp đến 1 tương ứng với tiêu chuẩn l1)
DPB

3

Tôi nghĩ bạn có thể bình thường hóa các yếu tố hàng sum tới 1 của thành viên này: new_matrix = a / a.sum(axis=1, keepdims=1). Và việc chuẩn hóa cột có thể được thực hiện với new_matrix = a / a.sum(axis=0, keepdims=1). Hy vọng điều này có thể hep.


2

Bạn có thể sử dụng hàm numpy tích hợp sẵn: np.linalg.norm(a, axis = 1, keepdims = True)


1

có vẻ như điều này cũng hoạt động

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

1

Bạn cũng có thể sử dụng chuyển vị ma trận:

(a.T / row_sums).T

0

Hoặc sử dụng hàm lambda, như

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

mỗi vector của vec sẽ có một định mức đơn vị.


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

trong đó input_data là tên mảng 2D của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.