In [1]:
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn as sns
import random
import time
sns.set()

In [2]:
def get_vocab(file, lower = False):
    with open(file, 'r') as fopen:
        data = fopen.read()
    if lower:
        data = data.lower()
    vocab = list(set(data))
    return data, vocab

def embed_to_onehot(data, vocab):
    onehot = np.zeros((len(data), len(vocab)), dtype = np.float32)
    for i in range(len(data)):
        onehot[i, vocab.index(data[i])] = 1.0
    return onehot

In [3]:
text, text_vocab = get_vocab('shakespeare.txt', lower = False)
onehot = embed_to_onehot(text, text_vocab)

In [4]:
learning_rate = 0.01
batch_size = 128
sequence_length = 64
epoch = 3000
num_layers = 2
size_layer = 512
possible_batch_id = range(len(text) - sequence_length - 1)

In [5]:
class Model:
    def __init__(self, num_layers, size_layer, dimension, sequence_length, learning_rate):
        def lstm_cell():
            return tf.nn.rnn_cell.LSTMCell(size_layer, sequence_length, state_is_tuple = False)
        self.rnn_cells = tf.nn.rnn_cell.MultiRNNCell([lstm_cell() for _ in range(num_layers)], 
                                                     state_is_tuple = False)
        self.X = tf.placeholder(tf.float32, (None, None, dimension))
        self.Y = tf.placeholder(tf.float32, (None, None, dimension))
        self.hidden_layer = tf.placeholder(tf.float32, (None, num_layers * 2 * size_layer))
        self.outputs, self.last_state = tf.nn.dynamic_rnn(self.rnn_cells, self.X, 
                                                          initial_state = self.hidden_layer, 
                                                          dtype = tf.float32)
        rnn_W = tf.Variable(tf.random_normal((size_layer, dimension)))
        rnn_B = tf.Variable(tf.random_normal([dimension]))
        self.logits = tf.matmul(tf.reshape(self.outputs, [-1, size_layer]), rnn_W) + rnn_B
        y_batch_long = tf.reshape(self.Y, [-1, dimension])
        self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = self.logits, 
                                                                           labels = y_batch_long))
        self.optimizer = tf.train.RMSPropOptimizer(learning_rate, 0.9).minimize(self.cost)
        self.correct_pred = tf.equal(tf.argmax(self.logits, 1), tf.argmax(y_batch_long, 1))
        self.accuracy = tf.reduce_mean(tf.cast(self.correct_pred, tf.float32))
        seq_shape = tf.shape(self.outputs)
        self.final_outputs = tf.reshape(tf.nn.softmax(self.logits), 
                                        (seq_shape[0], seq_shape[1], 
                                         dimension))

In [6]:
tf.reset_default_graph()
sess = tf.InteractiveSession()
model = Model(num_layers, size_layer, len(text_vocab), sequence_length, learning_rate)
sess.run(tf.global_variables_initializer())


WARNING:tensorflow:<tensorflow.python.ops.rnn_cell_impl.LSTMCell object at 0x7fa3fc140ef0>: Using a concatenated state is slower and will soon be deprecated.  Use state_is_tuple=True.
WARNING:tensorflow:<tensorflow.python.ops.rnn_cell_impl.LSTMCell object at 0x7fa3fc1407f0>: Using a concatenated state is slower and will soon be deprecated.  Use state_is_tuple=True.

In [7]:
split_text = text.split()
tag = split_text[np.random.randint(0, len(split_text))]
print(tag)


fisher

In [8]:
def train_random_batch():
    LOST, ACCURACY = [], []
    for i in range(epoch):
        last_time = time.time()
        init_value = np.zeros((batch_size, num_layers * 2 * size_layer))
        batch_x = np.zeros((batch_size, sequence_length, len(text_vocab)))
        batch_y = np.zeros((batch_size, sequence_length, len(text_vocab)))
        batch_id = random.sample(possible_batch_id, batch_size)
        for k in range(batch_size):
            batch_x[k,:,:] = embed_to_onehot(text[batch_id[k]:batch_id[k]+sequence_length],text_vocab)
            batch_y[k,:,:] = embed_to_onehot(text[batch_id[k]+1:batch_id[k]+sequence_length+1],text_vocab)
        last_state, _, loss = sess.run([model.last_state, model.optimizer, model.cost], 
                                       feed_dict = {model.X: batch_x, 
                                                    model.Y: batch_y,
                                                    model.hidden_layer: init_value})
        accuracy = sess.run(model.accuracy, feed_dict = {model.X: batch_x, 
                                                         model.Y: batch_y, 
                                                         model.hidden_layer: init_value})
        ACCURACY.append(accuracy); LOST.append(loss)
        init_value = last_state
        if (i + 1) % 100 == 0:
            print('epoch:',i+1, ', accuracy:', accuracy, ', loss:', loss, ', s/epoch:', time.time()-last_time)
    return LOST, ACCURACY

