<jupyter_start><jupyter_text>INFERENCE<jupyter_code>%tensorflow_version 1.x
%cd /content/calling-out-bluff/Model5-MemoryNets/
import tensorflow as tf
import pickle
import numpy as np
from IPython.display import display, HTML
# from xhtml2pdf import pisa
import gc
fold_no = 1
step = 8190
essay_set_id = 3
ATTRS_DIR = '/content/drive/My Drive/IG RESULTS/MEMORY NET/P'+str(essay_set_id)+'/'
ATTRS_TSV = '/content/drive/My Drive/IG RESULTS/MEMORY NET/P'+str(essay_set_id)+'/attrs.tsv'

def convert_html_to_pdf(source_html, output_filename):
  # open output file for writing (truncated binary)
  result_file = open(output_filename, "w+b")

  # convert HTML to PDF
  pisa_status = pisa.CreatePDF(
          source_html,                # the HTML to convert
          dest=result_file)           # file handle to recieve result

  # close output file
  result_file.close()                 # close output file

  # return False on success and True on errors
  return pisa_status.err   
with open('/content/drive/My Drive/IG RESULTS/MEM MODELS/'+str(essay_set_id)+'_'+str(fold_no)+'.pkl', 'rb') as f:
  (t,m,test_scores) = pickle.load(f)
  
saver = tf.train.import_meta_graph("/content/drive/My Drive/IG RESULTS/MEM MODELS/"+str(essay_set_id)+"/checkpoints_"+str(fold_no)+"-"+str(step)+".meta")  
sess=tf.Session()
saver.restore(sess,"/content/drive/My Drive/IG RESULTS/MEM MODELS/"+str(essay_set_id)+"/checkpoints_"+str(fold_no)+"-"+str(step))
from tqdm import tqdm
class integrated_gradients:
  def __init__(self, graph, sess, min, tokenizer_file = 'tokenizer.pkl',batch_size = 20, num_reps = 20):
    
    self.graph = graph
    self.sess = sess
    w1 = self.graph.get_tensor_by_name("input/question:0")
    w2 = self.graph.get_tensor_by_name("input/memory_key:0")
    w3 = self.graph.get_tensor_by_name("input/keep_prob:0")
    self.batch_size = batch_size
    self.min = min
    self.INPUT_TENSORS = [w1,w2,w3]
    self.num_reps = num_reps

    with open(tokenizer_file, 'rb') as f:
      tokenizer = pickle.load(f)
    self.reverse_word_map = dict(map(reversed, tokenizer.items()))
      
    self.OUTPUT_TENSOR =  self.graph.get_tensor_by_name('prediction/Softmax:0')
    self.PRED_TENSOR =  self.graph.get_tensor_by_name('prediction/predict_op:0')
    self.EMBEDDING_TENSOR =  self.graph.get_tensor_by_name('embedding_lookup/Identity:0')
    self.outchannels = self.OUTPUT_TENSOR.shape[1]._value
    self.get_gradients = {}
    print(self.outchannels)
    for c in range(self.outchannels):
      GRADIENT_TENSOR = tf.gradients(self.OUTPUT_TENSOR[:,c], self.EMBEDDING_TENSOR)
      self.get_gradients[c] = GRADIENT_TENSOR
  
  def get_tensor(self, name):
    return self.graph.get_tensor_by_name(name)

  def generate_baseline(self, sample):
    baseline = np.zeros(sample.shape)
    return baseline

  def _get_feed_dict(self, input_df):
      feed = {}
      for i, key in enumerate(self.INPUT_TENSORS):
          feed[key.name] = [input_df[i]]
      return feed

  def _get_ig_error(self, integrated_gradients, baseline_prediction, prediction,
                  debug=False):
      sum_attributions = 0
      sum_attributions += np.sum(integrated_gradients)

      delta_prediction = prediction - baseline_prediction

      error_percentage = \
          100 * (delta_prediction - sum_attributions) / delta_prediction
      if debug:
          print(f'prediction is {prediction}')
          print(f'baseline_prediction is {baseline_prediction}')
          print(f'delta_prediction is {delta_prediction}')
          print(f'sum_attributions are {sum_attributions}')
          print(f'Error percentage is {error_percentage}')

      return error_percentage

  def _get_scaled_inputs(self, input_val, baseline_val, num_reps):
      list_scaled_embeddings = []
      scaled_embeddings = \
          [baseline_val + (float(i) / (num_reps * self.batch_size - 1)) *
          (input_val - baseline_val) for i in range(0, num_reps * self.batch_size)]

      for i in range(num_reps):
          list_scaled_embeddings.append(
              np.array(scaled_embeddings[i * self.batch_size:i * self.batch_size +
                                                        self.batch_size]))
      return np.array(list_scaled_embeddings)

  def _get_unscaled_inputs(self, input_val):
      unscaled_embeddings = [input_val] * self.batch_size

      return np.array(unscaled_embeddings)

  def _calculate_integral(self, ig):
      ig = (ig[:-1] + ig[1:]) / 2.0  # trapezoidal rule
      integral = np.average(ig, axis=0)
      return integral

  def explain(self, x, memory, max_allowed_error=5, debug=False):
      num_reps = self.num_reps
      baseline = self.generate_baseline(np.array(x))
      # baseline_memory = self.generate_baseline(np.array(memory))
      inp = [x, memory, 1]
      base = [baseline, memory, 1]
      
      pred = self.predict(inp)
      c =  pred
      # print('channel:', c)
      
      attributions, baseline_prediction, prediction = \
          self._compute_ig(inp, base, c, num_reps=num_reps) #### MAIN FUNC
      if debug:
        error_percentage = \
            self._get_ig_error(attributions, baseline_prediction, prediction,
                          debug=debug)

      igs = attributions.astype('float')
      words = self.sequence_to_text(inp[0])
      assert len(igs) == len(words)
      # html_code = self.visualize_token_attrs(words , igs)
      return igs, words
  
  def predict(self, inp):
      pred = self.sess.run(self.PRED_TENSOR,
                              self._get_feed_dict(inp))
      return pred[0]

  def _get_feed_dict_batch(self, input_df):
      feed = {}
      for i, key in enumerate(self.INPUT_TENSORS):
          feed[key.name] = input_df[i]
      return feed

  def predict_batch(self, inp):
      pred = self.sess.run(self.PRED_TENSOR,
                              self._get_feed_dict_batch(inp))
      return pred

  def visualize_token_attrs(self, tokens, attrs):
    import matplotlib as mpl
    cmap='PiYG'
    cmap_bound = np.abs(attrs).max()
    norm = mpl.colors.Normalize(vmin=-cmap_bound, vmax=cmap_bound)
    cmap = mpl.cm.get_cmap(cmap)

    html_text = ""
    for i, tok in enumerate(tokens):
        if tok is not None:
          color = mpl.colors.rgb2hex(cmap(norm(attrs[i])))
          html_text += " <mark style='background-color:{}'>{}</mark>".format(color, tok)
    return (html_text)
  
  def sequence_to_text(self, list_of_indices):
      words = [self.reverse_word_map.get(letter) for letter in list_of_indices]
      return words

  def _compute_ig(self, inp, base, c, num_reps):
      tensor_values = self.sess.run(self.EMBEDDING_TENSOR,
                              self._get_feed_dict(inp))

      tensor_baseline_values = self.sess.run(self.EMBEDDING_TENSOR,
                              self._get_feed_dict(base))
      
      # print(tensor_values.shape, tensor_baseline_values.shape)
      scaled_embeddings = self._get_scaled_inputs(tensor_values[0],
                                            tensor_baseline_values[0],
                                            num_reps)
      
      # print(scaled_embeddings) # num_reps x batch_size x emb_shape
      scaled_input_feed = {}
      
      for i, key in enumerate(self.INPUT_TENSORS):
          ui = self._get_unscaled_inputs(inp[i])
          if 'input/keep_prob:0' in key.name: ### SCALAR VALUE
            scaled_input_feed[ self.get_tensor(key.name) ] = 1.0
          else:
            scaled_input_feed[ self.get_tensor(key.name) ] = ui
      
      scores = []
      path_gradients = []
      # print(c)
      for i in range(num_reps):
          scaled_input_feed[self.EMBEDDING_TENSOR] = scaled_embeddings[i]
            
          path_gradients_rep, scores_rep = self.sess.run(
              [self.get_gradients[c], self.OUTPUT_TENSOR[:,c]], scaled_input_feed)
          
          path_gradients.append(path_gradients_rep[0])
          scores.append(scores_rep)
      
      # print(scores[0])
      baseline_prediction = scores[0][0]  # first score is the baseline prediction
      prediction = scores[-1][-1]  # last score is the input prediction

      # integrating the gradients and multiplying with the difference of the baseline and input.
      ig = np.concatenate(path_gradients, axis=0)
      integral = self._calculate_integral(ig)
      igs = (tensor_values[0] - tensor_baseline_values[0]) * integral
      igs = np.sum(igs, axis=-1)

      return igs, baseline_prediction, prediction
