def gen():
    for i in range(10):
        yield i

dataset = tf.data.Dataset.from_generator(gen, tf.float32)\
        .make_one_shot_iterator()\
        .get_next()

with tf.Session() as sess:
    _data = sess.run(dataset)
    print(_data)

with tf.Session() as sess:
    for _ in range(10):
        _data = sess.run(dataset)
        print(_data)

# End of sequence Error 발생
with tf.Session() as sess:
    for _ in range(12):
        _data = sess.run(dataset)
        print(_data)

"""
Explanation: 참고 자료

이찬우님 유튜브

(1) 보편적 Case

Generator를 사용
python api를 의존하기 때문에 병목이 있을 수 있음
End of explanation
"""


def gen():
    for i, j in zip(range(10, 20), range(10)):
        yield (i, j)

dataset = tf.data.Dataset.from_generator(gen, (tf.float32, tf.float32))\
        .make_one_shot_iterator()\
        .get_next()

with tf.Session() as sess:
    for _ in range(10):
        _label, _feature = sess.run(dataset)
        print(_label, _feature)

"""
Explanation: generator로 label, feature까지 출력하고 싶다면
End of explanation
"""


def gen():
    for i, j in zip(range(10, 1010), range(1000)):
        yield (i, j)

dataset = tf.data.Dataset.from_generator(gen, (tf.float32, tf.float32))\
        .shuffle(7777)\
        .batch(20)\
        .make_one_shot_iterator()\
        .get_next()

with tf.Session() as sess:
    for _ in range(10):
        _label, _feature = sess.run(dataset)
        print(_label, _feature)

"""
Explanation: Minibatch를 하고 싶다면

shuffle한 후, batch 설정
End of explanation
"""


dataset = tf.data.TextLineDataset("./test_data.csv")\
        .make_one_shot_iterator()\
        .get_next()

with tf.Session() as sess:
    _data = sess.run(dataset)
    print(_data)

"""
Explanation: (2) TextLineDataset

병목을 해결 가능
End of explanation
"""


dataset = tf.data.TextLineDataset("./test_data.csv")\
        .make_one_shot_iterator()\
        .get_next()

lines = tf.decode_csv(dataset, record_defaults=[[0]]*10)

feature = tf.stack(lines[1:]) #, axis=1)

label = lines[0]

with tf.Session() as sess:
    _fea, _lab = sess.run([feature, label])
    print(_lab, _fea)

dataset = tf.data.TextLineDataset("./test_data.csv")\
        .batch(2)\
        .repeat(999999)\
        .make_one_shot_iterator()\
        .get_next()

lines = tf.decode_csv(dataset, record_defaults=[[0]]*10)
feature = tf.stack(lines[1:], axis=1)
label = tf.expand_dims(lines[0], axis=-1)

feature = tf.cast(feature, tf.float32)
label = tf.cast(label, tf.float32)
# float형으로 정의해야 이상없이 연산이 됨

with tf.Session() as sess:
    _fea, _lab = sess.run([feature, label])
    for f, l in zip(_fea, _lab):
        print(f, l)

"""
Explanation: b'1,1,2,3,4,5,6,7,8,9' : decoding 필요
End of explanation
"""


layer1 = tf.layers.dense(feature, units=9, activation=tf.nn.relu)
layer2 = tf.layers.dense(layer1, units=9, activation=tf.nn.relu)
layer3 = tf.layers.dense(layer2, units=9, activation=tf.nn.relu)
layer4 = tf.layers.dense(layer3, units=9, activation=tf.nn.relu)
out = tf.layers.dense(layer4, units=1)

print("label's shape {}".format(label))
# label's shape (?,) : [1, 2, 3, 4, 5, 6]
# int면 계산이 안됨

print("out's shape {}".format(out))
# [[1], [2], [3], [4], [5], [6]]

"""
Explanation: Modeling
End of explanation
"""


loss = tf.losses.sigmoid_cross_entropy(label, out)

"""
Explanation: loss, Optimizer 정의
End of explanation
"""


train_op = tf.train.GradientDescentOptimizer(1e-2).minimize(loss)

pred = tf.nn.sigmoid(out)
accuracy = tf.metrics.accuracy(label, tf.round(pred))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    sess.run(tf.local_variables_initializer())
    for i in range(30):
        _, _loss, _acc = sess.run([train_op, loss, accuracy])
        print("step: {}, loss: {}, accuracy: {}".format(i, _loss, _acc))

"""
Explanation: Shapes (?, 1) and (?,) are incompatible error
shape를 맞춰주기 : tf.expand_dims 사용


Value passed to parameter 'x' has DataType int32 not in list of allowed values error
value의 type을 float32로 바꾸기 : tf.cast 사용


Attempting to use uninitialized value accuracy/total error
accuracy 관련 tf.local_variables_initializer() 실행
End of explanation
"""


