텐서플로우의 동작의 구성
1. 만들고
2. 실행하기
1) 그래프 -> 세션 -> 실행 ; 만들고 실행하기
import tensorflow as tf로 tensorflow를 import하면 그 시점에 있는 기본 그래프가 만들어지면 우리가 만드는 노드는 이 기본그래프에 자동으로 연결된다.
그래서 노드를 어떻게 만드는가?!
a = tf.constant(5)
b = tf.constant(2)
그러면 만들어진 노드로 연산을 진행하는 연산 그래프는 어떻게 만드는가?!
흔히 사용되는 tensorflow 연산이나 축약형 연산자를 이용한다.
d = tf.multiply(a, b) #a*b
c = tf.add(a, b)#a+b
이렇게 노드와, 연산 그래프를 만드고 나면 연산 그래프를 실행할 준비가 된 것이며, 연산을 실행하려면 세션을 만들고 실행하면 된다.
sess = tf.Session() #연산 그래프를 시작하는 Session객체
#- Session객체는 텐서플로 API의 일부로, 파이썬 객체와 데이터, 객체의 메모리가 할당되어 있는 실행 환경 사이를 연결하며, 중간 결과를 저장하고 최종 결과를 작업환경으로 보내준다.
outs = sess.run(f) #연산 그래프가 실행(run) 즉, 계산이 된다.
#- 이때 계산은, 출력이 나와야 하는 노드에서 시작해 역방향으로 처리하여 의존관계 집합에 따라 실행되어야 하는 노드의 연산을 수행한다. 이 f라는 것은, 노드 f의 계산을 실행요청 한다는 것을 의미한다.
sess.close() #연산 작업이 마무리되면,
#이 명령을 사용하여 Session을 닫아서 해당 session에서 사용하는 자원을 해제하는 것이 좋다.
print("out = {}".format(outs)) #결과 출력
여기서 연산 그래프가 실행(run) 될때 출력이 나와야 하는 노드(이 예에서는 f)에서 시작해 역방향으로 처리하여 의존관계 집합에 따라 실행되어야 하는 노드의 연산을 수행한다.고 하였다. 즉 sess.run(노드) 에서 하나의 특정 노드의 실행을 요청한 것인데 이 인수를 fetches라고 한다. fetches는 노드들이 담긴 리스트가 될 수도 있으며 여러 노드의 출력을 요청한다.
2) 만들기 - 새로운 그래프 생성과 관리
앞에서 살펴보았듯이 tensorflow를 import하면 그 시점에 있는 기본 그래프가 만들어지지만 이와 별개로 그래프를 추가로 생성하고 관계를 직접 제어할 수도 있다.
기본 그래프가 아닌 새로운 그래프의 생성은
import tensorflow as tf
g = tf.Graph() #.Graph()를 사용하여 새로운 그래프를 생성
print(g)
이렇게 새로운 그래프를 많이 생성하다보면, 연산의 제어가 필요할 것이다. 즉, 원하는 그래프와 노드를 명확히 연결하고, 그에 관련된 연산을 실행 시킬 수 있는 것이 중요하다. 이를 위해서는 1. tf.get_default_graph()를 사용해서 특정 노드가 어떤 그래프와 연결되어 있는지를 확인하고, 2. 파이썬의 with구문을 이용하여 노드와 원하는 그래프와 명확한 연결을 수행할 수 있다. 또한 3. with구문을 as_default()명령과 함께 사용하면 해당 그래프가 기본 그래프인 콘텍스트 관리자를 반환한다.
* with 구문을 사용하여 세션을 열면 모든 연산이 완료된 후 자동으로 세션이 닫힌다,
graph1 = tf.get_default_graph()
graph2 = tf.Graph()
print(g1 is tf.get_default_graph()) #True
with g2.as_default():
print(g1 is tf.get_default_graph()) #False
print(g1 is tf.get_default_graph()) #True
#즉, with g2.as_default(): 구문 안에서는 g2 그래프가 기본 그래프가 되는 것이다.
#이 with구문을 명시적으로 닫지 않고 세션을 시작할 수도 있다.
3) 텐서의 흐름
앞에서 '이렇게 노드와, 연산 그래프를 만드고 나면 연산 그래프를 실행할 준비가 된 것이며, 연산을 실행하려면 세션을 만들고 실행하면 된다. '라고 했던 것과 같이 그래프에서 노드를 만들 때, 실제로는 연산 인스턴스가 생성되어 준비가 된 것이다. 생성된 연산 인스턴스는 그래프가 실행되기 전까지는 실제 값을 내놓지 않고 흐름(flow)골격이 형성된것에 불과하다. 이런 흐름은 계산된 결과를 다른 노드로 전달할 수 있는 handle(;edge)로 연결되며, 이 edge는 Tensor object라고 한다.
이후 세션이 실행되면, 그때 그래프에 데이터가 입력되고 연산이 시작된다.
이제 '1) 그래프 -> 세션 -> 실행; 만들고 실해하기' 를 다시 보면 이해가 더 잘 될것이다.
4) 더 자세히 ..
이제 그래프 -> 세션 -> 실행의 각각의 단계에서 더욱 자세하고 깊게 알아보고자 한다.
1. 텐서 객체
-
1. 데이터 타입
그래프에 전달되는 데이터는 숫자, boolean, string 등의 다양한 데이터 타입을 가진다. 따라서 텐서 객체를 만들 때 데이터 타입을 지정하여 명시적으로 선택할 수 있다.
c = tf.constant(4.0, dtype = tf.float64)
print(c.dtype) #.dtype을 사용하면 타입을 확인 할 수 있다.
-
2. 형 변환
연산시 데이터 타입이 일치하도록 하는 것은 매우 중요하다.
tf.cast(해당 텐서, 변환할 데이터 타입) 을 이용하여 형 변환을 진행해준다. ==> 정말 자주 쓰인다!!
x = tf.constant([1, 2, 3], name = 'x', dtype = tf.float32)
x = tf.cast(x, tf.int64)
2. 텐서 배열과 형태
Tensorflow에서의 'Tensor'는 두가지 의미가 있다.
- 1. 이때까지 사용한 '그래프에서 연산의 결과에 대한 handle로 파이싼 API에서 사용하는 객체 이름'
- 2. n차원 배열을 가리키는 수학 용어로, Tensorflow에서는 다차원 배열, 벡터, 행렬, 스칼라 등 그래프에서 전달되는 모든 단위 데이터를 Tensor로 간주한다.
이번에는 그래프에서 전달되는 모든 단위 데이터인 Tensor를 다루어 보도록 한다. 파이썬의 자료형인 list와 Numpy 배열을 사용하여 Tensor를 초기화하고 이용할 수 있다.
import numpy as np
import tensorflow as tf
c = tf.constant([[1, 2, 3], [4, 5, 6]]) #List를 사용한 Tensor
print('List input:', c.get_shape())
c = tf.constant(np.array([
[[1, 2, 3], [4, 5, 6]],
[[1, 1, 1],[2, 2, 2]] ]) #Numpy array를 사용한 Tensor
print('Numpy array input:', c.get_shape())
이 외에도 다양한 Tensor 초기화 함수들이 있다.
tf.constant(value) | 인수 value에 지정한 값 또는 값들로 채워진 텐서를 생성 |
tf.fill(shape, value) | shape에 지정한 형태의 텐서를 만들고, value에 지정한 값으로 초기화 |
tf.zeros(shape) | shape에 지정한 형태의 텐서를 만들고, 모든 원소의 값을 0으로 초기화 |
tf.zeros_like(tensor) | tensor와 동일한 타입과 형태의 텐서를 만들고, 모든 원소의 값을 0으로 초기화 |
tf.ones(shape) | shape에 지정한 형태의 텐서를 만들고, 모든 원소의 값을 1로 초기화 |
tf.ones_like(tensor) | tensor와 동일한 타입과 형태의 텐서를 만들고, 모든 원소의 값을 1로 초기화 |
tf.random_normal(shape, mean, stddev) | 정규분포를 따르는 난수를 생성 |
tf.truncated_normal(shape, mean, stddev) | 절단정규분포(평균을 기준으로 표준편차보다 크거나 작은 데이터를 제외)를 따르는 난수를 생성 |
tf.random_uniform(shape, minval, maxval) | [minval, maxval) 구간의 균등분포의 값을 생성 |
tf.random_shuffle(tensor) | 첫 번째 차원에 따라 텐서를 무작위로 뒤섞음 |
표 출처: https://excelsior-cjh.tistory.com/151?category=940399
3. Tensor의 연산 - 행렬 곱
Tensor에서는 두 Tensor 객체 A, B에 대해 tf.matmul(A, B) 로 행렬곱을 수행한다. => 매우 유용한 산술 연산이다.
주의 할 것은, matmul()을 사용하기 전에 양쪽 Tensor의 차원이 같은지, 순서가 맞춰져있는지 확인해야 한다.
A = tf.constant([[1, 2, 3], [4, 5, 6]])
print(A.get_shape()) #(2, 3)
x = tf.constant([1, 0, 1])
print(x.get_shape()) #(3, )
#Ax = b 연산을 수행하기 위해서는 x에 차원을 추가하여 1차원 벡터에 하나의 열을 가진 2차원 행렬로 변환해야 한다.
4. Tensor의 연산 - 차원의 추가
위 예의 경우, Ax = b 연산을 수행하기 위해서는 x에 차원을 추가하여 1차원 벡터에 하나의 열을 가진 2차원 행렬로 변환해야 한다. tf.expand_dims()를 사용하여 차원을 하나 추가할 수 있다. => CNN등에서 매우 자주 사용된다.
x = tf.expand_dims(x, 1)
print(x.get_shape())
b = tf.matmul(A, x)
sess = tf.InteractiveSession()
print('matmul result:'.format(b.eval())
sess.close()
#matmul result:
[[4] [10]]
5. Tensor의 연산 - 배열 뒤집기(전치)
열 벡터를 행 벡터로 바꾸거나 그 반대로 바꾸는 식으로 배열을 뒤집으려면 tf.transpose()를 사용한다.
'Data Science > Tensorflow2.0, Pytorch' 카테고리의 다른 글
pytorch) 선형회귀분석 (0) | 2020.05.29 |
---|---|
Learning Tensorflow) 4. 합성곱신경망 (0) | 2020.04.19 |
10. Tensorflow2.0 Evaluating & Predicting (0) | 2020.03.27 |
8. Tensorflow2.0 Optimization & Training (Expert) (0) | 2020.03.27 |
7. Tensorflow2.0 Optimization & Training (Keras) (0) | 2020.03.27 |