! cp /content/drive/My\ Drive/IG\ RESULTS/MEM\ MODELS/tokenizer.pkl ./
graph = tf.get_default_graph()
IG = integrated_gradients(graph, sess, min = 0, batch_size= 20, num_reps=40)
from google_drive_downloader import GoogleDriveDownloader as gdd
gdd.download_file_from_google_drive(file_id='1CIEpiDmzLmJ6LMCVSOmCKw_eOg4ocuS4', dest_path='/content/AES.zip', unzip=True)
import re
import os as os
import numpy as np
import itertools
import pandas as pd
from collections import Counter

def load_training_data(training_df):
    resolved_score = training_df['label_orig']
    essays = training_df['text']
    essay_list = []
    # turn an essay to a list of words
    for idx, essay in essays.iteritems():
        essay = clean_str(essay)
        essay_list.append(tokenize(essay))
    return essay_list, resolved_score.tolist()

def tokenize(sent):
    '''Return the tokens of a sentence including punctuation.
    >>> tokenize('Bob dropped the apple. Where is the apple?')
    ['Bob', 'dropped', 'the', 'apple', '.', 'Where', 'is', 'the', 'apple', '?']
    >>> tokenize('I don't know')
    ['I', 'don', '\'', 'know']
    '''
    return [x.strip() for x in re.split('(\W+)', sent) if x.strip()]

def clean_str(string):
    """
    Tokenization/string cleaning for all datasets except for SST.
    Original taken from https://github.com/yoonkim/CNN_sentence/blob/master/process_data.py
    """
    string = re.sub(r"[^A-Za-z0-9(),!?\'\`]", " ", string)
    string = re.sub(r"\'s", " \'s", string)
    string = re.sub(r"\'ve", " \'ve", string)
    string = re.sub(r"n\'t", " n\'t", string)
    string = re.sub(r"\'re", " \'re", string)
    string = re.sub(r"\'d", " \'d", string)
    string = re.sub(r"\'ll", " \'ll", string)
    string = re.sub(r",", " , ", string)
    string = re.sub(r"!", " ! ", string)
    string = re.sub(r"\(", " ( ", string)
    string = re.sub(r"\)", " ) ", string)
    string = re.sub(r"\?", " ? ", string)
    string = re.sub(r"\s{2,}", " ", string)

    return string.strip().lower()

def build_vocab(sentences, vocab_limit):
    """
    Builds a vocabulary mapping from word to index based on the sentences.
    Returns vocabulary mapping and inverse vocabulary mapping.
    """
    # Build vocabulary
    word_counts = Counter(itertools.chain(*sentences))
    print( 'Total size of vocab is {}'.format(len(word_counts.most_common())))
    # Mapping from index to word
    # vocabulary_inv = [x[0] for x in word_counts.most_common(vocab_limit)]
    vocabulary_inv = [x[0] for x in word_counts.most_common(vocab_limit)]
    
    vocabulary_inv = list(sorted(vocabulary_inv))
    # Mapping from word to index
    vocabulary = {x: i+1 for i, x in enumerate(vocabulary_inv)}
    return [vocabulary, vocabulary_inv]

# data is DataFrame
def vectorize_data(data, word_idx, sentence_size):
    E = []
    for essay in data:
        ls = max(0, sentence_size - len(essay))
        wl = []
        for w in essay:
            if w in word_idx:
                wl.append(word_idx[w])
            else:
                wl.append(0)
        wl += [0]*ls
        E.append(wl)
    return E
import pandas as pd

names = ['song_beg', 'song_end', 'false_beg','false_end','normal','shuffle', 'syn']
adv_data_list = {}
for name in names:
  adv_data = pd.read_csv('/content/drive/My Drive/IG RESULTS/'+str(essay_set_id)+'_'+name+'.csv')
  adv_data_list[name] = adv_data
E_list = {}
M_list = {}
for adv_data in adv_data_list.keys():
  essay_list, resolved_scores = load_training_data(adv_data_list[adv_data])
  E = data_utils.vectorize_data(essay_list, word_idx, len(t[0][0]))
  E_list[adv_data]= E
  M_list[adv_data] = m[0][:len(E)]
e   = E_list['normal']
mem = M_list['normal']
inp = [e,mem,1.0]
labels_orig = IG.predict_batch(inp)
labels_orig = [x+0 for x in labels_orig]
labels_orig
from xhtml2pdf import pisa
def convert_html_to_pdf(source_html, output_filename):
  result_file = open(output_filename, "w+b")
  pisa_status = pisa.CreatePDF(source_html, dest=result_file)          
  result_file.close()

def save_stats_add(diff, diff_attr, word_list, ratio,output_filename):
  result = open(output_filename, 'w')
  result.write('\ndiff in scores:  '+str(diff))
  result.write('\ndiff in attrs:  '+ str(diff_attr))
  result.write('\nnew words in top 10%:  '+ ', '.join(word_list))
  result.write('\npercent of top words in added words:  '+ str(ratio))
  result.close()

def save_stats_mod(diff, diff_attr, changed_no,output_filename):
  result = open(output_filename, 'w')
  result.write('\ndiff in scores:  '+str(diff))
  result.write('\ndiff in attrs:  '+ str(diff_attr))
  result.write('\nno of words which changed attr:  '+ str(changed_no))
  result.close()

def save_stats_gen(babel_total, babel_unattrib, output_filename):
  result = open(output_filename, 'w')
  result.write('\ntop attributed words:  '+ str(babel_total))
  result.write('\ntop unattributed words:  '+ str(babel_unattrib))
  result.close()

def top_k_attrs(tokens, attrs, sign = None, k=None):
    k = min(k, len(tokens))
    
    if sign != None:
      tokens_list = []
      signs_list = []
      for i in np.argpartition(attrs, -k)[-k:]:
          tokens_list.append(tokens[i].strip())
          signs_list.append(sign[i])
      return  tokens_list , signs_list
    
    else:
      return ([tokens[i].strip() for i in np.argpartition(attrs, -k)[-k:]])

def bottom_k_attrs(tokens, attrs, k):
    k = min(k, len(tokens))
    return [tokens[i] for i in np.argpartition(attrs, k)[:k]]

def save_normal_attrs(data, memory, labels_orig, essay_type):
  dir =  ATTRS_DIR+essay_type+'/'
  if not os.path.exists(dir):
    os.makedirs(dir)

  a_total = []
  w_total= [] 
  for i,essay in enumerate(data):
    attrs, words= IG.explain(x = data[i][:395], memory= memory[0])
    label_new = IG.predict([data[i][:395], memory[0],1.0])
    html = IG.visualize_token_attrs(words, attrs)
    convert_html_to_pdf(html, dir+str(i)+'_'+str(labels_orig[i])+'_'+str(label_new+0)+'.pdf')
    a_total.append(attrs)
    w_total.append(words)

  return a_total, w_total

def subfinder(l, sl):
    sll=len(sl)
    for ind in (i for i,e in enumerate(l) if e==sl[0]):
        if l[ind:ind+sll]==sl:
            return ind,ind+sll-1

