본문 바로가기

Minding's Programming/Numpy & Pandas

[Numpy exercise 100] 81번 ~ 90번 문제풀이

728x90
반응형

[Numpy exercise 100] 1번 ~ 30번 문제풀이

[Numpy exercise 100] 31번 ~ 60번 문제풀이

[Numpy exercise 100] 61번 ~ 70번 문제풀이

[Numpy exercise 100] 71번 ~ 80번 문제풀이

 

https://github.com/rougier/numpy-100

 

GitHub - rougier/numpy-100: 100 numpy exercises (with solutions)

100 numpy exercises (with solutions). Contribute to rougier/numpy-100 development by creating an account on GitHub.

github.com

 


81. Consider an array Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14], how to generate an array R = [[1,2,3,4], [2,3,4,5], [3,4,5,6], ..., [11,12,13,14]]? (★★★)

  • 어레이 Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14], 어레이 R = [[1,2,3,4], [2,3,4,5], [3,4,5,6], ..., [11,12,13,14]]를 생성하는 방법을 고려하십시오.
  • 1차원 벡터를 다차원 array로 reshape. 단, 원소 한칸씩 전진하며 쌓아가야 함
  • stride_tricks.as_strided : 주어진 모양 및 보폭으로 배열을 만듦
 

numpy.lib.stride_tricks.as_strided — NumPy v1.21 Manual

Create a view into the array with the given shape and strides. Warning This function has to be used with extreme care, see notes. as_strided creates a view into the array given the exact strides and shape. This means it manipulates the internal data struct

numpy.org

from numpy.lib import stride_tricks

Z = np.arange(1,15,dtype=np.uint32)
R = stride_tricks.as_strided(Z,(11,4),(4,4)) # 최종 shape은 (11,4)가 되도록, 보폭은 (4,4)씩
print(R)

>>>
[[ 1  2  3  4]
 [ 2  3  4  5]
 [ 3  4  5  6]
 [ 4  5  6  7]
 [ 5  6  7  8]
 [ 6  7  8  9]
 [ 7  8  9 10]
 [ 8  9 10 11]
 [ 9 10 11 12]
 [10 11 12 13]
 [11 12 13 14]]

 

82. Compute a matrix rank (★★★)

  • 행렬 순위를 계산합니다
  • 문제가 잘 이해는 안되지만... 특이값 분해(Singular Value Decomposition, SVD)를 사용하여 행렬을 대각화한다.
  • 특이값분해 설명 블로그(다크 프로그래머 님) : https://darkpgmr.tistory.com/106
 

