基于Keras的多标签分类任务中JSON文件处理方法咨询
Got it, let's break down exactly how to convert your JSON multi-label image data into the binary vector format that works with Keras—just like the tutorial you referenced. Here's a step-by-step solution tailored to your setup:
First, we'll read in your JSON file and restructure it into a usable format. Note: Make sure your JSON has unique image filenames as keys (the example you shared has duplicate "PIC_NAME" keys, which standard JSON parsers will overwrite—fix that first if it's an actual issue in your data).
import json import numpy as np import pandas as pd from sklearn.preprocessing import MultiLabelBinarizer # Load the JSON label file with open('your_label_data.json', 'r') as f: label_data = json.load(f) # Convert to a list of (image_filename, label_list) tuples for easy processing image_label_pairs = [(img_filename, labels) for img_filename, labels in label_data.items()]
We'll use MultiLabelBinarizer (from scikit-learn) to handle the conversion from string labels to binary vectors. First, we'll extract all unique labels from your dataset to define our label set.
# Collect all unique labels across all images all_labels = [label for _, label_list in image_label_pairs for label in label_list] unique_labels = sorted(list(set(all_labels))) print(f"Identified {len(unique_labels)} unique labels: {unique_labels}") # Initialize the binarizer with our fixed label set (ensures consistent indices every time) mlb = MultiLabelBinarizer(classes=unique_labels) mlb.fit([unique_labels])
If you actually need a 23-dimensional vector (like the tutorial mentioned, even though you have 20 labels), just add 3 placeholder labels to the unique_labels list before fitting the binarizer.
Now we'll transform each image's label list into the binary format Keras expects. For example, if an image has labels ["Label2", "Label6"], the vector will have 1s at the indices corresponding to Label2 and Label6, and 0s everywhere else.
# Convert all label lists to binary vectors binary_label_matrix = mlb.transform([label_list for _, label_list in image_label_pairs]) # Example verification to make sure it works sample_idx = 0 print(f"\nSample Image: {image_label_pairs[sample_idx][0]}") print(f"Original Labels: {image_label_pairs[sample_idx][1]}") print(f"Binary Label Vector: {binary_label_matrix[sample_idx]}")
To match the tutorial's workflow, we can convert this into a CSV file (like the tutorials use) or keep it as a DataFrame for direct use with Keras' ImageDataGenerator.
Option A: Save to CSV (for flow_from_dataframe)
# Create a DataFrame with image paths and expanded binary label columns df = pd.DataFrame({ 'image_path': [img_filename for img_filename, _ in image_label_pairs] }) # Add each label as a separate column (0/1 values) for label_idx, label in enumerate(unique_labels): df[label] = binary_label_matrix[:, label_idx] # Save to CSV for easy use in Keras df.to_csv('image_labels_binary.csv', index=False)
Option B: Use directly in Keras
If you don't want a CSV, you can use the binary_label_matrix directly with a custom data loader, or pair it with image paths for flow_from_dataframe:
from tensorflow.keras.preprocessing.image import ImageDataGenerator # Initialize image data generator (add augmentations as needed) datagen = ImageDataGenerator(rescale=1./255) # Create a generator that loads images and their binary labels train_generator = datagen.flow_from_dataframe( dataframe=df, directory='path/to/your/image/folder', # Path where your images are stored x_col='image_path', y_col=unique_labels, # Use the label columns we created target_size=(224, 224), # Adjust to your model's input size batch_size=32, class_mode='raw' # Critical for multi-label binary classification )
- Ensure your image filenames in the JSON match the actual filenames in your image directory (including file extensions like .jpg).
- The
class_mode='raw'tells Keras we're passing binary vectors for multi-label classification, instead of single-class labels. - If you need to map back from binary vectors to string labels later, use
mlb.inverse_transform(binary_label_matrix)to convert vectors back to label lists.
内容的提问来源于stack exchange,提问作者glomba