def save_attrs_pdf(data, data_normal, memory, labels_orig, essay_type, type_add = False, type_mod = False, type_gen = False):
  dir =  ATTRS_DIR+essay_type+'/'
  if not os.path.exists(dir):
    os.makedirs(dir)

  a,w = data_normal
  babel_total = {}
  babel_unattrib = {}
  pattern_none = [None, None, None, None, None]
          
  for i,essay in enumerate(data):
    attrs, words= IG.explain(x = data[i][:395], memory= memory[0])
    labels_new = IG.predict([data[i][:395], memory[0],1.0])
    
    if type_gen:
        try:
          loc = subfinder(words, pattern_none)[0] 
        except Exception as e:
          loc = len(words)
        attrs_sign= []
        for x in attrs:
            if x>0:
              attrs_sign.append('+')
            else:
              attrs_sign.append('-')

        top_words, top_words_signs = top_k_attrs(words, attrs, attrs_sign, k = int(0.1*loc))
        
        for j,x in enumerate(top_words):
          if x in babel_total.keys():
            if top_words_signs[j] == '+':
              babel_total[x][0]+=1
            else:
              babel_total[x][1]+=1
          else:
            if top_words_signs[j] == '+':
              babel_total[x] = [1,0]
            else:
              babel_total[x] = [0,1]

        attrs_abs = [abs(x) for x in attrs]
        bottom_words = bottom_k_attrs(words[:loc], attrs_abs[:loc], k = int(0.1*loc))
        
        for j,x in enumerate(bottom_words):
          if x in babel_unattrib.keys():
            babel_unattrib[x]+= 1
          else:
            babel_unattrib[x] = 1
 
        html = IG.visualize_token_attrs(words, attrs)
        convert_html_to_pdf(html, dir+str(i)+'_'+str(labels_new+0)+'.pdf')

    else:
      html = IG.visualize_token_attrs(words, attrs)
      convert_html_to_pdf(html, dir+str(i)+'_'+str(labels_orig[i])+'_'+str(labels_new+0)+'.pdf')
    
  if type_gen:
    del babel_unattrib[None]
    save_stats_gen(babel_total, babel_unattrib, dir+'stats_word_attributions.txt')
e_normal = E_list['normal']
m_normal = M_list['normal']
data_normal = save_normal_attrs(e_normal , m_normal, labels_orig, 'normal')
gc.collect()
e_add_song = E_list['song_beg']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'song_beg')

gc.collect()
e_add_song = E_list['song_end']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'song_end')

gc.collect()
e_add_song = E_list['false_beg']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'false_beg')

gc.collect()
e_add_song = E_list['false_end']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'false_end')
gc.collect()
e_add_song = E_list['syn']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'syn', type_mod = True)
gc.collect()
e_add_song = E_list['shuffle']
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'shuffle', type_mod = True)
gc.collect()
babel_data = pd.read_csv('/content/AES_testcases/prompt'+str(essay_set_id)+'/prompt 3 babel - Sheet1.csv', names= ['text'])
babel_data['label_orig'] = min_score

essay_list, resolved_scores = load_training_data(babel_data)
E_babel = data_utils.vectorize_data(essay_list, word_idx, len(t[0][0]))

e_add_song = E_babel
memory = M_list['normal']
save_attrs_pdf(e_add_song, data_normal, memory, labels_orig, 'babel', type_gen = True)

###NORMAL STUFF:
def top_k_attrs(tokens, attrs, sign = None, k=None):
    k = min(k, len(tokens))
    
    if sign != None:
      tokens_list = []
      signs_list = []
      for i in np.argpartition(attrs, -k)[-k:]:
          tokens_list.append(tokens[i].strip())
          signs_list.append(sign[i])
      return  tokens_list , signs_list
    
    else:
      return ([tokens[i].strip() for i in np.argpartition(attrs, -k)[-k:]])

# ATTRS_TSV = '/content/drive/My Drive/IG RESULTS/P1/MEMORY NET/attrs.tsv'
lines = []
with open(ATTRS_TSV) as f:
    for line in f:
      lines.append(line)
lines = list(set(lines))

def get_counts_list_normal( top_k = 10, is_abs = False, is_sign = False, is_percent = None):
  
  essay_list = []
  counts_list = []
  signs_list = []
  for line in lines:
      line = line.strip()
      question_attrs = line.split('\t')[0]
      question_tokens = []
      attrs = []
      for word_attr in question_attrs.split('||'): 
          word, attr = word_attr.split('|')
          question_tokens.append(word)
          if is_abs:
            attrs.append(abs(float(attr)))
          else:
            attrs.append(float(attr))

      essay_list.append(question_tokens)
      if is_percent!=None:
        top_k = int(is_percent*len(question_tokens))
  
      if top_k == None:
        k = len(question_tokens)
      else:
        k = min(top_k, len(question_tokens))
      
      if is_sign:
        signs = []

        for i in attrs:
          if i>0:
            signs.append('+')
          else:
            signs.append('-')
      # get top k words by attribution 
      c_list, sign_list = top_k_attrs(question_tokens , attrs, signs,  k = k)
      counts_list.extend(c_list)
      signs_list.extend(sign_list)

  return counts_list, signs_list, essay_list
counts_list, signs_list, essay_list = get_counts_list_normal(is_percent = 0.1, is_sign = True)
signs_dict= {}
frequent_attributions = Counter(counts_list).most_common(50)
for i in frequent_attributions:
  w = i[0]
  for j,w2 in enumerate(counts_list):
    if w ==w2 :
      if w not in signs_dict.keys():
        signs_dict[w] = []
      else:
        signs_dict[w].append(signs_list[j])

for k,v in signs_dict.items():
  signs_dict[k] = Counter(v)

with open(ATTRS_DIR+'NORMAL_word_importance.txt','w') as f:
  f.write(str(signs_dict))
###NORMAL UNATTRIBUTED STUFF:
def bottom_k_attrs(tokens, attrs, k=None):
    k = min(k, len(tokens))    
    return ([tokens[i].strip() for i in np.argpartition(attrs, k)[:k]])

def neg_k_attrs(tokens, attrs, k=None):
    k = min(k, len(tokens))    
    return ([tokens[i].strip() for i in np.argpartition(attrs, k)[:k] if attrs[i]<0 ])

lines = []
with open(ATTRS_TSV) as f:
    for line in f:
      lines.append(line)
lines = list(set(lines))

def get_bottom_list_normal( top_k = 10, is_abs = True, is_percent = None, is_neg= False):
  
  counts_list = []
  signs_list = []
  for line in lines:
      line = line.strip()
      question_attrs = line.split('\t')[0]
      question_tokens = []
      attrs = []
      for word_attr in question_attrs.split('||'): 
          word, attr = word_attr.split('|')
          question_tokens.append(word)
          if is_abs:
            attrs.append(abs(float(attr)))
          else:
            attrs.append(float(attr))

      if is_percent!=None:
        top_k = int(is_percent*len(question_tokens))
  
      if top_k == None:
        k = len(question_tokens)
      else:
        k = min(top_k, len(question_tokens))
      
      # get top k words by attribution 
      if is_neg:
        c_list = neg_k_attrs(question_tokens , attrs, k = k)
      else:
        c_list = bottom_k_attrs(question_tokens , attrs, k = k)
      counts_list.extend(c_list)
      
  return counts_list

counts_list_unattrib = get_bottom_list_normal(is_percent = 0.1)
counts_list_neg = get_bottom_list_normal(is_percent = 0.1, is_abs = False, is_neg = True)

with open(ATTRS_DIR+'NORMAL_bottom_attributed_words.txt','w') as f:
  f.write(str(Counter(counts_list_unattrib).most_common(50)))
with open(ATTRS_DIR+'NORMAL_negative_attributed_words.txt','w') as f:
  f.write(str(Counter(counts_list_neg).most_common(50)))
def plot_and_save(curve_data, filename, x = 'num. words in vocab', y= 'relative accuracy', title= 'title'):
  import matplotlib.pyplot as plt
  OVERSTABILITY_CURVE_FILE = filename
  plt.plot(list(curve_data.keys()), list(curve_data.values()))
  # plt.xscale('symlog')
  plt.xlabel(x)
  plt.ylabel(y)
  plt.title(title)

  plt.savefig(OVERSTABILITY_CURVE_FILE, format='eps')
  plt.savefig(OVERSTABILITY_CURVE_FILE.replace('eps','png'), format='png')
  plt.tight_layout()
  plt.show()

def plot_and_save_both(a,b, filename, x = 'num. words in vocab', y= 'relative accuracy', title= 'title'):
  import matplotlib.pyplot as plt
  OVERSTABILITY_CURVE_FILE = filename
  plt.plot(a,b)
  # plt.xscale('symlog')
  ax = plt.gca()
  ax.invert_xaxis()
  plt.xlabel(x)
  plt.title(title)
  plt.ylabel(y)
  plt.savefig(OVERSTABILITY_CURVE_FILE, format='eps')
  plt.savefig(OVERSTABILITY_CURVE_FILE.replace('eps','png'), format='png')
  plt.tight_layout()
  plt.show()
# ### NORMAL ATTR %%%%
# pattern_none = [None, None, None, None, None]
# data = e_normal
# memory = m_normal
# for i in range(len(data)):
#   attrs, words = IG.explain(data[i][:395], memory = memory[0])
#   loc = subfinder(words, pattern_none)[0]
#   attrs = attrs[:loc]
#   attrs = [abs(x) for x in attrs]
#   words = words[:loc]
#   s= {}
#   l = len(attrs)
#   for j in range(0, l, l//5):
#     s[(j)] = sum(attrs[j: j+ l//5])
  
