[인공지능] TensorFlow 기초 문법

참조


TensorFlow 란

  • 가장 널리 쓰이는 딥러닝 프레임워크 중 하나
  • 구글이 주도적으로 개발하는 플래폼
  • 파이썬, C++ API를 기본적으로 제공하고, 자바스크립트(JavaScript), 자바(Java), 고(Go), 스위프트(Swift) 등 다양한 프로그래밍 언어를 지원
  • tf.keras를 중심으로 고수준 API 통합 (2.x 버전)
  • TPU(Tensor Processing Unit) 지원 : 구글에서 자체적으로 만든 프로세싱 유닛
    • TPU는 GPU보다 전력을 적게 소모, 경제적
    • 일반적으로 32비트(float32) 로 수행되는 곱센 연산을 16비트(float16) 으로 낮춤

텐서플로우 시작하기

import numpy as np
import tensorflow as tf

print(tf.__version__)
2.8.0

텐서의 객체

  • 타입 : string, float32, float16, int32, int8 등
  • 형상(Shape) : 0, 1, 2 차원 등의 데이터 차원
  • 축(Rank) : 차원의 개수
import numpy as np
import tensorflow as tf

# 상수
a = tf.constant(2)
print(tf.rank(a)) # rank가 0이면 0차원
print(a)

b = tf.constant([2, 3])
print(tf.rank(b)) # rank가 1이면 1차원
print(b)

c = tf.constant([[2,3], [6,7]])
print(tf.rank(c)) # rank가 2이면 2차원
print(c)

