#----------------
# 01_02 文本分类
#----------------

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

# TensorFlow's version : 1.12.0
print('TensorFlow\'s version : ', tf.__version__)

#----------------
# 1 下载 IMDB 数据集
#----------------

imdb = keras.datasets.imdb

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

#----------------
# 2 探索数据
#----------------

# Training entries: 25000, labels: 25000
print("Training entries: {}, labels: {}".format(len(train_data), len(train_labels)))

print(train_data[0])

# (218, 189)
print(len(train_data[0]), len(train_data[1]))

# A dictionary mapping words to an integer index
word_index = imdb.get_word_index()

# The first indices are reserved
word_index = {k:(v+3) for k,v in word_index.items()}
word_index["<PAD>"] = 0
word_index["<START>"] = 1
word_index["<UNK>"] = 2  # unknown
word_index["<UNUSED>"] = 3

reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])

def decode_review(text):
    return ' '.join([reverse_word_index.get(i, '?') for i in text])

decode_review(train_data[0])

#----------------
# 3 准备数据
#----------------

train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                        value=word_index["<PAD>"],
                                                        padding='post',
                                                        maxlen=256)

test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=word_index["<PAD>"],
                                                       padding='post',
                                                       maxlen=256)

# (256, 256)
print((len(train_data[0]), len(train_data[1])))

print(train_data[0])

#----------------
# 4 构建模型
#----------------

# input shape is the vocabulary count used for the movie reviews (10,000 words)
vocab_size = 10000

model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 16))
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

model.summary()

model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy',
              metrics=['accuracy'])

#----------------
# 5 创建验证集
#----------------

x_val = train_data[:10000]
partial_x_train = train_data[10000:]

y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]

#----------------
# 6 训练模型
#----------------

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=40,
                    batch_size=512,
                    validation_data=(x_val, y_val),
                    verbose=1)

#----------------
# 7 评估模型
#----------------

results = model.evaluate(test_data, test_labels)

print(results)

#----------------
# 8 创建准确率和损失随时间变化的图
#----------------

history_dict = history.history

# dict_keys(['loss', 'val_loss', 'val_acc', 'acc'])
print(history_dict.keys())

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

# loss

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

# acc

plt.clf()   # clear figure
acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

plt.show()

[(57, 'tensorflow.keras.preprocessing.sequence.pad_sequences', 'keras.preprocessing.sequence.pad_sequences', False, 'from tensorflow import keras\n'), (62, 'tensorflow.keras.preprocessing.sequence.pad_sequences', 'keras.preprocessing.sequence.pad_sequences', False, 'from tensorflow import keras\n'), (79, 'tensorflow.keras.Sequential', 'keras.Sequential', False, 'from tensorflow import keras\n'), (139, 'matplotlib.pyplot.plot', 'plt.plot', True, 'import matplotlib.pyplot as plt\n'), (141, 'matplotlib.pyplot.plot', 'plt.plot', True, 'import matplotlib.pyplot as plt\n'), (142, 'matplotlib.pyplot.title', 'plt.title', True, 'import matplotlib.pyplot as plt\n'), (143, 'matplotlib.pyplot.xlabel', 'plt.xlabel', True, 'import matplotlib.pyplot as plt\n'), (144, 'matplotlib.pyplot.ylabel', 'plt.ylabel', True, 'import matplotlib.pyplot as plt\n'), (145, 'matplotlib.pyplot.legend', 'plt.legend', True, 'import matplotlib.pyplot as plt\n'), (147, 'matplotlib.pyplot.show', 'plt.show', True, 'import matplotlib.pyplot as plt\n'), (151, 'matplotlib.pyplot.clf', 'plt.clf', True, 'import matplotlib.pyplot as plt\n'), (155, 'matplotlib.pyplot.plot', 'plt.plot', True, 'import matplotlib.pyplot as plt\n'), (156, 'matplotlib.pyplot.plot', 'plt.plot', True, 'import matplotlib.pyplot as plt\n'), (157, 'matplotlib.pyplot.title', 'plt.title', True, 'import matplotlib.pyplot as plt\n'), (158, 'matplotlib.pyplot.xlabel', 'plt.xlabel', True, 'import matplotlib.pyplot as plt\n'), (159, 'matplotlib.pyplot.ylabel', 'plt.ylabel', True, 'import matplotlib.pyplot as plt\n'), (160, 'matplotlib.pyplot.legend', 'plt.legend', True, 'import matplotlib.pyplot as plt\n'), (162, 'matplotlib.pyplot.show', 'plt.show', True, 'import matplotlib.pyplot as plt\n'), (80, 'tensorflow.keras.layers.Embedding', 'keras.layers.Embedding', False, 'from tensorflow import keras\n'), (81, 'tensorflow.keras.layers.GlobalAveragePooling1D', 'keras.layers.GlobalAveragePooling1D', False, 'from tensorflow import keras\n'), (82, 'tensorflow.keras.layers.Dense', 'keras.layers.Dense', False, 'from tensorflow import keras\n'), (83, 'tensorflow.keras.layers.Dense', 'keras.layers.Dense', False, 'from tensorflow import keras\n'), (87, 'tensorflow.train.AdamOptimizer', 'tf.train.AdamOptimizer', True, 'import tensorflow as tf\n')]