#   dir = ATTRS_DIR+'normal/'
#   plot_and_save(s, dir+str(i)+'_attrs_variation.txt', title = str(i)+'_attrib_graph')
with open('/content/drive/My Drive/IG RESULTS/MEM MODELS/tokenizer.pkl', 'rb') as f:
    word_to_idx = pickle.load(f)

idx_to_word = {v: k for k, v in word_to_idx.items()}
lines = []
with open(ATTRS_TSV) as f:
    for line in f:
      lines.append(line)
lines = lines[-1097:]
lines = list(set(lines))

def get_essay_list(tsv_lines):
  
  essay_list = []
  attrs_list = []
  for line in tsv_lines:
      line = line.strip()
      question_attrs = line.split('\t')[0]
      question_tokens = []
      attrs = []
      for word_attr in question_attrs.split('||'): 
          word, attr = word_attr.split('|')
          question_tokens.append(word)
          attrs.append(float(attr))
      question_tokens_idx = [word_to_idx[x] for x in question_tokens] + [0]*(395 - len(question_tokens))
      essay_list.append(question_tokens_idx)
      attrs_list.append(attrs)

  return essay_list, attrs_list

essay_list, attrs_list = get_essay_list(lines)
w1 = graph.get_tensor_by_name("input/question:0")
w2 = graph.get_tensor_by_name("input/memory_key:0")
w3 = graph.get_tensor_by_name("input/keep_prob:0")
INPUT_TENSORS = [w1,w2,w3]
PRED_TENSOR = graph.get_tensor_by_name('prediction/predict_op:0')
mem_total = []
for i in range(len(essay_list)):
  mem_total.append(m[0][0])
feed = {}
pred_array_orig = []
input_df = [np.array(essay_list), np.array(mem_total), 1]
for i, key in enumerate(INPUT_TENSORS):
    feed[key.name] = input_df[i]
pred = sess.run(PRED_TENSOR,feed)
pred_array_orig.extend(pred)
def npos(orig, new):
  count = 0
  for i in range(len(orig)):
    if new[i]>orig[i]:
      count+=1 
  return (count/len(orig))*100

def nneg(orig, new):
  count = 0
  for i in range(len(orig)):
    if new[i]<orig[i]:
      count+=1 
  return (count/len(orig))*100

def nsame(orig, new):
  count = 0
  for i in range(len(orig)):
    if new[i]==orig[i]:
      count+=1 
  return (count/len(orig))*100

def mu(orig, new):
  s=0
  n = len(orig)
  for i in range(n):
    s+=(orig[i] - new[i])
  return (s/n)/4

def absmu(orig, new):
  s=0
  n = len(orig)
  for i in range(n):
    s+=(orig[i] - new[i])
  return (abs(s)/n)/4

def sd(orig, new):
  mu_val = mu(orig, new)
  s=0
  n = len(orig)
  for i in range(n):
    s+=(orig[i] - new[i] - mu_val)**2
  return ((s/n)**(1/2))/4

def mupos(orig, new):
  s=0
  n = len(orig)
  for i in range(n):
    if new[i]>orig[i]:
      s+=(orig[i] - new[i])
  return (s/n)/4

def muneg(orig, new):
  s=0
  n = len(orig)
  for i in range(n):
    if orig[i] > new[i]:
      s+=-(orig[i] - new[i])
  return (s/n)/4

def get_pred_stats(orig, new, filename, K):
  b = ('NPOS',  npos(orig, new))
  c = ('NNEG',  nneg(orig, new))
  d = ('NSAME', nsame(orig, new))
  e = ('MU',    mu(orig, new))
  f = ('ABSMU', absmu(orig, new))
  g = ('SD',    sd(orig, new))
  h = ('MUPOS', mupos(orig, new))
  i = ('MUNEG', muneg(orig, new))
  with open(filename, 'a') as file:
    file.write(str(K)+"___"+str([b,c,d,e,f,g,h,i])+ "\n")
from sklearn.metrics import cohen_kappa_score
from random import randint

import numpy as np
def top_k_attrs(tokens, attrs,k=None):
    k = min(k, len(tokens))
    return ([tokens[i] for i in np.argpartition(attrs, -k)[-k:]])

d = {}
p_list = {}
for K in range(0,6):
  
  percent = K*0.2
  preds_new = []
  new_essay_list = []
  avg_len = 0
  c_list_total = []

  # chosen_id = randint(0, 10)  
  for id, essay in enumerate(essay_list):
    
    top_k = int(percent* len(attrs_list[id]))
    attrs = attrs_list[id]
    question_tokens = essay_list[id]
    try:
      c_list = top_k_attrs(question_tokens , attrs, k = top_k)
    except Exception as e:
      c_list = list(set(question_tokens))
    if top_k==0:
      c_list = []
    c_list_total.extend(c_list)
    new_essay = []
    count = 0
    for i in range(len(question_tokens)):  
      if question_tokens[i] in c_list and count<top_k:
        new_essay.append(question_tokens[i])
        count+=1
    
    # print(len(new_essay)/  len(question_tokens[:len(attrs)])  )
    new_essay = new_essay + [0]*(395 - len(new_essay))
    # if id == chosen_id and K>1 and K<5:
    #   save_attrs(new_essay, mem_total, K, essay_type='incomplete_data')
    new_essay_list.append(new_essay)
    
    # input_df = [np.array([new_essay]), np.array([mem_total[0]]), 1]
    # for i, key in enumerate(INPUT_TENSORS):
    #     feed[key.name] = input_df[i]
    # pred = sess.run(PRED_TENSOR,feed)[0]
    # print(pred_array_orig[id],pred)
    # # print(abs(pred - pred_array_orig[id]))
    # if round(abs(round(pred) - pred_array_orig[id])) == 1:
    #   if id not in p_list.keys():
    #     p_list[id] = percent*100
    #   else:
    #     pass

  avg_len/=len(new_essay_list)
  c_len = len(set(c_list_total))
  feed = {}
  input_df = [np.array(new_essay_list), np.array(mem_total), 1]
  for i, key in enumerate(INPUT_TENSORS):
      feed[key.name] = input_df[i]
  pred = sess.run(PRED_TENSOR,feed)
  preds_new.extend(pred)
  preds_new = [int(x) for x in preds_new]

  acc = cohen_kappa_score(preds_new, pred_array_orig, weights='quadratic')
  get_pred_stats(pred_array_orig, preds_new, ATTRS_DIR+'stats_top.txt', int(percent*100))
  d[percent*100] = acc
l = p_list.values()
sum(l)/len(l)
d
plot_and_save(d,ATTRS_DIR+'adding_top', x = '% length of response', y ='relative QWK', title= 'iteratively adding words(in order of importance)')
def bottom_k_attrs(tokens, attrs,k=None):
    k = min(k, len(tokens))
    return ([tokens[i] for i in np.argpartition(attrs, k)[:k]])

d2_keys = []
d2_vals = []
for K in range(0,6):
  percent = K*0.2
  preds_new = []
  new_essay_list = []
  avg_len = 0
  c_list_total = []
  for id, essay in enumerate(essay_list):
    top_k = int(percent* len(attrs_list[id]))
    attrs = attrs_list[id]
    question_tokens = essay_list[id]
    attrs = [abs(x) for x in attrs]
    try:
      c_list = bottom_k_attrs(question_tokens , attrs, k = top_k)
    except Exception as e:
      c_list = list(set(question_tokens))
    if top_k==0:
      c_list = []

    # c_list_total.extend(c_list)
    new_essay = []
    count = 0
    for i in range(len(question_tokens[:len(attrs)])):  
      if question_tokens[:len(attrs)][i] in c_list and count<top_k:
        count+=1
        pass
      else:
        new_essay.append( question_tokens[:len(attrs)][i])
    # avg_len+=len(new_essay)
    # print(len(new_essay)/  len(question_tokens[:len(attrs)]) , new_essay, question_tokens[:len(attrs)])
    
    new_essay = new_essay + [0]*(395 - len(new_essay))
    new_essay_list.append(new_essay)

    # input_df = [np.array([new_essay]), np.array([mem_total[0]]), 1]
    # for i, key in enumerate(INPUT_TENSORS):
    #     feed[key.name] = input_df[i]
    # pred = sess.run(PRED_TENSOR,feed)[0]
    # # print(abs(pred - pred_array_orig[id]))
    # if round(abs(pred - pred_array_orig[id])) == 1:
    #   if id not in p_list.keys():
    #     p_list[id] = percent*100
    #   else:
    #     pass

  avg_len/=len(new_essay_list)
  c_len = len(set(c_list_total))
  feed = {}
  input_df = [np.array(new_essay_list), np.array(mem_total), 1]
  for i, key in enumerate(INPUT_TENSORS):
      feed[key.name] = input_df[i]
  pred = sess.run(PRED_TENSOR,feed)
  preds_new.extend(pred)
  preds_new = [int(x) for x in preds_new]
  
  acc = cohen_kappa_score(preds_new, pred_array_orig, weights='quadratic')
  get_pred_stats(pred_array_orig, preds_new, ATTRS_DIR+'stats_bottom.txt', int(100-percent*100))
  # print(percent*100, avg_len, acc)
  d2_keys.append(100-percent*100)
  d2_vals.append(acc)
