Ars135 commited on
Commit
4cf0bf1
·
verified ·
1 Parent(s): 08e7167

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -25
app.py CHANGED
@@ -6,66 +6,64 @@ from transformers import AutoImageProcessor, AutoModelForImageClassification
6
 
7
  # --- Configuration ---
8
  MODEL_NAME = "nateraw/fer-2013"
9
- # CRITICAL FIX: Explicitly set DEVICE to 'cpu' to prevent CUDA initialization errors
10
- # and memory issues on default Hugging Face Spaces hardware.
11
  DEVICE = "cpu"
12
 
13
  # --- Model and Processor Loading ---
14
- # Load model outside the prediction function for efficiency
15
  try:
16
  processor = AutoImageProcessor.from_pretrained(MODEL_NAME)
17
 
18
- # CRITICAL FIX: Load model with map_location='cpu' to prevent Out-Of-Memory (OOM)
19
- # errors during the loading process by mapping all tensors directly to CPU memory.
20
  model = AutoModelForImageClassification.from_pretrained(
21
  MODEL_NAME,
22
  map_location=DEVICE
23
- ).to(DEVICE)
24
-
 
25
  model.eval()
 
26
  LABELS = model.config.id2label
27
 
28
  print(f"Model loaded successfully on device: {DEVICE}")
29
 
30
  except Exception as e:
31
- # If loading fails, ensure the error message is descriptive.
32
  print(f"CRITICAL ERROR during model loading: {e}")
33
  processor = None
34
  model = None
35
- LABELS = {0: "Load_Error"}
 
36
 
37
  # --- Inference Function ---
38
  def classify_emotion(image_np: np.ndarray) -> str:
39
- """
40
- Performs emotion classification on an input image (numpy array).
41
- """
42
  if model is None or processor is None:
43
- return "System Error: Model failed to initialize. Please perform a Factory Reboot or check Space logs."
44
 
45
  try:
46
- # Convert numpy array (from Gradio) to PIL Image
47
  image = Image.fromarray(image_np).convert("RGB")
48
 
49
- # Preprocess the image
50
  inputs = processor(images=image, return_tensors="pt").to(DEVICE)
51
 
52
- # Run inference
53
  with torch.no_grad():
54
  outputs = model(**inputs)
55
 
56
- # Get predictions
57
  probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
58
-
59
- # Find the dominant emotion
60
  confidence, predicted_class_idx = torch.max(probabilities, 1)
61
 
62
  dominant_emotion = LABELS[predicted_class_idx.item()]
63
  confidence_score = confidence.item()
64
 
65
- # Format the result with clear markdown
66
  result_str = (
67
- f"**Predicted Emotion:** **{dominant_emotion.upper()}**\n\n"
68
- f"Confidence: {confidence_score:.2f}"
 
69
  )
70
  return result_str
71
 
@@ -80,10 +78,9 @@ iface = gr.Interface(
80
  label="Upload an image of a face"
81
  ),
82
  outputs=gr.Markdown(label="Predicted Emotion"),
83
- title="😊 PyTorch Facial Emotion Detection",
84
  description=(
85
- "Upload an image to classify the dominant emotion. Uses the **nateraw/fer-2013** PyTorch model. "
86
- "Built for stable deployment on Hugging Face Spaces."
87
  ),
88
  allow_flagging="never",
89
  theme=gr.themes.Soft()
 
6
 
7
  # --- Configuration ---
8
  MODEL_NAME = "nateraw/fer-2013"
9
+ # CRITICAL FIX: Explicitly and unconditionally set DEVICE to 'cpu'
 
10
  DEVICE = "cpu"
11
 
12
  # --- Model and Processor Loading ---
 
13
  try:
14
  processor = AutoImageProcessor.from_pretrained(MODEL_NAME)
15
 
16
+ # CRITICAL FIX: Use map_location='cpu' for memory-safe loading.
17
+ # We also use the local_files_only=False default to re-attempt download if necessary.
18
  model = AutoModelForImageClassification.from_pretrained(
19
  MODEL_NAME,
20
  map_location=DEVICE
21
+ )
22
+ # Ensure all layers are formally moved to the CPU
23
+ model.to(DEVICE)
24
  model.eval()
25
+
26
  LABELS = model.config.id2label
27
 
28
  print(f"Model loaded successfully on device: {DEVICE}")
29
 
30
  except Exception as e:
31
+ # If loading fails, return a highly specific error message to the user.
32
  print(f"CRITICAL ERROR during model loading: {e}")
33
  processor = None
34
  model = None
35
+ # This error message directs the user to the only remaining physical solution
36
+ LABELS = {0: "System Error: Failed to load model. Likely OOM. Try a paid CPU/GPU tier."}
37
 
38
  # --- Inference Function ---
39
  def classify_emotion(image_np: np.ndarray) -> str:
40
+ """Performs emotion classification on an input image (numpy array)."""
 
 
41
  if model is None or processor is None:
42
+ return LABELS[0]
43
 
44
  try:
45
+ # 1. Convert numpy array to PIL Image
46
  image = Image.fromarray(image_np).convert("RGB")
47
 
48
+ # 2. Preprocess
49
  inputs = processor(images=image, return_tensors="pt").to(DEVICE)
50
 
51
+ # 3. Run inference
52
  with torch.no_grad():
53
  outputs = model(**inputs)
54
 
55
+ # 4. Process predictions
56
  probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
 
 
57
  confidence, predicted_class_idx = torch.max(probabilities, 1)
58
 
59
  dominant_emotion = LABELS[predicted_class_idx.item()]
60
  confidence_score = confidence.item()
61
 
62
+ # 5. Format the result
63
  result_str = (
64
+ f"<h2 class='text-xl font-bold'>Predicted Emotion:</h2>"
65
+ f"<p class='text-3xl mt-2'>**{dominant_emotion.upper()}**</p>"
66
+ f"<p class='text-lg text-gray-600 mt-1'>Confidence: {confidence_score:.2f}</p>"
67
  )
68
  return result_str
69
 
 
78
  label="Upload an image of a face"
79
  ),
80
  outputs=gr.Markdown(label="Predicted Emotion"),
81
+ title="😊 PyTorch Facial Emotion Detection (Optimized)",
82
  description=(
83
+ "Upload an image containing a face to classify the dominant emotion. Built for maximum stability on Hugging Face Spaces."
 
84
  ),
85
  allow_flagging="never",
86
  theme=gr.themes.Soft()