In [9]:
def train_random_sequence():
    LOST, ACCURACY = [], []
    for i in range(epoch):
        last_time = time.time()
        init_value = np.zeros((batch_size, num_layers * 2 * size_layer))
        batch_x = np.zeros((batch_size, sequence_length, len(text_vocab)))
        batch_y = np.zeros((batch_size, sequence_length, len(text_vocab)))
        batch_id = random.sample(possible_batch_id, batch_size)
        for n in range(sequence_length):
            id1 = [k + n for k in batch_id]
            id2 = [k + n + 1 for k in batch_id]
            batch_x[:,n,:] = onehot[id1, :]
            batch_y[:,n,:] = onehot[id2, :]
        last_state, _, loss = sess.run([model.last_state, model.optimizer, model.cost], 
                                       feed_dict = {model.X: batch_x, 
                                                    model.Y: batch_y,
                                                    model.hidden_layer: init_value})
        accuracy = sess.run(model.accuracy, feed_dict = {model.X: batch_x, 
                                                         model.Y: batch_y, 
                                                         model.hidden_layer: init_value})
        ACCURACY.append(accuracy); LOST.append(loss)
        init_value = last_state
        if (i + 1) % 100 == 0:
            print('epoch:',i+1, ', accuracy:', accuracy, ', loss:', loss, ', s/epoch:', time.time()-last_time)
    return LOST, ACCURACY

In [10]:
def generate_based_length(length_sentence, argmax=False):
    sentence_generated = tag
    init_value = np.zeros((1, num_layers * 2 * size_layer))
    initial_tags=embed_to_onehot(tag,text_vocab)
    batch_x = np.zeros((1, initial_tags.shape[0], len(text_vocab)))
    batch_x[0,:,:] = initial_tags
    last_state, prob=sess.run([model.last_state, model.final_outputs], 
                              feed_dict = {model.X: batch_x, 
                                           model.hidden_layer: init_value})
    init_value = last_state
    for i in range(length_sentence):
        if argmax:
            char = np.argmax(prob[0,-1,:])
        else:
            char = np.random.choice(range(len(text_vocab)), p = prob[0,-1,:])
        sentence_generated += text_vocab[char]
        if len(sentence_generated) < sequence_length:
            onehot = embed_to_onehot(sentence_generated[i+1:], text_vocab)
            batch_x = np.zeros((1, onehot.shape[0], len(text_vocab)))
            batch_x[0,:,:] = onehot
        else:
            onehot = embed_to_onehot(sentence_generated[-sequence_length:], text_vocab)
            batch_x = np.zeros((1, sequence_length, len(text_vocab)))
            batch_x[0,:,:] = onehot
        last_state, prob=sess.run([model.last_state, model.final_outputs], 
                                  feed_dict = {model.X: batch_x, 
                                               model.hidden_layer: init_value})
        init_value = last_state
    return sentence_generated

In [11]:
def generate_based_sequence(length_sentence, argmax=False):
    sentence_generated = tag
    onehot = embed_to_onehot(tag, text_vocab)
    init_value = np.zeros((batch_size, num_layers * 2 * size_layer))
    for i in range(len(tag)):
        batch_x = np.zeros((batch_size, 1, len(text_vocab)))
        batch_x[:, 0, :] = onehot[i, :]
        last_state, prob = sess.run([model.last_state, model.final_outputs], feed_dict = {model.X: batch_x, model.hidden_layer: init_value})
        init_value = last_state
        
    for i in range(length_sentence):
        if argmax:
            char = np.argmax(prob[0][0])
        else:
            char = np.random.choice(range(len(text_vocab)), p = prob[0][0])
        char = np.random.choice(range(len(text_vocab)), p = prob[0][0])
        element = text_vocab[char]
        sentence_generated += element
        onehot = embed_to_onehot(element, text_vocab)
        batch_x = np.zeros((batch_size, 1, len(text_vocab)))
        batch_x[:, 0, :] = onehot[0, :]
        last_state, prob = sess.run([model.last_state, model.final_outputs], feed_dict = {model.X: batch_x, model.hidden_layer: init_value})
        init_value = last_state
    
    return sentence_generated

In [12]:
LOST, ACCURACY = train_random_sequence()