l = p_list.values()
sum(l)/len(l)
plot_and_save_both(d2_keys, d2_vals, ATTRS_DIR+'removing_bottom', x = '% length of response', y ='relative QWK', title= 'iteratively removing words(in reverse order of importance)')
import os
import gc
import multiprocessing

def create_model_and_train(low, high, mem, attr_type = 'add'):
  ATTRS_DIR = '/content/drive/MyDrive/IG RESULTS/'
  ATTRS_TSV = ATTRS_DIR+'MEMORY NET/P3/attrs_'+attr_type+'.tsv'
  
  saver = tf.train.import_meta_graph("/content/drive/MyDrive/IG RESULTS/MEM MODELS/"+str(essay_set_id)+"/checkpoints_"+str(fold_no)+"-"+str(step)+".meta")  
  sess = tf.Session()
  saver.restore(sess,"/content/drive/MyDrive/IG RESULTS/MEM MODELS/"+str(essay_set_id)+"/checkpoints_"+str(fold_no)+"-"+str(step))

  graph = tf.get_default_graph()
  IG = integrated_gradients(graph, sess, min = 0, batch_size= 20, num_reps=40)

  data = pd.read_csv(ATTRS_DIR+'big_3_'+attr_type+'.csv')
  essay_list, resolved_scores = load_training_data(data)
  E = data_utils.vectorize_data(essay_list, word_idx, 395)
  
  with open(ATTRS_TSV, 'w') as outf:
    ans = ''
    for i,v in enumerate(E[low:high]):
        tsv_string = ''
        attrs, words= IG.explain(x = E[i][:395], memory= mem)

        question_attrs = []
        for ind in range(len(words)):
          if words[ind] != None and str(attrs[ind])!=None:
            question_attrs.append(
                '|'.join([ words[ind], str(attrs[ind]) ])
                )
        tsv_string = ['||'.join(question_attrs)]
        ans += '\t'.join(tsv_string) + '\n'
        del attrs, words, question_attrs, tsv_string
        gc.collect()
    
    outf.write(ans)
    outf.flush()
    del ans
    gc.collect()
    outf.write('done')
  print('DONE')
attr_type = 'normal'
ranges = [[0,50], [50,100]]
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()
attr_type = 'song_beg'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()

attr_type = 'song_end'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()
attr_type = 'false_beg'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()
  
attr_type = 'false_end'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()
attr_type = 'shuffle'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()

attr_type = 'syn'
for r in (ranges):
  p = multiprocessing.Process(target = create_model_and_train, args = (r[0], r[1], m[0][0], attr_type))
  p.start()
  p.join()
  p.terminate()

def get_w_a(essay_type):
  ATTRS_DIR = '/content/drive/MyDrive/IG RESULTS/MEMORY NET/P3/'

  ### NORMAL
  path = ATTRS_DIR + 'attrs_'+essay_type+'.tsv'
  w = []
  a = []

  with open(path, 'r') as f:
    for line in f:
        line = line.strip()
        question_attrs = line.split('\t')[0]
        question_tokens = []
        attrs = []
        for word_attr in question_attrs.split('||'): 
          if word_attr != 'done':
            word, attr = word_attr.split('|')
            question_tokens.append(word)
            attrs.append(float(attr))
        question_tokens = question_tokens + [None]*(395 - len(attrs))
        attrs = attrs + [0]*(395 - len(attrs))

        w.append(question_tokens)
        a.append(attrs)
  return a[:-1], w[:-1]
def save_stats_add(diff, diff_attr, percent, output_filename):
  result = open(output_filename, 'w')
  result.write('\ndiff in scores:  '+str(diff))
  result.write('\ndiff in attrs:  '+ str(diff_attr))
  result.write('\npercent of top words in added words:  '+ str(percent))
  result.close()

def save_stats_mod_shuffle(diff, diff_attr, changed_no,output_filename):
  result = open(output_filename, 'w')
  result.write('\ndiff in scores:  '+str(diff))
  result.write('\ndiff in attrs:  '+ str(diff_attr))
  result.write('\nno of top words which changed attr:  '+ str(changed_no))
  result.close()

def save_stats_mod_syn(diff, diff_attr, changed_top_no,changed_bottom_no, top_words, bottom_words, output_filename):
  result = open(output_filename, 'w')
  result.write('\n diff in scores:  '+str(diff))
  result.write('\n diff in attrs:  '+ str(diff_attr))
  result.write('\n no of top words which changed attr:  '+ str(changed_top_no))
  result.write('\n no of bottom words which changed attr:  '+ str(changed_bottom_no))
  result.write('\n top words which changed attr:  '+ str(top_words))
  result.write('\n bottom words which changed attr:  '+ str(bottom_words))
  result.close()

def subfinder(l, sl):
    sll=len(sl)
    for ind in (i for i,e in enumerate(l) if e==sl[0]):
        if l[ind:ind+sll]==sl:
            return ind,ind+sll-1

def top_k_attrs(tokens, attrs, sign = None, k=None):
    k = min(k, len(tokens))
    
    if sign != None:
      tokens_list = []
      signs_list = []
      for i in np.argpartition(attrs, -k)[-k:]:
          tokens_list.append(tokens[i])
          signs_list.append(sign[i])
      return  tokens_list , signs_list
    
    else:
      return ([tokens[i] for i in np.argpartition(attrs, -k)[-k:]])

def bottom_k_attrs(tokens, attrs, sign = None, k=None):
    k = min(k, len(tokens))

    if sign != None:
      tokens_list = []
      signs_list = []
      for i in np.argpartition(attrs, k)[:k]:
          tokens_list.append(tokens[i])
          signs_list.append(sign[i])
      return  tokens_list , signs_list
    
    else:
      return ([tokens[i] for i in np.argpartition(attrs, k)[:k]])
