tf.train.Saver 객체를 통해서 모델을 저장하고 불러올 수 있다.


1. 모델 저장

# saver 객체 생성.
# max_to_keep를 안쓰면, 최대 5개만 저장된다. (이전에 저장된 checkpoint가 지워짐)
saver = tf.train.Saver(max_to_keep=10)

# 세션에 있는 variable들을 저장.
# 총 3가지 파일이 한번에 저장된다.  파일명.data-00000-of-00001, .index, .meta
# 아직 세개가 뭘 의미하는 지는 잘 모르지만, meta는 모델 구조를 명시한다.
# global_step을 써주면, baseline_model-100.meta 처럼 저장되어 유용함.
saver.save(sess, "./checkpoints/baseline_model", global_step=step)




2. 모델 불러오기

두 가지 방법이 있다.

2.1 먼저 코드로 학습된 모델을 작성하고(train에 사용한 네트워크 코드를 그대로 사용), 해당하는 웨이트들에 덮어씌우는 방식 (웨이트 범위를 설정해서 특정 부분만 load할 수도 있다.)

2.2 meta 파일을 이용하여, 모델 코드 없이 바로 불러서 사용하기 (keras와 매우 유사)

일단 두 번째 방법만 정리하였다.

하나하나 설명하는 것보다 예시 코드를 보여주는게 나을거같아서 통으로 올림

import numpy as np import tensorflow as tf import os import dataset batch_size = 128 model_name = 'baseline_model' step_list = [600, 700, 800, 900] model_names = [] for step in step_list: model_names.append(model_name + '-' + str(step)) print('dataset loading... ') DB = dataset.SVPC_Dataset('./dataset/test.csv', 'test', divide_value=10000000, round=4, normaliza=False) print('dataset loaded !! ') for idx, model_name in enumerate(model_names): writer = dataset.Result_Writer(fileName=model_name) saver = tf.train.import_meta_graph(os.path.join('./checkpoints',model_name + '.meta')) print('{}: predicting...{}/{}'.format(model_names, idx, len(model_names))) with tf.Session() as sess: saver.restore(sess, os.path.join('./checkpoints',model_name)) graph = tf.get_default_graph() x = graph.get_tensor_by_name("input:0") y_pred = graph.get_tensor_by_name("output:0") for idx, (test_x, id) in enumerate(DB.generator(batch_size)): predicted_y = sess.run(y_pred, feed_dict={x: test_x}) predicted_y[np.where(predicted_y < 0)] = 0. writer.add_rows(id, (predicted_y * 10000).astype('int32')) writer.save_to_csv() print('result saved; {}'.format(model_name + '.csv'))


kaggle의 csv 파일을 다루려다 보니, dataset을 직접 구성해야할 일이 생겼다.


dataset을 다루는데에 여러가지 방법이 있는데,

대부분의 dataset은 파일이 크기 때문에 generator 형식이 제일 좋은 것같다.


하지만 csv 포멧으로는 그게 힘들어서 파일을 전부 읽은 다음 사용했다.

그런데 읽은 dataset을 이용하는 방법 또한 두 가지로 나뉘는것같다.

하나는 gpu 메모리에 올리고 사용하는 방법. 하나는 generator 형식으로 사용 데이터만 gpu에 올리는 방법

처음엔 잘 몰라서 전자를 선택했지만, 메모리 부족으로 후자를 택해야했다.


두 방법을 모두 정리하고자 글을 썼다.



1. csv 데이터 읽은 후, tf함수 from_tensor_slices로 사용하기

# train_x, train_y는 numpy 포멧 [데이터 수, value]로 구성.
# tf.data.Dataset.from_tensor_slices을 이용하면 대규모 데이터셋은 불리하다고한다
# 참고 : https://www.tensorflow.org/api_docs/python/tf/data/Dataset

dataset = tf.data.Dataset.from_tensor_slices((train_x, train_y))

dataset = dataset.batch(batch_size)
iterator = dataset.make_initializable_iterator()

