2020. 3. 22. 18:02ㆍ분석 Python/Tensorflow
광고 한번만 눌러주세요 ㅎㅎ 블로그 운영에 큰 힘이 됩니다.
예전에 tf.data로 인풋 파이프라인을 만들고, 모델을 만든 뒤, 모델을 저장해서 사용해봤는데,
추론 결과가 계속 동일한 이상한 현상이 발견했다.
그래서 오랜만에 tf.data도 다시 공부하고 모델 학습 후 저장한 것을 다른 스크립트에서 돌릴 때 어떻게 했는지에 대해서 공유한다.
일단은 정확한 답은 아닐 수 있지만, 충분히 사용할만할 것 같다고 생각한다.
일단 중요한 것은 데이터 처리 이후니까 전처리 단계는 가볍게 패스
개인적으로 initializer를 사용하는 것을 선호한다.
tf.data에서는 batch_size를 정해줘야하는데, 이 부분을 빈 홀더로 남겨놓고, 전체 추론할 때는 바꾸면서 사용할 수 있게 했다.
import tensorflow as tf
tf.reset_default_graph()
X = tf.placeholder(tf.float32 , shape = [None,train_x.shape[1]])
y = tf.placeholder(tf.float32 , shape = [None,1])
batch_size = tf.placeholder(tf.int64)
데이터 파이프 라인을 만들어 보자.
data_tuple = (X,y)
dataset = tf.data.Dataset.from_tensor_slices(data_tuple)
dataset = dataset.shuffle(buffer_size= 1000)
dataset = dataset.batch(batch_size=batch_size, drop_remainder=True)
iter = dataset.make_initializable_iterator()
feature_batch , label_batch = iter.get_next()
이제 이 데이터 파이프 라인은 데이터를 어떻게 초기값을 넣어주는냐에 따라서, 다른 값들이 들어갈 것이다.
이제 네트워크를 만들어 보자.
W1 = tf.get_variable("w",shape=[train_x.shape[1],25])
B1 = tf.get_variable("b",shape=[25])
W2 = tf.get_variable("w2",shape=[25,15])
B2 = tf.get_variable("b2",shape=[15])
W3 = tf.get_variable("w3",shape=[15,1])
B3 = tf.get_variable("b3",shape=[1])
def Layer(X , reuse = False) :
layer1 = tf.nn.relu(tf.matmul(X, W1) + B1)
layer2 = tf.nn.selu(tf.matmul(layer1, W2) + B2)
logit = tf.matmul(layer2, W3) + B3
return logit
만든 네트워크에다가 loss랑 optimizer까지 구성해보자.
loss = tf.nn.sigmoid_cross_entropy_with_logits(labels = label_batch , logits=logit)
Loss = tf.reduce_mean(loss)
vars = tf.trainable_variables()
optimizer = tf.train.AdadeltaOptimizer(1e-3).minimize(Loss , var_list = vars)
그리고 metric으로는 auc를 보고 싶으니, auc를 볼 수 있게 해보자.
prob= tf.nn.sigmoid(logit)
auc_value , update_auc = tf.metrics.auc(label_batch , prob , curve="ROC")
## 여기가 추론 부분의 핵심 ##
보통 추론을 할 때는 batch성으로 나누지 않고, 바로 실시간이나 전체 데이터를 추론하기를 원할 것이다.
하지만 지금 포맷을 그대로 유지해서 $prob$는 객체를 그대로 쓰게 되면, 데이터 들어올 때마다 파이프라인을 초기화해줘야 하는 상황이 된다. 그래서 나는 바로 $X$를 받아서 네트워크를 태운 후 확률 값이 나올 수 있게, 새로 하나를 만들었다. 그리고 이것을 나중에 쉽게 꺼내서 사용하기 위해 tf.get_collection을 사용해서 $Probability$에 넣어 놓았다.
output = tf.nn.sigmoid(Layer(X))
tf.add_to_collection('Probability', X)
tf.add_to_collection('Probability', output)
자 일단 다 구성은 했으니, 학습을 시켜보자.
먼가 기존에 feed_dict을 쓰는 것보다 훨씬 간단해진 것 같아서 보기 좋다.
주요하게 볼 점은 배치성 작업을 하는 것은 while 문에 넣어 놓고, 학습되게 하고, test 데이터로 추론하는 것은 while 문 밖에서 처리해서 출력하게 하는 구조로 하였다.
그래서 학습이 모두 끝나고 저장하게 했다.
config = tf.ConfigProto(log_device_placement=True)
config.gpu_options.allow_growth = True
EPOCHS = 10
with tf.Session(config=config) as sess:
saver = tf.train.Saver()
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init)
for i in range(EPOCHS):
sess.run(iter.initializer ,
feed_dict= {X : train_x.values,
y : train_y.values.reshape(-1,1),
batch_size : 1000}) # switch to train dataset
while True :
try :
probs , _,auc,Loss2,_=sess.run([prob, auc_value,update_auc,Loss,optimizer])
except tf.errors.OutOfRangeError :
break
sess.run(iter.initializer ,
feed_dict= {X : test_x.values,
y : test_y.values.reshape(-1,1),
batch_size : len(test_x)
}) # switch to train dataset
probs , _ , auc = sess.run([prob,auc_value,update_auc])
print(f"Epoch : {i}, AUC : {auc*100:.2f}", end="\r")
meta_graph_bool = True
saver.save(sess,
"./tf_data_test_model.ckpt",
global_step=i, write_meta_graph=meta_graph_bool)
그러면 이런 식으로 떨궈지게 된다.
이제 저장된 모델을 사용해서 추론을 해보자.
추론 코드는 만약 tf.get_collection을 사용했다면, 아주 간단하게 할 수 있다.
일단 모델을 불러들인다.
import tensorflow as tf
import os
file_path = "./tf_data_test_model.ckpt-9.meta"
tf.reset_default_graph()
config=tf.ConfigProto(log_device_placement=True)
config.gpu_options.allow_growth = True
sess = tf.Session(config= config)
sess.run(tf.global_variables_initializer())
saver = tf.train.import_meta_graph(file_path)
saver.restore(sess, "tf_data_test_model.ckpt-9")
그리고 불러들인 모델에서 위에서 $Probability$에 넣어놓았던, $X,Prob$를 꺼내보자. 꺼낼 때는 get_collection을 사용한다.
X = tf.get_collection("Probability")[0]
prob = tf.get_collection("Probability")[1]
이제 우리에게 이런 데이터가 있다고 했을 때 추론을 하게 되면?
import numpy as np
sample_data = np.array([[-0.97979798, -0.89655172, -0.2 , -0.2 , -0.8 ,
-0.8 , -1. , -1. , -0.61658433, -0.86167135,
-0.82655422, -0.51359173, -0.83870382, -0.553858 , -1. ,
-0.99886628, -1. , -1. , -0.97543583, -1. ,
0. , 1. , 0. , 0. , 1. ,
0. , 0. , 0. , 0. , 0. ,
1. , 0. , 0. ]])
sess.run(prob, feed_dict={X : sample_data})
이제 또 다른 데이터를 넣으면 어떻게 될까?
sample_data2 = np.array([[-0.61616162, -0.72413793, -0.60341802, -1. , -0.8 ,
-0.64320093, -0.8 , -0.77777778, -0.61658433, -0.86755913,
-0.82298324, -0.57483715, -0.83900129, -0.63972138, -1. ,
-0.99351527, -0.93544249, -1. , -0.98723429, -1. ,
0. , 1. , 0. , 1. , 0. ,
0. , 0. , 0. , 0. , 0. ,
0. , 1. , 0. ]])
확률 값이 다르게 나오는 것을 확인했다!
tf.data에 집착하는 이유는, tf.data가 더 빠르다고 한다.
그리고 유틸성이 증가한다. shuffle에 용이성, run session할 때 깔끔하게 할 수 있고, 다른 feed_dict 같이 관리하는 것에 대해서 편리함 등이 있는 것 같다.
그리고 보통 이미지 데이터를 처리할 때 좋을 것 같고, 그리고 만약 데이터가 크다고 했을 때,
tf.data 같은 경우 배치 단위로 가져올 수 있기 때문에, 리소스 측면에서도 훨씬 좋다고 생각한다!
http://www.programmersought.com/article/1339534134/
'분석 Python > Tensorflow' 카테고리의 다른 글
tf.py_func 사용해보기 (0) | 2020.04.17 |
---|---|
tf.data 삽질해보기 (two iterator, feed_dict, GAN) (0) | 2020.04.08 |
Tensorflow에서 tf.data 사용하는 방법 (0) | 2020.03.22 |
tf.stop_gradient 사용해서 학습시킬 가중치 조절해보기 (3) | 2020.03.21 |
Shared Weight AutoEncoder 구현해보기 (0) | 2020.02.24 |