def save_big_attrs_pdf(memory, essay_type, type_add = False, type_mod = False, type_gen = False):
  ATTRS_DIR = '/content/drive/MyDrive/IG RESULTS/MEMORY NET/P3/'
  dir =  ATTRS_DIR
  if not os.path.exists(dir):
    os.makedirs(dir)

  pattern_none = [None, None, None, None, None]
  
  if type_add:
    diff_array = [] 
    diff_attr_array = []
    percent_array = []

  if type_mod:
    diff_array = []
    diff_attr_array = []
    changed_count_array = []
    changed_count_top_array = []
    changed_count_bottom_array = []
    changed_top_words = {}
    changed_bottom_words = {}

  ### NORMAL
  a, w = get_w_a('normal')
  ### ADV
  a_new, w_new = get_w_a(essay_type)
  
  for i,essay in enumerate(w_new):
    attrs, words= a_new[i], essay
    E = vectorize_data([words], word_idx, 359)
    E_normal = vectorize_data([w[i]], word_idx, 359)
    # assert (E_normal[0]) == (E[0])
    labels_new = (IG.predict([E[0], memory[0],1.0]))
    labels_orig =(IG.predict([E_normal[0], memory[0],1.0]))
    if type_add:
        try:
          loc = subfinder(w[i], pattern_none)[0]
        except Exception as e:
          loc = len(w[i]) 
        try: 
          loc2 = subfinder(words, pattern_none)[0]
        except Exception as e:
          loc2 = len(words)
        # print(loc, loc2, w[i])

        if essay_type == 'song_beg' or essay_type =='false_beg' :
          pattern = w[i][:5]
          try:
            loc_patt = subfinder(words, pattern)[0]
          except Exception as e:
            loc_patt = 0
          new_w = words[:loc_patt]
          new_a = attrs[:loc_patt]
          other_a = attrs[loc_patt:loc2]

        elif essay_type == 'song_end' or essay_type =='false_end':
          new_w = words[loc:loc2]
          new_a = attrs[loc:loc2]
          other_a = attrs[:loc]

        if (new_w) !=[]:
          top_words_orig = top_k_attrs(w[i], a[i], k = int(0.2*loc))
          top_words = top_k_attrs(words , attrs, k = int(0.2*loc2))

          top_words_final = [x for x in top_words if x in new_w]

          diff = int(labels_new) - int(labels_orig)
          diff_array.append(abs(diff))

          diff_attr_frac = []
          for i_attrs in range(0,len(other_a), len(new_a)):
            if i_attrs+len(new_a) < len(other_a):
              diff_attr_frac.append(   sum(other_a[   i_attrs:i_attrs+len(new_a)  ])  )
            else:
              diff_attr_frac.append(   sum(other_a[   i_attrs:len(other_a)  ])  )
              break

          new_diff_frac = sum(diff_attr_frac) / len(diff_attr_frac)

          diff_attr = sum(new_a)/new_diff_frac
          diff_attr_array.append(diff_attr)

          percent = len(top_words_final)/len(new_w)
          percent_array.append(percent)
    
    elif type_mod:
        diff = int(labels_new) - int(labels_orig)
        diff_array.append(abs(diff))

        diff_attr = sum(attrs) - sum(a[i])
        diff_attr_array.append(diff_attr)

        ###### SYN

        if essay_type == 'syn':
          # normal
          loc = subfinder(w[i], pattern_none)[0]
          
          attrs_abs=[]
          attrs_sign_orig =[]
          for x in a[i]:
            attrs_abs.append(abs(x))
            if x>0:
              attrs_sign_orig.append('+')
            else:
              attrs_sign_orig.append('-')

          top_words_orig, token_signs_orig = top_k_attrs(w[i][:loc], attrs_abs[:loc], attrs_sign_orig[:loc], k = int(0.2*loc))
          bottom_words_orig, bottom_token_signs_orig = bottom_k_attrs(w[i][:loc], attrs_abs[:loc], attrs_sign_orig[:loc], k = int(0.2*loc))
          
          # adv
          loc2 = subfinder(words, pattern_none)[0]
          attrs_abs=[]
          attrs_sign =[]
          for x in attrs:
            attrs_abs.append(abs(x))
            if x>0:
              attrs_sign.append('+')
            else:
              attrs_sign.append('-')
          
          top_words, token_signs = top_k_attrs(words[:loc2], attrs_abs[:loc2], attrs_sign[:loc2], k = int(0.2*loc2))
          bottom_words, bottom_token_signs = bottom_k_attrs(words[:loc2], attrs_abs[:loc2], attrs_sign[:loc2], k = int(0.2*loc2))

          changed_count_top = 0
          changed_count_bottom = 0
          
          # top    
          for orig_index,t in enumerate(top_words_orig):
            try:
              ind = w[i].index(t)
            except Exception as e:
              ind = -1

            if ind!=-1:
              if attrs_sign[ind] != attrs_sign_orig[ind]:
                  changed_count_top+=1
                  changed_top_words[t] = words[ind]
          
          # bottom
          for orig_index,t in enumerate(bottom_words_orig):
            try:
              ind = w[i].index(t)
            except Exception as e:
              ind = -1

            if ind!=-1:
              if attrs_sign[ind] != attrs_sign_orig[ind]:
                  changed_count_bottom+=1
                  changed_bottom_words[t] = words[ind]
          
          changed_count_top_array.append(changed_count_top)
          changed_count_bottom_array.append(changed_count_bottom)

        ###### SHUFFLE 
        if essay_type == 'shuffle':
          loc = subfinder(w[i], pattern_none)[0]
          attrs_abs=[]
          attrs_sign =[]
          for x in a[i]:
            attrs_abs.append(abs(x))
            if x>0:
              attrs_sign.append('+')
            else:
              attrs_sign.append('-')

          top_words_orig, token_signs_orig = top_k_attrs(w[i], attrs_abs, attrs_sign, k = int(0.2*loc))
          
          loc = subfinder(words, pattern_none)[0]
          attrs_abs=[]
          attrs_sign =[]
          for x in attrs:
            attrs_abs.append(abs(x))
            if x>0:
              attrs_sign.append('+')
            else:
              attrs_sign.append('-')
          
          top_words, token_signs = top_k_attrs(words, attrs_abs, attrs_sign, k = int(0.2*loc))
          
          changed_count = 0

          for orig_index,t in enumerate(top_words_orig):
            try:
              ind = top_words.index(t)
            except Exception as e:
              ind = -1

            if ind!=-1:
              if token_signs_orig[orig_index] != token_signs[ind]:
                  changed_count+=1
          changed_count_array.append(changed_count)

  def Average(lst): 
    return sum(lst) / len(lst) 
  
  if type_add:
    save_stats_add(Average(diff_array), Average(diff_attr_array), Average(percent_array),       dir+'stats_'+essay_type+'.txt')

  if type_mod and essay_type == 'syn':
    save_stats_mod_syn(Average(diff_array), Average(diff_attr_array), Average(changed_count_top_array), \
                   Average(changed_count_bottom_array), set(changed_top_words),  set(changed_bottom_words), \
                   dir+'stats_'+essay_type+'.txt')

  if type_mod and essay_type == 'shuffle':
    save_stats_mod_shuffle(Average(diff_array), Average(diff_attr_array), Average(changed_count_array), dir+'stats_'+essay_type+'.txt')
save_big_attrs_pdf(m[0], 'song_beg', type_add=True)
save_big_attrs_pdf(m[0], 'song_end', type_add=True)
save_big_attrs_pdf(m[0], 'false_beg', type_add=True)
save_big_attrs_pdf(m[0], 'false_end', type_add=True)
save_big_attrs_pdf(m[0], 'shuffle', type_mod=True)
save_big_attrs_pdf(m[0], 'syn', type_mod=True)

from sklearn.metrics import cohen_kappa_score
for i,v in enumerate(orig_array):
      orig_array[i] = v+0
orig_acc = cohen_kappa_score(test_scores, orig_array, weights='quadratic')
orig_acc

curve_data = {}
question_lengths = {}
all_accs = []
counts_list,_ = get_counts_list(top_k = None)
counts_list = [item for sublist in counts_list for item in sublist]
c = (counts_list)
with open('/content/drive/My Drive/IG RESULTS/MEM MODELS/tokenizer.pkl', 'rb') as f:
    tokenizer = pickle.load(f)
for K in np.append(0, np.unique(np.floor(np.geomspace(1, len(c), 10)))):
    # take K most top attributed words
    if K in curve_data:
        continue
    
    counts_list,_ = get_counts_list(int(K))
    counts_list = [item for sublist in counts_list for item in sublist]

    whitelist = set([tokenizer[w] for w in counts_list[:int(K)]]) if K > 0 else set()
    print('wh len', len(whitelist))
    num_batches = 0
    avg_question_length_orig = 0
    avg_question_length_new = 0
    num_questions = 0
    pred_array = []
    # iterator over the validation dataset
    for test,mem in (zip(t,m)):

        test = np.array(test)
        new_test = np.zeros(test.shape)
        curr_batch_size = int(test.shape[0])
        for batch_i in range(curr_batch_size):
            len_counter = 0
            # avg_question_length_orig += int(test[batch_i])
            for word_i, w in enumerate(test[batch_i]):
                if int(w) in whitelist:
                    new_test[batch_i, len_counter] = int(w)
                    len_counter += 1
            if len_counter == 0:
                len_counter = 1
            avg_question_length_new += int(len_counter)
            num_questions += 1
            
        feed = {}
        input_df = [new_test, mem, 1]
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        pred_array.extend(pred)

    # print("avg question length orig: ", float(avg_question_length_orig)/num_questions)
    print("avg question length new: ", float(avg_question_length_new)/num_questions)
    for i,v in enumerate(pred_array):
      pred_array[i] = v+0
    acc = cohen_kappa_score(pred_array, test_scores, weights='quadratic')
    print("accuracy for ", K, " is", acc)
    curve_data[K] = acc
    question_lengths[K] = float(avg_question_length_new)/num_questions
curve_data = {}
question_lengths = {}
all_accs = []
counts_list,_ = get_counts_list(top_k = None)
counts_list = [item for sublist in counts_list for item in sublist]
c = (counts_list)
with open('/content/drive/My Drive/IG RESULTS/MEM MODELS/tokenizer.pkl', 'rb') as f:
    tokenizer = pickle.load(f)