_data = tf.placeholder(tf.float32, [None, cfg.INPUT_DATA_LEN])
_labels = tf.placeholder(tf.float32, [None, 1])

next_batch = iterator.get_next()
x = tf.placeholder(tf.float32, [None, 4991], 'input')
y = tf.placeholder(tf.float32, [None, 1], 'label')

y_pred = baseline.predict(x)
y_pred = tf.identity(y_pred, 'output')

mse = tf.reduce_mean(tf.square(y - y_pred))
#optimizer = tf.train.GradientDescentOptimizer(0.01)
optimizer = tf.train.AdamOptimizer(0.01)
grad_vars = optimizer.compute_gradients(mse)
capped_grad_vars = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in grad_vars]
train_op = optimizer.apply_gradients(capped_grad_vars)
saver = tf.train.Saver()
init = tf.global_variables_initializer()

print('train start')
with tf.Session() as sess:
    sess.run(init)
    #print('1')
    for i in range(step):
        sess.run(iterator.initializer, feed_dict={_data: train_x, _labels: train_y})
        iteration = 0
        #print('2')
        while True:
            try:
                train_x, train_y = sess.run(next_batch)

                sess.run(train_op, feed_dict={x:train_x, y:train_y})
                if iteration == 0:
                    loss = sess.run(mse, feed_dict={x:train_x, y:train_y})
                    print('step: {}, mse: {}'.format(i, loss))
                iteration += 1
            except tf.errors.OutOfRangeError:
                break
        if i % 100 == 0:
            if not i == 0:
                saver.save(sess, "./checkpoints/baseline_model", global_step=i)
                print('save model [{}]'.format(i))


2. csv 데이터 읽은 후, generator 만들어서 사용하기

2.1. generator를 새로 코딩 (발코딩인점은 감안.. generator가 핵심이고 나머진 안봐도됨)

import os
import pandas as pd
import numpy as np

class SVPC_Dataset():
    def __init__(self, dataDir, data_type='train', divide_value=None, divide_label=None, round=None, normaliza=False):
        self.dataDir = dataDir
        self.data_type = data_type

        if self.data_type == 'train':
            return self.read_train_data_from_csv(divide_value, divide_label, round, normaliza)
        else:
            return self.read_test_data_from_csv(divide_value, round, normaliza)
        print('data loaded')

    def read_train_data_from_csv(self, divide_value=None, divide_label=None, round=None, normaliza=False):
        df = pd.read_csv(self.dataDir, low_memory=False)
        label_df = df.iloc[:, 1]  # label column
        value_df = df.iloc[:, 2:]  # value column

        if divide_value is not None:
            value_df = value_df / divide_value  # 나누기
        if divide_label is not None:
            label_df = label_df / divide_value  # 나누기
        df = pd.concat([label_df, value_df], axis=1, sort=False)
        if round is not None:
            df = df.round(round)  # 소수점 제거
        if normaliza:
            df = (df - df.mean()) / (df.max() - df.min())
        self.x = np.array(df.values[:, 1:], dtype=np.float32)
        y = np.array(df.values[:, 0], dtype=np.float32)
        self.y = np.expand_dims(y, axis=1)

    def read_test_data_from_csv(self, divide_value=None, round=None, normaliza=False):
        df = pd.read_csv(self.dataDir, low_memory=False)
        id_df = df.iloc[:, 0]  # id column
        value_df = df.iloc[:, 1:]  # value column

        if divide_value is not None:
            value_df = value_df / divide_value  # 나누기
        if round is not None:
            value_df = value_df.round(round)  # 소수점 제거
        if normaliza:
            value_df = (value_df - value_df.mean()) / (value_df.max() - value_df.min())
        self.x = np.array(value_df.values, dtype=np.float32)
        id = np.array(id_df.values)
        self.id = np.expand_dims(id, axis=1)

    def __len__(self):
        return len(self.x)

    def __getitem__(self, idx):
        if self.data_type == 'train':
            return self.x[idx], self.y[idx]
        else:
            return self.x[idx], self.id[idx]

    def generator(self, batch_size=1):
        length = self.__len__()
        for n_idx in range(0, length, batch_size):
            yield self[n_idx:min(n_idx + batch_size, length)]

