利用RNN做文章生成

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 28 16:40:04 2018

@author: yanghe
"""
import tensorflow as tf
import numpy as np
import io

text = io.open('shakespeare.txt', encoding='utf-8').read().lower()

chars = sorted(list(set(text)))
learning_rate = 0.01
training_steps = 30
batch_size = 64
display_step = 10
n_steps = 38
n_input = 38
n_hidden = 256
n_classes = 38
# 构建数据集 
#  X:[len(text)-n_steps,n_steps]
#
def build_data(text, n_steps = 40, stride = 3):
    X = []
    Y = []
    for i in range(0, len(text) - n_steps, stride):
        X.append(text[i: i + n_steps])
        Y.append(text[i + n_steps])
    print('number of training examples:', len(X))
    
    return X, Y


def vectorization(X, Y, n_input, char_indices, n_steps = n_steps):
    m = len(X)
    x = np.zeros((m, n_steps, n_input), dtype=np.bool)
    y = np.zeros((m, n_input), dtype=np.bool)
    for i, sentence in enumerate(X):
        for t, char in enumerate(sentence):
            x[i, t, char_indices[char]] = 1
        y[i, char_indices[Y[i]]] = 1
        
    return x, y 
    
    
def sample(preds, temperature=1.0):
    e_x = np.exp(preds - np.max(preds))
    preds = e_x / e_x.sum(axis=1)
    out = np.random.choice(range(len(chars)), p = preds.ravel())
    return out
    

    
def random_mini_batches(x,y,mini_bath_size =64,seed =0):
    np.random.seed(seed)
    m = x.shape[0]
    mini_batches = []
    permutation = list(np.random.permutation(m))
    shuffled_x = x[permutation]
    shuffled_y = y[permutation]
    
    num_complete_minibatches = int(np.floor(m/mini_bath_size))
    for k in range(0,num_complete_minibatches):
        mini_batch_x = shuffled_x[k*mini_bath_size:(k+1)*mini_bath_size,:,:]
        mini_batch_y = shuffled_y[k*mini_bath_size:(k+1)*mini_bath_size,]
        mini_batch = (mini_batch_x,mini_batch_y)
        mini_batches.append(mini_batch)
    if m % mini_bath_size  != 0:
        mini_batch_x = shuffled_x[(k+1)*mini_bath_size:,:,:]
        mini_batch_y = shuffled_y[(k+1)*mini_bath_size:,:]      
        mini_batch = (mini_batch_x,mini_batch_y)
        mini_batches.append(mini_batch)
    return mini_batches

def BiRNN(x):
    with tf.variable_scope('Bi_RNN'):
        weights = tf.get_variable('weights', shape=[2*n_hidden, n_classes], initializer=tf.truncated_normal_initializer(stddev=0.1))
        biases = tf.get_variable('biases', shape=[n_classes], initializer=tf.truncated_normal_initializer(stddev=0.1))
        x = tf.transpose(x, [1, 0, 2])
        x = tf.reshape(x, [-1, n_steps])
        x = tf.split(x, n_steps)
        lstm_fw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)
        lstm_bw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)
        outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(lstm_fw_cell,
                                                                lstm_bw_cell,
                                                                x,
                                                                dtype=tf.float32)
        
    return tf.matmul(outputs[-1], weights) + biases

def train():
    y_ = BiRNN(x)
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y_, labels=y))
    train_op = tf.train.AdamOptimizer(learning_rate).minimize(cost)
    correct_pred = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    saver = tf.train.Saver()
    with tf.Session() as sess :
        tf.global_variables_initializer().run()
        mini_batches = random_mini_batches(X_, Y_, mini_bath_size=batch_size) 
        for i in range(training_steps):
            for x_train,y_train in mini_batches:
                _ = sess.run(train_op, feed_dict={x:x_train , y:y_train })
            if i % 5 == 0 :
                j = np.random.randint(len(mini_batches[0]))
                validate_acc = sess.run([accuracy], feed_dict={x:mini_batches[j][0] , y:mini_batches[j][1]})
                print("After %d , validation accuracy is %s " % (i,  validate_acc))
        test_acc=sess.run(accuracy,feed_dict={x:mini_batches[-1][0] , y:mini_batches[-1][1]})
        print(("After %d training step(s), test accuracy using average model is %.2f" %(training_steps, test_acc)))    
        saver.save(sess , 'saver/moedl1.ckpt')
    
def generate_output():
    #with tf.variable_scope('Bi_RNN') as scope:
    #scope.reuse_variables()
    y_ = BiRNN(x)
    saver = tf.train.Saver()
    with tf.Session() as sess:
        saver.restore(sess,'saver/moedl1.ckpt')
        generated = ''
        usr_input = input("Write the beginning of your poem, the Shakespeare machine will complete it. Your input is: ")
        sentence = ('{0:0>' + str(n_steps) + '}').format(usr_input).lower()
        generated += usr_input 
        for i in range(400):
            x_pred = np.zeros((1, n_steps, len(chars)))
    
            for t, char in enumerate(sentence):
                if char != '0':
                    x_pred[0, t, char_indices[char]] = 1.
            preds = sess.run(y_ ,feed_dict={x:x_pred})
    
            
            next_index = sample(preds, temperature = 1.0)
            next_char = indices_char[next_index]
            generated += next_char
            sentence = sentence[1:] + next_char
            if next_char == '\n':
                continue
        print(generated)
        
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
X, Y = build_data(text, n_steps, stride = 3)
X_, Y_ = vectorization(X, Y, n_input = len(chars), char_indices = char_indices) 

x = tf.placeholder(tf.float32, [None, n_steps,n_input])
y = tf.placeholder(tf.float32, [None, n_classes])

#train()
generate_output()

你可能感兴趣的:(利用RNN做文章生成)