fungi00 commited on
Commit
8427494
Β·
verified Β·
1 Parent(s): a8087a9

Update app.py

Browse files

Updated with MIA Analysis

Files changed (1) hide show
  1. app.py +157 -34
app.py CHANGED
@@ -20,7 +20,7 @@ from PIL import Image
20
  import torch
21
  import torch.nn as nn
22
 
23
- # Dynamic import from enhanced IBOM backend
24
  from IBOM import DetailedIBOMGenerator, get_paths_with_smart_fallback
25
 
26
  # Page configuration
@@ -118,17 +118,17 @@ def load_tbom_data(file_path="TBOM.json"):
118
  with open(tbom_path, 'r') as f:
119
  return json.load(f)
120
  except Exception:
121
- st.error("DBOM-T file not found. Please ensure TBOM.json is available.")
122
  return None
123
  except Exception as e:
124
- st.error(f"Error loading DBOM_T data: {str(e)}")
125
  return None
126
 
127
  #Enhanced IBOM Interface
128
 
129
  def create_enhanced_ibom_interface(tbom_data):
130
  """Complete enhanced IBOM interface with all advanced features"""
131
- st.markdown('<h2 class="sub-header">πŸ” Interactive Decision Bill of Materials (DBOM-I)</h2>', unsafe_allow_html=True)
132
 
133
  # Feature overview
134
  with st.expander("Enhanced Features Overview", expanded=False):
@@ -148,7 +148,7 @@ def create_enhanced_ibom_interface(tbom_data):
148
  with col2:
149
  st.markdown("""
150
  **πŸ“₯ Export Functionality:**
151
- - Download DBOM-I JSON files
152
  - CSV exports for spreadsheet analysis
153
  - Detailed analysis reports
154
 
@@ -164,12 +164,8 @@ def create_enhanced_ibom_interface(tbom_data):
164
  "Upload a mushroom image for comprehensive analysis",
165
  type=['jpg', 'jpeg', 'png', 'bmp'],
166
  help="Upload a clear image showing cap, gills, and stalk for detailed AI analysis"
167
- )
168
 
169
- # Display the disclaimer and caption AFTER the file uploader
170
- st.info("Disclaimer: **🚨 NEVER consume any mushroom based solely on AI analysis.**")
171
- st.caption("This tool is for educational and research purposes only.")
172
-
173
  # Main layout: Image on the left, results on the right
174
  img_col, results_col = st.columns([1, 2.5])
175
 
@@ -195,7 +191,7 @@ def create_enhanced_ibom_interface(tbom_data):
195
  st.warning("⚠️ Low resolution - results may be less accurate")
196
 
197
  # Enhanced analysis trigger
198
- if st.button(" Analyze for Detailed DBOM-I", type="primary"):
199
  perform_enhanced_ibom_analysis(uploaded_image)
200
  else:
201
  st.info("Upload an image to begin analysis")
@@ -208,13 +204,22 @@ def create_enhanced_ibom_interface(tbom_data):
208
  - Show any bruising or discoloration
209
  - Minimal background distractions
210
  """)
211
-
212
  with results_col:
213
- # Display results if available
214
  if 'enhanced_ibom_data' in st.session_state:
215
  display_comprehensive_ibom_results()
216
- create_concept_score_modification_interface()
217
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
 
220
  def perform_enhanced_ibom_analysis(uploaded_file):
@@ -286,7 +291,7 @@ def display_comprehensive_ibom_results():
286
  # --- Add download button for Original IBOM ---
287
  original_json_data = json.dumps(original_result, indent=2)
288
  st.download_button(
289
- label="πŸ“„ Download Original DBOM-I.json",
290
  data=original_json_data,
291
  file_name=f"IBOM_{data['analysis_timestamp'].strftime('%Y%m%d_%H%M%S')}.json",
292
  mime="application/json"
@@ -577,7 +582,7 @@ def display_enhanced_export_options():
577
 
578
  with col1:
579
  st.download_button(
580
- label="πŸ“„ Original DBOM-I JSON",
581
  data=json.dumps(data['original_result'], indent=2),
582
  file_name=f"original_IBOM_{timestamp}.json",
583
  mime="application/json"
@@ -585,7 +590,7 @@ def display_enhanced_export_options():
585
  with col2:
586
  if 'modified_result' in data:
587
  st.download_button(
588
- label="πŸ“„ Modified DBOM-I JSON",
589
  data=json.dumps(data['modified_result'], indent=2),
590
  file_name=f"modified_IBOM_{timestamp}.json",
591
  mime="application/json"
@@ -612,7 +617,7 @@ def create_performance_overview(tbom_data):
612
  test_results = perf_metrics.get('final_test_results', {})
613
  cv_results = perf_metrics.get('cross_validation_results', {})
614
 
615
- col1, col2, col3 = st.columns(3)
616
 
617
  with col1:
618
  test_acc = test_results.get('accuracy', 0) * 100
@@ -638,6 +643,14 @@ def create_performance_overview(tbom_data):
638
  delta=f"CV: {cv_results.get('mean_pr_auc', 0)*100:.2f}%"
639
  )
640
 
 
 
 
 
 
 
 
 
641
  def create_confusion_matrix_viz(tbom_data):
642
  """Create interactive confusion matrix visualization (UNCHANGED)"""
643
  test_results = tbom_data.get('performance_metrics', {}).get('final_test_results', {})
@@ -1068,7 +1081,7 @@ def create_technical_details(tbom_data):
1068
 
1069
  st.markdown(f"""
1070
  <div class="metric-card">
1071
- <h4>πŸ“‹ DBOM-T Information</h4>
1072
  <p><strong>Version:</strong> {tbom_version}</p>
1073
  <p><strong>Generated:</strong> {timestamp}</p>
1074
  <p><strong>Training Time:</strong> {training_time/3600:.2f} hours</p>
@@ -1097,19 +1110,126 @@ def create_technical_details(tbom_data):
1097
 
1098
  st.markdown("---")
1099
  # --- Add download button for TBOM.json ---
1100
- st.subheader("Download Full DBOM-T")
1101
  tbom_json_data = json.dumps(tbom_data, indent=2)
1102
  st.download_button(
1103
- label="πŸ“₯ Download DBOM-T.json",
1104
  data=tbom_json_data,
1105
  file_name="TBOM.json",
1106
  mime="application/json"
1107
  )
1108
 
1109
  # Expander for raw data
1110
- with st.expander("πŸ” View Raw DBOM-T Data"):
1111
  st.json(tbom_data)
1112
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1113
 
1114
  #Main function to run the Streamlit app
1115
 
@@ -1117,13 +1237,13 @@ def main():
1117
  """Main Streamlit application with enhanced IBOM integration"""
1118
  # Header (keeping your original style)
1119
  st.markdown('<h1 class="main-header">πŸ„ Dependable FungAI</h1>', unsafe_allow_html=True)
1120
- st.markdown('<h2 class="sub-header">Descision Bill of Materials DBOM-T & DBOM-I</h2>', unsafe_allow_html=True)
1121
 
1122
  # Load TBOM data
1123
  tbom_data = load_tbom_data()
1124
 
1125
  if tbom_data is None:
1126
- st.error("Could not load DBOM-T data. Please ensure the TBOM.json file is available.")
1127
  st.stop()
1128
 
1129
  # Sidebar information (keeping your original sidebar)
@@ -1145,7 +1265,7 @@ def main():
1145
  st.markdown('</div>', unsafe_allow_html=True)
1146
 
1147
  # File info
1148
- st.markdown("### πŸ“„ DBOM-T Info")
1149
  tbom_version = tbom_data.get('tbom_version', 'Unknown')
1150
  timestamp = tbom_data.get('generation_details', {}).get('timestamp_utc', 'Unknown')
1151
  st.markdown(f"**Version:** {tbom_version}")
@@ -1153,16 +1273,17 @@ def main():
1153
 
1154
  # Main content tabs
1155
  tabs = st.tabs([
1156
- "πŸ” Detailed DBOM-I",
1157
- "🎯 Overview",
1158
- "πŸ“ˆ Performance",
1159
- "πŸ—οΈ Architecture",
1160
- "🧠 Concepts",
1161
- "πŸ“Š Data Summary",
1162
- "πŸ’» Technical"
 
1163
  ])
1164
 
1165
- # NEW ENHANCED IBOM TAB
1166
  with tabs[0]:
1167
  create_enhanced_ibom_interface(tbom_data)
1168
 
@@ -1194,6 +1315,8 @@ def main():
1194
 
1195
  with tabs[6]:
1196
  create_technical_details(tbom_data)
 
 
1197
 
1198
  if __name__ == "__main__":
1199
  main()
 
20
  import torch
21
  import torch.nn as nn
22
 
23
+ # Dynamic import from enhanced IBOM backend (no hardcoded paths)
24
  from IBOM import DetailedIBOMGenerator, get_paths_with_smart_fallback
25
 
26
  # Page configuration
 
118
  with open(tbom_path, 'r') as f:
119
  return json.load(f)
120
  except Exception:
121
+ st.error("TBOM file not found. Please ensure TBOM.json is available.")
122
  return None
123
  except Exception as e:
124
+ st.error(f"Error loading TBOM data: {str(e)}")
125
  return None
126
 
127
  #Enhanced IBOM Interface
128
 
129
  def create_enhanced_ibom_interface(tbom_data):
130
  """Complete enhanced IBOM interface with all advanced features"""
131
+ st.markdown('<h2 class="sub-header">πŸ” Enhanced Interactive Inference Bill of Materials (IBOM)</h2>', unsafe_allow_html=True)
132
 
133
  # Feature overview
134
  with st.expander("Enhanced Features Overview", expanded=False):
 
148
  with col2:
149
  st.markdown("""
150
  **πŸ“₯ Export Functionality:**
151
+ - Download IBOM JSON files
152
  - CSV exports for spreadsheet analysis
153
  - Detailed analysis reports
154
 
 
164
  "Upload a mushroom image for comprehensive analysis",
165
  type=['jpg', 'jpeg', 'png', 'bmp'],
166
  help="Upload a clear image showing cap, gills, and stalk for detailed AI analysis"
167
+ )
168
 
 
 
 
 
169
  # Main layout: Image on the left, results on the right
170
  img_col, results_col = st.columns([1, 2.5])
171
 
 
191
  st.warning("⚠️ Low resolution - results may be less accurate")
192
 
193
  # Enhanced analysis trigger
194
+ if st.button(" Analyze with Enhanced IBOM", type="primary"):
195
  perform_enhanced_ibom_analysis(uploaded_image)
196
  else:
197
  st.info("Upload an image to begin analysis")
 
204
  - Show any bruising or discoloration
205
  - Minimal background distractions
206
  """)
207
+ # Results Section
208
  with results_col:
 
209
  if 'enhanced_ibom_data' in st.session_state:
210
  display_comprehensive_ibom_results()
 
211
 
212
+ # Add MIA analysis section
213
+ st.markdown("---")
214
+ st.markdown("### πŸ” Membership Inference Attack (MIA) Analysis")
215
+ st.markdown("**Description:** Analysis to distinguish members from non-members using Loss and Confidence metrics.")
216
+
217
+ # Display MIA results for uploaded image
218
+ if uploaded_image is not None:
219
+ display_mia_analysis_for_image(st.session_state.enhanced_ibom_data['ibom_generator'],
220
+ Image.open(uploaded_image))
221
+
222
+ create_concept_score_modification_interface()
223
 
224
 
225
  def perform_enhanced_ibom_analysis(uploaded_file):
 
291
  # --- Add download button for Original IBOM ---
292
  original_json_data = json.dumps(original_result, indent=2)
293
  st.download_button(
294
+ label="πŸ“„ Download Original IBOM.json",
295
  data=original_json_data,
296
  file_name=f"IBOM_{data['analysis_timestamp'].strftime('%Y%m%d_%H%M%S')}.json",
297
  mime="application/json"
 
582
 
583
  with col1:
584
  st.download_button(
585
+ label="πŸ“„ Original IBOM JSON",
586
  data=json.dumps(data['original_result'], indent=2),
587
  file_name=f"original_IBOM_{timestamp}.json",
588
  mime="application/json"
 
590
  with col2:
591
  if 'modified_result' in data:
592
  st.download_button(
593
+ label="πŸ“„ Modified IBOM JSON",
594
  data=json.dumps(data['modified_result'], indent=2),
595
  file_name=f"modified_IBOM_{timestamp}.json",
596
  mime="application/json"
 
617
  test_results = perf_metrics.get('final_test_results', {})
618
  cv_results = perf_metrics.get('cross_validation_results', {})
619
 
620
+ col1, col2, col3, col4 = st.columns(4)
621
 
622
  with col1:
623
  test_acc = test_results.get('accuracy', 0) * 100
 
643
  delta=f"CV: {cv_results.get('mean_pr_auc', 0)*100:.2f}%"
644
  )
645
 
646
+ with col4:
647
+ training_time = tbom_data.get('generation_details', {}).get('training_time_seconds', 0)
648
+ st.metric(
649
+ label="⏱️ Training Time",
650
+ value=f"{training_time/60:.1f} min",
651
+ delta=f"{training_time:.0f}s total"
652
+ )
653
+
654
  def create_confusion_matrix_viz(tbom_data):
655
  """Create interactive confusion matrix visualization (UNCHANGED)"""
656
  test_results = tbom_data.get('performance_metrics', {}).get('final_test_results', {})
 
1081
 
1082
  st.markdown(f"""
1083
  <div class="metric-card">
1084
+ <h4>πŸ“‹ TBOM Information</h4>
1085
  <p><strong>Version:</strong> {tbom_version}</p>
1086
  <p><strong>Generated:</strong> {timestamp}</p>
1087
  <p><strong>Training Time:</strong> {training_time/3600:.2f} hours</p>
 
1110
 
1111
  st.markdown("---")
1112
  # --- Add download button for TBOM.json ---
1113
+ st.subheader("Download Full TBOM")
1114
  tbom_json_data = json.dumps(tbom_data, indent=2)
1115
  st.download_button(
1116
+ label="πŸ“₯ Download TBOM.json",
1117
  data=tbom_json_data,
1118
  file_name="TBOM.json",
1119
  mime="application/json"
1120
  )
1121
 
1122
  # Expander for raw data
1123
+ with st.expander("πŸ” View Raw TBOM Data"):
1124
  st.json(tbom_data)
1125
+
1126
+ # Membership Inference Attack Analysis tab
1127
+ def create_mia_analysis(tbom_data):
1128
+ """Display Membership Inference Attack analysis results"""
1129
+ st.markdown("### πŸ” Membership Inference Attack (MIA) Analysis")
1130
+
1131
+ mia_data = tbom_data.get('membership_inference_analysis', {})
1132
+ if not mia_data:
1133
+ st.warning("No MIA analysis data available")
1134
+ return
1135
+
1136
+ # Display description and method
1137
+ st.markdown(f"**Description:** {mia_data.get('description', 'N/A')}")
1138
+
1139
+ # Create metrics display
1140
+ col1, col2 = st.columns(2)
1141
+ with col1:
1142
+ threshold = mia_data.get('threshold_finding_summary', {}).get('decision_threshold', 0)
1143
+ st.metric(
1144
+ "Decision Threshold",
1145
+ f"{threshold:.4f}",
1146
+ help="Confidence score threshold for member/non-member classification"
1147
+ )
1148
+
1149
+ with col2:
1150
+ auc_score = mia_data.get('threshold_finding_summary', {}).get('attack_auc_score_on_confidence', 0)
1151
+ st.metric(
1152
+ "Attack AUC Score",
1153
+ f"{auc_score:.4f}",
1154
+ help="Area Under Curve score for the membership inference attack"
1155
+ )
1156
+
1157
+ # Display visualization if available
1158
+ viz_path = mia_data.get('visualization_artifact')
1159
+ if viz_path and os.path.exists(viz_path):
1160
+ st.markdown("### Confidence Score Distribution")
1161
+ st.image(viz_path, caption="Member vs Non-member Confidence Distributions")
1162
+
1163
+ # Display detailed statistics
1164
+ st.markdown("### Detailed Statistics")
1165
+
1166
+ stats_tabs = st.tabs(["Member Statistics", "Non-member Statistics"])
1167
+
1168
+ with stats_tabs[0]:
1169
+ member_stats = mia_data.get('metric_statistics', {}).get('members', {})
1170
+ if member_stats:
1171
+ st.dataframe(pd.DataFrame(member_stats))
1172
+ else:
1173
+ st.info("No member statistics available")
1174
+
1175
+ with stats_tabs[1]:
1176
+ non_member_stats = mia_data.get('metric_statistics', {}).get('non_members', {})
1177
+ if non_member_stats:
1178
+ st.dataframe(pd.DataFrame(non_member_stats))
1179
+ else:
1180
+ st.info("No non-member statistics available")
1181
+
1182
+ # Display MIA analysis for uploaded image
1183
+ def display_mia_analysis_for_image(model_wrapper, image):
1184
+ """Display MIA analysis results for an uploaded image"""
1185
+ st.markdown("### πŸ” MIA Analysis for Uploaded Image")
1186
+
1187
+ # Get MIA metrics for single image
1188
+ transform = model_wrapper.preprocess
1189
+ img_tensor = transform(image).unsqueeze(0).to(model_wrapper.device)
1190
+
1191
+ with torch.no_grad():
1192
+ # Feature extraction
1193
+ img_features = model_wrapper.clip_model.encode_image(img_tensor).float()
1194
+ img_features_norm = img_features / img_features.norm(dim=1, keepdim=True)
1195
+ concept_scores = img_features_norm @ model_wrapper.text_embeddings.T
1196
+ hybrid_features = torch.cat([img_features, concept_scores], dim=1)
1197
+
1198
+ # Get predictions
1199
+ logits = model_wrapper.model(hybrid_features)
1200
+ probabilities = torch.sigmoid(logits)
1201
+ confidence = torch.max(probabilities, 1 - probabilities).item()
1202
+
1203
+ # Load threshold from TBOM
1204
+ tbom_path = "TBOM.json"
1205
+ with open(tbom_path, 'r') as f:
1206
+ tbom_data = json.load(f)
1207
+
1208
+ mia_data = tbom_data.get('membership_inference_analysis', {})
1209
+ threshold = mia_data.get('threshold_finding_summary', {}).get('decision_threshold', 0.92)
1210
+
1211
+ # Display results
1212
+ col1, col2 = st.columns(2)
1213
+ with col1:
1214
+ st.metric(
1215
+ "Confidence Score",
1216
+ f"{confidence:.4f}",
1217
+ help="Model's confidence in its prediction"
1218
+ )
1219
+
1220
+ with col2:
1221
+ is_member = confidence > threshold
1222
+ st.metric(
1223
+ "MIA Classification",
1224
+ "Training Set Member" if is_member else "Non-Member",
1225
+ help=f"Threshold: {threshold:.4f}"
1226
+ )
1227
+
1228
+ # Add interpretation
1229
+ if is_member:
1230
+ st.success("βœ… This image is likely a member of the training data")
1231
+ else:
1232
+ st.warning("⚠️ This image is likely NOT a member of the training data")
1233
 
1234
  #Main function to run the Streamlit app
1235
 
 
1237
  """Main Streamlit application with enhanced IBOM integration"""
1238
  # Header (keeping your original style)
1239
  st.markdown('<h1 class="main-header">πŸ„ Dependable FungAI</h1>', unsafe_allow_html=True)
1240
+ st.markdown('<h2 class="sub-header">Training Bill of Materials (TBOM) & Enhanced Inference Analysis</h2>', unsafe_allow_html=True)
1241
 
1242
  # Load TBOM data
1243
  tbom_data = load_tbom_data()
1244
 
1245
  if tbom_data is None:
1246
+ st.error("Could not load TBOM data. Please ensure the TBOM.json file is available.")
1247
  st.stop()
1248
 
1249
  # Sidebar information (keeping your original sidebar)
 
1265
  st.markdown('</div>', unsafe_allow_html=True)
1266
 
1267
  # File info
1268
+ st.markdown("### πŸ“„ TBOM Info")
1269
  tbom_version = tbom_data.get('tbom_version', 'Unknown')
1270
  timestamp = tbom_data.get('generation_details', {}).get('timestamp_utc', 'Unknown')
1271
  st.markdown(f"**Version:** {tbom_version}")
 
1273
 
1274
  # Main content tabs
1275
  tabs = st.tabs([
1276
+ "πŸ” Enhanced IBOM",
1277
+ "Overview",
1278
+ "Performance",
1279
+ "Architecture",
1280
+ "Concepts",
1281
+ "Data Summary",
1282
+ "Technical",
1283
+ "MIA Analysis"
1284
  ])
1285
 
1286
+ # NEW ENHANCED IBOM TAB WITH ALL REQUESTED FEATURES
1287
  with tabs[0]:
1288
  create_enhanced_ibom_interface(tbom_data)
1289
 
 
1315
 
1316
  with tabs[6]:
1317
  create_technical_details(tbom_data)
1318
+ with tabs[7]:
1319
+ create_mia_analysis(tbom_data)
1320
 
1321
  if __name__ == "__main__":
1322
  main()