<jupyter_start><jupyter_text>from tensorflow.random import set_seedfrom numpy.random import seedimport randomseed_value = 0set_seed(seed_value)seed(seed_value)os.environ['PYTHONHASHSEED'] = str(seed_value)random.seed(seed_value)<jupyter_code>import All_RUT_Models
import RUT_Utils
# hyper parameters for this model

max_len = 150
embed_size = 300
pre_trained_flag = True
embed_trainable = False
emb_weights_init = 'glorot_normal'
spdrpt = 0.40
drpt = 0.2
fc_weights_init = 'glorot_uniform'
fc_act = 'elu'
lr_rate = 0.001
optimizer = 'adam'
lstm_units = 130
multi_gpu_flag = 0
gpus = 2
batch = 16
nepochs = 10
patience = 5
decay = True
decay_rate = 0.5
decay_after = 3
#embeddingfile = './General_Embeddings/glove.txt'
#embeddingfile = './General_Embeddings/w2v_cbow.txt'
#embeddingfile = './General_Embeddings/w2v_sg.txt'
#embeddingfile = './General_Embeddings/ft_cbow.vec'
embeddingfile = 'wiki-news-300d-1M.vec'

embedding_matrix = []
#max_features = 100000

modelname = 'BLSTM_ft_sg'

modelpath = './Models/' + modelname + '/'

if not os.path.exists( modelpath ):
    os.makedirs( modelpath )
if not os.path.exists( './Results/' ):
    os.makedirs( './Results/' )
def hms_string(sec_elapsed):
    h = int(sec_elapsed / (60 * 60))
    m = int((sec_elapsed % (60 * 60)) / 60)
    s = sec_elapsed % 60
    return "{}:{:>02}:{:>05.2f}".format(h, m, s)
def convert_lower_case(data):
    # Convert the input text into lowercase text
    return np.char.lower(str(data))

def remove_stop_words(data):
    # Tokenize the input text and remove stopwords from the corpus
    stop_words = stopwords.words('english')
    lemmatizer = WordNetLemmatizer()
    words = word_tokenize(str(data))
    new_text = ""
    for w in words:
        if w not in stop_words and len(w) > 3:
            new_text = new_text + " " + lemmatizer.lemmatize(w)
    return new_text

def remove_punctuation(data):
    # Remove punctuations defined below from input text
    symbols = "!\"#$%&()*+-./:;<=>?@[\]^_`{|}~\n"
    for i in range(len(symbols)):
        data = np.char.replace(data, symbols[i], ' ')
        data = np.char.replace(data, "  ", " ")
    data = np.char.replace(data, ',', '')
    return data

def remove_apostrophe(data):
    # Remove apostrophe from the input text
    return np.char.replace(data, "'", "")

def preprocess(data):
    # Preprocess the input text
    data = convert_lower_case(data)
    data = remove_punctuation(data) #remove comma seperately
    data = remove_apostrophe(data)
    data = remove_stop_words(data)
    return data

def get_tokens(dataframe, column):
    tokens = []
    for i in tqdm_notebook(dataframe[column][:]):
        _tokens = word_tokenize(preprocess(str(i)))
        tokens.append(_tokens)
        
    return tokens
train_data = pd.read_csv('data\\wiki_train.csv')
train_data = train_data.dropna(axis = 0)
#train_data = train_data.sample(n=100000, random_state=0)
train_data['toxicity'] = train_data['toxicity'].round()

df_test = pd.read_csv('test_data.csv')
df_test.loc[df_test['Label'] == 'BAD', 'Label'] = 1
df_test.loc[df_test['Label'] == 'NOT_BAD', 'Label'] = 0


train_feature = get_tokens(train_data, 'comment')
train_label = train_data['toxicity']

test_feature = get_tokens(df_test, 'Text')
test_label = df_test['Label']

identity_terms = []
for i in tqdm_notebook(range(len(df_test['Text']))):
    _comment = df_test.loc[i,  'Text'].split(" ")
    if len(_comment) < 3:
        _term = _comment[1]
        identity_terms.append(_term)
identity_terms = list(set(identity_terms))


terms = []
for i in range(len(df_test['Text'])):
    _text = df_test.loc[i, 'Text'].split(' ')
    _term = list(set(_text).intersection(set(identity_terms)))
    if len(_term) > 0:
        terms.append(_term[0])
    else:
        terms.append(np.nan)
        
df_test['Identity_Terms'] = terms
skf = StratifiedKFold( n_splits=5, random_state=0, shuffle=True )
print(skf)
tokenizer = Tokenizer()
tokenizer.fit_on_texts(train_feature)
train_features = tokenizer.texts_to_sequences(train_feature)
train_features = pad_sequences(train_features, maxlen = 128, dtype="int32")
train_features_vocab_size = len(tokenizer.word_index) + 1
print(train_features_vocab_size)

train_labels = tf.convert_to_tensor(train_label, dtype="int32")

test_features = tokenizer.texts_to_sequences(test_feature)
test_features = pad_sequences(test_features, maxlen = 128, dtype="int32")
features_vocab_size = len(tokenizer.word_index) + 1
print(features_vocab_size)

test_labels = tf.convert_to_tensor(test_label, dtype="int32")
def get_coefs( word, *arr ):
    return word, np.asarray( arr, dtype='float32' )

def get_vectors( tokenizer ):
    word_index = tokenizer.word_index
    num_words = min( len(tokenizer.word_index) + 1, len( word_index ) + 1 )
    embedding_matrix = np.zeros( ( num_words, embed_size ) )
    for word, i in word_index.items(  ):
        if i >= len(tokenizer.word_index) + 1:
            continue
        embedding_vector = embeddings_index.get( word )
        if embedding_vector is not None:
            embedding_matrix[i] = embedding_vector
    gc.collect()
    return embedding_matrix

if pre_trained_flag == True:
    embeddings_index = dict( get_coefs( *o.rstrip().rsplit(' ') ) for o in open( embeddingfile, encoding='utf-8' ) )<jupyter_output><empty_output><jupyter_text>from tensorflow.python.framework import opsops.reset_default_graph()checkpoint_filepath = 'checkpoints/model.h5'model_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(    filepath=checkpoint_filepath,    save_weights_only=False,    monitor='val_false_positives',    mode='min',    save_best_only=True,    verbose=1)embedding_matrix = get_vectors( tokenizer=tokenizer)inputs = tf.keras.Input(shape=(None,), dtype="int32")x = tf.keras.layers.Embedding( input_dim=len(tokenizer.word_index)+1, output_dim=embed_size,                      weights=[embedding_matrix], trainable=embed_trainable, name='Embedding' )(inputs)x = tf.keras.layers.SpatialDropout1D( spdrpt, name='SpatialDropout1D' )( x )x = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(128))(x)x =  tf.keras.layers.Dropout( drpt, name='Dropout' )( x )fc1 =  tf.keras.layers.Dense( 128, activation=fc_act, kernel_initializer=fc_weights_init, name='FC1' )( x )fc2 = tf.keras.layers.Dense( 64, activation=fc_act, kernel_initializer=fc_weights_init, name='FC2')( fc1 )outputs =  tf.keras.layers.Dense( 1, activation='sigmoid', name='Output' )( fc2 )model = tf.keras.Model(inputs = inputs, outputs = outputs)model.compile( loss='binary_crossentropy', optimizer=optimizer, metrics = ['accuracy',tf.keras.metrics.AUC(), tf.keras.metrics.FalsePositives(thresholds=None, name=None, dtype=None)] )xtrain, xval, ytrain, yval = train_test_split( train_features, train_label, test_size=0.25, random_state=0 )hist = model.fit( xtrain, ytrain, batch_size=batch, validation_data=( xval,yval ),                     epochs=nepochs, verbose=1, callbacks=[model_checkpoint_callback])model.load_weights(checkpoint_filepath)<jupyter_code>model = tf.keras.models.load_model('checkpoints/model.h5')
xf_positive = 0
xd_positive = 0
xf_total = 0
xd_total = 0

for i in tqdm_notebook(range(len(train_feature))):
    if(train_labels[i] == 1 and len(list(set(train_feature[i]).intersection(set(terms)))) > 0):
        xd_positive += 1
        xd_total += 1
    elif(len(list(set(train_feature[i]).intersection(set(terms)))) > 0):
        xd_total += 1
    elif(train_labels[i] == 1 and len(list(set(train_feature[i]).intersection(set(terms))))==0):
        xf_positive += 1
        xf_total += 1
    elif(len(list(set(train_feature[i]).intersection(set(terms))))== 0):
        xf_total += 1
        
pf = xf_positive / xf_total
pd = xd_positive / xd_total
discrimination = pf - pd
discrimination
pred = model.predict(train_features)
xf_positive = 0
xd_positive = 0
xf_total = 0
xd_total = 0

for i in tqdm_notebook(range(len(train_feature))):
    if(pred[i].round() == 1 and len(list(set(train_feature[i]).intersection(set(terms)))) > 0):
        xd_positive += 1
        xd_total += 1
    elif(len(list(set(train_feature[i]).intersection(set(terms)))) > 0):
        xd_total += 1
    elif(pred[i].round() == 1 and len(list(set(train_feature[i]).intersection(set(terms))))==0):
        xf_positive += 1
        xf_total += 1
    elif(len(list(set(train_feature[i]).intersection(set(terms))))== 0):
        xf_total += 1
pf = xf_positive / xf_total
pd = xd_positive / xd_total
discrimination = pf - pd
discrimination
pred = model.predict(test_features)
df_test['prediction_scores'] = pred
accuracy_score(test_labels, pred.round())
xf_positive = 0
xd_positive = 0
xf_total = 0
xd_total = 0

for i in tqdm_notebook(range(len(test_feature))):
    if(pred[i].round() == 1 and len(list(set(test_feature[i]).intersection(set(terms)))) > 0):
        xd_positive += 1
        xd_total += 1
    elif(len(list(set(test_feature[i]).intersection(set(terms)))) > 0):
        xd_total += 1
    elif(pred[i].round() == 1 and len(list(set(test_feature[i]).intersection(set(terms))))==0):
        xf_positive += 1
        xf_total += 1
    elif(len(list(set(test_feature[i]).intersection(set(terms))))== 0):
        xf_total += 1
        
pf = xf_positive / xf_total
pd = xd_positive / xd_total
discrimination = pf - pd
discrimination
import pandas as pd
def perf_measure(y_actual, y_hat):
    TP = 0
    FP = 0
    TN = 0
    FN = 0

    for i in range(len(y_hat)): 
        if y_actual[i]==y_hat[i]==1:
           TP += 1
        if y_hat[i]==1 and y_actual[i]!=y_hat[i]:
           FP += 1
        if y_actual[i]==y_hat[i]==0:
           TN += 1
        if y_hat[i]==0 and y_actual[i]!=y_hat[i]:
           FN += 1

    return(TN, FP, FN, TP)



total_tn, total_fp, total_fn, total_tp = confusion_matrix(test_labels, pred.round()).ravel()
total_fpr = total_fp / (total_fp + total_tn )
total_fnr = total_fn / (total_fn + total_tp)
false_positive = []
false_negative = []
identity_terms = []
for identity_term in set(terms):
    data = df_test[df_test['Identity_Terms'] == identity_term].reset_index()
    y_true, y_pred = data['Label'].astype(int), data['prediction_scores']
    tn, fp, fn, tp = perf_measure(y_true, y_pred.round())
    try:
        fpr = fp / (fp + tn)
        fnr = fn / (fn + tp)
        false_positive.append(fpr)
        false_negative.append(fnr)
        identity_terms.append(identity_term)
    except:
        print("Error in ", identity_term)

    
eval_scores = pd.DataFrame(identity_terms, columns = ['Identity_Titles'])
eval_scores['Identity_Term_False_Positive'] = false_positive
eval_scores['Total_False_Positive'] = total_fpr
eval_scores['Identity_Term_False_Negatives'] = false_negative
eval_scores['Total_False_Negative'] = total_fnr
eval_scores['FPR - FPRt'] = abs(total_fpr - eval_scores['Identity_Term_False_Positive'])
eval_scores['FNR - FNRt'] = abs(total_fnr - eval_scores['Identity_Term_False_Negatives'])
eval_scores
eval_scores['FPR - FPRt'].sum(), eval_scores['FNR - FNRt'].sum()

total_auc = roc_auc_score(test_labels, pred.round())
terms_auc = []
identity_terms = []
for identity_term in set(terms):
    term_data = df_test[df_test['Identity_Terms'] == identity_term].reset_index()
    data = df_test.sample(n=len(term_data['Text']), random_state=0)
    data = term_data.append(data, ignore_index=True)
    y_true, y_pred = data['Label'].astype(int), data['prediction_scores']

    try:
        term_auc = roc_auc_score(y_true, y_pred.round())
        terms_auc.append(term_auc)
        identity_terms.append(identity_term)
    except:
        print("Error in ",identity_term)


    
eval_scores = pd.DataFrame(identity_terms, columns = ['Identity_Titles'])
eval_scores['AUCt'] = terms_auc
eval_scores['AUC'] = total_auc
eval_scores['AUC - AUCt'] = abs(eval_scores['AUC'] - eval_scores['AUCt'])
eval_scores
print(eval_scores['AUC - AUCt'].sum())<jupyter_output>0.8434344934908964<jupyter_text>theta = 0.55features = []labels = []for i in tqdm_notebook(range(len(test_features[:]))):    p_positive = pred[i]    p_negative = 1 - p_positive    feature = test_features[i]    label = df_test.loc[i, 'Label']    feature = [np.hstack((feature, label))]    if max(p_positive, p_negative) < theta:        features.append(feature)        labels.append(label)from sklearn.neighbors import KNeighborsClassifierKNN = KNeighborsClassifier(n_neighbors=3, weights = 'distance',n_jobs = -1)KNN.fit(features, labels)SM_pred = []indices = []for i in tqdm_notebook(range(len(test_features[:]))):    p_positive = pred[i]    p_negative = 1 - p_positive    feature = [test_features[i]]    label = df_test.loc[i, 'Label']    feature = [np.hstack((feature, label))]    if max(p_positive, p_negative) < theta:        prediction = KNN.predict(feature)        SM_pred.append(int(prediction))    else:        SM_pred.append(int(p_positive))<jupyter_code>from sklearn.neighbors import KNeighborsClassifier
KNN = KNeighborsClassifier(n_neighbors=3, weights = 'distance',n_jobs = -1)
KNN.fit(test_features, test_labels)

theta = 0.8
SM_pred = []
for i in tqdm_notebook(range(len(test_features[:]))):
    p_positive = pred[i]
    p_negative = 1 - p_positive
    feature = [test_features[i]]
    label = df_test.loc[i, 'Label']
    #feature = [np.hstack((feature, label))]
    if max(p_positive, p_negative) < theta:
        prediction = KNN.predict(feature)
        SM_pred.append(prediction)
    else:
        SM_pred.append(pred[i].round())
xf_positive = 0
xd_positive = 0
xf_total = 0
xd_total = 0

for i in tqdm_notebook(range(len(test_feature))):
    if(SM_pred[i] == 1 and len(list(set(test_feature[i]).intersection(set(terms)))) > 0):
        xd_positive += 1
        xd_total += 1
    elif(len(list(set(test_feature[i]).intersection(set(terms)))) > 0):
        xd_total += 1
    elif(SM_pred[i] == 1 and len(list(set(test_feature[i]).intersection(set(terms))))== 0):
        xf_positive += 1
        xf_total += 1
    elif(len(list(set(test_feature[i]).intersection(set(terms))))== 0):
        xf_total += 1
pf = xf_positive / xf_total
pd = xd_positive / xd_total
discrimination = pf - pd
discrimination
accuracy_score(test_labels, SM_pred)
#test_data['prediction_scores'] = ROC_pred
import pandas as pd
total_tn, total_fp, total_fn, total_tp = confusion_matrix(test_labels, SM_pred).ravel()
total_fpr = total_fp / (total_fp + total_tn )
total_fnr = total_fn / (total_fn + total_tp)
false_positive = []
false_negative = []
identity_terms = []
for identity_term in set(terms):
    data = df_test[df_test['Identity_Terms'] == identity_term].reset_index()
    y_true, y_pred = data['Label'].astype(int), data['prediction_scores']
    tn, fp, fn, tp = perf_measure(y_true, y_pred.round())
    try:
        fpr = fp / (fp + tn)
        fnr = fn / (fn + tp)
        false_positive.append(fpr)
        false_negative.append(fnr)
        identity_terms.append(identity_term)
    except:
        print("Error in ", identity_term)

    
eval_scores = pd.DataFrame(identity_terms, columns = ['Identity_Titles'])
eval_scores['Identity_Term_False_Positive'] = false_positive
eval_scores['Total_False_Positive'] = total_fpr
eval_scores['Identity_Term_False_Negatives'] = false_negative
eval_scores['Total_False_Negative'] = total_fnr
eval_scores['FPR - FPRt'] = abs(total_fpr - eval_scores['Identity_Term_False_Positive'])
eval_scores['FNR - FNRt'] = abs(total_fnr - eval_scores['Identity_Term_False_Negatives'])
eval_scores
eval_scores['FPR - FPRt'].sum(), eval_scores['FNR - FNRt'].sum()
total_auc = roc_auc_score(test_labels, SM_pred)
terms_auc = []
identity_terms = []
for identity_term in set(terms):
    term_data = df_test[df_test['Identity_Terms'] == identity_term].reset_index()
    data = df_test.sample(n=len(term_data['Text']), random_state=0)
    data = term_data.append(data, ignore_index=True)
    y_true, y_pred = data['Label'].astype(int), data['prediction_scores']

    try:
        term_auc = roc_auc_score(y_true, y_pred.round())
        terms_auc.append(term_auc)
        identity_terms.append(identity_term)
    except:
        print("Error in ",identity_term)


    
eval_scores = pd.DataFrame(identity_terms, columns = ['Identity_Titles'])
eval_scores['AUCt'] = terms_auc
eval_scores['AUC'] = total_auc
eval_scores['AUC - AUCt'] = abs(eval_scores['AUC'] - eval_scores['AUCt'])
eval_scores
print(eval_scores['AUC - AUCt'].sum())<jupyter_output>6.044544566408519
{'fraction_non_alphanumeric': 0.1407734264877122, 'fraction_numerical': 0.015198872341729485, 'mean_word_length': 4.496126641966992, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '163694', 'license': 'MIT', 'n_tokens_mistral': 6214, 'n_tokens_neox': 5783, 'n_words': 1057, 'path': 'SM-LSTM.ipynb', 'repo_name': 'Abubakarjutt/Unintended-Identity-Bias-in-Text-Classification', 'size': '16317'}