4일차 문제¶
numpy.ndarray
타입의 임의의 모양을 가진 2차원 배열(행렬)들이 담긴 리스트arr_list
가 존재한다.arr_list
에 담긴 배열을 순서대로 사용하여 아래의 조건에 맞게 사용한다.
- 초기 A의 상태는 [[0]]이며, arr를 사용하여 계산한 결과값을 A로 대체한다.
arr_list를 앞에서부터 순서대로 배열을 꺼낸 후, arr로 정의하고 계산을 진행하는데, 아래 두 가지 경우는 유의한다.
- A와 arr 간 행렬곱이 불가할 경우, arr를 버리고 다음배열을 꺼낸다.
- A와 arr 간 행렬곱이 가능할 경우, 아래과 같이 계산한다.
- `A = (A + 1) (arr 2)
위 과정을 통해 arr_list에 있는 모든 배열을 처리한 뒤 최종 A를 반환하라.
In [7]:
import numpy as np
In [8]:
arr_list = np.array([
[[ -9, -14]],
[[ 14, -2, 0], [-14, -5, 1], [-11, 3, -6]],
[[-2, -6], [18, 0]]
])
arr_list
C:\Users\ysjin\AppData\Local\Temp/ipykernel_12544/598695102.py:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray. arr_list = np.array([
Out[8]:
array([list([[-9, -14]]), list([[14, -2, 0], [-14, -5, 1], [-11, 3, -6]]), list([[-2, -6], [18, 0]])], dtype=object)
In [10]:
# arr_list[0]의 값이 어떤 타입인지 확인한다.
type(arr_list[0])
Out[10]:
list
행렬의 곱이 가능하기 위해서는 아래의 조건이 충족되어야 한다.
np.dot(A, B)
에서 행렬A와 행렬B는 행렬A의 열과 행렬B의 행의 개수가 동일해야 한다.
In [25]:
# 행렬의 곱이 가능한 arr_list[0]과 arr_list[2]를 예시로 보여준다.
# arr_list[0] - 행 : 1, 열 : 2
np.shape(arr_list[0])
Out[25]:
(1, 2)
In [26]:
# arr_list[2] - 행 : 2, 열 : 2
np.shape(arr_list[2])
Out[26]:
(2, 2)
In [32]:
# 행렬 곱 이후 모양은 행 : 1, 열 : 2
np.shape(np.dot(arr_list[0], arr_list[2]))
Out[32]:
(1, 2)
즉, 이를 이용하여 우리는 아래의 과정을 거쳐 문제를 해결한다.
- 지정된 arr와 추출한 arr간 행렬곱이 가능한지 확인
- if True : 행렬곱 실시 (2번으로 이어짐)
- if False : 다음 행렬 추출
- 지정된 arr와 추출된 arr의 행렬곱이 영행렬인가?
- if True : 지정된 식에 의한 행렬곱 실시
- if False : 행렬곱 실시
In [61]:
# 1. 지정된 arr와 추출된 arr간 행렬곱이 가능한가?
In [51]:
# 순서대로 행렬을 추출한다.
for i in arr_list:
# 만약, 행렬A의 열 갯수와, np.shape의 행 갯수가 같으면 (즉, 행렬곱이 가능하면)
if np.shape(arr)[1] == np.shape(i)[0]:
# 만약 두 행렬의 곱이 영행렬과 같다면?
if np.dot(arr, i) == np.zeros(np.shape(np.dot(arr, i))):
# 지정된 식에 따른 계산 실시
# arr를 일행렬로 만들어준다.
arr = np.ones(np.shape(arr))
# 행렬B에 2 곱하기
i = (np.array(i) * 2).tolist()
# 행렬곱 실시한 후 arr에 저장
arr = np.dot(arr, i)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) ~\AppData\Local\Temp/ipykernel_12544/3270770293.py in <module> 4 if np.shape(arr)[1] == np.shape(i)[0]: 5 # 만약 두 행렬의 곱이 영행렬과 같다면? ----> 6 if np.dot(arr, i) == np.zeros(np.shape(np.dot(arr, i))): 7 # 지정된 식에 따른 계산 실시 8 # arr를 일행렬로 만들어준다. ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
error : ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
- 해당 오류는 boolean값이 복수로 나오는 경우에 발생하는 오류이다.
- 아래 예시를 살펴보자.
In [52]:
np.dot(arr, arr_list[0]) == np.zeros(np.shape(np.dot(arr, arr_list[0])))
Out[52]:
array([[ True, True]])
이는, 오류메세지에 나온 대로, np.all()를 사용하여 해결할 수 있다.
In [65]:
# boolean이 하나만 추출된다.
np.any(np.dot([[0]], arr_list[0]) == np.zeros(np.shape(np.dot([[0]], arr_list[0]))))
Out[65]:
True
In [73]:
# 초기값 설정 = [[0]]
arr = [[0]]
# 순서대로 행렬을 추출한다.
for i in arr_list:
# 만약, 행렬A의 열 갯수와, np.shape의 행 갯수가 같으면 (즉, 행렬곱이 가능하면)
if np.shape(arr)[1] == np.shape(i)[0]:
# 지정된 식에 따른 계산 실시
# arr에 1을 더해준다.
arr = (np.array(arr) + 1).tolist()
# 행렬B에 2 곱하기
i = (np.array(i) * 2).tolist()
# 행렬곱 실시한 후 arr에 저장
arr = np.dot(arr, i)
print(arr)
else:
print(arr)
arr
[[-18 -28]] [[-18 -28]] [[-904 204]]
Out[73]:
array([[-904, 204]])
5일차 문제¶
흑백 이미지는 컬러 이미지를 아래 공식에 따라 변환하여 적용한다고 한다.
- 명도 값 = Red 0.3 + Green 0.5 + Blue * 0.2
이 때 높이가 H, 너비가 W인 컬러이미지에서 RGB 정보를 추출하여 만든 3차원 배열 img는 H W 3의 모양을 가지며, 반드시 RGB순으로 수가 배치되어 있다. 이때, 컬러이미지를 흑백이미지로 변환하는 알고리즘을 구현하라.
In [75]:
col_img = np.array([
[[51, 60, 74], [92, 20, 74]],
[[14, 82, 87], [71, 86, 99]]
])
col_img
Out[75]:
array([[[51, 60, 74], [92, 20, 74]], [[14, 82, 87], [71, 86, 99]]])
이번 문제는 for문을 세 개 돌려서 해결한다.
- 전체 array를 돌아주는 for문 하나,
- array 안의 리스트를 돌아주는 for문 하나,
- array 안의 list 내부 요소를 추출하는 for문 하나이다.
In [92]:
# 아래의 중첩문을 이용한다.
for a in col_img:
print(a)
print("--------------")
for b in a:
print(b)
print("--------------")
for c in b:
print(c)
print("--------------")
[[51 60 74] [92 20 74]] -------------- [51 60 74] -------------- 51 -------------- 60 -------------- 74 -------------- [92 20 74] -------------- 92 -------------- 20 -------------- 74 -------------- [[14 82 87] [71 86 99]] -------------- [14 82 87] -------------- 14 -------------- 82 -------------- 87 -------------- [71 86 99] -------------- 71 -------------- 86 -------------- 99 --------------
In [109]:
# 정답을 저장할 빈배열 생성
answer = []
for a in col_img:
# n번째 행의 색깔수치를 저장할 list 생성
temp_list = []
for b in a:
# n번째 행의 m번째 색깔수치를 저장할 빈 변수 생성
temp_num = 0
for c in range(len(b)):
# 배열 c는 무조건 R, G, B 순서대로 나온다.
# temp_num에 R * 0.3 + G * 0.5 + B * 0.2 공식을 적용한 값을 저장한다.
# 만약 추출된 값이 R이면
if c == 0:
#temp_num에 추출된 값의 0.3을 곱하여 더한다.
temp_num = temp_num + (b[c] * 0.3)
# 만약 추출된 값이 G이면
elif c == 1:
# temp_num에 추출된 값의 0.5를 곱하여 더한다.
temp_num = temp_num + (b[c] * 0.5)
# 만약 추출된 값이 R 혹은 G가 아니라면 (추출된 값이 B라면)
else:
# temp_num에 추출된 값의 0.5를 곱하여 더한다.
temp_num = temp_num + (b[c] * 0.2)
# 계산이 끝난 temp_num값을 temp_list에 저장한다.
temp_list.append(round(temp_num, 2))
# 모든 계산이 끝난 temp_list값을 anaswer에 저장한다.
answer.append(temp_list)
In [107]:
answer = np.array(answer)
answer
Out[107]:
array([[60.1, 52.4], [62.6, 84.1]])
In [277]:
testA = np.array([
[[3, 1],[3, 3]],
[[1, 1],[3, 2]]
])
testB = np.array([
[[3, 3],[3, 3]],
[[1, 3],[2, 1]]
])
In [117]:
resultA = np.dot(testA, testB)
resultA
Out[117]:
array([[[[12, 12], [ 5, 10]], [[18, 18], [ 9, 12]]], [[[ 6, 6], [ 3, 4]], [[15, 15], [ 7, 11]]]])
In [119]:
# 4차원의 값이 나오는 것을 확인할 수 있다.
np.ndim(resultA)
Out[119]:
4
np.matmul()¶
- np.matmul()은 testA = [행렬A, 행렬B], testB = [행렬C, 행렬D]가 존재한다고 가정할 때, testA와 testB를 가지고 계산할 경우, 행렬A의 행과 행렬C의 열만을 곱하여 값을 산출한다.
- np.matmul 대신 @을 사용하여 계산할 수 있다.
In [278]:
resultB = np.matmul(testA, testB)
resultB
Out[278]:
array([[[12, 12], [18, 18]], [[ 3, 4], [ 7, 11]]])
In [121]:
# 3차원의 값이 나오는 것을 확인할 수 있다.
np.ndim(resultB)
Out[121]:
3
2. 스칼라의 구현¶
- 스칼라는 단일 차원의 값을 의미한다. 방향이 없고, 오직 크기만을 가지는 값으로 상수로 표현할 수 있다.
- 선형대수에서는 자연수의 곱으로 표현하며, 선형대수에서도 브로드캐스팅을 활용한 곱으로 표현 가능하다.
In [123]:
testC = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
testC
Out[123]:
array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [124]:
testC * 10
Out[124]:
array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
3. 같은 차원의 다른 모양을 가진 2차원 배열의 경우 시스템의 처리¶
- 연산을 할 배열에서 크기가 1인 차원이 존재한다면, 다른 배열에서 해당 차원의 크기만큼 확장하여 계산
In [125]:
testD = np.array([
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]
])
testE = np.array([
[1, 2, 3]
])
testF = np.array([
[2, 2, 3],
[4, 5, 6],
])
In [126]:
# 벡터와 행렬의 덧셈
testD + testE
Out[126]:
array([[11, 12, 13], [21, 22, 23], [31, 32, 33]])
In [131]:
# 벡터가 아닌 경우, 오류가 출력된다.
testD + testF
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) ~\AppData\Local\Temp/ipykernel_12544/3254901123.py in <module> 1 # 벡터가 아닌 경우, 오류가 출력된다. ----> 2 testD + testF ValueError: operands could not be broadcast together with shapes (3,3) (2,3)
In [132]:
# 1 * 3 벡터와 3 * 1 벡터가 존재할 경우
testG = np.array([
[1],
[2],
[3]
])
testH = np.array([
[1, 2, 3]
])
In [133]:
testG + testH
Out[133]:
array([[2, 3, 4], [3, 4, 5], [4, 5, 6]])
In [136]:
# 브로드캐스팅은 차원 간에서도 적용된다.
testI = np.array(
[[[3, 2, 1]],
[[0, 1, 3]]]
)
testJ = np.array(
[[0, 2, 1],[2, 2, 3]
])
In [135]:
testI + testJ
Out[135]:
array([[[3, 4, 2], [5, 4, 4]], [[0, 3, 4], [2, 3, 6]]])
4. any()와 all()¶
- any() : 주어빈 배열에 True가 하나라도 있다면 True를 반환하고, True가 하나도 없다면 False를 반환
- all() : 주어진 배열 모두 True라면 True를 반환하고, 하나라도 False가 있다면 False를 반환
In [137]:
np.random.seed(42)
arr = np.random.randint(0, 100, size=(3, 3, 3))
print(arr)
[[[51 92 14] [71 60 20] [82 86 74]] [[74 87 99] [23 2 21] [52 1 87]] [[29 37 1] [63 59 20] [32 75 57]]]
In [142]:
answer1 = ((arr == 52) | (arr == 1)).any()
answer1
Out[142]:
True
In [143]:
answer2 = (arr[0, :, :] >= 20).all()
answer2
Out[143]:
False
심화문제1. 지뢰찾기¶
아래 조건에 맞게 문제를 해결하시오
- board는 10 10 크기를 가진 2차원의 향렬이며, 5 5 크기로 4개의 구역으로 나눈다.
- bomb는 bomb1부터 bomb4까지 총 4종류가 있다.
- 각 구역마다 bomb n에 해당하는 요소를 제거한다.
- bomb1 ~ 4는 순서대로 bombs에 담겨서 1차원 배열로 주어지며, 지뢰로 판단되는 값은 0으로 변경하도록 하자.
In [255]:
board = np.array([
[3, 4, 2, 4, 4, 1, 2, 2, 2, 4],
[3, 2, 4, 1, 3, 1, 3, 4, 0, 3],
[1, 4, 3, 0, 0, 2, 2, 1, 3, 3],
[2, 3, 3, 0, 2, 4, 2, 4, 0, 1],
[3, 0, 3, 1, 1, 0, 1, 4, 1, 3],
[3, 3, 3, 4, 2, 0, 3, 1, 3, 1],
[1, 3, 4, 1, 1, 3, 1, 1, 3, 3],
[0, 4, 4, 1, 4, 1, 0, 3, 3, 3],
[4, 0, 4, 4, 0, 0, 0, 0, 3, 2],
[2, 0, 2, 2, 0, 2, 4, 1, 1, 0]
])
bombs = [1, 2, 3, 4]
In [154]:
num = int(len(board)/2)
area1 = board[0:num, 0:num]
area1
Out[154]:
array([[3, 4, 2, 4, 4], [3, 2, 4, 1, 3], [1, 4, 3, 0, 0], [2, 3, 3, 0, 2], [3, 0, 3, 1, 1]])
In [156]:
area2 = board[0:num, num:num*2]
area2
Out[156]:
array([[1, 2, 2, 2, 4], [1, 3, 4, 0, 3], [2, 2, 1, 3, 3], [4, 2, 4, 0, 1], [0, 1, 4, 1, 3]])
In [157]:
area3 = board[num:num*2, 0:num]
area3
Out[157]:
array([[3, 3, 3, 4, 2], [1, 3, 4, 1, 1], [0, 4, 4, 1, 4], [4, 0, 4, 4, 0], [2, 0, 2, 2, 0]])
In [158]:
area4 = board[num:num*2, num:num*2]
area4
Out[158]:
array([[0, 3, 1, 3, 1], [3, 1, 1, 3, 3], [1, 0, 3, 3, 3], [0, 0, 0, 3, 2], [2, 4, 1, 1, 0]])
In [256]:
num = int(len(board)/2)
# "행"을 순회하는 인덱스 i
for i in range(len(board)):
# '열"을 순회하는 인덱스 j
for j in range(len(board[i])):
# 만약 1구역이라면
if (i >= 0 and i < num) and (j >= 0 and j < num):
# 1구역에서 bombs[0]의 값과 원소의 값이 같으면
if board[i][j] == bombs[0]:
# 0으로 만든다.
board[i][j] = 0
print("1을 제거합니다")
# 만약 2구역이라면
elif (i >= 0 and i < num) and (j >= num and j < num * 2):
# 2구역에서 bombs[1]의 값과 원소의 값이 같으면
if board[i][j] == bombs[1]:
# 0으로 만든다.
board[i][j] = 0
print("2을 제거합니다")
# 만약 3구역이라면
elif (i >= num and i < num * 2) and (j >= 0 and j < num):
# 3구역에서 bombs[2]의 값과 원소의 값이 같으면
if board[i][j] == bombs[2]:
# 0으로 만든다.
board[i][j] = 0
print("3을 제거합니다")
else:
# 4구역에서 bombs[3]의 값과 원소의 값이 같으면
if board[i][j] == bombs[3]:
# 0으로 만든다.
board[i][j] = 0
print("4을 제거합니다")
board
2을 제거합니다 2을 제거합니다 2을 제거합니다 1을 제거합니다 1을 제거합니다 2을 제거합니다 2을 제거합니다 2을 제거합니다 1을 제거합니다 1을 제거합니다 3을 제거합니다 3을 제거합니다 3을 제거합니다 3을 제거합니다 4을 제거합니다
Out[256]:
array([[3, 4, 2, 4, 4, 1, 0, 0, 0, 4], [3, 2, 4, 0, 3, 1, 3, 4, 0, 3], [0, 4, 3, 0, 0, 0, 0, 1, 3, 3], [2, 3, 3, 0, 2, 4, 0, 4, 0, 1], [3, 0, 3, 0, 0, 0, 1, 4, 1, 3], [0, 0, 0, 4, 2, 0, 3, 1, 3, 1], [1, 0, 4, 1, 1, 3, 1, 1, 3, 3], [0, 4, 4, 1, 4, 1, 0, 3, 3, 3], [4, 0, 4, 4, 0, 0, 0, 0, 3, 2], [2, 0, 2, 2, 0, 2, 0, 1, 1, 0]])
심화문제2.¶
아래 조건을 충족하여 문제를 해결하라.
- 2차원 배열 n개가 쌓여 만들어진 m m 데이터A와, 2차원 배열 m m 데이터B가 존재한다.
- 데이터를 처리할 때 데이터B에서 데이터A에 축적된 배열의 수 n만큼을 나눈 후, 행렬곱 연산을 진행한다.
In [280]:
data = np.array([
[[1, 2], [2, 2]],
[[3, 2], [1, 1]],
[[5, 4], [2, 2]]
])
data_filter = np.array([
[[6, 3], [3, 6]]
])
In [258]:
np.ndim(data)
Out[258]:
3
In [286]:
data_filter = data_filter/len(data)
In [287]:
data_filter
Out[287]:
array([[[2., 1.], [1., 2.]]])
In [288]:
data @ data_filter
Out[288]:
array([[[ 4., 5.], [ 6., 6.]], [[ 8., 7.], [ 3., 3.]], [[14., 13.], [ 6., 6.]]])
심화문제3¶
아래 조건을 충족한 결과물을 산출하라.
- 자료의 첫번째 열은 식별번호이다.
- 자료의 두번째 열은 처리방식이다. (0 : A처리, 1: B처리, 2 : C처리)
- 자료의 세번째부터 아홉 번째 열까지는 전형 방식에 따라 필요하지 않는 경우가 있으며, 이 경우 NAN으로 표시한다.
- A처리 : 2, 3, 4열을 제외한 나머지 NAN이다. (2열 0.3 + 3열 0.3 + 4열 * 0.4, 0.8 통과)
- B처리 : 5, 6, 7, 8열을 제외한 나머지 NAN이다. (5열 0.5 + (6열 0.3 + 7열 0.4 + 8열 0.3) * 0.5, 0.75 통과)
- C처리 : 8, 7, 8열을 제외한 나머지 NAN이다. (6열 0.3 + 7열 0.4 + 8열 * 0.3, 0.75 통과)
- 각 데이터처리 이후 통과된 식별아이디를 오름차순에 따라 list에 담아 반환하라.
In [315]:
# nan값을 대체하는 string의 변수
data = np.array([
[0, 2, None, None, None, None, 0.39, 0.21, 0.54],
[1, 0, 0.74, 0.22, 0.22, None, None, None, None],
[2, 0, 0.65, 0.48, 0.79, None, None, None, None],
[3, 1, None, None, None, 0.76, 0.64, 0.99, 0.87]
])
In [334]:
data
Out[334]:
array([[0, 2, None, None, None, None, 0.39, 0.21, 0.54], [1, 0, 0.74, 0.22, 0.22, None, None, None, None], [2, 0, 0.65, 0.48, 0.79, None, None, None, None], [3, 1, None, None, None, 0.76, 0.64, 0.99, 0.87]], dtype=object)
In [350]:
# 각 list를 순회하면서 1번 인덱스의 값에 따라 처리방식을 달리 하는 if문을 작성한다.
# 통과된 데이터를 담는 빈 리스트 생성
data_passed = []
for i in data:
# 만약 데이터 처리방식이 A처리방식이라면
if i[1] == 0:
# A처리방식에서 정해진 계산식의 값이 0.8 이상이라면
if (i[2] * 0.3) + (i[3] * 0.3) + (i[4] * 0.4) >= 0.8:
print((i[2] * 0.3) + (i[3] * 0.3) + (i[4] * 0.4))
# 해당 데이터는 유효한 것으로 등록한다.
data_passed.append(i[0])
print(i[0])
# 만약 데이터 처리방식이 B라면
elif i[1] == 1:
# B처리방식에서 정해진 계산식의 값이 0.75 이상이라면
if (i[5] * 0.5) + ((i[6] * 0.3) + (i[7] * 0.4) + (i[8] * 0.3)) * 0.5 >= 0.75:
print((i[5] * 0.5) + ((i[6] * 0.3) + (i[7] * 0.4) + (i[8] * 0.3)) * 0.5)
# 해당 데이터는 유효한 것으로 등록한다.
data_passed.append(i[0])
print(i[0])
# 만약 데이터 처리방식이 C라면
elif i[1] == 2:
# C처리방식에서 정해진 계산식의 결과값이 0.75 이상이라면
if (i[6] * 0.3) + (i[7] * 0.4) + (i[8] * 0.3) >= 0.75:
print((i[6] * 0.3) + (i[7] * 0.4) + (i[8] * 0.3))
# 해당 데이터는 유효한 것으로 등록한다.
data_passed.append(i[0])
print(i[0])
data_passed.sort()
print(data_passed)
0.8045 3 [3]
'전문지식 함양 > TIL' 카테고리의 다른 글
[프로그래머스 겨울방학 인공지능 과정] pytorch 예제 살펴보기1 (0) | 2022.01.25 |
---|---|
[프로그래머스 겨울방학 인공지능 과정] 딥러닝 기초이론 (0) | 2022.01.24 |
[프로그래머스 겨울방학 인공지능 과정] np.where (0) | 2022.01.19 |
[프로그래머스 겨울방학 인공지능 과정] numpy 복습 2 (0) | 2022.01.18 |
[프로그래머스 겨울방학 인공지능 과정] numpy 복습 (0) | 2022.01.17 |