TensorFlow 2.x Basics
ML 모델을 개발하고 학습시키는 데 도움이 되는 핵심 오픈소스 라이브러리로 TensorFlow와 Keras는 모두 약 4년전쯤 릴리즈 되었음 (Keras는 2015년 3월, TensorFlow는 2015년 11월). 딥러닝 세계의 관점에서 볼 때, 꽤 오랜시간이라고 볼 수 있음.
TensorFlow 1.x + Keras의 문제점
- TensorFlow를 사용한다는것은 정적인 계산 그래프 조작을 의미하는 것으로, Imperative 코딩 스타일을 사용하는 프로그래머에게 어렵고 불편한 느낌을 받게 함
- TensorFlow API : 매우 강력하면서도 유연하지만 빠른 코드의 작성의 가능성 결여 및 사용법이 어렵고 혼란스러움
- Keras: 매우 생산적이고 사용이 쉽지만 유연성 결여
TensorFlow 2.0
TensorFlow와 Keras를 대대적으로 새로이 디자인한 것으로, 지난 4년간의 사용자 피드백과 기술의 진보가 모두 고려
- 사용자들이 계산을 eager mode로 수행할 수 있게 해줌
- Numpy 사용법과 유사
- 프로그래밍이 직관적
- pythonic
- 1.x에서의 컴파일된 그래프의 엄청난 이점을 그대로 보존
- 성능, 분산, 그리고 배포를 위함
- TensorFlow를 빠르고, 분산 구조에서의 확장 가능하며, 상용화에 준비될 수 있도록 해 줌
- Keras를 딥러닝의 고수준 API로 채택
- TensorFlow를 이해하기 쉬우면서 높은 생산성을 가질 수 있게 만들어 줌
- 매우 고수준(더 쉬운 사용성, 약간 부족한 유연성)에서부터 매우 저수준(더 깊은 전문성, 매우 뛰어난 유연성)의 다양한 범위의 작업으로까지 Keras를 확장
Google Colab에서 TensorFlow 2.x 버전 사용하기
try:
# %tensorflow_version only exists in Colab.
# %tensorflow_version 2.x
except Exception:
pass
### TensorFlow library import
import tensorflow as tf
import numpy as np
from tensorflow import keras
### version 확인
print(tf.__version__)
print(keras.__version__)
Tensors
Tensor는 multi-dimensional array를 나타내는 말로, TensorFlow의 기본 data type
## Hello World
hello = tf.constant("Hello World")
print(hello)
tf.Tensor(b'Hello World', shape=(), dtype=string)
상수형 tensor 만들기
x = tf.constant([[1.0, 2.0],
[3.0, 4.0]])
print(x)
tf.Tensor(
[[1. 2.]
[3. 4.]], shape=(2, 2), dtype=float32)
## numpy ndarray나 python의 list도 tensor로 바꾸기
x_np = np.array([[1.0, 2.0],
[3.0, 4.0]])
x_np = tf.convert_to_tensor(x_np)
x_list = [[1.0, 2.0],
[3.0, 4.0]]
x_list = tf.convert_to_tensor(x_list)
## tensor를 numpy ndarray로 바꾸기
x.numpy()
많이 사용되는 방법
print(tf.ones(shape=(2,2)))
print(tf.zeros(shape=(2,2)))
tf.Tensor(
[[1. 1.]
[1. 1.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[0. 0.]
[0. 0.]], shape=(2, 2), dtype=float32)
Random한 상수형 tensor 만들기
## 표준정규분포로부터 random 상수 생성
tf.random.normal(shape=(2,2), mean=0., stddev=1.)
## 균등(uniform)분포로부터 random 상수 생성
tf.random.uniform(shape=(2, 2), minval=0, maxval=10, dtype='int32')
tensor 연산 : element-wise 연산 기본
a = tf.ones((2,2))*2
b = tf.ones((2,2))*6
print (a.numpy())
print (b.numpy())
## 덧셈
print (tf.add(a, b).numpy())
print ((a + b).numpy())
## 뺄셈
print (tf.subtract(b, a).numpy())
print ((b - a).numpy())
## 곱셈
print (tf.multiply(a, b).numpy())
print ((a * b).numpy())
## 나눗셈
print (tf.divide(b, a).numpy())
print ((b / a).numpy())
[[2. 2.]
[2. 2.]]
[[6. 6.]
[6. 6.]]
[[8. 8.]
[8. 8.]]
[[8. 8.]
[8. 8.]]
[[4. 4.]
[4. 4.]]
[[4. 4.]
[4. 4.]]
[[12. 12.]
[12. 12.]]
[[12. 12.]
[12. 12.]]
[[3. 3.]
[3. 3.]]
[[3. 3.]
[3. 3.]]
## Tensor와 numpy ndarray 호환
ndarray = np.ones((3, 3))
print(ndarray)
## Tensor연산에 입력으로 tensor가 아닌 ndarray가 입력으로 들어갈 수 있음
tensor = tf.multiply(ndarray, 10)
print(tensor)
## numpy ndarray연산에 입력으로 tensor가 들어갈 수도 있습니다
print(np.add(tensor, 2))
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
tf.Tensor(
[[10. 10. 10.]
[10. 10. 10.]
[10. 10. 10.]], shape=(3, 3), dtype=float64)
[[12. 12. 12.]
[12. 12. 12.]
[12. 12. 12.]]
Variables (변수)
- 변할 수 있는 상태를 저장하는데 사용되는 특별한 텐서
- 대부분의 경우 학습해야 할 가중치(weight, parameter)들을 variable로 생성
- 변수 텐서의 값을 바꿀 때는 assign, assign_add, assign_sub 메서드 사용
- assign: 값을 완전히 할당. =에 해당
- assign_add: 값을 증가. +=에 해당
- assign_sub: 값을 감소. -=에 해당
## 초기값 사용
initial_value = tf.random.normal(shape=(2, 2))
weight = tf.Variable(initial_value)
## variable 초기화해주는 initializer 사용
weight = tf.Variable(tf.random_normal_initializer(stddev=0.1)(shape=(2,2)))
## .assign(value)`, `.assign_add(increment)`, 또는 `.assign_sub(decrement)`와 같은 메소드로 Variable 갱신
new_value = tf.random.normal(shape=(2,2))
weight.assign(new_value)
added_value = tf.ones(shape=(2,2))
weight.assign_add(added_value)
Shape
t = tf.constant([[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]])
print(t.shape)
(1, 2, 3, 4)
Broadcasting
- 배열의 랭크가 같지 않으면 두 모양이 같은 길이가 될 때까지 배열의 낮은 랭크쪽에 1을 붙인다.
- 두 배열은 차원에서 크기가 같거나 배열 중 하나의 차원에 크기가 1 인 경우 차원에서 호환 가능하다.
- 배열은 모든 차원에서 호환되면 함께 브로드캐스트 될 수 있다.
- 브로드캐스트 후 각 배열은 두 개의 입력 배열의 요소 모양 최대 개수와 동일한 모양을 가진 것처럼 동작한다.
- 한 배열의 크기가 1이고 다른 배열의 크기가 1보다 큰 차원에서 첫 번째 배열은 마치 해당 차원을 따라 복사 된 것처럼 작동한다.
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])
print(matrix1)
print(matrix2)
tf.Tensor([[3. 3.]], shape=(1, 2), dtype=float32)
tf.Tensor(
[[2.]
[2.]], shape=(2, 1), dtype=float32)
print(matrix1+matrix2)
print(matrix1/matrix2)
tf.Tensor(
[[5. 5.]
[5. 5.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[1.5 1.5]
[1.5 1.5]], shape=(2, 2), dtype=float32)
Tensor Operations
Indexing, Slicing
x = tf.constant([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
## indexing - 항상 차원 감소
print(x[0])
print(x[1, 2])
print(x[2, 3])
## slicing
print(x[:2, 1:3])
print(x[1:3, 3:])
tf.Tensor([1 2 3 4], shape=(4,), dtype=int32)
tf.Tensor(7, shape=(), dtype=int32)
tf.Tensor(12, shape=(), dtype=int32)
tf.Tensor(
[[2 3]
[6 7]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[ 8]
[12]], shape=(2, 1), dtype=int32)
Reshape, Expend_dims
t = tf.constant([[[0, 1, 2],
[3, 4, 5]],
[[6, 7, 8],
[9, 10, 11]]])
print(t.shape)
print(tf.reshape(t, shape=[-1, 3]))
print(tf.reshape(t, shape=[-1, 1, 3]))
(2, 2, 3)
tf.Tensor(
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]], shape=(4, 3), dtype=int32)
tf.Tensor(
[[[ 0 1 2]]
[[ 3 4 5]]
[[ 6 7 8]]
[[ 9 10 11]]], shape=(4, 1, 3), dtype=int32)
x = tf.constant([0, 1, 2])
print(x.shape)
print(tf.expand_dims(x, axis=0))
print(tf.expand_dims(x, axis=1))
(3,)
tf.Tensor([[0 1 2]], shape=(1, 3), dtype=int32)
tf.Tensor(
[[0]
[1]
[2]], shape=(3, 1), dtype=int32)
Reduce Mean/Sum
x = tf.constant([[1., 2.],
[3., 4.]])
print(tf.reduce_mean(x))
print(tf.reduce_mean(x, axis=0)) ### x.shape[axis]: x.shape[0] 에 대해 연산
print(tf.reduce_mean(x, axis=1)) ### x.shape[axis]: x.shape[1] 에 대해 연산
print(tf.reduce_mean(x, axis=-1))
tf.Tensor(2.5, shape=(), dtype=float32)
tf.Tensor([2. 3.], shape=(2,), dtype=float32)
tf.Tensor([1.5 3.5], shape=(2,), dtype=float32)
tf.Tensor([1.5 3.5], shape=(2,), dtype=float32)
print(tf.reduce_sum(x))
print(tf.reduce_sum(x, axis=0))
print(tf.reduce_sum(x, axis=-1))
print(tf.reduce_mean(tf.reduce_sum(x, axis=-1)))
tf.Tensor(10.0, shape=(), dtype=float32)
tf.Tensor([4. 6.], shape=(2,), dtype=float32)
tf.Tensor([3. 7.], shape=(2,), dtype=float32)
tf.Tensor(5.0, shape=(), dtype=float32)
print(t)
print(tf.reduce_sum(t, axis=0))
print(tf.reduce_sum(t, axis=1))
print(tf.reduce_sum(t, axis=-1))
tf.Tensor(
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]], shape=(2, 2, 3), dtype=int32)
tf.Tensor(
[[ 6 8 10]
[12 14 16]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[ 3 5 7]
[15 17 19]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[ 3 12]
[21 30]], shape=(2, 2), dtype=int32)
Argmax
x = [[0, 1, 2],
[2, 1, 0]]
print(tf.argmax(x, axis=0))
print(tf.argmax(x, axis=1))
print(tf.argmax(x, axis=-1))
tf.Tensor([1 0 0], shape=(3,), dtype=int64)
tf.Tensor([2 0], shape=(2,), dtype=int64)
tf.Tensor([2 0], shape=(2,), dtype=int64)
One-hot Encoding
label = tf.constant([0, 1, 2, 0])
onehot1 = tf.one_hot(label, depth=3)
onehot2 = keras.utils.to_categorical(label, num_classes=3)
print(onehot1, type(onehot1))
print(onehot2, type(onehot2))
tf.Tensor(
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]], shape=(4, 3), dtype=float32) <class 'tensorflow.python.framework.ops.EagerTensor'>
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]] <class 'numpy.ndarray'>
Type Casting
print(tf.cast([1.8, 2.2, 3.3, 4.9], tf.int32))
print(tf.cast([True, False, 1 == 1, 0 == 1], tf.int32))
tf.Tensor([1 2 3 4], shape=(4,), dtype=int32)
tf.Tensor([1 0 1 0], shape=(4,), dtype=int32)
'DEEP LEARNING > Tensorflow Training' 카테고리의 다른 글
cnn 실습_나만의 이미지 데이터를 만들고 학습하기(3) - functional API & save_model (0) | 2020.03.26 |
---|---|
cnn 실습_나만의 이미지 데이터를 만들고 학습하기(2) - sequential API (0) | 2020.03.21 |
cnn 실습_나만의 이미지 데이터를 만들고 학습하기(1) - image crawling (0) | 2020.03.20 |
Linear Regression & Logistic Regression (0) | 2020.03.01 |
Make A Dataset (0) | 2020.02.26 |