for K in np.append(0, np.unique(np.floor(np.geomspace(1, len(c), 10)))):
    # take K most top attributed words
    if K in curve_data:
        continue
    
    counts_list,_ = get_counts_list(int(K))
    counts_list = [item for sublist in counts_list for item in sublist]

    whitelist = set([tokenizer[w] for w in counts_list[:int(K)]]) if K > 0 else set()
    print('wh len', len(whitelist))
    num_batches = 0
    avg_question_length_orig = 0
    avg_question_length_new = 0
    num_questions = 0
    pred_array = []
    # iterator over the validation dataset
    for test,mem in (zip(t,m)):

        test = np.array(test)
        new_test = np.zeros(test.shape)
        curr_batch_size = int(test.shape[0])
        for batch_i in range(curr_batch_size):
            len_counter = 0
            # avg_question_length_orig += int(test[batch_i])
            for word_i, w in enumerate(test[batch_i]):
                if int(w) in whitelist:
                    new_test[batch_i, len_counter] = int(w)
                    len_counter += 1
            if len_counter == 0:
                len_counter = 1
            avg_question_length_new += int(len_counter)
            num_questions += 1
            
        feed = {}
        input_df = [new_test, mem, 1]
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        pred_array.extend(pred)

    # print("avg question length orig: ", float(avg_question_length_orig)/num_questions)
    print("avg question length new: ", float(avg_question_length_new)/num_questions)
    for i,v in enumerate(pred_array):
      pred_array[i] = v+0
    acc = cohen_kappa_score(pred_array, test_scores, weights='quadratic')
    print("accuracy for ", K, " is", acc)
    curve_data[K] = acc
    question_lengths[K] = float(avg_question_length_new)/num_questions






