함수
파이썬 함수는 ‘def’ 키워드를 통해 정의됩니다
def sign(x):
if x > 0:
return '양수'
elif x < 0:
return '음수'
else:
return 'zero'
for x in [-1, 0, 1]:
print(sign(x))
# 출력 "음수", "zero", "양수", 한 줄에 하나씩 출력.
클래스
Numpy 라이브러리
대량의 데이터를 사용할때 빠르게 사용할수있음 (내부는 C언어로 이루어져 있음)
- 각각의 값들은 튜플
- rank는 배열이 몇 차원인지를 의미
- shape는 는 각 차원의 크기를 알려주는 정수들이 모인 튜플
import numpy as np
arr = [1, 2, 3, 4, 5] #list
print(type(arr)) #출력 <class 'list'>
print(arr + 5) #이 줄은 에러처리된다.
print(arr - 5) #이것도 에러처리된다
npArr = np.array(arr) #convert from list to numpy
print(type(npArr)) #<class 'numpy.ndarray'>
print(npArr + 5) #출력 [ 6 7 8 9 10]
print(npArr - 5) #출력 [-4 -3 -2 -1 0]
#numpy.Array는 Broadcasting 때문에 덧셈 혹은 뺄셈 등 사칙연산이 가능하다.
#이게 바로 array와 numpy.Array의 차이이다
arr2D = [[1, 2, 3, 3.5], [4, 5, 6, 6.5], [7, 8, 9, 9.5]]
npArr2D = np.array(arr2D)
print(npArr2D)
print(npArr2D.shape) #npArray의 모양을 알고싶을때
'''
-print(npArr2D)출력-
[[1. 2. 3. 3.5]
[4. 5. 6. 6.5]
[7. 8. 9. 9.5]]
-print(npArr2D.shape)의 출력-
(3, 4)
'''
import numpy as np
a = np.array([1, 2, 3]) # rank가 1인 배열 생성
print (type(a)) # 출력 "<type 'numpy.ndarray'>"
print (a.shape) # 출력 "(3,)"
print (a[0], a[1], a[2]) # 출력 "1 2 3"
a[0] = 5 # 요소를 변경
print (a) # 출력 "[5, 2, 3]"
b = np.array([[1,2,3],[4,5,6]]) # rank가 2인 배열 생성
print (b.shape ) # 출력 "(2, 3)"
print (b[0, 0], b[0, 1], b[1, 0]) # 출력 "1 2 4"
Numpy Shape 기능
arr2D = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [14, 15, 16]]
npArr2D = np.array(arr2D)
N = npArr2D.shape[0]
for i in range(N):
print(npArr2D[i][0])
'''
출력값
1
4
7
10
14
'''
Numpy각종 초기화 방법
arr = np.array([0, 1, 3, 4, 5])
print(arr) #출력 [0 1 3 4 5]
arr = np.array(range(10))
print(arr) #출력 [0 1 2 3 4 5 6 7 8 9]
arr = np.zeros((3, 3))
print(arr)
'''
출력
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
'''
arr = np.ones((3, 3))
print(arr)
'''
출력
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
'''
import numpy as np
a = np.zeros((2,2)) # 모든 값이 0인 배열 생성
print(a) # 출력 "[[ 0. 0.]
# [ 0. 0.]]"
b = np.ones((1,2)) # 모든 값이 1인 배열 생성
print(b) # 출력 "[[ 1. 1.]]"
c = np.full((2,2), 7) # 모든 값이 특정 상수인 배열 생성
print(c) # 출력 "[[ 7. 7.]
# [ 7. 7.]]"
d = np.eye(2) # 2x2 단위행렬 생성
print(d) # 출력 "[[ 1. 0.]
# [ 0. 1.]]"
e = np.random.random((2,2)) # 임의의 값으로 채워진 배열 생성
print(e) # 임의의 값 출력 "[[ 0.91940167 0.08143941]
# [ 0.68744134 0.87236687]]"
배열 인덱싱
import numpy as np
# Create the following rank 2 array with shape (3, 4)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 슬라이싱을 이용하여 첫 두 행과 1열, 2열로 이루어진 부분배열을 만들어 봅시다;
# b는 shape가 (2,2)인 배열이 됩니다:
# [[2 3]
# [6 7]]
b = a[:2, 1:3]
# 슬라이싱된 배열은 원본 배열과 같은 데이터를 참조합니다, 즉 슬라이싱된 배열을 수정하면
# 원본 배열 역시 수정됩니다.
print (a[0, 1]) # 출력 "2"
b[0, 0] = 77 # b[0, 0]은 a[0, 1]과 같은 데이터입니다
print (a[0, 1]) # 출력 "77"
Numpy배열 슬라이싱
import numpy as np
# 아래와 같은 요소를 가지는 rank가 2이고 shape가 (3, 4)인 배열 생성
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 배열의 중간 행에 접근하는 두 가지 방법이 있습니다.
# 정수 인덱싱과 슬라이싱을 혼합해서 사용하면 낮은 rank의 배열이 생성되지만,
# 슬라이싱만 사용하면 원본 배열과 동일한 rank의 배열이 생성됩니다.
row_r1 = a[1, :] # 배열a의 두 번째 행을 rank가 1인 배열로
row_r2 = a[1:2, :] # 배열a의 두 번째 행을 rank가 2인 배열로
print (row_r1, row_r1.shape) # 출력 "[5 6 7 8] (4,)"
print (row_r2, row_r2.shape) # 출력 "[[5 6 7 8]] (1, 4)"
# 행이 아닌 열의 경우에도 마찬가지입니다:
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print (col_r1, col_r1.shape) # 출력 "[ 2 6 10] (3,)"
print (col_r2, col_r2.shape) # 출력 "[[ 2]
# [ 6]
# [10]] (3, 1)"
정수 배열 인덱싱
Numpy 배열을 슬라이싱하면, 결과로 얻어지는 배열은 언제나 원본 배열의 부분 배열입니다. 그러나 정수 배열 인덱싱을 한다면, 원본과 다른 배열을 만들 수 있습니다
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
# 정수 배열 인덱싱의 예.
# 반환되는 배열의 shape는 (3,)
print (a[[0, 1, 2], [0, 1, 0]]) # 출력 "[1 4 5]"
# 위에서 본 정수 배열 인덱싱 예제는 다음과 동일합니다:
print (np.array([a[0, 0], a[1, 1], a[2, 0]])) # 출력 "[1 4 5]"
# 정수 배열 인덱싱을 사용할 때,
# 원본 배열의 같은 요소를 재사용할 수 있습니다:
print (a[[0, 0], [1, 1]]) # 출력 "[2 2]"
# 위 예제는 다음과 동일합니다
print (np.array([a[0, 1], a[0, 1]])) # 출력 "[2 2]"
불리언 배열 인덱싱
불리언 배열 인덱싱은 특정 조건을 만족하게 하는 요소만 선택하고자 할 때 자주 사용됩니다.
a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2) # 2보다 큰 a의 요소를 찾습니다;
# 이 코드는 a와 shape가 같고 불리언 자료형을 요소로 하는 numpy 배열을 반환합니다,
# bool_idx의 각 요소는 동일한 위치에 있는 a의
# 요소가 2보다 큰지를 말해줍니다.
print (bool_idx) # 출력 "[[False False]
# [ True True]
# [ True True]]"
# 불리언 배열 인덱싱을 통해 bool_idx에서
# 참 값을 가지는 요소로 구성되는
# rank 1인 배열을 구성할 수 있습니다.
print (a[bool_idx]) # 출력 "[3 4 5 6]"
# 위에서 한 모든것을 한 문장으로 할 수 있습니다:
print (a[a > 2]) # 출력 "[3 4 5 6]"
Numpy자료형
Numpy에선 배열을 구성하는 데 사용할 수 있는 다양한 숫자 자료형을 제공합니다. Numpy는 배열이 생성될 때 자료형을 스스로 추측합니다, 그러나 배열을 생성할 때 명시적으로 특정 자료형을 지정할 수도 있습니다
import numpy as np
x = np.array([1, 2]) # Numpy가 자료형을 추측해서 선택
print (x.dtype) # 출력 "int64"
x = np.array([1.0, 2.0]) # Numpy가 자료형을 추측해서 선택
print (x.dtype) # 출력 "float64"
x = np.array([1, 2], dtype=np.int64) # 특정 자료형을 명시적으로 지정
print (x.dtype) # 출력 "int64"
배열 연산
기본적인 수학함수는 배열의 각 요소별로 동작하며 연산자를 통해 동작하거나 numpy 함수모듈을 통해 동작합니다
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)
print(x)
#[[1. 2.]
#[3. 4.]]
print(y)
#[[5. 6.]
#[7. 8.]]
# 요소별 합; 둘 다 다음의 배열을 만듭니다
# [[ 6.0 8.0]
# [10.0 12.0]]
print (x + y)
print (np.add(x, y))
# 요소별 차; 둘 다 다음의 배열을 만듭니다
# [[-4.0 -4.0]
# [-4.0 -4.0]]
print (x - y)
print (np.subtract(x, y))
# 요소별 곱; 둘 다 다음의 배열을 만듭니다
# [[ 5.0 12.0]
# [21.0 32.0]]
print (x * y)
print (np.multiply(x, y))
# 요소별 나눗셈; 둘 다 다음의 배열을 만듭니다
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print (x / y)
print (np.divide(x, y))
# 요소별 제곱근; 다음의 배열을 만듭니다
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
print (np.sqrt(x))
dot함수
x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
v = np.array([9,10])
w = np.array([11, 12])
print(x)
#[[1 2]
#[3 4]]
print(y)
#[[5 6]
#[7 8]]
print(v)
#[ 9 10]
print(w)
#[11 12]
# 벡터의 내적; 둘 다 결과는 219
print (v.dot(w))
print (np.dot(v, w))
# 행렬과 벡터의 곱; 둘 다 결과는 rank 1인 배열 [29 67]
print (x.dot(v))
print (np.dot(x, v))
# 행렬곱; 둘 다 결과는 rank 2인 배열
# [[19 22]
# [43 50]]
print (x.dot(y))
print (np.dot(x, y))
Numpy sum
import numpy as np
x = np.array([[1,2],[3,4]])
print (np.sum(x)) # 모든 요소를 합한 값을 연산; 출력 "10"
print (np.sum(x, axis=0)) # 각 열에 대한 합을 연산; 출력 "[4 6]"
print (np.sum(x, axis=1)) # 각 행에 대한 합을 연산; 출력 "[3 7]"
np.transpose 트렌스포즈
import numpy as np
x = np.array([[1,2], [3,4]])
print (x) # 출력 "[[1 2]
# [3 4]]"
print (x.T) # 출력 "[[1 3]
# [2 4]]"
# rank 1인 배열을 전치할 경우 아무 일도 일어나지 않습니다:
v = np.array([1,2,3])
print (v) # 출력 "[1 2 3]"
print (v.T) # 출력 "[1 2 3]"
브로드 캐스팅
브로트캐스팅은 Numpy에서 shape가 다른 배열 간에도 산술 연산이 가능하게 하는 메커니즘
작은 배열과 큰 배열이 있을 때, 큰 배열을 대상으로 작은 배열을 여러 번 연산하고자 할 때가 있습니다. 예를 들어, 행렬의 각 행에 상수 벡터를 더하는 걸 생각해보세요. 이는 다음과 같은 방식으로 처리될 수 있습니다
import numpy as np
# 행렬 x의 각 행에 벡터 v를 더한 뒤,
# 그 결과를 행렬 y에 저장하고자 합니다
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) # x와 동일한 shape를 가지며 비어있는 행렬 생성
# 명시적 반복문을 통해 행렬 x의 각 행에 벡터 v를 더하는 방법
for i in range(4):
y[i, :] = x[i, :] + v
# 이제 y는 다음과 같습니다
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
print (y)
위의 방식대로 하면 됩니다; 그러나 ‘x’가 매우 큰 행렬이라면, 파이썬의 명시적 반복문을 이용한 위 코드는 매우 느려질 수 있습니다. 벡터 ‘v’를 행렬 ‘x’의 각 행에 더하는 것은 ‘v’를 여러 개 복사해 수직으로 쌓은 행렬 ‘vv’를 만들고 이 ‘vv’를 ‘x’에 더하는것과 동일합니다. 이 과정을 아래의 코드로 구현할 수 있습니다
import numpy as np
# 벡터 v를 행렬 x의 각 행에 더한 뒤,
# 그 결과를 행렬 y에 저장하고자 합니다
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1)) # v의 복사본 4개를 위로 차곡차곡 쌓은 것이 vv
print (vv) # 출력 "[[1 0 1]
# [1 0 1]
# [1 0 1]
# [1 0 1]]"
y = x + vv # x와 vv의 요소별 합
print (y) # 출력 "[[ 2 2 4
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
Numpy 브로드캐스팅을 이용한다면 이렇게 v의 복사본을 여러 개 만들지 않아도 동일한 연산을 할 수 있습니다. 아래는 브로드캐스팅을 이용한 예시 코드
import numpy as np
# 벡터 v를 행렬 x의 각 행에 더한 뒤,
# 그 결과를 행렬 y에 저장하고자 합니다
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = x + v # 브로드캐스팅을 이용하여 v를 x의 각 행에 더하기
print (y) # 출력 "[[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
두 배열의 브로드캐스팅은 아래의 규칙을 따릅니다:
- 두 배열이 동일한 rank를 가지고 있지 않다면, 낮은 rank의 1차원 배열이 높은 rank 배열의 shape로 간주합니다.
- 특정 차원에서 두 배열이 동일한 크기를 갖거나, 두 배열 중 하나의 크기가 1이라면 그 두 배열은 특정 차원에서 compatible하다고 여겨집니다.
- 두 행렬이 모든 차원에서 compatible하다면, 브로드캐스팅이 가능합니다.
- 브로드캐스팅이 이뤄지면, 각 배열 shape의 요소별 최소공배수로 이루어진 shape가 두 배열의 shape로 간주합니다.
- 차원에 상관없이 크기가 1인 배열과 1보다 큰 배열이 있을 때, 크기가 1인 배열은 자신의 차원 수만큼 복사되어 쌓인 것처럼 간주합니다.
import numpy as np
# 벡터의 외적을 계산
v = np.array([1,2,3]) # v의 shape는 (3,)
w = np.array([4,5]) # w의 shape는 (2,)
# 외적을 계산하기 위해, 먼저 v를 shape가 (3,1)인 행벡터로 바꿔야 합니다;
# 그다음 이것을 w에 맞춰 브로드캐스팅한뒤 결과물로 shape가 (3,2)인 행렬을 얻습니다,
# 이 행렬은 v와 w 외적의 결과입니다:
# [[ 4 5]
# [ 8 10]
# [12 15]]
print (np.reshape(v, (3, 1)) * w)
# 벡터를 행렬의 각 행에 더하기
x = np.array([[1,2,3], [4,5,6]])
# x는 shape가 (2, 3)이고 v는 shape가 (3,)이므로 이 둘을 브로드캐스팅하면 shape가 (2, 3)인
# 아래와 같은 행렬이 나옵니다:
# [[2 4 6]
# [5 7 9]]
print (x + v)
# 벡터를 행렬의 각 행에 더하기
# x는 shape가 (2, 3)이고 w는 shape가 (2,)입니다.
# x의 전치행렬은 shape가 (3,2)이며 이는 w와 브로드캐스팅이 가능하고 결과로 shape가 (3,2)인 행렬이 생깁니다;
# 이 행렬을 전치하면 shape가 (2,3)인 행렬이 나오며
# 이는 행렬 x의 각 열에 벡터 w을 더한 결과와 동일합니다.
# 아래의 행렬입니다:
# [[ 5 6 7]
# [ 9 10 11]]
print ((x.T + w).T)
# 다른 방법은 w를 shape가 (2,1)인 열벡터로 변환하는 것입니다;
# 그런 다음 이를 바로 x에 브로드캐스팅해 더하면
# 동일한 결과가 나옵니다.
print (x + np.reshape(w, (2, 1)))
# 행렬의 스칼라배:
# x 의 shape는 (2, 3)입니다. Numpy는 스칼라를 shape가 ()인 배열로 취급합니다;
# 그렇기에 스칼라 값은 (2,3) shape로 브로드캐스트 될 수 있고,
# 아래와 같은 결과를 만들어 냅니다:
# [[ 2 4 6]
# [ 8 10 12]]
print (x * 2)
Matplotlib
우리가 가지고 있는 데이터를 시각화 시켜주는 라이브러리
import matplotlib.pyplot as plt
import tensorflow as tf
n = 20
y = tf.random.normal([n], 0, 1)
x = range(n)
plt.plot(x, y, 'k-') #k-는 실선 ko는 점/파란실선b- 파란점bo/빨간실선r- 빨간점ro
plt.show()
Plotting
matplotlib에서 가장 중요한 함수는 2차원 데이터를 그릴 수 있게 해주는 plot 입니다.
import numpy as np
import matplotlib.pyplot as plt
# 사인과 코사인 곡선의 x,y 좌표를 계산
x = np.arange(0, 3 * np.pi, 0.1)
y = np.sin(x)
# matplotlib를 이용해 점들을 그리기
plt.plot(x, y)
plt.show() # 그래프를 나타나게 하기 위해선 plt.show()함수를 호출해야만 합니다.
약간의 몇 가지 추가적인 작업을 통해 여러 개의 그래프와 제목, 범주, 축 이름을 한 번에 쉽게 나타낼 수 있습니다
import numpy as np
import matplotlib.pyplot as plt
# 사인과 코사인 곡선의 x,y 좌표를 계산
x = np.arange(0, 3 * np.pi, 0.1)
y_sin = np.sin(x)
y_cos = np.cos(x)
# matplotlib를 이용해 점들을 그리기
plt.plot(x, y_sin)
plt.plot(x, y_cos)
plt.xlabel('x axis label')
plt.ylabel('y axis label')
plt.title('Sine and Cosine')
plt.legend(['Sine', 'Cosine'])
plt.show()
Subplots
‘subplot’함수를 통해 다른 내용도 동일한 그림 위에 나타낼 수 있습니다
import numpy as np
import matplotlib.pyplot as plt
# 사인과 코사인 곡선의 x,y 좌표를 계산
x = np.arange(0, 3 * np.pi, 0.1)
y_sin = np.sin(x)
y_cos = np.cos(x)
# 높이가 2이고 너비가 1인 subplot 구획을 설정하고,
# 첫 번째 구획을 활성화.
plt.subplot(2, 1, 1)
# 첫 번째 그리기
plt.plot(x, y_sin)
plt.title('Sine')
# 두 번째 subplot 구획을 활성화 하고 그리기
plt.subplot(2, 1, 2)
plt.plot(x, y_cos)
plt.title('Cosine')
# 그림 보이기.
plt.show()
(계속 수정중)
'파이썬' 카테고리의 다른 글
불리언(Boolean) : 참과 거짓 (0) | 2021.05.07 |
---|---|
양식문자(형식 제어 문자) (0) | 2021.05.07 |
숫자(Numeric) : 정수와 실수 (0) | 2021.05.07 |
복합대입연산자 (0) | 2021.05.07 |
파이썬 함수 (0) | 2021.04.27 |