Empathic-Insight-Face-Large
10
license:cc-by-4.0
by
laion
Other
OTHER
New
0 downloads
Early-stage
Edge AI:
Mobile
Laptop
Server
Unknown
Mobile
Laptop
Server
Quick Summary
Empathic-Insight-Face-Large [](https://colab.
Code Examples
--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")--- 1. Define MLP Architecture (Big Model) ---pythontransformers
import torch
import torch.nn as nn
from transformers import AutoModel, AutoProcessor
from PIL import Image
import numpy as np
import json
from pathlib import Path # Used for cleaner path handling
# --- 1. Define MLP Architecture (Big Model) ---
class MLP(nn.Module):
def __init__(self, input_size=1152, output_size=1):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 1024),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, output_size)
)
def forward(self, x):
return self.layers(x)
# --- 2. Load Models and Processor ---
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# === IMPORTANT: Set this to the directory where your .pth models are downloaded ===
# If you've cloned the repo, it might be "./" or the name of the cloned folder.
# Example: MODEL_DIRECTORY = Path("./Empathic-Insight-Face-Large_cloned_repo")
MODEL_DIRECTORY = Path(".") # Assumes models are in the current directory or a sub-directory
# If the models are in the root of where this script runs after cloning, "." is fine.
# If they are in a subfolder, e.g., "Empathic-Insight-Face-Large", use Path("./Empathic-Insight-Face-Large")
# ================================================================================
# Load SigLIP (ensure it's the correct one for 1152 dim)
siglip_model_id = "google/siglip2-so400m-patch16-384" # Produces 1152-dim embeddings
siglip_processor = AutoProcessor.from_pretrained(siglip_model_id)
siglip_model = AutoModel.from_pretrained(siglip_model_id).to(device).eval()
# Load neutral stats
neutral_stats_filename = "neutral_stats_cache-_human-binary-big-mlps_v8_two_stage_higher_lr_stage2_5_200+"
neutral_stats_path = MODEL_DIRECTORY / neutral_stats_filename
neutral_stats_all = {}
if neutral_stats_path.exists():
with open(neutral_stats_path, 'r') as f:
neutral_stats_all = json.load(f)
else:
print(f"Warning: Neutral stats file not found at {neutral_stats_path}. Mean subtraction will use 0.0 for all models.")
# Load all emotion MLP models
emotion_mlps = {}
print(f"Loading emotion MLP models from: {MODEL_DIRECTORY.resolve()}") # .resolve() gives absolute path
model_files_found = list(MODEL_DIRECTORY.glob("model_*_best.pth"))
if not model_files_found:
print(f"Warning: No model files found in {MODEL_DIRECTORY.resolve()}. Please check the MODEL_DIRECTORY path.")
for pth_file in model_files_found:
model_key_name = pth_file.stem # e.g., "model_elation_best"
try:
mlp_model = MLP().to(device)
mlp_model.load_state_dict(torch.load(pth_file, map_location=device))
mlp_model.eval()
emotion_mlps[model_key_name] = mlp_model
# print(f"Loaded: {model_key_name}")
except Exception as e:
print(f"Error loading {model_key_name} from {pth_file}: {e}")
if not emotion_mlps:
print(f"Error: No MLP models were successfully loaded. Check MODEL_DIRECTORY and file integrity.")
else:
print(f"Successfully loaded {len(emotion_mlps)} emotion MLP models.")
# --- 3. Prepare Image and Get Embedding ---
def normalized(a, axis=-1, order=2):
a = np.asarray(a) # Ensure 'a' is a numpy array
l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
l2[l2 == 0] = 1
return a / np.expand_dims(l2, axis)
# === Replace with your actual image path ===
# image_path_str = "path/to/your/image.jpg"
# try:
# image = Image.open(image_path_str).convert("RGB")
# inputs = siglip_processor(images=[image], return_tensors="pt", padding="max_length", truncation=True).to(device)
# with torch.no_grad():
# image_features = siglip_model.get_image_features(**inputs) # PyTorch tensor
# embedding_numpy_normalized = normalized(image_features.cpu().numpy()) # Normalize on CPU
# embedding_tensor = torch.from_numpy(embedding_numpy_normalized).to(device).float()
# except FileNotFoundError:
# print(f"Error: Image not found at {image_path_str}")
# embedding_tensor = None # Or handle error as appropriate
# except Exception as e:
# print(f"Error processing image {image_path_str}: {e}")
# embedding_tensor = None
# ==========================================
# --- For demonstration, let's use a random embedding if no image is processed ---
print("\nUsing a random embedding for demonstration purposes as no image path was set.")
embedding_tensor = torch.randn(1, 1152).to(device).float()
# ==============================================================================
# --- 4. Inference for all loaded models ---
results = {}
if embedding_tensor is not None and emotion_mlps:
with torch.no_grad():
for model_key_name, mlp_model_instance in emotion_mlps.items():
raw_score = mlp_model_instance(embedding_tensor).item()
neutral_mean = neutral_stats_all.get(model_key_name, {}).get("mean", 0.0)
mean_subtracted_score = raw_score - neutral_mean
# Derive a human-readable emotion name from the model key
emotion_name = model_key_name.replace("model_", "").replace("_best", "").replace("_", " ").title()
results[emotion_name] = {
"raw_score": raw_score,
"neutral_mean": neutral_mean,
"mean_subtracted_score": mean_subtracted_score
}
# Print results, sorted alphabetically by emotion name
print("\n--- Emotion Scores (Mean-Subtracted) ---")
# Sort items by emotion name for consistent output
for emotion, scores in sorted(results.items()):
print(f"{emotion:<35}: {scores['mean_subtracted_score']:.4f} (Raw: {scores['raw_score']:.4f}, Neutral Mean: {scores['neutral_mean']:.4f})")
else:
print("Skipping inference as either embedding_tensor is None or no MLP models were loaded.")Deploy This Model
Production-ready deployment in minutes
Together.ai
Instant API access to this model
Production-ready inference API. Start free, scale to millions.
Try Free APIReplicate
One-click model deployment
Run models in the cloud with simple API. No DevOps required.
Deploy NowDisclosure: We may earn a commission from these partners. This helps keep LLMYourWay free.