<s> """<STR_LIT>""" <EOL> import argparse <EOL> import codecs <EOL> import collections <EOL> import random <EOL> import re <EOL> import time <EOL> import numpy as np <EOL> import chainer <EOL> from chainer import cuda <EOL> import chainer . functions as F <EOL> import chainer . links as L <EOL> from chainer import optimizers <EOL> parser = argparse . ArgumentParser ( ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , default = - <NUM_LIT:1> , type = int , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , default = <NUM_LIT> , type = int , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , default = <NUM_LIT:30> , type = int , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , type = int , default = <NUM_LIT> , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , type = int , default = <NUM_LIT:5> , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , '<STR_LIT>' , type = int , default = <NUM_LIT:5> , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , dest = '<STR_LIT:test>' , action = '<STR_LIT:store_true>' ) <EOL> parser . set_defaults ( test = False ) <EOL> args = parser . parse_args ( ) <EOL> if args . gpu >= <NUM_LIT:0> : <EOL> cuda . check_cuda_available ( ) <EOL> xp = cuda . cupy if args . gpu >= <NUM_LIT:0> else np <EOL> n_epoch = args . epoch <EOL> n_units = args . unit <EOL> batchsize = args . batchsize <EOL> n_label = args . label <EOL> epoch_per_eval = args . epocheval <EOL> class SexpParser ( object ) : <EOL> def __init__ ( self , line ) : <EOL> self . tokens = re . findall ( r'<STR_LIT>' , line ) <EOL> self . pos = <NUM_LIT:0> <EOL> def parse ( self ) : <EOL> assert self . pos < len ( self . tokens ) <EOL> token = self . tokens [ self . pos ] <EOL> assert token != '<STR_LIT:)>' <EOL> self . pos += <NUM_LIT:1> <EOL> if token == '<STR_LIT:(>' : <EOL> children = [ ] <EOL> while True : <EOL> assert self . pos < len ( self . tokens ) <EOL> if self . tokens [ self . pos ] == '<STR_LIT:)>' : <EOL> self . pos += <NUM_LIT:1> <EOL> break <EOL> else : <EOL> children . append ( self . parse ( ) ) <EOL> return children <EOL> else : <EOL> return token <EOL> def convert_tree ( vocab , exp ) : <EOL> assert isinstance ( exp , list ) and ( len ( exp ) == <NUM_LIT:2> or len ( exp ) == <NUM_LIT:3> ) <EOL> if len ( exp ) == <NUM_LIT:2> : <EOL> label , leaf = exp <EOL> if leaf not in vocab : <EOL> vocab [ leaf ] = len ( vocab ) <EOL> return { '<STR_LIT:label>' : int ( label ) , '<STR_LIT>' : vocab [ leaf ] } <EOL> elif len ( exp ) == <NUM_LIT:3> : <EOL> label , left , right = exp <EOL> node = ( convert_tree ( vocab , left ) , convert_tree ( vocab , right ) ) <EOL> return { '<STR_LIT:label>' : int ( label ) , '<STR_LIT>' : node } <EOL> def read_corpus ( path , vocab , max_size ) : <EOL> with codecs . open ( path , encoding = '<STR_LIT:utf-8>' ) as f : <EOL> trees = [ ] <EOL> for line in f : <EOL> line = line . strip ( ) <EOL> tree = SexpParser ( line ) . parse ( ) <EOL> trees . append ( convert_tree ( vocab , tree ) ) <EOL> if max_size and len ( trees ) >= max_size : <EOL> break <EOL> return trees <EOL> class RecursiveNet ( chainer . Chain ) : <EOL> def __init__ ( self , n_vocab , n_units ) : <EOL> super ( RecursiveNet , self ) . __init__ ( <EOL> embed = L . EmbedID ( n_vocab , n_units ) , <EOL> l = L . Linear ( n_units * <NUM_LIT:2> , n_units ) , <EOL> w = L . Linear ( n_units , n_label ) ) <EOL> def leaf ( self , x ) : <EOL> return self . embed ( x ) <EOL> def node ( self , left , right ) : <EOL> return F . tanh ( self . l ( F . concat ( ( left , right ) ) ) ) <EOL> def label ( self , v ) : <EOL> return self . w ( v ) <EOL> def traverse ( model , node , train = True , evaluate = None , root = True ) : <EOL> if isinstance ( node [ '<STR_LIT>' ] , int ) : <EOL> word = xp . array ( [ node [ '<STR_LIT>' ] ] , np . int32 ) <EOL> loss = <NUM_LIT:0> <EOL> x = chainer . Variable ( word , volatile = not train ) <EOL> v = model . leaf ( x ) <EOL> else : <EOL> left_node , right_node = node [ '<STR_LIT>' ] <EOL> left_loss , left = traverse ( <EOL> model , left_node , train = train , evaluate = evaluate , root = False ) <EOL> right_loss , right = traverse ( <EOL> model , right_node , train = train , evaluate = evaluate , root = False ) <EOL> v = model . node ( left , right ) <EOL> loss = left_loss + right_loss <EOL> y = model . label ( v ) <EOL> if train : <EOL> label = xp . array ( [ node [ '<STR_LIT:label>' ] ] , np . int32 ) <EOL> t = chainer . Variable ( label , volatile = not train ) <EOL> loss += F . softmax_cross_entropy ( y , t ) <EOL> if evaluate is not None : <EOL> predict = cuda . to_cpu ( y . data . argmax ( <NUM_LIT:1> ) ) <EOL> if predict [ <NUM_LIT:0> ] == node [ '<STR_LIT:label>' ] : <EOL> evaluate [ '<STR_LIT>' ] += <NUM_LIT:1> <EOL> evaluate [ '<STR_LIT>' ] += <NUM_LIT:1> <EOL> if root : <EOL> if predict [ <NUM_LIT:0> ] == node [ '<STR_LIT:label>' ] : <EOL> evaluate [ '<STR_LIT>' ] += <NUM_LIT:1> <EOL> evaluate [ '<STR_LIT>' ] += <NUM_LIT:1> <EOL> return loss , v <EOL> def evaluate ( model , test_trees ) : <EOL> m = model . copy ( ) <EOL> m . volatile = True <EOL> result = collections . defaultdict ( lambda : <NUM_LIT:0> ) <EOL> for tree in test_trees : <EOL> traverse ( m , tree , train = False , evaluate = result ) <EOL> acc_node = <NUM_LIT> * result [ '<STR_LIT>' ] / result [ '<STR_LIT>' ] <EOL> acc_root = <NUM_LIT> * result [ '<STR_LIT>' ] / result [ '<STR_LIT>' ] <EOL> print ( '<STR_LIT>' . format ( <EOL> acc_node , result [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] ) ) <EOL> print ( '<STR_LIT>' . format ( <EOL> acc_root , result [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] ) ) <EOL> vocab = { } <EOL> if args . test : <EOL> max_size = <NUM_LIT:10> <EOL> else : <EOL> max_size = None <EOL> train_trees = read_corpus ( '<STR_LIT>' , vocab , max_size ) <EOL> test_trees = read_corpus ( '<STR_LIT>' , vocab , max_size ) <EOL> develop_trees = read_corpus ( '<STR_LIT>' , vocab , max_size ) <EOL> model = RecursiveNet ( len ( vocab ) , n_units ) <EOL> if args . gpu >= <NUM_LIT:0> : <EOL> model . to_gpu ( ) <EOL> optimizer = optimizers . AdaGrad ( lr = <NUM_LIT:0.1> ) <EOL> optimizer . setup ( model ) <EOL> optimizer . add_hook ( chainer . optimizer . WeightDecay ( <NUM_LIT> ) ) <EOL> accum_loss = <NUM_LIT:0> <EOL> count = <NUM_LIT:0> <EOL> start_at = time . time ( ) <EOL> cur_at = start_at <EOL> for epoch in range ( n_epoch ) : <EOL> print ( '<STR_LIT>' . format ( epoch ) ) <EOL> total_loss = <NUM_LIT:0> <EOL> cur_at = time . time ( ) <EOL> random . shuffle ( train_trees ) <EOL> for tree in train_trees : <EOL> loss , v = traverse ( model , tree , train = True ) <EOL> accum_loss += loss <EOL> count += <NUM_LIT:1> <EOL> if count >= batchsize : <EOL> model . zerograds ( ) <EOL> accum_loss . backward ( ) <EOL> optimizer . update ( ) <EOL> total_loss += float ( accum_loss . data ) <EOL> accum_loss = <NUM_LIT:0> <EOL> count = <NUM_LIT:0> <EOL> print ( '<STR_LIT>' . format ( total_loss ) ) <EOL> now = time . time ( ) <EOL> throuput = float ( len ( train_trees ) ) / ( now - cur_at ) <EOL> print ( '<STR_LIT>' . format ( throuput , now - cur_at ) ) <EOL> print ( ) <EOL> if ( epoch + <NUM_LIT:1> ) % epoch_per_eval == <NUM_LIT:0> : <EOL> print ( '<STR_LIT>' ) <EOL> evaluate ( model , train_trees ) <EOL> print ( '<STR_LIT>' ) <EOL> evaluate ( model , develop_trees ) <EOL> print ( '<STR_LIT>' ) <EOL> print ( '<STR_LIT>' ) <EOL> evaluate ( model , test_trees ) </s>