epoch: 100 , accuracy: 0.0322266 , loss: 41.8017 , s/epoch: 0.5465905666351318
epoch: 200 , accuracy: 0.0648193 , loss: 10.2083 , s/epoch: 0.5494217872619629
epoch: 300 , accuracy: 0.0969238 , loss: 3.49561 , s/epoch: 0.5476682186126709
epoch: 400 , accuracy: 0.0955811 , loss: 3.34558 , s/epoch: 0.5471758842468262
epoch: 500 , accuracy: 0.165771 , loss: 3.38921 , s/epoch: 0.5506572723388672
epoch: 600 , accuracy: 0.0933838 , loss: 3.44816 , s/epoch: 0.5516619682312012
epoch: 700 , accuracy: 0.169312 , loss: 3.3581 , s/epoch: 0.5481834411621094
epoch: 800 , accuracy: 0.353882 , loss: 2.14967 , s/epoch: 0.553795576095581
epoch: 900 , accuracy: 0.532593 , loss: 1.67657 , s/epoch: 0.5421340465545654
epoch: 1000 , accuracy: 0.589355 , loss: 1.52215 , s/epoch: 0.5455362796783447
epoch: 1100 , accuracy: 0.630615 , loss: 1.38969 , s/epoch: 0.5467808246612549
epoch: 1200 , accuracy: 0.656494 , loss: 1.35013 , s/epoch: 0.5456545352935791
epoch: 1300 , accuracy: 0.694336 , loss: 1.26314 , s/epoch: 0.5483503341674805
epoch: 1400 , accuracy: 0.705933 , loss: 1.23529 , s/epoch: 0.5480208396911621
epoch: 1500 , accuracy: 0.727905 , loss: 1.19278 , s/epoch: 0.5463554859161377
epoch: 1600 , accuracy: 0.725464 , loss: 1.20549 , s/epoch: 0.5453212261199951
epoch: 1700 , accuracy: 0.75415 , loss: 1.13645 , s/epoch: 0.5501730442047119
epoch: 1800 , accuracy: 0.759277 , loss: 1.13091 , s/epoch: 0.5479681491851807
epoch: 1900 , accuracy: 0.763306 , loss: 1.1342 , s/epoch: 0.5484757423400879
epoch: 2000 , accuracy: 0.788086 , loss: 1.06481 , s/epoch: 0.5479118824005127
epoch: 2100 , accuracy: 0.808716 , loss: 1.04259 , s/epoch: 0.5486807823181152
epoch: 2200 , accuracy: 0.798218 , loss: 1.04263 , s/epoch: 0.5441150665283203
epoch: 2300 , accuracy: 0.796509 , loss: 1.06102 , s/epoch: 0.5462024211883545
epoch: 2400 , accuracy: 0.81189 , loss: 1.01275 , s/epoch: 0.5469760894775391
epoch: 2500 , accuracy: 0.827515 , loss: 0.989201 , s/epoch: 0.5579116344451904
epoch: 2600 , accuracy: 0.832886 , loss: 0.98582 , s/epoch: 0.5478026866912842
epoch: 2700 , accuracy: 0.837524 , loss: 0.946344 , s/epoch: 0.5458438396453857
epoch: 2800 , accuracy: 0.835693 , loss: 0.967556 , s/epoch: 0.555034875869751
epoch: 2900 , accuracy: 0.852051 , loss: 0.924789 , s/epoch: 0.5529537200927734
epoch: 3000 , accuracy: 0.863892 , loss: 0.902093 , s/epoch: 0.2738816738128662

In [13]:
plt.figure(figsize = (15, 5))
plt.subplot(1, 2, 1)
EPOCH = np.arange(len(LOST))
plt.plot(EPOCH, LOST)
plt.xlabel('epoch'); plt.ylabel('loss')
plt.subplot(1, 2, 2)
plt.plot(EPOCH, ACCURACY)
plt.xlabel('epoch'); plt.ylabel('accuracy')
plt.show()



In [14]:
print(generate_based_sequence(1000,True))


fisher divories hung
Aloud his last entire.

QUEEN:
'Twill be you call name, my lord; that thou wilt fled,
Yet, Derby, no incinting me, his Clarence,
Some fine's meturn and make him szoon: but it contented
The stewarding while he perfles, the benefit
Worse vaws may; not he did make the people,
For yet more war to make his wife and a ren
Jest true and wail their gill and seconding foot.
My liege, I'll build a lane to Friar Laurence;
But for my business in their true souls, thou art not noble;
For now is he wounded to support me!
O, he is wonted in the viewly parden
Whereon that shall be now. To be kilf miscarry.

ABHORSON:
Go remember these lands are named, she hath
left Warwick that there, that way thou art a tall fellow of your sin
Myself and no man had chance the seat of his
mad aged hath been current.

TRANIO:
Mistake her so much to us.

CORIOLANUS:
Yield to your kindness promised in his
with duty strewd off from me and his son thire
Under the grain or fozer to be bring forth,
Beg not thy

In [ ]: