import torch from torch import nn from transformers import AutoModel, AutoTokenizer import gradio as gr device = torch.device("cpu") class RaceClassifier(nn.Module): def __init__(self, n_classes): super(RaceClassifier, self).__init__() self.bert = AutoModel.from_pretrained("vinai/bertweet-base") self.drop = nn.Dropout(p=0.3) # can be changed in future self.out = nn.Linear(self.bert.config.hidden_size, n_classes) # linear layer for the output with the number of classes def forward(self, input_ids, attention_mask): bert_output = self.bert( input_ids=input_ids, attention_mask=attention_mask ) last_hidden_state = bert_output[0] pooled_output = last_hidden_state[:, 0] output = self.drop(pooled_output) return self.out(output) race_labels = { 0: "African American", 1: "Asian", 2: "Latin", 3: "White" } age_labels = { 0: "Adult", 1: "Elderly", 2: "Young" } education_labels = { 0: "Educated", 1: "Uneducated" } gender_labels = { 0: "Female", 1: "Male", 2: "Non-Binary", 3: "Transgender" } orientation_labels = { 0: "Heterosexual", 1: "LGBTQ" } model_race = RaceClassifier(n_classes=4) model_race.to(device) model_race.load_state_dict(torch.load('best_model_race.pt', map_location=torch.device('cpu'))) model_age = RaceClassifier(n_classes=3) model_age.to(device) model_age.load_state_dict(torch.load('best_model_age.pt', map_location=torch.device('cpu'))) model_education = RaceClassifier(n_classes=2) model_education.to(device) model_education.load_state_dict(torch.load('best_model_education.pt', map_location=torch.device('cpu'))) model_gender = RaceClassifier(n_classes=4) model_gender.to(device) model_gender.load_state_dict(torch.load('best_model_gender.pt', map_location=torch.device('cpu'))) model_orientation = RaceClassifier(n_classes=2) model_orientation.to(device) model_orientation.load_state_dict(torch.load('best_model_orientation.pt', map_location=torch.device('cpu'))) def evaluate(model, input, mask): model.eval() with torch.no_grad(): outputs = model(input, mask) probs = torch.nn.functional.softmax(outputs, dim=1) predictions = torch.argmax(outputs, dim=1) predictions = predictions.cpu().numpy() return probs, predictions def write_output(probs, predictions, title, labels): output_string = f"{title.upper()}\n Probabilities:\n" for i, prob in enumerate(probs[0]): print(f"{labels[i]} = {round(prob.item() * 100, 2)}%") output_string += f"{labels[i]} = {round(prob.item() * 100, 2)}%\n" output_string += f"Predicted as: {labels[predictions[0]]}\n" return output_string def predict(*text): tweets = [tweet for tweet in text if tweet] print(tweets) sentences = tweets tokenizer = AutoTokenizer.from_pretrained("vinai/bertweet-base", normalization=True) encoded_sentences = tokenizer( sentences, padding=True, truncation=True, return_tensors='pt', max_length=100, ) input_ids = encoded_sentences["input_ids"].to(device) attention_mask = encoded_sentences["attention_mask"].to(device) race_probs, race_predictions = evaluate(model_race, input_ids, attention_mask) age_probs, age_predictions = evaluate(model_age, input_ids, attention_mask) education_probs, education_predictions = evaluate(model_education, input_ids, attention_mask) gender_probs, gender_predictions = evaluate(model_gender, input_ids, attention_mask) orientation_probs, orientation_predictions = evaluate(model_orientation, input_ids, attention_mask) final_output = str() final_output += write_output(race_probs, race_predictions, "race", race_labels) final_output += "\n" final_output += write_output(age_probs, age_predictions,"age",age_labels) final_output += "\n" final_output += write_output(education_probs,education_predictions,"education", education_labels) final_output += "\n" final_output += write_output(gender_probs, gender_predictions, "gender", gender_labels) final_output += "\n" final_output += write_output(orientation_probs, orientation_predictions, "sexual orientation", orientation_labels) return final_output max_textboxes = 20 def update_textboxes(k): components = [] if k is None: k = 0 for i in range(max_textboxes): if i < k: components.append(gr.update(visible=True)) else: components.append(gr.update(visible=False)) return components def clear_textboxes(): return [gr.update(value='') for _ in range(max_textboxes)] def clear_output_box(): return gr.update(value='') with gr.Blocks() as demo: with gr.Row(): with gr.Column(scale=1): s = gr.Slider(1, max_textboxes, value=1, step=1, label="How many tweets do you want to enter:") textboxes = [gr.Textbox(label=f"Tweet {i + 1}", visible=(i == 0)) for i in range(max_textboxes)] s.change(fn=update_textboxes, inputs=s, outputs=textboxes) btn = gr.Button("Predict") btn_clear = gr.Button("Clear") with gr.Column(scale=1): output = gr.Textbox(label="Profile of User") btn.click(fn=predict, inputs=textboxes, outputs=output) btn_clear.click(fn=clear_textboxes, outputs=textboxes) btn_clear.click(fn=clear_output_box, outputs=output) demo.launch()