RNN in tensorflow


In [1]:
import tensorflow as tf
import numpy as np
import random

In [2]:
# import text and extract chars
text = open('fdp.txt', 'r').read()
unique_chars = list(set(text))
text_size, vocab_size = len(text), len(unique_chars)
print('data has %d characters, %d unique.' % (text_size, vocab_size))
char_to_ix = {ch:i for i,ch in enumerate(unique_chars)}
ix_to_char = {i:ch for i,ch in enumerate(unique_chars)}


data has 12175 characters, 72 unique.

In [3]:
# Hyperparameters of RNN
hidden_size = 100
seq_length = 25

In [4]:
def one_hot(v):
    '''
    Convert character labels to one-hot variants
    :param v - index in char_to_index of character to convert
    :returns - 0-Vector with 1 at index v
    '''
    return np.eye(vocab_size)[v]

In [5]:
# defining the network
# start with parameters
x = tf.placeholder(tf.float32, [None, vocab_size]) # 25x76 = seq_length x vocab_size
y_in = tf.placeholder(tf.float32, [None, vocab_size]) # 25x76 = seq_length x vocab_size
h_start = tf.placeholder(tf.float32, [1, hidden_size]) # 1x100

In [6]:
# define architecture
initializer = tf.random_normal_initializer(stddev=0.1)
with tf.variable_scope("RNN") as scope:
    h_state = h_start # initialize hidden state
    y_out_all = [] # collect each of y values choosen by network
    # split input of seq_length into single inputs x_in with t as timestep
    for t, x_in in enumerate(tf.split(x, seq_length,0)):
        if t > 0: 
            # reuse same variables within one iteration of training (one seq_length)
            scope.reuse_variables()
        Wxh = tf.get_variable('Wxh', [vocab_size, hidden_size], initializer=initializer)
        Whh = tf.get_variable('Whh', [hidden_size, hidden_size], initializer=initializer)
        Why = tf.get_variable('Why', [hidden_size, vocab_size], initializer=initializer)
        bh = tf.get_variable('bh', [hidden_size], initializer=initializer)
        by = tf.get_variable('by', [vocab_size], initializer=initializer)
        
        # forward-pass through first hidden layer
        h_state = tf.tanh(tf.matmul(x_in, Wxh) + tf.matmul(h_state, Whh) + bh)
        # forward-pass through output layer
        y_out = tf.matmul(h_state, Why) + by
        y_out_all.append(y_out)

In [9]:
# store last hidden state and calculate loss of all predicted y_out_all
h_last = h_state
output_softmax = tf.nn.softmax(y_out_all[-1])  # only for sampling
outputs = tf.concat(y_out_all, 0)
loss = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(logits=outputs, labels=y_in))

In [11]:
# minimize loss by using backprop and sgd through adam optimizer
minimizer = tf.train.AdamOptimizer()
grads_and_vars = minimizer.compute_gradients(loss)

# prevent gradient vanishing and explosion
grad_clipping = tf.constant(5.0, name='grad_clipping')
clipped_grads_and_vars = []
for grad, var in grads_and_vars:
    clipped_grad = tf.clip_by_value(grad, -grad_clipping, grad_clipping)
    clipped_grads_and_vars.append((clipped_grad, var))
    
updates = minimizer.apply_gradients(clipped_grads_and_vars)

In [13]:
# sampling from the network to see progress (in textual form)
def sample_network():
    sample_length = 200
    start_ix = random.randint(0, len(text) - seq_length)
    sample_seq_ix = [char_to_ix[ch] for ch in text[start_ix:start_ix + seq_length]]
    ixes = []
    sample_prev_state_val = np.copy(h_start_val)
    
    for t in range(sample_length):
        sample_input_vals = one_hot(sample_seq_ix)
        sample_output_softmax_val, sample_prev_state_val = sess.run([output_softmax, h_last], feed_dict={x: sample_input_vals, h_start: sample_prev_state_val})
        ix = np.random.choice(range(vocab_size), p=sample_output_softmax_val.ravel())
        ixes.append(ix)
        sample_seq_ix = sample_seq_ix[1:] + [ix]
    
    txt = ''.join(ix_to_char[ix] for ix in ixes)
    print('-----\n %s \n ----\n' % txt)