d = tf.constant(['Hello'])
print(tf.rank(d))
print(d)
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor([2 3], shape=(2,), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(
[[2 3]
 [6 7]], shape=(2, 2), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor([b'Hello'], shape=(1,), dtype=string)

난수 생성

from turtle import shape
import numpy as np
import tensorflow as tf

# 난수 생성
rand = tf.random.uniform([1], 0, 1)
print(rand.shape)
print(rand)

rand2 = tf.random.normal([1, 2], 0, 1)
print(rand2.shape)
print(rand2)

rand3 = tf.random.normal(shape=(3,2), mean=0, stddev=1)
print(rand3.shape)
print(rand3)
(1,)
tf.Tensor([0.21045697], shape=(1,), dtype=float32)
(1, 2)
tf.Tensor([[0.6325889 0.5149823]], shape=(1, 2), dtype=float32)
(3, 2)
tf.Tensor(
[[-1.4163237  -1.5869609 ]
 [ 0.75265956 -0.6949195 ]
 [ 0.15497519  2.074221  ]], shape=(3, 2), dtype=float32)

즉시 실행 모드(Eager Mode) 지원

  • 즉시 실행모드를 통해 텐서플로우를 파이썬처럼 사용할 수 있슴
  • 1.x 버전에서는 그래프 를 생성하고, 초기화 한 뒤에 세션을 통해 값을 흐르게 하는 갓업을 진행해야함.
from turtle import shape
import numpy as np
import tensorflow as tf

# 즉시 실행 모드
a = tf.constant(3)
b = tf.constant(2)

print(tf.add(a,b))
print(a + b)

print(tf.subtract(a, b))
print(a - b)

print(tf.multiply(a, b))
print(a * b)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)

텐서플로우 <-> 넘파이

from turtle import shape
import numpy as np
import tensorflow as tf

a = tf.constant(2)
b = tf.constant(3)

c = tf.add(a,b).numpy()
print(type(c))

c_square = np.square(c, dtype=np.float32)
c_tensor = tf.convert_to_tensor(c_square)

print(c_tensor)
print(type(c_tensor))
<class 'numpy.int32'>
tf.Tensor(25.0, shape=(), dtype=float32)
<class 'tensorflow.python.framework.ops.EagerTensor'>

넘파이처럼 사용하기

from turtle import shape
import numpy as np
import tensorflow as tf

t = tf.constant([[1., 2., 3.,], [4., 5., 6.]])

print(t.shape)
print(t.dtype)

print(t[:, 1:])

print(t[..., 1, tf.newaxis])

print(t + 10)

print(t.square(t))

# tensor 곱
print(t @ tf.transpose(t))
(2, 3)
<dtype: 'float32'>
tf.Tensor(        
[[2. 3.]
 [5. 6.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[2.]
 [5.]], shape=(2, 1), dtype=float32)
tf.Tensor(
[[11. 12. 13.]
 [14. 15. 16.]], shape=(2, 3), dtype=float32)

타입 변환

  • 텐서의 기본 dtype
    • float형 텐서 : float32
    • int형 텐서 : int32
  • 연산시 텐서의 타입을 맞춰줘야 함
    • float32 ~ float32
    • int32 ~ int32
    • float32 ~ int32 (x)
  • 타입 변환에는 tf.cast() 사용
from turtle import shape
import numpy as np
import tensorflow as tf

a = tf.constant(2)
print(a)

b = tf.constant(2.)
print(b)

#print(tf.constant(2.) + tf.constant(40))

#tf.constant(2.) + tf.constant(30., dtype=tf.float64)

t = tf.constant(30., dtype=tf.float64)
t2 = tf.constant(4.)

print(t2 + tf.cast(t, tf.float32))
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(2.0, shape=(), dtype=float32)
tf.Tensor(34.0, shape=(), dtype=float32)

AutoGraph(오토그래프)

  • TensorFlow 가 작업을 좀 더 빠르게 동작하게 하기 위한 방법으로 Graph로 만들어 연산을 진행
  • tf.Graph
  • 유연성이 있음
    • 모바일 애플리케이션, 임베디드 기기, 백엔드 서버와 같이 Python 인터프리터가 없는 환경에서 TensorFlow 사용 가능
  • @tf.function
    • 자동으로 그래프를 생성(Auto Graph)
    • 그래프로 변환하여 사용 -> GPU 연산 가능
    • 파이썬으로 구성된 함수를 텐서플로우의 그래프 형태로 다루고 싶을 때 사용 가능
    • 원본 함수가 필요하다면 (tf.function).python_function()
import timeit
import numpy as np
import tensorflow as tf

@tf.function
def my_function(x):
    return x**2 - 10*x + 3

def my_function_(x):
    return x**2 -10*x + 3

def function_to_get_faster(x, y, b):
    x = tf.matmul(x, y) # 행렬 곱
    x = x + b
    return x

def inner_function(x, y, b):
    x = tf.matmul(x, y) # 행렬 곱
    x = x + b
    return x

@tf.function
def outer_function(x):
    y = tf.constant([[2.], [3.]])
    b = tf.constant(4.)
    return inner_function(x, y, b)

print(my_function(2))
print(my_function(tf.constant(2)))

print(my_function_(2))
print(my_function_(tf.constant(2)))

tf_my_func = tf.function(my_function_)
print(tf_my_func)
print(tf_my_func(2))

print(tf_my_func.python_function(2))

a_function_that_uses_a_graph = tf.function(function_to_get_faster) # 그래프 구조로 변환

x1 = tf.constant([[1., 2.]])
y1 = tf.constant([[2.], [3.]])
b1 = tf.constant(4.)

print(a_function_that_uses_a_graph(x1, y1, b1).numpy())

print(outer_function(tf.constant([[1., 2.]])).numpy())

# 텐서플로우가 tf.function으로 변환한 코드
print(tf.autograph.to_code(my_function.python_function))
print(tf.autograph.to_code(tf_my_func.python_function))
print(tf.autograph.to_code(outer_function.python_function))
tf.Tensor(-13, shape=(), dtype=int32)
tf.Tensor(-13, shape=(), dtype=int32)
-13
tf.Tensor(-13, shape=(), dtype=int32)
<tensorflow.python.eager.def_function.Function object at 0x00000271269A70D0>
tf.Tensor(-13, shape=(), dtype=int32)
-13
[[12.]]
[[12.]]
def tf__my_function(x):
    with ag__.FunctionScope('my_function', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()
        try:
            do_return = True
            retval_ = ag__.ld(x) ** 2 - 10 * ag__.ld(x) + 3
        except:
            do_return = False
            raise
        return fscope.ret(retval_, do_return)

def tf__my_function_(x):
    with ag__.FunctionScope('my_function_', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()
        try:
            do_return = True
            retval_ = ag__.ld(x) ** 2 - 10 * ag__.ld(x) + 3
        except:
            do_return = False
            raise
        return fscope.ret(retval_, do_return)

def tf__outer_function(x):
    with ag__.FunctionScope('outer_function', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()
        y = ag__.converted_call(ag__.ld(tf).constant, ([[2.0], [3.0]],), None, fscope)
        b = ag__.converted_call(ag__.ld(tf).constant, (4.0,), None, fscope)
        try:
            do_return = True
            retval_ = ag__.converted_call(ag__.ld(inner_function), (ag__.ld(x), ag__.ld(y), ag__.ld(b)), None, fscope)
        except:
            do_return = False
            raise
        return fscope.ret(retval_, do_return)

속도 향상

  • Graph 이용한 모델이 월등히 빠릅니다.
import timeit
import numpy as np
import tensorflow as tf

class SequentialModel(tf.keras.Model):
    def __init__(self, **kwargs):
        super(SequentialModel, self).__init__(**kwargs)
        self.flatten = tf.keras.layers.Flatten(input_shape=(28,28))
        self.dense_1 = tf.keras.layers.Dense(128, activation='relu')
        self.dropout = tf.keras.layers.Dropout(0.2)
        self.dense_2 = tf.keras.layers.Dense(10)

    def call(self, x):
        x = self.flatten(x)
        x = self.dense_1(x)
        x = self.dropout(x)
        x = self.dense_2(x)
        return x

input_data = tf.random.uniform([60, 28, 28])

eager_model = SequentialModel()
graph_model = tf.function(eager_model)

print("Eager time :", timeit.timeit(lambda: eager_model(input_data), number=10000))
print("Graph time :", timeit.timeit(lambda: graph_model(input_data), number=10000))
Eager time : 19.930444599944167
Graph time : 5.891941000008956

변수 생성

import timeit
import numpy as np
import tensorflow as tf

X = tf.Variable(20.0)
print(X)
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=20.0>

Autograd(자동 미분)

  • tf.GradientTape API를 사용
  • tf.Variable 같은 일부 입력에 대한 기울기 계산
    • 기본적으로 한번만 사용됨
  • 변수가 포함된 연산만 기록
import timeit
import numpy as np
import tensorflow as tf

x = tf.Variable(3.0)

with tf.GradientTape() as tape:
    y = x**2

dy_dx = tape.gradient(y, x)
print(dy_dx.numpy())

# x2 = tf.Variable(4)
# dy_dx = tape.gradient(y, x2)

# print(dy_dx.numpy())

x = tf.Variable(2.0)
y = tf.Variable(3.0)

with tf.GradientTape() as tape:
    y_sq = y**2
    z = x**2 + tf.stop_gradient(y_sq)

grad = tape.gradient(z, {'x' : x, 'y' : y})

print('dz/dx:', grad['x'])
print('dz/dy', grad['y'])

weights = tf.Variable(tf.random.normal((3,2), name = 'weights'))
biases = tf.Variable(tf.zeros(2, dtype=tf.float32), name='biases')
x = [[1.,2.,3.]]

with tf.GradientTape(persistent=True) as tape:
    y = x @ weights + biases
    loss = tf.reduce_mean(y**2)

[dl_dw, dl_db] = tape.gradient(loss, [weights, biases])
print(weights.shape)
print(dl_dw.shape)

6.0
dz/dx: tf.Tensor(4.0, shape=(), dtype=float32)
dz/dy None
(3, 2)
(3, 2)

728x90

이 글을 공유하기

댓글

Designed by JB FACTORY