You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求验证基于TensorFlow的RESNET架构二分类机器学习代码

Code Validation for TensorFlow ResNet Binary Classification Project

Hi Karl, let's walk through validating your code, focusing first on the two areas you mentioned—dataset splitting and brightness augmentation—then covering overall correctness.


1. Dataset Splitting Logic (splitdataset.ipynb)

Your core 80/10/10 split approach makes sense, but there are several critical bugs and fragilities to address:

Critical Bugs

  • Mismatched Directory Names: You create directories under data_set/ but copy files to split_ds/. This will throw a FileNotFoundError unless split_ds already exists. Replace all split_ds/ references with data_set/ to align with your directory setup.
  • Fragile Class Detection: Checking image[8] to determine class relies on hardcoded path indices, which will break if your directory structure changes. Use os.path utilities instead to safely extract the class:
    # Replace this:
    if(image[8] == "D"):
        im = image[14:]
    # With this:
    class_dir = os.path.basename(os.path.dirname(image))
    filename = os.path.basename(image)
    if class_dir == "DU145":
    
  • Unsafe Filename Extraction: image[14:] and image[12:] are hardcoded. Use os.path.basename(image) to get the filename reliably regardless of path length.

Improvements for Robustness

  • Class Balance Preservation: Combining both classes before shuffling can lead to imbalanced splits if your original dataset has unequal class sizes. Split each class separately to maintain balance:
    # Split DU145
    random.shuffle(du145)
    du145_train = du145[:int(0.8*len(du145))]
    du145_val = du145[int(0.8*len(du145)):int(0.9*len(du145))]
    du145_test = du145[int(0.9*len(du145)):]
    
    # Split PC3 similarly
    random.shuffle(pc3)
    pc3_train = pc3[:int(0.8*len(pc3))]
    pc3_val = pc3[int(0.8*len(pc3)):int(0.9*len(pc3))]
    pc3_test = pc3[int(0.9*len(pc3)):]
    
    # Combine and shuffle to mix classes
    train = du145_train + pc3_train
    val = du145_val + pc3_val
    test = du145_test + pc3_test
    random.shuffle(train)
    random.shuffle(val)
    random.shuffle(test)
    
  • Clean Existing Split Directory: Add !rm -r data_set at the start to avoid duplicate files when re-running the script.
  • Handle Missing Directories: Add checks to ensure full_ds/DU145 and full_ds/PC3 exist before proceeding to avoid errors.

2. Brightness Augmentation Implementation (classifyimages.ipynb)

Your custom augmentation layer has two critical issues that will prevent it from working as intended:

Critical Bugs

  • Numpy Random in Graph Mode: Using np.random.uniform inside the layer's call method will generate a single random value once when the model graph is built, not per batch or image. Replace with TensorFlow's random operations for dynamic, graph-compatible augmentation:
    # Replace np.random.uniform with tf.random.uniform
    contrast = tf.random.uniform(shape=[], minval=self.contrast_range[0], maxval=self.contrast_range[1])
    brightness = tf.random.uniform(shape=[], minval=self.brightness_delta[0], maxval=self.brightness_delta[1])
    
  • Incorrect Augmentation Order: You apply color distortion before rescaling. Since image_dataset_from_directory loads images as uint8 (0-255), your brightness delta ([-0.15, 0.15]) is negligible against 0-255 pixel values. Reorder your augmentation sequence to rescale first, then apply color/brightness adjustments:
    augment_and_normalize = tf.keras.Sequential([
        tf.keras.layers.experimental.preprocessing.Rescaling(1.0 / 255),  # Rescale first
        RandomColorDistortion(contrast_range=[0.5,1.5], brightness_delta=[-0.15, 0.15]),
        tf.keras.layers.RandomFlip("horizontal"),
        tf.keras.layers.RandomRotation(0.1),
    ], name="augment_and_normalize")
    
    This ensures your brightness/contrast adjustments operate on 0-1 normalized images, making the delta values meaningful.

Minor Improvement

  • Redundant Clipping: tf.image.adjust_contrast and tf.image.adjust_brightness already clamp values to valid ranges for normalized images, so tf.clip_by_value(images, 0, 1) is redundant but harmless.

3. Full Code Validation Notes

Model Architecture

  • Redundant Flatten Layer: GlobalAveragePooling2D outputs a 1D tensor, so the subsequent Flatten() layer does nothing. You can safely remove it.
  • Base Model Freezing: When using pre-trained ResNet50, consider freezing the base layers initially to avoid destroying pre-trained features during early training:
    feature_extractor = tf.keras.applications.resnet.ResNet50(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
    feature_extractor.trainable = False  # Freeze base model
    # After initial training, unfreeze some layers for fine-tuning if needed
    
  • Binary Classification Output: Using Dense(1, activation="sigmoid") with binary_crossentropy is correct for binary classification.

Training Workflow

  • ModelCheckpoint Best Weights: Your callback saves the best weights based on val_accuracy, but you manually copy weights.05.ckpt. Instead, use a fixed filename for best weights to avoid copying arbitrary epochs:
    ModelCheckpoint(filepath="best_weights.ckpt", monitor='val_accuracy', save_best_only=True, save_weights_only=True)
    
    Then copy best_weights.ckpt.* to your drive.
  • Data Prefetching: Add prefetching to speed up training by overlapping data loading and model execution:
    train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
    val_ds = val_ds.prefetch(tf.data.AUTOTUNE)
    test_ds = test_ds.prefetch(tf.data.AUTOTUNE)
    

Corrected Code Snippets

Fixed RandomColorDistortion Layer

class RandomColorDistortion(tf.keras.layers.Layer):
    def __init__(self, contrast_range=[0.5, 1.5], brightness_delta=[-0.2, 0.2], **kwargs):
        super(RandomColorDistortion, self).__init__(**kwargs)
        self.contrast_range = contrast_range
        self.brightness_delta = brightness_delta
    def call(self, images, training=None):
        if not training:
            return images
        # Use TensorFlow random operations instead of numpy
        contrast = tf.random.uniform(shape=[], minval=self.contrast_range[0], maxval=self.contrast_range[1])
        brightness = tf.random.uniform(shape=[], minval=self.brightness_delta[0], maxval=self.brightness_delta[1])
        images = tf.image.adjust_contrast(images, contrast)
        images = tf.image.adjust_brightness(images, brightness)
        return images

Fixed Dataset Splitting Class Handling

for image in train:
    class_dir = os.path.basename(os.path.dirname(image))
    filename = os.path.basename(image)
    if class_dir == "DU145":
        shutil.copyfile(image, "data_set/training/DU145/"+filename)
    elif class_dir == "PC3":
        shutil.copyfile(image, "data_set/training/PC3/"+filename)

These fixes will ensure your dataset splitting works reliably and your brightness augmentation operates as intended. Let me know if you need further clarification on any part!

内容的提问来源于stack exchange,提问作者karl-gardner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:02:32