[선형대수학 #4] 특이값 분해(Singular Value Decomposition, SVD)의 활용

활용도 측면에서 선형대수학의 꽃이라 할 수 있는 특이값 분해(Singular Value Decomposition, SVD)에 대한 내용입니다. 보통은 복소수 공간을 포함하여 정의하는 것이 일반적이지만 이 글에서는 실수(real

darkpgmr.tistory.com

Z = np.random.uniform(0,1,(10,10))
U, S, V = np.linalg.svd(Z) # Singular Value Decomposition
rank = np.sum(S > 1e-10)
print(rank)

# 또 다른 방법
rank = np.linalg.matrix_rank(Z)
print(rank)

>>>
10

 

83. How to find the most frequent value in an array?

  • 배열에서 가장 빈번한 값을 찾는 방법은 무엇입니까?
  • np.bincount()를 통해서 각 값을 count한 뒤, argmax()로 가장 큰 값을 찾아냄
  • argmax() : f(x)의 최대값을 만들어주는 입력 x 자체를 뜻함 (인덱스 반환)
Z = np.random.randint(0,10,50)
print(np.bincount(Z).argmax())

>>>
6

 

84. Extract all the contiguous 3x3 blocks from a random 10x10 matrix (★★★)

  • 랜덤 10x10 행렬에서 모든 연속 3x3 블럭 추출
Z = np.random.randint(0,5,(10,10))
n = 3
i = 1 + (Z.shape[0]-3)
j = 1 + (Z.shape[1]-3)
C = stride_tricks.as_strided(Z, shape=(i, j, n, n), strides=Z.strides + Z.strides)
print(C)
>>>
[[[[1 1 1]
   [4 2 0]
   [4 4 4]]

  [[1 1 3]
   [2 0 2]
   [4 4 3]]

  [[1 3 2]
   [0 2 0]
   [4 3 3]]

  ...

  [[4 4 2]
   [4 4 4]
   [3 2 4]]]]

 

85. Create a 2D array subclass such that Z[i,j] == Z[j,i] (★★★)

  • Z[i,j] == Z[j,i]와 같은 2D 배열 하위 클래스 만들기
class Symetric(np.ndarray):
    def __setitem__(self, index, value):
        i,j = index
        super(Symetric, self).__setitem__((i,j), value)
        super(Symetric, self).__setitem__((j,i), value)
        
def symetric(Z):
    return np.asarray(Z + Z.T - np.diag(Z.diagonal())).view(Symetric)

S = symetric(np.random.randint(0, 10, (5,5)))
S[2,3] = 42
print(S)


>>>
[[ 1  9 14 12  0]
 [ 9  9 10 11  5]
 [14 10  1 42  6]
 [12 11 42  3  6]
 [ 0  5  6  6  7]]

 

86. Consider a set of p matrices wich shape (n,n) and a set of p vectors with shape (n,1). How to compute the sum of of the p matrix products at once? (result has shape (n,1)) (★★★)

 

numpy.tensordot — NumPy v1.21 Manual

(2,) array_like Or, a list of axes to be summed over, first sequence applying to a, second to b. Both elements array_like must be of the same length.

numpy.org

p, n = 10, 20
M = np.ones((p,n,n))
V = np.ones((p,n,1))
S = np.tensordot(M, V, axes=[[0, 2], [0, 1]]) # np.tensordot(a, b, 축) : 지정된 축에 따라 텐서 곱을 계산
print(S)

# 추가설명... (설명해주실 분 계시면 댓글 부탁드리겠습니다ㅜㅜ)
# It works, because:
# M is (p,n,n)
# V is (p,n,1)
# Thus, summing over the paired axes 0 and 0 (of M and V independently),
# and 2 and 1, to remain with a (n,1) vector.

>>>
[[200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]]

 

87. Consider a 16x16 array, how to get the block-sum (block size is 4x4)? (★★★)

  • 16x16 array가 주어질 때, 4x4의 블록합계로 결과값을 가져오는 방법
      1. np.add.reduceat() : 주어진 배열의 인덱스를 고려하여 해당인덱스부터 끝까지의 합계를 구해 배열로 반환
      1. stride_tricks.sliding_window_view()를 이용해 합계
Z = np.ones((16,16))
print(Z)
k = 4
S = np.add.reduceat(np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
                                       np.arange(0, Z.shape[1], k), axis=1)
print(S)

>>>
# Z
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]
 
 # S
 [[16. 16. 16. 16.]
 [16. 16. 16. 16.]
 [16. 16. 16. 16.]
 [16. 16. 16. 16.]]
# sliding_window_view 사용
Z = np.ones((16,16))
k = 4

windows = np.lib.stride_tricks.sliding_window_view(Z, (k, k))
S = windows[::k, ::k, ...].sum(axis=(-2, -1))
print(S)

 

88. How to implement the Game of Life using numpy arrays? (★★★)

 

라이프 게임 - 위키백과, 우리 모두의 백과사전

Hasbro의 보드 게임인 인생 게임도 가끔 ‘라이프 게임’으로 불린다. ‘글라이더’ 패턴의 진행. 라이프 게임(Game of Life) 또는 생명 게임은 영국의 수학자 존 호턴 콘웨이가 고안해낸 세포 자동자

ko.wikipedia.org

def iterate(Z):
    # Count neighbours
    N = (Z[0:-2,0:-2] + Z[0:-2,1:-1] + Z[0:-2,2:] +
         Z[1:-1,0:-2]                + Z[1:-1,2:] +
         Z[2:  ,0:-2] + Z[2:  ,1:-1] + Z[2:  ,2:])

    # Apply rules
    birth = (N==3) & (Z[1:-1,1:-1]==0)
    survive = ((N==2) | (N==3)) & (Z[1:-1,1:-1]==1)
    Z[...] = 0
    Z[1:-1,1:-1][birth | survive] = 1
    return Z

Z = np.random.randint(0,2,(50,50))
for i in range(100): Z = iterate(Z)
print(Z)

>>>
[[0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]]

 

89. How to get the n largest values of an array (★★★)

  • 배열의 최대값 n개를 가져오는 방법
    • argsort()으로 오름차순 정렬 뒤 뒤에서 n개 가져오기 (arg가 붙으면 인덱스를 반환한다.)
    • argpartition()로 배열 내 가장 작은값 (-Z로 파라미터를 주었기 때문에) n개를 찾고 인덱스 반환
Z = np.arange(10000)
np.random.shuffle(Z) # 원소 순서를 랜덤으로 섞음
n = 5

# 일반적인 방법 (전체를 sorting하므로 조금 느림)
print (Z[np.argsort(Z)[-n:]])

# 좀 더 빠른 방법 (일부만 sorting하므로)
print (Z[np.argpartition(-Z,n)[:n]])

>>>
[8178 4152 4340 ...  229 3725 3684]
[9995 9996 9997 9998 9999]
[9998 9999 9996 9997 9995]

 

90. Given an arbitrary number of vectors, build the cartesian product (every combinations of every item) (★★★)

 

곱집합 - 위키백과, 우리 모두의 백과사전

집합 A = {x, y, z}와 B = {1, 2, 3}의 곱집합 A × B. 52장의 포커 패의 집합은 모양의 집합 {♠, ♥, ♣, ♦}과 숫자의 집합 {2, ..., 10, J, Q, K, A}의 곱집합이라 생각할 수 있다. 집합론에서, 곱집합(곱集合,

ko.wikipedia.org

def cartesian(arrays):
    arrays = [np.asarray(a) for a in arrays]
    shape = (len(x) for x in arrays)

    ix = np.indices(shape, dtype=int)
    ix = ix.reshape(len(arrays), -1).T

    for n, arr in enumerate(arrays):
        ix[:, n] = arrays[n][ix[:, n]]

    return ix

print (cartesian(([1, 2, 3], [4, 5], [6, 7])))

>>>
[[1 4 6]
 [1 4 7]
 [1 5 6]
 [1 5 7]
 [2 4 6]
 [2 4 7]
 [2 5 6]
 [2 5 7]
 [3 4 6]
 [3 4 7]
 [3 5 6]
 [3 5 7]]
728x90