[python] python 0으로 numpy 배열을 채우는 방법
numpy 버전 1.5.0과 함께 python 2.6.6을 사용하여 2D numpy 배열을 0으로 채우는 방법을 알고 싶습니다. 죄송합니다! 그러나 이것이 나의 한계입니다. 따라서 사용할 수 없습니다 np.pad
. 예를 들어, a
모양이 일치하도록 0으로 채우고 싶습니다 b
. 내가 이것을하고 싶은 이유는 내가 할 수 있기 때문입니다.
b-a
그런
>>> a
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
>>> b
array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
>>> c
array([[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
제가 이것을 할 수있는 유일한 방법은 추가하는 것입니다. 그러나 이것은 꽤 추한 것 같습니다. 사용 가능한 클리너 솔루션이 b.shape
있습니까?
편집, MSeiferts 답변에 감사드립니다. 나는 그것을 약간 정리해야했고 이것이 내가 얻은 것입니다.
def pad(array, reference_shape, offsets):
"""
array: Array to be padded
reference_shape: tuple of size of ndarray to create
offsets: list of offsets (number of elements must be equal to the dimension of the array)
will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference_shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = array
return result
답변
매우 간단하게 참조 모양을 사용하여 0을 포함하는 배열을 만듭니다.
result = np.zeros(b.shape)
# actually you can also use result = np.zeros_like(b)
# but that also copies the dtype not only the shape
그런 다음 필요한 곳에 배열을 삽입하십시오.
result[:a.shape[0],:a.shape[1]] = a
그리고 당신은 그것을 패딩했습니다.
print(result)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
왼쪽 상단 요소를 삽입해야하는 위치를 정의하면 좀 더 일반적으로 만들 수도 있습니다.
result = np.zeros_like(b)
x_offset = 1 # 0 would be what you wanted
y_offset = 1 # 0 in your case
result[x_offset:a.shape[0]+x_offset,y_offset:a.shape[1]+y_offset] = a
result
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.]])
하지만 허용 된 것보다 큰 오프셋이 없도록주의하십시오. 예 x_offset = 2
를 들어 이것은 실패합니다.
임의의 차원 수가있는 경우 슬라이스 목록을 정의하여 원래 배열을 삽입 할 수 있습니다. 나는 조금 놀아보고 배열과 참조가 동일한 수의 차원을 가지고 오프셋이 너무 크지 않은 한 임의의 모양의 배열을 (오프셋으로) 채울 수있는 패딩 함수를 만들었습니다.
def pad(array, reference, offsets):
"""
array: Array to be padded
reference: Reference array with the desired shape
offsets: list of offsets (number of elements must be equal to the dimension of the array)
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference.shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offset[dim], offset[dim] + array.shape[dim]) for dim in range(a.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = a
return result
그리고 일부 테스트 사례 :
import numpy as np
# 1 Dimension
a = np.ones(2)
b = np.ones(5)
offset = [3]
pad(a, b, offset)
# 3 Dimensions
a = np.ones((3,3,3))
b = np.ones((5,4,3))
offset = [1,0,0]
pad(a, b, offset)
답변
NumPy 1.7.0 ( numpy.pad
추가 되었을 때 )은 지금 꽤 오래되었습니다 (2013 년에 출시되었습니다). 그래서 질문에서 그 기능 을 사용하지 않고 방법 을 요청했지만 .NET을 사용하여 어떻게 달성 할 수 있는지 아는 것이 유용 할 것이라고 생각했습니다 numpy.pad
.
실제로는 매우 간단합니다.
>>> import numpy as np
>>> a = np.array([[ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.]])
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
이 경우 0
에 대한 기본값을 사용했습니다 mode='constant'
. 그러나 명시 적으로 전달하여 지정할 수도 있습니다.
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant', constant_values=0)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
두 번째 인수 ( [(0, 1), (0, 1)]
)가 혼란스러워 보이는 경우 : 각 목록 항목 (이 경우 튜플)은 차원에 해당하고 그 안의 항목은 앞 (첫 번째 요소)과 뒤 (두 번째 요소) 의 패딩을 나타냅니다 . 그래서:
[(0, 1), (0, 1)]
^^^^^^------ padding for second dimension
^^^^^^-------------- padding for first dimension
^------------------ no padding at the beginning of the first axis
^--------------- pad with one "value" at the end of the first axis.
이 경우 첫 번째 및 두 번째 축의 패딩이 동일하므로 2- 튜플을 전달할 수도 있습니다.
>>> np.pad(a, (0, 1), mode='constant')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
앞뒤의 패딩이 동일한 경우 튜플을 생략 할 수도 있습니다 (이 경우에는 해당되지 않음).
>>> np.pad(a, 1, mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0.]])
또는 이전과 이후의 패딩이 동일하지만 축에 대해 다른 경우 내부 튜플에서 두 번째 인수를 생략 할 수도 있습니다.
>>> np.pad(a, [(1, ), (2, )], mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
그러나 나는 실수하기 쉽기 때문에 항상 명시적인 것을 선호하는 경향이 있습니다 (NumPys 기대치가 당신의 의도와 다를 때) :
>>> np.pad(a, [1, 2], mode='constant')
array([[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.]])
여기서 NumPy는 모든 축을 각 축 앞의 요소 1 개와 각 축 뒤의 요소 2 개로 패딩하기를 원한다고 생각합니다! 축 1의 요소 1 개와 축 2의 요소 2 개로 패딩하려는 경우에도 마찬가지입니다.
패딩을 위해 튜플 목록을 사용했습니다. 이것은 단지 “내 규칙”일뿐입니다. 목록 목록이나 튜플 튜플 또는 배열 튜플을 사용할 수도 있습니다. NumPy는 인수의 길이 (또는 길이가없는 경우)와 각 항목의 길이 (또는 길이가있는 경우) 만 확인합니다!
답변
나는 당신의 주요 문제가 당신이 계산해야한다는 것을 이해합니다. d=b-a
하지만 배열의 크기가 다르다는 것을 이해합니다. 중간 패딩이 필요하지 않습니다c
패딩없이이 문제를 해결할 수 있습니다.
import numpy as np
a = np.array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
b = np.array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
d = b.copy()
d[:a.shape[0],:a.shape[1]] -= a
print d
산출:
[[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 3. 3. 3. 3. 3. 3.]]
답변
배열에 울타리 1을 추가해야하는 경우 :
>>> mat = np.zeros((4,4), np.int32)
>>> mat
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
>>> mat[0,:] = mat[:,0] = mat[:,-1] = mat[-1,:] = 1
>>> mat
array([[1, 1, 1, 1],
[1, 0, 0, 1],
[1, 0, 0, 1],
[1, 1, 1, 1]])
답변
나는 이것에 약간 늦었다는 것을 알고 있지만 상대 패딩 (일명 가장자리 패딩)을 수행하려는 경우이를 구현할 수있는 방법은 다음과 같습니다. 할당의 첫 번째 인스턴스는 제로 패딩을 생성하므로이를 제로 패딩 및 상대 패딩 모두에 사용할 수 있습니다 (원래 배열의 가장자리 값을 패딩 된 배열로 복사하는 곳입니다).
def replicate_padding(arr):
"""Perform replicate padding on a numpy array."""
new_pad_shape = tuple(np.array(arr.shape) + 2) # 2 indicates the width + height to change, a (512, 512) image --> (514, 514) padded image.
padded_array = np.zeros(new_pad_shape) #create an array of zeros with new dimensions
# perform replication
padded_array[1:-1,1:-1] = arr # result will be zero-pad
padded_array[0,1:-1] = arr[0] # perform edge pad for top row
padded_array[-1, 1:-1] = arr[-1] # edge pad for bottom row
padded_array.T[0, 1:-1] = arr.T[0] # edge pad for first column
padded_array.T[-1, 1:-1] = arr.T[-1] # edge pad for last column
#at this point, all values except for the 4 corners should have been replicated
padded_array[0][0] = arr[0][0] # top left corner
padded_array[-1][0] = arr[-1][0] # bottom left corner
padded_array[0][-1] = arr[0][-1] # top right corner
padded_array[-1][-1] = arr[-1][-1] # bottom right corner
return padded_array
복잡성 분석 :
이에 대한 최적의 솔루션은 numpy의 패드 방법입니다. 5 회 실행에 대한 평균을 구한 후 상대 패딩이있는 np.pad는 8%
위에 정의 된 함수보다 낫습니다. 이것은 이것이 상대 패딩 및 제로 패딩 패딩을위한 최적의 방법임을 보여줍니다.
#My method, replicate_padding
start = time.time()
padded = replicate_padding(input_image)
end = time.time()
delta0 = end - start
#np.pad with edge padding
start = time.time()
padded = np.pad(input_image, 1, mode='edge')
end = time.time()
delta = end - start
print(delta0) # np Output: 0.0008790493011474609
print(delta) # My Output: 0.0008130073547363281
print(100*((delta0-delta)/delta)) # Percent difference: 8.12316715542522%
답변
Tensorflow는 이미지 크기 조정 / 패딩 tf.image.pad tf.pad 함수도 구현 했습니다 .
padded_image = tf.image.pad_to_bounding_box(image, top_padding, left_padding, target_height, target_width)
padded_image = tf.pad(image, paddings, "CONSTANT")
이러한 함수는 tensorflow의 다른 입력 파이프 라인 기능과 동일하게 작동하며 기계 학습 애플리케이션에서 훨씬 더 잘 작동합니다.