s= {}
l = len(attrs)
for i in range(0, len(attrs), l//5):
  s[(i)] = sum(attrs[i: i+ l//5])


for name in names:
  e = E_list[name]
  mem = M_list[name]
  save_attrs_pdf(e, mem, labels_orig, name)





# # ATTRS_TSV = '/content/drive/My Drive/IG RESULTS/P1/MEMORY NET/attrs_1_new.tsv'
# # with open(ATTRS_TSV, 'a') as outf:
# c = 1
# ans = ''
# for test,mem in tqdm(zip(t,m)): 
#   # IG = integrated_gradients(graph, sess, min = 1, batch_size= 20, num_reps=20)
#   for j in range(len(test)):   
#       if c<= 271:
#         c+=1
#         continue  

#       question_attrs = []
#       tsv_string= ''
#       attrs, words= IG.explain(x = test[j], memory= mem[j], debug=False)
#       for ind in range(len(words)):
#         if words[ind] is not None:
#             question_attrs.append(
#                 '|'.join([ words[ind], str(attrs[ind]) ])
#                 )
#       tsv_string = ['||'.join(question_attrs)]
#       ans += '\t'.join(tsv_string) + '\n'
#       del attrs, words, question_attrs, tsv_string
#       gc.collect()
#       c+=1
      
#   if  c>271:
#     with open(ATTRS_TSV, 'a') as outf:
#       outf.write(ans)
#     print(c)
#   # del ans, IG
#   # gc.collect()
ATTRS_TSV = '/content/drive/My Drive/IG RESULTS/MEMORY NET/P7/attrs.tsv'
ATTRS_DIR = '/content/drive/My Drive/IG RESULTS/MEMORY NET/P7/'
from collections import Counter

counts_list = []
top_k = 10
with open(ATTRS_TSV) as f:
    for line in f:
        line = line.strip()
        question_attrs = line.split('\t')[0]
        question_tokens = []
        attrs = []
        for word_attr in question_attrs.split('||'): 
            word, attr = word_attr.split('|')
            question_tokens.append(word)
            attrs.append(float(attr))
        k = min(top_k, len(question_tokens))
        # get top k words by attribution 
        counts_list.append([question_tokens[i].strip() for i in np.argpartition(attrs, -k)[-k:]])

flat_counts_list = [item for sublist in counts_list for item in sublist]
frequent_attributions = Counter(flat_counts_list)

with open(ATTRS_DIR+'highest_attrs.txt', 'w') as f:
  attr_to_save = frequent_attributions.most_common(10)
  f.write(str(attr_to_save))
frequent_attributions = Counter(counts_list)
frequent_attributions
w1 = graph.get_tensor_by_name("input/question:0")
w2 = graph.get_tensor_by_name("input/memory_key:0")
w3 = graph.get_tensor_by_name("input/keep_prob:0")
INPUT_TENSORS = [w1,w2,w3]
PRED_TENSOR = graph.get_tensor_by_name('prediction/predict_op:0')
orig_array =[] 
for test,mem in (zip(t,m)):

        test = np.array(test)
        feed = {}
        input_df = [test, mem, 1]
        # baseline = np.zeros(test.shape)
        # baseline_mem = np.zeros(np.array(mem).shape)
        # input_df = [baseline, np.array(mem), 1]
      
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        orig_array.extend(pred)
# orig_array
from sklearn.metrics import cohen_kappa_score
for i,v in enumerate(orig_array):
      orig_array[i] = v+2
orig_acc = cohen_kappa_score(test_scores, orig_array, weights='quadratic')
orig_acc
curve_data = {}
question_lengths = {}
all_accs = []
with open('/content/drive/My Drive/IG RESULTS/MEM MODELS/tokenizer.pkl', 'rb') as f:
    tokenizer = pickle.load(f)
for K in np.append(0, np.unique(np.floor(np.geomspace(1, len(Counter(counts_list)), 10)))):
    # take K most top attributed words
    if K in curve_data:
        continue
    whitelist = set([tokenizer[w] for w in counts_list[:int(K)]]) if K > 0 else set()
    print('wh len', len(whitelist))
    num_batches = 0
    avg_question_length_orig = 0
    avg_question_length_new = 0
    num_questions = 0
    pred_array = []
    # iterator over the validation dataset
    for test,mem in (zip(t,m)):

        test = np.array(test)
        new_test = np.zeros(test.shape)
        curr_batch_size = int(test.shape[0])
        for batch_i in range(curr_batch_size):
            len_counter = 0
            # avg_question_length_orig += int(test[batch_i])
            for word_i, w in enumerate(test[batch_i]):
                if int(w) in whitelist:
                    new_test[batch_i, len_counter] = int(w)
                    len_counter += 1
            if len_counter == 0:
                len_counter = 1
            avg_question_length_new += int(len_counter)
            num_questions += 1
            
        feed = {}
        input_df = [new_test, mem, 1]
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        pred_array.extend(pred)

    # print("avg question length orig: ", float(avg_question_length_orig)/num_questions)
    print("avg question length new: ", float(avg_question_length_new)/num_questions)
    for i,v in enumerate(pred_array):
      pred_array[i] = v+2
    acc = cohen_kappa_score(pred_array, test_scores, weights='quadratic')
    print("accuracy for ", K, " is", acc)
    curve_data[K] = acc
    question_lengths[K] = float(avg_question_length_new)/num_questions
import matplotlib.pyplot as plt
OVERSTABILITY_CURVE_FILE = 'over_1.eps'
plt.plot(list(curve_data.keys()), list(curve_data.values())/orig_acc)
plt.xscale('symlog')
plt.xlabel('num. words in vocab')
plt.ylabel('relative accuracy')
plt.savefig(OVERSTABILITY_CURVE_FILE, format='eps')
plt.savefig(OVERSTABILITY_CURVE_FILE.replace('eps','png'), format='png')
plt.tight_layout()
plt.show()
ATTRS_TSV = '/content/drive/My Drive/IG RESULTS/P1/MEMORY NET/attrs_1_new.tsv'
with open(ATTRS_TSV, 'a') as outf:
  c = 1
  for test,mem in tqdm(zip(t,m)): 
    ans = ''
    IG = integrated_gradients(graph, sess, min = 2, batch_size= 20, num_reps=20)
    for j in range(len(test)):
        question_attrs = []
        tsv_string= ''
        attrs, words= IG.explain(x = test[j], memory= mem[j], debug=False)
        for ind in range(len(words)):
          if words[ind] is not None:
              question_attrs.append(
                  '|'.join([ words[ind], str(attrs[ind]) ])
                  )
        tsv_string = ['||'.join(question_attrs)]
        ans += '\t'.join(tsv_string) + '\n'
        del attrs, words, question_attrs, tsv_string
        gc.collect()
        c+=1
        print(c)
    outf.write(ans)
    outf.flush()
    del ans, IG
    gc.collect()

###### MAIN RUN
import time
start = time.time()
c = 1
for test,mem in zip(t,m): 
  for j in range(len(test)):
    out = IG.explain(x = test[j], memory= mem[j], debug=False) ## debug for errors
    convert_html_to_pdf(out, ATTRS_DIR+str(fold_no)+'_'+str(c)+'.pdf')
    c+=1
end = time.time()
print(start-end)
from google_drive_downloader import GoogleDriveDownloader as gdd
gdd.download_file_from_google_drive\
(file_id='1CIEpiDmzLmJ6LMCVSOmCKw_eOg4ocuS4', dest_path='/content/AES.zip', unzip=True)

import nltk
from nltk import tokenize
import pickle
from random import shuffle
import random
def create_adv_data(data_test, file_path):	
    def rindex(lst, value):
      lst.reverse()
      i = lst.index(value)
      lst.reverse()
      return len(lst) - i - 1
    
    with open('/content/calling-out-bluff/'+file_path, 'rb') as handle:
        songs= pickle.load(handle)
    song_list = []
    for i in songs:
      song_sents = tokenize.sent_tokenize(i)
      song_list.extend(song_sents)
    
    song_lyrics = []
    for x in song_list:
      a = []
      for w in tokenize.word_tokenize(x):
        try:
          a.append(tokenizer[w.lower()])
        except:
          a.append(0)
      song_lyrics.append(a)
    
    songs_beg=[]
    mem_beg = []
    songs_end=[]
    mem_end = []
    
    for r in data_test:
      test = r[0]
      mem = r[1]
      for i,r in enumerate(test):
        if 0 in r:
          ind = rindex(r.tolist(), 0)
        else:
          ind = 0
        ar = random.sample(song_lyrics, 20)
        ar = [x for sublist in ar for x in sublist]
        ar = ar[:ind+1]
        songs_beg.append(ar + r[ind+1:].tolist())
        songs_end.append(r[ind+1:].tolist() + ar)
        mem_beg.append(mem[i])
        mem_end.append(mem[i])
    
    song_beg_data = pad_sequences(songs_beg, maxlen=MAX_SEQUENCE_LENGTH, padding = 'pre', truncating='pre') #padding to max_length
    song_end_data = pad_sequences(songs_end, maxlen=MAX_SEQUENCE_LENGTH, padding = 'post', truncating='post') #padding to max_length
    return song_beg_data, song_end_data, mem_beg, mem_end
def predict_and_score_save(model, beg, end, orig, f_name, prompt, data=None):
    def npos(orig, new):
      count = 0
      for i in range(len(orig)):
        if new[i]>orig[i]:
          count+=1 
      return count

    def nneg(orig, new):
      count = 0
      for i in range(len(orig)):
        if new[i]<orig[i]:
          count+=1 
      return count

    def nsame(orig, new):
      count = 0
      for i in range(len(orig)):
        if new[i]==orig[i]:
          count+=1 
      return count

    def mu(orig, new):
      s=0
      n = len(orig)
      for i in range(n):
        s+=(orig[i] - new[i])
      return s/n

    def absmu(orig, new):
      s=0
      n = len(orig)
      for i in range(n):
        s+=(orig[i] - new[i])
      return abs(s)/n

    def sd(orig, new):
      mu_val = mu(orig, new)
      s=0
      n = len(orig)
      for i in range(n):
        s+=(orig[i] - new[i] - mu_val)**2
      return (s/n)**(1/2)

    def muneg(orig, new):
      s=0
      n = len(orig)
      for i in range(n):
        if orig[i] < new[i]:
          s+=-(orig[i] - new[i])
      return s/n

    def mupos(orig, new):
      s=0
      n = len(orig)
      for i in range(n):
        if orig[i] > new[i]:
          s+=-(orig[i] - new[i])
      return s/n
    
    def get_pred_stats(orig, new):
      a = ('kappa', cohen_kappa_score(orig, new, weights='quadratic'))
      b = ('NPOS', npos(orig, new))
      c = ('NNEG', nneg(orig, new))
      d = ('NSAME', nsame(orig, new))
      e = ('MU', mu(orig, new))
      f = ('ABSMU', absmu(orig, new))
      g = ('SD', sd(orig, new))
      h = ('MUPOS', mupos(orig, new))
      i = ('MUNEG', muneg(orig, new))
      return [a,b,c,d,e,f,g,h,i]

    beg_preds = []
    for test,mem in beg:

        feed = {}
        input_df = [test, mem, 1]
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        beg_preds.extend(pred)
    
    end_preds = []
    for test,mem in end:

        feed = {}
        input_df = [test, mem, 1]
        for i, key in enumerate(INPUT_TENSORS):
            feed[key.name] = input_df[i]
        pred = sess.run(PRED_TENSOR,feed)
        end_preds.extend(pred)

    beg_fin =[a+2 for a in beg_preds.flatten().tolist()]
    end_fin =[a+2 for a in end_preds.flatten().tolist()]
    # y_pred_fin =  [int(round(a*(range_max-range_min)+range_min)) for a in main_preds.flatten().tolist()]
    orig_fin =   [int(a) for a in orig]
    return (beg_fin, end_fin, orig_fin)
    # print(, orig_fin)

    # with open('/content/drive/My Drive/IG RESULTS/P'+prompt+'/SKIPFLOW/ADV/'+f_name+'_results_'+prompt+'.txt', 'w') as f:
    #   f.write(str(get_pred_stats(orig_fin, beg_fin)))
    #   f.write(str(get_pred_stats(orig_fin, end_fin)))
def store_attr(f_name, data, prompt, n =10):
  import os
  import gc
  ATTRS_TSV = './drive/My Drive/IG RESULTS/P'+prompt+'/MEMORY NET/attrs_stor_'+f_name+'.tsv'
  ATTRS_DIR = './drive/My Drive/IG RESULTS/P'+prompt+'/MEMORY NET/'+f_name+'/'
  if os.path.isdir(ATTRS_DIR):
    pass
  else:
    os.mkdir(ATTRS_DIR)
  with open(ATTRS_DIR+f_name+'.pkl', 'wb') as f:
    pickle.dump(data,f)
  batch = 1
  with open(ATTRS_TSV, 'a') as outf:
    c=0
    while c<n:
      ans = ''
      for i,v in enumerate(data[c:c+batch]):
          tsv_string = ''
          attrs = get_attributions(np.array([v]))[0]
          words,count = sequence_to_text(v)
          assert len(words[count:]) == len(attrs[count:])
          question_attrs = []
          html = vis(attrs[count:], words[count:])
          convert_html_to_pdf(html, ATTRS_DIR+str(c)+'.pdf')
          for ind in range(len(words[count:])):
            # print( '|'.join([ words[count:][ind], str(attrs[count:][ind]) ]))
            if words[count:][ind] != None and str(attrs[count:][ind])!=None:
              question_attrs.append(
                  '|'.join([ words[count:][ind], str(attrs[count:][ind]) ])
                  )
          tsv_string = ['||'.join(question_attrs)]
          ans += '\t'.join(tsv_string) + '\n'
          del attrs, words, question_attrs, tsv_string
          gc.collect()
      c+=batch
      outf.write(ans)
      outf.flush()
      del ans
      gc.collect()
    outf.write('done')
  print('DONE')
import nltk
nltk.download('punkt')
songs_beg, songs_end = create_adv_data([t,m], 'song.pickle')
speech_beg, speech_end = create_adv_data([t,m], 'speeches.pickle')
truth_beg, truth_end = create_adv_data([t,m], 'un_truth.pickle')
false_beg, false_end = create_adv_data([t,m], 'un_false.pickle')
f_names = ['song_beg', 'song_end', 'speech_beg', 'speech_end', 'truth_beg', 'truth_end', 'false_beg', 'false_end']
datas = [songs_beg, songs_end, speech_beg, speech_end, truth_beg, truth_end,  false_beg, false_end]
for i in range(len(f_names)):
  store_attr(f_names[i], datas[i],prompt =str(1),n=10)
range_max =12
range_min =2<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13892698797486525, 'fraction_numerical': 0.009170361391981118, 'mean_word_length': 2.8753399258343633, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '650876', 'license': 'MIT', 'n_tokens_mistral': 23478, 'n_tokens_neox': 22706, 'n_words': 4600, 'path': 'IG_MEMORY_3_FINAL.ipynb', 'repo_name': 'midas-research/interpreting-AES-Integrated-Gradients', 'size': '62702'}