In [14]:
# run tensorflow session
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

In [17]:
# set starting position in text and number of iterations
position_in_text = 0
number_of_iterations = 0
total_iterations = 10000
h_start_val = np.zeros([1,hidden_size])

In [18]:
# loop for going through document and see if end was reached if not train again
while number_of_iterations < total_iterations:
    if position_in_text + seq_length + 1 >= len(
            text) or number_of_iterations == 0:
        # reset value of hidden state
        h_start_val = np.zeros([1, hidden_size])
        position_in_text = 0

    inputs = one_hot([
        char_to_ix[ch]
        for ch in text[position_in_text:position_in_text + seq_length]
    ])
    targets = one_hot([
        char_to_ix[ch]
        for ch in text[position_in_text + 1:position_in_text + seq_length + 1]
    ])
    h_start_val, loss_val, _ = sess.run([h_last, loss, updates], feed_dict={x:inputs, y_in:targets, h_start:h_start_val})
    
    # sample every 500 iterations
    if number_of_iterations % 500 == 0:
        print('iter: %d, p: %d, loss: %f' %(number_of_iterations, position_in_text, loss_val))
        sample_network()
        
    position_in_text += seq_length
    number_of_iterations += 1


iter: 0, p: 0, loss: 3.195930
-----
 htdn  oinen Uin äescheen.
dun  Eübendr.
Dmlegesa dsn sinn schlde 1ichiendn kZschldgen siit Sn.
Znd ch-npil ian ernlgengen uans Denden venseie benden.
Suwichtchuus en:tNmet EiölEnzBhndsnes daentenHwhnu 
 ----

iter: 500, p: 350, loss: 2.026916
-----
 t men LaGüe Zaso hin nit dir “ugüfte-enft.
Mir ge dit Gengen tibeiln fer gze  füe gen un ku sin Vorlen mnde Erropl sallen Mabeao san an kiulen Alfe foolenn In eln dan di.
Dasoen sobwie Heut, ie  eund  
 ----

iter: 1000, p: 700, loss: 1.772866
-----
 lbden.
Zndern
olineln tändegein: Unierserfen.ichen ehSch ben ich mid eunderefennecht schumeder er:-Fue .unsenznbehten Alder soaden hatchenichtelng den sbeldermelann senebtn Zinden.
Uäder undernelt aäw 
 ----

iter: 1500, p: 1050, loss: 1.934769
-----
 u1ndern.
Lis kapn.
EUNO9NIS5HzO Firlgen Lah eltebthen schen Soe Lneserenn deremzhlren solaus worten Sichändase nerNes ein Shumgt AU vom Foren.
0Men BlTsch fen.
Int dnischenPm?er komnen
Westger edar  
 ----

iter: 2000, p: 1400, loss: 2.081880
-----
 e gaschee Bies.
Wie Soust hezn mit er 4an.
Dien solrschen kommen.
DeensR Intscham din flen, tinze für INgz Eereen le
schwelbem sehren mehrer.
Dad ure sicht den gane öinechern gedeicho find eicht der g 
 ----

iter: 2500, p: 1750, loss: 1.293652
-----
 n bendah me reuts sie nenhn, des kinhe Pelatas gert dam en
eln-Scheler ender nechenn.
Sier gekoIn.
Dade mache Fleichestet: Sie Unio Deschreffn sir vo mutschpien zuf chalen worben.
Dabem mefer worben h 
 ----

iter: 3000, p: 2100, loss: 1.236113
-----
 otpute sich uhbeisgeitäes
in zist mutr Cönderhre Schulen seie Sokwind en ause kenro dieglern daeunichenn de-Richälschen.
Deen schzr öom en anzumgem
eisArmet nich buld en gien.
Daut gasdie Pueltelncchw 
 ----

iter: 3500, p: 2450, loss: 1.187340
-----
 ein zband Für lal mür iherben sal habdernn hren Gelang GelzuL jeder kongrneg d?e dei
Lini beinn Srund-Nacher-Cowln id Eunoplie? Vorlenn kann.
Wie Schüler gllonn nin tin gnender
So konnden Schulen.
Wir 
 ----

iter: 4000, p: 2800, loss: 0.844030
-----
 n viest.
