@@ -313,50 +313,84 @@ def export_to_onnx(self):
313313
314314 with open (output_path , "wb" ) as f :
315315 f .write (model_proto .SerializeToString ())
316- logger .info (f"TensorFlow multilabel model successfully exported to ONNX: { output_path } " )
316+
317+ # Verify export success by checking file size
318+ file_size = Path (output_path ).stat ().st_size
319+ if file_size > 1000 : # If larger than 1KB, it's likely a real model
320+ logger .info (f"TensorFlow multilabel model successfully exported to ONNX: { output_path } ({ file_size } bytes)" )
321+ return # Exit early on success
322+ else :
323+ logger .warning (f"ONNX export produced small file ({ file_size } bytes), trying fallback methods..." )
324+ raise Exception ("Export produced suspiciously small file" )
317325
318326 except Exception as e :
319327 logger .error (f"Failed to export TensorFlow multilabel model to ONNX: { e } " )
320- # Try fallback approach with older opset
328+ # Try functional model approach as primary fallback
321329 try :
322- logger .info ("Trying fallback ONNX export method with older opset ..." )
330+ logger .info ("Trying functional model approach ..." )
323331 actual_input_shape = self .model .input_shape [1 :]
332+ # Create a functional model with correct architecture
333+ input_layer = tf .keras .layers .Input (shape = actual_input_shape , name = "float_input" )
334+ x = tf .keras .layers .Dense (128 , activation = "relu" )(input_layer )
335+ x = tf .keras .layers .Dropout (0.5 )(x )
336+ outputs = tf .keras .layers .Dense (self .num_classes , activation = "sigmoid" )(x )
337+
338+ functional_model = tf .keras .Model (inputs = input_layer , outputs = outputs , name = "multilabel_model" )
339+
340+ # Copy weights from Sequential model to Functional model
341+ # Sequential: [Dense(128), Dropout, Dense(4)]
342+ # Functional: [Input, Dense(128), Dropout, Dense(4)]
343+ for i , layer in enumerate (self .model .layers ):
344+ if layer .get_weights ():
345+ # Skip input layer (no weights) and map correctly
346+ if i == 0 : # First layer in Sequential (Dense)
347+ functional_model .layers [1 ].set_weights (layer .get_weights ()) # Skip input layer
348+ elif i == 1 : # Second layer (Dropout - no weights)
349+ continue # Skip dropout layer
350+ elif i == 2 : # Third layer (Dense)
351+ functional_model .layers [3 ].set_weights (layer .get_weights ()) # Skip input and dropout
352+
353+ # Convert functional model to ONNX
324354 spec = (tf .TensorSpec ((None , actual_input_shape [0 ]), tf .float32 , name = "float_input" ),)
325355 model_proto , _ = tf2onnx .convert .from_keras (
326- self . model , input_signature = spec , opset = 11 # Use older opset
356+ functional_model , input_signature = spec , opset = 11
327357 )
358+
328359 with open (output_path , "wb" ) as f :
329360 f .write (model_proto .SerializeToString ())
330- logger .info (f"TensorFlow multilabel model exported to ONNX using fallback method: { output_path } " )
361+
362+ # Verify export success
363+ file_size = Path (output_path ).stat ().st_size
364+ if file_size > 1000 :
365+ logger .info (f"TensorFlow multilabel model exported to ONNX using functional model approach: { output_path } ({ file_size } bytes)" )
366+ return # Exit early on success
367+ else :
368+ logger .warning (f"Functional model approach produced small file ({ file_size } bytes), trying next fallback..." )
369+ raise Exception ("Functional model export produced suspiciously small file" )
370+
331371 except Exception as e2 :
332- logger .error (f"Fallback ONNX export also failed: { e2 } " )
333- # Try functional model approach as last resort
372+ logger .error (f"Functional model approach failed: { e2 } " )
373+ # Try fallback approach with older opset as secondary fallback
334374 try :
335- logger .info ("Trying functional model approach..." )
336- # Create a functional model with correct architecture
337- input_layer = tf .keras .layers .Input (shape = actual_input_shape , name = "float_input" )
338- x = tf .keras .layers .Dense (128 , activation = "relu" )(input_layer )
339- x = tf .keras .layers .Dropout (0.5 )(x )
340- outputs = tf .keras .layers .Dense (self .num_classes , activation = "sigmoid" )(x )
341-
342- functional_model = tf .keras .Model (inputs = input_layer , outputs = outputs , name = "multilabel_model" )
343-
344- # Copy weights from Sequential model to Functional model
345- for i , layer in enumerate (self .model .layers [1 :]): # Skip input layer
346- if layer .get_weights ():
347- functional_model .layers [i + 1 ].set_weights (layer .get_weights ())
348-
349- # Convert functional model to ONNX
375+ logger .info ("Trying direct conversion with older opset..." )
376+ actual_input_shape = self .model .input_shape [1 :]
350377 spec = (tf .TensorSpec ((None , actual_input_shape [0 ]), tf .float32 , name = "float_input" ),)
351378 model_proto , _ = tf2onnx .convert .from_keras (
352- functional_model , input_signature = spec , opset = 11
379+ self . model , input_signature = spec , opset = 11 # Use older opset
353380 )
354-
355381 with open (output_path , "wb" ) as f :
356382 f .write (model_proto .SerializeToString ())
357- logger .info (f"TensorFlow multilabel model exported to ONNX using functional model approach: { output_path } " )
383+
384+ # Verify export success
385+ file_size = Path (output_path ).stat ().st_size
386+ if file_size > 1000 :
387+ logger .info (f"TensorFlow multilabel model exported to ONNX using older opset: { output_path } ({ file_size } bytes)" )
388+ return # Exit early on success
389+ else :
390+ logger .warning (f"Older opset approach produced small file ({ file_size } bytes), creating placeholder..." )
391+ raise Exception ("Older opset export produced suspiciously small file" )
358392 except Exception as e3 :
359- logger .error (f"Functional model approach also failed: { e3 } " )
393+ logger .error (f"Older opset approach also failed: { e3 } " )
360394 # Create a simple ONNX model manually as last resort
361395 logger .warning ("Creating minimal ONNX model file as last resort..." )
362396 try :
0 commit comments