nishan-chatterjee
additional comments
468c17d
raw
history blame
4.5 kB
import torch
import numpy as np
import networkx as nx
from transformers import AutoModelForSequenceClassification, AutoTokenizer
# Function to make logits consistent based on the hierarchy matrix R
def _make_logits_consistent(x, R):
c_out = x.unsqueeze(1) + 10
c_out = c_out.expand(len(x), R.shape[1], R.shape[1])
R_batch = R.expand(len(x), R.shape[1], R.shape[1]).to(x.device)
final_out, _ = torch.max(R_batch * c_out, dim=2)
return final_out - 10
# Function to initialize the model, tokenizer, and hierarchy matrix
def initialize_model():
# Define the hierarchy graph
G = nx.DiGraph()
edges = [
("ROOT", "Logos"),
("Logos", "Repetition"), ("Logos", "Obfuscation, Intentional vagueness, Confusion"), ("Logos", "Reasoning"), ("Logos", "Justification"),
("Justification", "Slogans"), ("Justification", "Bandwagon"), ("Justification", "Appeal to authority"), ("Justification", "Flag-waving"), ("Justification", "Appeal to fear/prejudice"),
("Reasoning", "Simplification"),
("Simplification", "Causal Oversimplification"), ("Simplification", "Black-and-white Fallacy/Dictatorship"), ("Simplification", "Thought-terminating cliché"),
("Reasoning", "Distraction"),
("Distraction", "Misrepresentation of Someone's Position (Straw Man)"), ("Distraction", "Presenting Irrelevant Data (Red Herring)"), ("Distraction", "Whataboutism"),
("ROOT", "Ethos"),
("Ethos", "Appeal to authority"), ("Ethos", "Glittering generalities (Virtue)"), ("Ethos", "Bandwagon"), ("Ethos", "Ad Hominem"), ("Ethos", "Transfer"),
("Ad Hominem", "Doubt"), ("Ad Hominem", "Name calling/Labeling"), ("Ad Hominem", "Smears"), ("Ad Hominem", "Reductio ad hitlerum"), ("Ad Hominem", "Whataboutism"),
("ROOT", "Pathos"),
("Pathos", "Exaggeration/Minimisation"), ("Pathos", "Loaded Language"), ("Pathos", "Appeal to (Strong) Emotions"), ("Pathos", "Appeal to fear/prejudice"), ("Pathos", "Flag-waving"), ("Pathos", "Transfer")
]
G.add_edges_from(edges)
# model and tokenizer is saved in the current directory
model_dir = "."
# loading the model and tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = AutoModelForSequenceClassification.from_pretrained(model_dir)
# Set device to GPU if available
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
# Create the hierarchy matrix R based on the graph structure
A = nx.to_numpy_array(G).transpose()
R = np.zeros(A.shape)
np.fill_diagonal(R, 1)
g = nx.DiGraph(A)
for i in range(len(A)):
descendants = list(nx.descendants(g, i))
if descendants:
R[i, descendants] = 1
R = torch.tensor(R).transpose(1, 0).unsqueeze(0)
return tokenizer, model, R, G, device
# Function to predict persuasion labels for a given text
def predict_persuasion_labels(text, tokenizer, model, R, G, device):
# Tokenize and encode the input text
encoding = tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=128,
return_token_type_ids=False,
padding="max_length",
truncation=True,
return_attention_mask=True,
return_tensors="pt",
)
# Forward pass through the model
with torch.no_grad():
outputs = model(
input_ids=encoding["input_ids"].to(device),
attention_mask=encoding["attention_mask"].to(device),
)
# Make logits consistent based on the hierarchy matrix R
logits = _make_logits_consistent(outputs.logits, R)
logits[:, 0] = -1.0
logits = logits > 0.0
# Get the complete predicted hierarchy of labels
complete_predicted_hierarchy = np.array(G.nodes)[logits[0].cpu().nonzero()].flatten().tolist()
# Get the child-only labels (labels without any successors)
child_only_labels = []
for label in complete_predicted_hierarchy:
if not list(G.successors(label)):
child_only_labels.append(label)
return complete_predicted_hierarchy, child_only_labels
tokenizer, model, R, G, device = initialize_model()
# Main inference function
def inference(text):
return predict_persuasion_labels(text, tokenizer, model, R, G, device)
if __name__ == "__main__":
# ask the user for input
text = input("Enter the text: ")
print(inference(text))