Cie Schwlen warlen eusongehre Zuft Lä dar rich nisieder belten Kindernichoraust sie die Schulei tie Polldnfundssollen
yinm In Schulen.
Schulen sing dif deschtirtaschundwerte besschän iit bis  
 ----

iter: 4500, p: 3150, loss: 1.438160
-----
 köinen schün aunrter in? Daun kanfen
schufd.-Schultistischen Schwternen Unden ein sin siwer einied eitmmer jutkchelmehr wern.
Wir wollen.
Dast andererten min erbertufürei-rungeln Schumes acheiköinet.
 
 ----

iter: 5000, p: 3500, loss: 2.157581
-----
 en ust jeder für eis teuen.
Danne san din schun tiche Int.
gUna Lind aun chle nisle können.
Wih ienter Länderselen wie Feine getz Eurom ein dann.
MUHE FIMOG
WENROENI No LoUnjedes Dint died ues die f 
 ----

iter: 5500, p: 3850, loss: 0.989205
-----
 t.
In verum beiche fen.tIn Schulenim
ter ben.
Data ist gut faben eiter icht an anderten.
In Udaen meichteunk Arerenes Wis Gesn.
„Schurerde-Irt.
Wie wornen uer.
Und zwersten.
kamm hernehre.
Jan aute se 
 ----

iter: 6000, p: 4200, loss: 0.952860
-----
 dch idan sis Gesein Schuld.
Und zute Menncht Und ne sit onnen.
Dan machen iert Verasien.
In einen kumm.
Dauso kundebticht mist. Wal nicht.
Darun.chen Swoschne 
ehrmm-t.
Darur ternest.
Id Möng beint.
W 
 ----

iter: 6500, p: 4550, loss: 2.662700
-----
 den vorerenn briebRet ant dar vorkenberanz
ERZoplerofen.
Zau d.
Zicheint für gas Kind für
Minzl worlten sone nicht man singen.
In HInso ders gender
terseiten.
Ster, die kongen.
Darus 2mpamer ietern mu 
 ----

iter: 7000, p: 4900, loss: 1.221902
-----
 illeg fürfebeiter beisurgem
Virlan-inemen Es einen Länderarfön.
Daune Ambedarzu guch Gendan.
Wie finden:
Dasin:
Man siet eun her Gelo auts iemein mis sokomar ioaben Kindes: Men asts-heter wolle ver Eu 
 ----

iter: 7500, p: 5250, loss: 0.956903
-----
 len.
EUNEOAANLEGNTwBe MNGUNzELAUNG schäfo dien an sinder: dass-mehren.
DaschtÄmt, daes der Geldizeis
Mendanf
muhr ust den könninderen Stalles Geld.
VUrd.
USdaz So die Wis, de
sollet kunben: Int sie  
 ----

iter: 8000, p: 5600, loss: 0.553020
-----
 
Wir wellehre Mehrang beg un den in jedeus müchtwer find zues Infez eismen haben, wis tur Benolter finken metrum
Bsospäelltmummen dausoliet geschein hellosmen: Elgen.
Dauch winder gets-Nliein Sokaute  
 ----

iter: 8500, p: 5950, loss: 0.977351
-----
 neicht Monot.
Ibmes hneun best heter für
eim gein.
Was: voflu dan kümmen, die aus eimennwoltechwer uer Gele hat.
Daum
wercht die Mehstiese Verwoples zum dee Mitden, das achun konders ahs Geseihmter ie 
 ----

iter: 9000, p: 6300, loss: 1.507409
-----
 en, das aus is en wilden?
Dibe Dssollen dism eit asg.
AUS EuLeN.
Dle dan Kisden amfen,
wachune Intein eo iere defürt.
EURBERISBGHZapz Willein.
VEHPjIVERIPBEIOERN BEREHPUNI2HA Verwursez
wer dar füf  
 ----

iter: 9500, p: 6650, loss: 1.248812
-----
 d sie Rechten.
Es köml-Re Kieder aus eune Verantur fürer-Gele het-Rie Arbeinsitwer ume daon die Firten
ster Berund est nichtein wolimin mahwer wicht in deu ichti-Ze.
Die Aobeitsles
GemaCienn man wer I 
 ----


In [ ]: