2015-08-23 17 views

Trả lời

34

có lẽ cách sạch nhất là sử dụng np.repeat:

a = np.array([[1, 2], [1, 2]]) 
print(a.shape) 
# (2, 2) 

# indexing with np.newaxis inserts a new 3rd dimension, which we then repeat the 
# array along, (you can achieve the same effect by indexing with None, see below) 
b = np.repeat(a[:, :, np.newaxis], 3, axis=2) 

print(b.shape) 
# (2, 2, 3) 

print(b[:, :, 0]) 
# [[1 2] 
# [1 2]] 

print(b[:, :, 1]) 
# [[1 2] 
# [1 2]] 

print(b[:, :, 2]) 
# [[1 2] 
# [1 2]] 

có nói rằng, bạn thường có thể tránh lặp lại các mảng của bạn hoàn toàn bằng cách sử dụng broadcasting. Ví dụ, chúng ta hãy nói rằng tôi muốn thêm một vector (3,):

c = np.array([1, 2, 3]) 

để a. Tôi có thể sao chép nội dung của a 3 lần trong thứ nguyên thứ ba, sau đó sao chép nội dung của c hai lần ở cả thứ nguyên đầu tiên và thứ hai, sao cho cả hai mảng của tôi là (2, 2, 3), sau đó tính tổng của chúng. Tuy nhiên, nó đơn giản hơn nhiều và nhanh hơn để làm điều này:

d = a[..., None] + c[None, None, :] 

Ở đây, a[..., None] có hình (2, 2, 1)c[None, None, :] có hình (1, 1, 3) *. Khi tôi tính toán Tóm lại, kết quả được 'phát sóng' ra dọc theo kích thước của kích thước 1, đem lại cho tôi một kết quả của hình dạng (2, 2, 3):

print(d.shape) 
# (2, 2, 3) 

print(d[..., 0]) # a + c[0] 
# [[2 3] 
# [2 3]] 

print(d[..., 1]) # a + c[1] 
# [[3 4] 
# [3 4]] 

print(d[..., 2]) # a + c[2] 
# [[4 5] 
# [4 5]] 

Broadcasting là một kỹ thuật rất mạnh mẽ bởi vì nó tránh được sự bổ sung trên không liên quan đến việc tạo ra các bản sao lặp lại của các mảng đầu vào của bạn trong bộ nhớ.


* Mặc dù tôi bao gồm họ cho rõ ràng, các chỉ số None vào c là không thực sự cần thiết - bạn cũng có thể làm a[..., None] + c, ví dụ: phát sóng một mảng (2, 2, 1) chống lại một mảng (3,). Điều này là do nếu một trong các mảng có kích thước nhỏ hơn kích thước khác thì chỉ có kích thước trailing của hai mảng cần tương thích. Để đưa ra một ví dụ phức tạp hơn:

a = np.ones((6, 1, 4, 3, 1)) # 6 x 1 x 4 x 3 x 1 
b = np.ones((5, 1, 3, 2))  #  5 x 1 x 3 x 2 
result = a + b    # 6 x 5 x 4 x 3 x 2 
+0

Để xác minh rằng điều này thực sự mang lại cho kết quả đúng, bạn cũng có thể in ra 'b [:,:, 0] ',' b [:,:, 1] ', và' b [:,:, 2] '. Mỗi lát thứ nguyên thứ ba là một bản sao của mảng 2D gốc. Điều này không rõ ràng khi nhìn vào 'print (b)'. – ely

+0

Đây là một câu trả lời tuyệt vời !! Cảm ơn bạn! – drg

11

Một cách khác là sử dụng numpy.dstack. Giả sử rằng bạn muốn lặp lại các ma trận anum_repeats lần:

import numpy as np 
b = np.dstack([a]*num_repeats) 

Bí quyết là để bọc các ma trận a vào một danh sách các yếu tố duy nhất, sau đó sử dụng các nhà điều hành * lặp lại trong các yếu tố trong danh sách này num_repeats lần.

Ví dụ, nếu:

a = np.array([[1, 2], [1, 2]]) 
num_repeats = 5 

này lặp đi lặp lại các mảng [1 2; 1 2] 5 lần trong chiều thứ ba.Để xác minh (trong IPython):

In [110]: import numpy as np 

In [111]: num_repeats = 5 

In [112]: a = np.array([[1, 2], [1, 2]]) 

In [113]: b = np.dstack([a]*num_repeats) 

In [114]: b[:,:,0] 
Out[114]: 
array([[1, 2], 
     [1, 2]]) 

In [115]: b[:,:,1] 
Out[115]: 
array([[1, 2], 
     [1, 2]]) 

In [116]: b[:,:,2] 
Out[116]: 
array([[1, 2], 
     [1, 2]]) 

In [117]: b[:,:,3] 
Out[117]: 
array([[1, 2], 
     [1, 2]]) 

In [118]: b[:,:,4] 
Out[118]: 
array([[1, 2], 
     [1, 2]]) 

In [119]: b.shape 
Out[119]: (2, 2, 5) 

Cuối cùng, chúng ta có thể thấy hình dạng của ma trận là 2 x 2, với 5 lát trong chiều thứ ba.

+0

Làm cách nào để so sánh với 'định dạng lại '? Nhanh hơn? cho cùng một cấu trúc? Chắc chắn của nó neater. –

+0

@AnderBiguri Tôi chưa bao giờ điểm chuẩn ... Tôi đặt điều này ở đây chủ yếu để hoàn thành. Sẽ rất thú vị với thời gian và thấy sự khác biệt. – rayryeng

+1

Tôi chỉ img = np.dstack ([arr] * 3) và làm việc tốt! Cảm ơn bạn –

2
A=np.array([[1,2],[3,4]]) 
B=np.asarray([A]*N) 

Sửa @ Mr.F, giữ gìn trật tự không gian:

B=B.T 
+0

Điều này dẫn đến một mảng N x 2 x 2 cho tôi, ví dụ: 'B.shape' in' (N, 2, 2) 'cho bất kỳ giá trị' N' nào. Nếu bạn chuyển 'B' bằng' B.T' thì nó khớp với đầu ra mong đợi. – ely

+0

@ Mr.F - Bạn đã đúng. Điều này sẽ phát sóng dọc theo kích thước đầu tiên, và do đó, thực hiện 'B [0], B [1], ...' sẽ cung cấp cho bạn slice đúng, cái mà tôi sẽ tranh luận và nói rằng dễ dàng hơn để gõ hơn là sử dụng 'B [:,:, 0], B [:,:, 1] ', v.v. – rayryeng

+0

Có thể dễ dàng nhập, nhưng ví dụ nếu bạn làm điều này với dữ liệu hình ảnh thì phần lớn sẽ không chính xác, vì hầu hết các thuật toán sẽ mong đợi các quy ước của đại số tuyến tính được sử dụng cho các lát 2D của các kênh pixel. Thật khó để tưởng tượng một ứng dụng mà bạn bắt đầu với một mảng 2D, xử lý các hàng và cột với một quy ước nhất định, và sau đó bạn muốn nhiều bản sao của cùng một thứ đó mở rộng vào trục mới, nhưng đột nhiên bạn muốn trục đầu tiên thay đổi ý nghĩa thành là trục mới ... – ely

1

Dưới đây là một ví dụ phát sóng thực hiện chính xác những gì được yêu cầu.

a = np.array([[1, 2], [1, 2]]) 
a=a[:,:,None] 
b=np.array([1]*5)[None,None,:] 

Sau đó b*a là kết quả mong muốn và (b*a)[:,:,0] sản xuất array([[1, 2],[1, 2]]), đó là bản gốc a, cũng như (b*a)[:,:,1] vv

Các vấn đề liên quan