class Result_Writer():
    def __init__(self, outDir='./', fileName='model_result'):
        self.fileDir = os.path.join(outDir, fileName + '.csv')
        self.result_df = pd.DataFrame(columns=['ID', 'target'])

    def add_row(self, id, target):
        self.result_df = self.result_df.append({'ID':id, 'target':target}, ignore_index=True)

    def add_rows(self, ids, targets):
        for i in range(len(ids)):
            self.add_row(ids[i], targets[i])

    def save_to_csv(self):
        self.result_df.to_csv(self.fileDir, mode='w', header=False)

if __name__ == '__main__':
    db = SVPC_Dataset('./dataset/test.csv', 'test')
    for idx, (x, y) in enumerate(db.generator(3)):
        print(x)
        print(y)
        if idx > 5:
            break


2.2. generator를 통한 모델 학습

DB = dataset.SVPC_Dataset('./dataset/train.csv', 'train', divide_value=10000000, divide_label=10000, round=4, normaliza=False)

x = tf.placeholder(tf.float32, [None, 4991], 'input')
y = tf.placeholder(tf.float32, [None, 1], 'label')

y_pred = baseline.predict(x)
y_pred = tf.identity(y_pred, 'output')

mse = tf.reduce_mean(tf.square(y - y_pred))
#optimizer = tf.train.GradientDescentOptimizer(0.01)
optimizer = tf.train.AdamOptimizer(0.01)
grad_vars = optimizer.compute_gradients(mse)
capped_grad_vars = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in grad_vars]
train_op = optimizer.apply_gradients(capped_grad_vars)
saver = tf.train.Saver()
init = tf.global_variables_initializer()

print('train start')
with tf.Session() as sess:
    sess.run(init)
    #print('1')
    for step in range(steps):
        #print('2')
        for idx, (train_x, train_y) in enumerate(DB.generator(batch_size)):
            sess.run(train_op, feed_dict={x:train_x, y:train_y})
            if idx == 0:
                loss = sess.run(mse, feed_dict={x:train_x, y:train_y})
                print('step: {}, mse: {}'.format(step, loss))

        if step % 100 == 0:
            if not step == 0:
                saver.save(sess, "./checkpoints/baseline_model", global_step=step)
                print('save model [{}]'.format(step))


둘 다 ram에 data를 미리 다 올리고 사용하는 방법임.

(이것도 개선해야하는데, 당장은 방법을 모르겠음)


1번은 데이터 전부를 gpu에 올리는 듯함

그래서 크기가 작은 파일은 괜찮은데, 큰 파일에서는 메모리 초과 오류가 발생


2번은 ram에 있는 데이터를 batch_size만큼 씩 gpu에 올려서 사용

메모리 초과 오류가 발생하지 않음

pip install --ignore-installed --upgrade '링크'



tensorflow 1.0.1 & python 3.6 & linux

GPU

https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.1-cp36-cp36m-linux_x86_64.whl

CPU

https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.1-cp36-cp36m-linux_x86_64.whl


tensorflow 1.0.1 & python 2.7 & linux

GPU

https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.1-cp27-none-linux_x86_64.whl

CPU

https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.1-cp27-none-linux_x86_64.whl



(https://www.tensorflow.org/versions/r1.0/install/install_windows)

"The TensorFlow library wasn't compiled to use SSE instructions but these are available on your machine and could speed up CPU computations"


간단한 알림창이다.

그러나 너무나 거슬린다.


import os

os.environ['TF_CPP_MIN_LOG_LEVEL']='2'


를 추가하면 없어진다.

'실습 > tensorflow' 카테고리의 다른 글

학습된 모델 저장 및 불러오기  (0) 2018.07.15
Dataset 생성 및 사용  (0) 2018.07.15
버전 별 설치  (0) 2017.08.15

+ Recent posts